Migrating from Config Pages
If a code-native integration uses config pages, you can publish a new version that uses headless configuration instead.
Existing instances keep running on the config pages version until you update them, and your init function converts their config variable values to the new configuration.
What changes
| Config pages | Headless configuration |
|---|---|
configPages with configVar() elements | A configuration() with a schema |
| Prismatic renders the config wizard | Your app renders the form |
Values are strings in context.configVars | Values have real types in context.configuration |
| Data sources supply dynamic options | Server functions supply dynamic options |
| Connections are config variables on a page | Connections are declared in the configuration |
| A flow's schedule can come from a config variable | A flow's schedule is fixed, or supplied by the deployer |
Migrate the integration
-
Write the new schema. Describe the values your flows need with their real types, such as
batchSize: z.number()instead of a"Batch Size"string. See Defining a schema with zod. -
Describe the old values. Add a
configPagesSchemathat matches the config variables your config pages collected, keyed by name. Config pages store scalars as strings, so accept either form:src/configuration.tsexport const configPagesSchema = z.object({Region: z.string(),"Sync Enabled": z.union([z.boolean(), z.string()]),"Batch Size": z.union([z.number(), z.string()]),}); -
Replace config pages with a configuration, and convert the old values in
init. RemoveconfigPagesfrom your integration, and pass aconfigurationthat includes theconfigPagesSchema.An instance that was configured with config pages has never saved a headless configuration, so in
init,context.configurationVersionisnull. In that case,context.configurationholds the config page values, keyed by config variable name. Spectral types it from yourconfigPagesSchema, with every field optional. Convert each value, and report anything you can't carry over:src/configuration.tsconst DEFAULTS: Configuration = {region: "us-east",syncEnabled: true,batchSize: 100,};export const integrationConfiguration = configuration({instance: {schema: configurationSchema,version: "order-sync-v1",configPagesSchema,},init: {perform: async (context) => {if (context.configurationVersion === null) {// Typed from configPagesSchema, with every field optionalconst legacy = context.configuration;const batchSize = Number(legacy["Batch Size"]);const validBatch = Number.isInteger(batchSize) && batchSize > 0;return {configuration: {region: legacy.Region ?? DEFAULTS.region,syncEnabled:legacy["Sync Enabled"] === undefined? DEFAULTS.syncEnabled: String(legacy["Sync Enabled"]) === "true",batchSize: validBatch ? batchSize : DEFAULTS.batchSize,},unresolvedReasons: validBatch? []: [`Batch size "${String(legacy["Batch Size"])}" isn't valid; using 100.`,],};}// Handle the current version as shown in Configuration versions and initconst saved = configurationSchema.safeParse(context.configuration);return {configuration: saved.success ? saved.data : DEFAULTS,unresolvedReasons: [],};},},}); -
Read configuration in flows. Replace
context.configVarsreads withcontext.configuration, and delete the string parsing your flows no longer need. -
Replace data sources with server functions and declare your connections in the configuration.
-
Replace config variable schedules. A flow whose schedule reads a config variable,
schedule: { configVar: "..." }, won't build once the integration has a configuration. Change it to a fixed{ value }schedule, or to{ fromDeployer: true }so the customer chooses the schedule in your app. -
Publish the new version and make it available in your marketplace.
An instance on a config pages version has no headless configuration value, and your app can't read its config variables directly.
The only way across is the new version's init, followed by save.
If an instance's config page values are missing, return sensible defaults and explain them in unresolvedReasons, so the customer can review the values before saving.
Migrate instances
To your app, the new version appears as an update that requires reconfiguration:
- Your app sees
update.requiresReconfigurationon the instance. - It opens the update's configuration and runs
init, which converts the config variable values. - The customer reviews the suggested values, and any
unresolvedReasons, in your form. - Your app saves the configuration, which moves the instance to the new version, and deploys it.
Until you migrate an instance, it stays on a config pages version.
Its configuration experience is hosted, so your app can keep opening Prismatic's config wizard for it.
See Building configuration UIs with Solis React.