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:
# 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.
| Option | Description |
|---|---|
--target-spectral <version> | The Spectral version you're migrating to, such as 10.37.0 or latest. Required. |
--dry-run | List the files that would change without writing them. |
--list | Print the available codemods and what each one does. |
--help | Print 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 thattsconfig.jsonincludes. - Any other directory: every
.tsand.tsxfile beneath it, except innode_modulesanddist. - A
tsconfig.jsonfile: 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
| Codemod | Minimum --target-spectral | Use it when |
|---|---|---|
public-entry-points | 10.35.1 | Your code imports from @prismatic-io/spectral/dist/... paths. |
integration-configuration | 10.36.0 | You're moving a code-native integration from config pages to headless configuration. |
callable-component-packaging | 10.36.0 | You 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.
| From | To |
|---|---|
@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, andscopedConfigVarswith aconfiguration(). Config pages become theinstancescope, and user-level config pages become theuserLevelscope. - Schema: Writes a zod
configPagesSchemafor each scope, with a required field for each config variable, keyed by config variable name. The scope'sschemastarts as the same shape, and itsversionis"INITIAL". - Connections: Moves each connection into the
connectionsof its scope. - Init: Adds an
initfunction that proposes each instance's saved config page values unchanged. - Data sources: Converts each data source with an inline
performto a server function declared beside it. - Flows: Rewrites
context.configVarsreads tocontext.configuration,context.userConfiguration, orcontext.connections, and rewritesinvokeFlowcalls in flow tests to pass the configuration instead ofconfigVars. - 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:
- Convert the config page values in
init. The generatedinitpasses 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. - Resolve each warning,
TODO, and type error. The codemod leaves aTODOwhere it can't follow aconfigVarsread, such as a computed key orconfigVarspassed whole to a helper. It also leaves component data source references, and data sources whoseperformis declared elsewhere, for you to convert. - 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 handleundefined. - Review the schema.
The generated schema doesn't carry over default values, visibility settings, or permissions, and it describes
jsonFormvalues asz.unknown(). To change the schema later, give the scope a newversionas described in Configuration versions. - 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.3and Spectral>=10.36.0whose declared ranges exclude older releases, plus TypeScript and atsconfig.json. The codemod doesn't upgrade dependencies for you. src/index.tsdefault-exports Spectral'scomponent().- A single static tsdown
defineConfigthat buildssrc/index.tsto a self-contained CommonJSdist/index.js. The config may load Markdown files as text and copyassets/**/*, or the flattenedassets/*that Prism scaffolded before October 2026; other loaders, copy rules, or additional builds require manual changes. - A CommonJS package whose
buildscript ends withtsdown, such asnpm 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.