Skip to main content

Spectral Codemods

When a Spectral release changes how you write custom connectors or code-native integrations, a codemod can make most of the change for you. @prismatic-io/spectral-codemod is a command-line tool that rewrites your project's source and package files in place, then reports what it couldn't migrate so you can finish by hand.

Run a codemod​

Run the latest codemods with npx; you don't need to add the package to your project. Name the codemod, pass the Spectral version you're upgrading to with --target-spectral, and give the path to your project:

Preview a codemod, then apply it
# Report the files that would change, without writing them
npx @prismatic-io/spectral-codemod@latest public-entry-points --target-spectral latest . --dry-run

# Apply the changes
npx @prismatic-io/spectral-codemod@latest public-entry-points --target-spectral latest .

A codemod can have more than one version as Spectral changes. The tool runs the latest version of that codemod at or below your target, so you don't need to know which Spectral release introduced it. A preview release, such as 10.36.0-preview.1, counts as earlier than its release.

OptionDescription
--target-spectral <version>The Spectral version you're migrating to, such as 10.37.0 or latest. Required.
--dry-runList the files that would change without writing them.
--listPrint the available codemods and what each one does.
--helpPrint usage information.

Choose what to migrate​

The path argument defaults to the current directory, and it determines which files the codemod reads:

  • A directory with a tsconfig.json: the files that tsconfig.json includes.
  • Any other directory: every .ts and .tsx file beneath it, except in node_modules and dist.
  • A tsconfig.json file: the files it includes.
  • A single source file: that file, the files it imports, and the test files that import any of them.

If a project contains more than one code-native integration, pass the file that defines the integration you want to migrate.

Review the result​

Commit or stash your work before you run a codemod, so git diff shows exactly what it changed. After it runs, the codemod lists the files it changed:

v10.36.0/integration-configuration: scanned 1 files, changed 1
src/index.ts

It then prints a line beginning with warning: for each thing it left for you to handle, naming the file involved. Some codemods also leave TODO comments at the code that needs your attention. Run your type checker and tests before you publish the migrated project.

Available codemods​

CodemodMinimum --target-spectralUse it when
public-entry-points10.35.1Your code imports from @prismatic-io/spectral/dist/... paths.
integration-configuration10.36.0You're moving a code-native integration from config pages to headless configuration.
callable-component-packaging10.36.0You want to publish a custom connector as an npm package as well as to Prismatic.

Run npx @prismatic-io/spectral-codemod@latest --list for the current list. The list names each codemod version with its Spectral version, such as v10.35.1/public-entry-points; you can pass that name in place of the codemod name and --target-spectral.

Public entry points​

public-entry-points moves imports of Spectral's dist/ paths to the public entry points that load the same modules. It works on both custom connectors and code-native integrations.

FromTo
@prismatic-io/spectral/dist, @prismatic-io/spectral/dist/index@prismatic-io/spectral
@prismatic-io/spectral/dist/clients/http, @prismatic-io/spectral/dist/clients/http/index@prismatic-io/spectral/http
@prismatic-io/spectral/dist/testing@prismatic-io/spectral/testing

The codemod also rewrites these paths with a .js extension or trailing slash, and in export ... from, import() types, require(), dynamic import(), and mocks such as vi.mock(). Other dist/ paths, such as @prismatic-io/spectral/dist/conditionalLogic, have no public entry point and stay as they are; the codemod prints a warning naming each file that imports one. See the Spectral 10.35 upgrade guide for how to update those imports.

Integration configuration​

integration-configuration converts a code-native integration that uses config pages to headless configuration. It performs the code changes described in Migrating from config pages, starting from the config pages you already have:

  • Configuration: Replaces configPages, userLevelConfigPages, and scopedConfigVars with a configuration(). Config pages become the instance scope, and user-level config pages become the userLevel scope.
  • Schema: Writes a zod configPagesSchema for each scope, with a required field for each config variable, keyed by config variable name. The scope's schema starts as the same shape, and its version is "INITIAL".
  • Connections: Moves each connection into the connections of its scope.
  • Init: Adds an init function that proposes each instance's saved config page values unchanged.
  • Data sources: Converts each data source with an inline perform to a server function declared beside it.
  • Flows: Rewrites context.configVars reads to context.configuration, context.userConfiguration, or context.connections, and rewrites invokeFlow calls in flow tests to pass the configuration instead of configVars.
  • Schedules: Changes each flow schedule that reads a config variable to { fromDeployer: true }, so the deploying user supplies the schedule.

The codemod adds an import from zod; install it if your project doesn't already depend on it.

After the codemod runs, finish the migration yourself:

  1. Convert the config page values in init. The generated init passes the old values through with a type cast that isn't checked at runtime. Config pages stored values such as numbers and booleans as strings, so parse them as shown in Migrating from config pages.
  2. Resolve each warning, TODO, and type error. The codemod leaves a TODO where it can't follow a configVars read, such as a computed key or configVars passed whole to a helper. It also leaves component data source references, and data sources whose perform is declared elsewhere, for you to convert.
  3. Handle missing values in flows. The rewritten reads are optional, such as context.configuration?.["Batch Size"], because an instance's configuration can be absent. Code that assumed a config variable always had a value needs to handle undefined.
  4. Review the schema. The generated schema doesn't carry over default values, visibility settings, or permissions, and it describes jsonForm values as z.unknown(). To change the schema later, give the scope a new version as described in Configuration versions.
  5. Delete the config page declarations once you've reviewed the result. The generated configuration references connections where they're declared, such as configPages.Connections.elements["Acme Connection"], so move those definitions before you delete the pages.

When the codemod can't resolve a page, element, or spread to an object literal, it stops and reports the location rather than drop what it holds. The migrated flow tests require a Spectral release whose invokeFlow accepts configuration, userConfiguration, and connections.

Callable component packaging​

callable-component-packaging configures a custom connector to build a CommonJS npm package alongside its Prismatic build. Pass the connector's project directory as the path; this codemod doesn't accept a single file.

Before it writes anything, the codemod checks that the project meets these requirements, and stops if it doesn't:

  • Dependencies on tsdown >=0.22.3 and Spectral >=10.36.0 whose declared ranges exclude older releases, plus TypeScript and a tsconfig.json. The codemod doesn't upgrade dependencies for you.
  • src/index.ts default-exports Spectral's component().
  • A single static tsdown defineConfig that builds src/index.ts to a self-contained CommonJS dist/index.js. The config may load Markdown files as text and copy assets/**/*, or the flattened assets/* that Prism scaffolded before October 2026; other loaders, copy rules, or additional builds require manual changes.
  • A CommonJS package whose build script ends with tsdown, such as npm run lint && tsdown.

The codemod adds an npm-dist/index.cjs entry point and its type declarations, configures the package's exports and the files it publishes, and sets prismatic.component to ./dist/index.js. It moves Spectral to peerDependencies and devDependencies, appends npm run build to the prepare script, and excludes npm-dist wherever .gitignore or a Biome config excludes dist. Running it again makes no further changes.

The codemod warns about dependencies declared with file:, link:, or portal:, because npm can't install them from the published package. Bundle those dependencies into the npm build with deps.alwaysBundle in your tsdown config.

After applying the codemod, reinstall dependencies to update your lockfile, run your tests, and run npm pack to check the package contents. Projects that install the package need Spectral installed, and access the callable component through the package's default export.