Skip to content

Seed config and reference data on install

What you're doing

Making data rows travel with the .spk instead of a manual per-tenant POST. Two things need seeding:

  1. reference data you own — equipment categories, status pick-lists, default settings.
  2. rows in shared platform config tablesentity_status_date_sweep_config, entity_aggregation_config, entity_cadence_config, etc. — that make your scheduled jobs exist.

One file per data set under spk-assembly/metadata/seed-data/. The PluginDataSeedInstaller upserts them on every install, upgrade, and auto-provision — idempotently, keyed by the fields you nominate.

The complete example

spk-assembly/metadata/seed-data/office-equipment-categories.jsonreal file:

json
{
  "entity": "oeq_category",
  "keyFields": ["category_code"],
  "source": "office-equipment",
  "rows": [
    { "category_code": "LAPTOP",  "category_name": "Laptops",  "description": "Portable computers", "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "MONITOR", "category_name": "Monitors", "description": "External displays",  "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "PHONE",   "category_name": "Phones",   "description": "Mobile handsets",    "status": "ACTIVE", "seeded_by": "office-equipment" },
    { "category_code": "HEADSET", "category_name": "Headsets", "description": "Audio headsets",     "status": "ACTIVE", "seeded_by": "office-equipment" }
  ]
}

Line by line

  • entity — the target entity name. It must already exist — ship it in metadata/entities/ if your plugin owns it.
  • keyFields — the natural key. On re-install, a row matching allkeyFields is updated only if a non-key value changed, otherwise inserted. Never duplicated. Choose a key that is genuinely unique (category_code, not category_name).
  • source — your plugin id. Written into a seeded_by field if the entity has one — handy for WHERE seeded_by = 'office-equipment' cleanup later.
  • rows — plain field maps. No tenant id — the installer supplies it.

Idempotency in practice

Publish the plugin, then publish it again with a fifth category added. The installer log shows:

PluginDataSeedInstaller: office-equipment-categories.json -> entity oeq_category (tenant 2): 1 created, 0 updated, 4 unchanged

The four existing rows are left alone; only the new one is inserted. Verified against the tutorial module — the first install logged 4 created, and no re-run ever duplicates them.

Seeding shared platform config (the important use)

The job guides (reminder, aggregation, cadence, compliance) all seed a row into a shared config entity. For those you also ship:

  1. the shared config entity file (entity_status_date_sweep_config.json etc.) so a fresh environment that predates it gains the table. The installer is idempotent-additive: an existing table just gains any missing columns. Ship only the additive fields your rows need — see the tutorial's entity_status_date_sweep_config.json.
  2. an AFTER_CREATE register rule on the config entity, calling ensure<Job>Registered, so the first seeded row auto-registers the job. (The status-date-sweep job's register rule ships with the platform; the others you ship yourself — see each job guide.)

Ground yourself first

bash
erp schema pull plugin-seed-data
erp examples patterns --kind jobs     # "install-lifecycle-data-seeding"

How to verify it worked

bash
erp schema validate spk-assembly/metadata/seed-data/office-equipment-categories.json --schema plugin-seed-data
OK — ... matches schema "plugin-seed-data"

After publishing:

bash
erp api get "/api/v1/entities/oeq_category/records/query?size=10"
json
{ "rows": [
  { "id": 1, "category_code": "LAPTOP",  "category_name": "Laptops",  "status": "ACTIVE", "seeded_by": "office-equipment" },
  { "id": 2, "category_code": "MONITOR", "category_name": "Monitors", "status": "ACTIVE", "seeded_by": "office-equipment" }
], "total": 4 }

Common mistakes

SymptomCauseFix
re-install duplicates rowskeyFields not actually uniquepick a real key
seed fails: entity not founddidn't ship the metadata/entities/*.jsonship it
job doesn't register despite seedingno AFTER_CREATE register rule (for aggregation/cadence/compliance)ship it
a null in keyFields matches nothing / everythingkey field is optional and unset in some rowskeep key fields non-null in every row