@tailor-platform/sdk 2.29.2 → 2.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/aigateway-DsWDjzk4.mjs.map +1 -1
- package/dist/{application-Dm_21z-i.mjs → application-C2bPmmbh.mjs} +1 -1
- package/dist/{application-D8jruzwo.mjs → application-D0xNJbag.mjs} +32 -32
- package/dist/{application-D8jruzwo.mjs.map → application-D0xNJbag.mjs.map} +1 -1
- package/dist/assert-WeXvmG4j.mjs.map +1 -1
- package/dist/authconnection-CynFBIv8.mjs.map +1 -1
- package/dist/brand-C8nMKhJC.mjs.map +1 -1
- package/dist/cli/commands/machineuser/list.d.mts +2 -1
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +16 -16
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/error-json.d.mts +2 -0
- package/dist/completion/zsh-worker.zsh +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/context-D0QjfxzD.mjs.map +1 -1
- package/dist/{crashreport-BAG8c7hB.mjs → crashreport-BCIy33Cz.mjs} +2 -2
- package/dist/{crashreport-BAG8c7hB.mjs.map → crashreport-BCIy33Cz.mjs.map} +1 -1
- package/dist/crashreport-IN6H7GX3.mjs +1 -0
- package/dist/date-CgP7gMG_.mjs.map +1 -1
- package/dist/date-representation-Cr7W7Pn2.mjs.map +1 -1
- package/dist/errors-BOF68LJ5.mjs +5 -0
- package/dist/errors-BOF68LJ5.mjs.map +1 -0
- package/dist/es-builtins-SfvXRVoG.mjs.map +1 -1
- package/dist/field-parse-C41e3UAF.mjs.map +1 -1
- package/dist/file-DKBOj5q4.mjs.map +1 -1
- package/dist/globals-BCmGX05J.mjs.map +1 -1
- package/dist/guards-yDXyKC9F.mjs.map +1 -1
- package/dist/iconv-DlFMt2gW.mjs.map +1 -1
- package/dist/idp-G_ojPBB5.mjs.map +1 -1
- package/dist/interceptor-DQg3cR_9.mjs.map +1 -1
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-BWMfV301.mjs.map +1 -1
- package/dist/logger-DP2BjQ93.mjs.map +1 -1
- package/dist/{logger-DuaT2zY3.mjs → logger-RgtbhJ83.mjs} +3 -3
- package/dist/logger-RgtbhJ83.mjs.map +1 -0
- package/dist/manager-Bk-7vkwd.mjs.map +1 -1
- package/dist/migration-steps-C6F3zNdQ.mjs.map +1 -1
- package/dist/multiline-EyzjEwn9.mjs.map +1 -1
- package/dist/node-builtins-DYfhPBnz.mjs.map +1 -1
- package/dist/package-json-C690ceex.mjs.map +1 -1
- package/dist/platform-serialize-DkiTdHOt.mjs.map +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/{register-ts-hook-B5ZbbJwS.mjs → register-ts-hook-CDnN_Jx2.mjs} +65 -65
- package/dist/register-ts-hook-CDnN_Jx2.mjs.map +1 -0
- package/dist/registry-BijIDRVA.mjs.map +1 -1
- package/dist/repl-editor-DGJBfIt1.mjs.map +1 -1
- package/dist/schema-B6hJQWp6.mjs.map +1 -1
- package/dist/secret-file-C9wp_FCX.mjs.map +1 -1
- package/dist/secretmanager-vHQoXdQz.mjs.map +1 -1
- package/dist/seed/idp-user-password.d.mts +15 -0
- package/dist/seed/index.d.mts +19 -1
- package/dist/seed/index.mjs +6 -6
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-C3P_T_Eh.mjs → seed-Cn-3JApy.mjs} +12 -8
- package/dist/seed-Cn-3JApy.mjs.map +1 -0
- package/dist/{service-l_tEI8sS.mjs → service-9SBPNpK8.mjs} +2 -2
- package/dist/{service-l_tEI8sS.mjs.map → service-9SBPNpK8.mjs.map} +1 -1
- package/dist/{service-b1g22NN9.mjs → service-9rwi_I4d.mjs} +2 -2
- package/dist/{service-b1g22NN9.mjs.map → service-9rwi_I4d.mjs.map} +1 -1
- package/dist/service-Ca1WwyIt.mjs +1 -0
- package/dist/service_pb-Bbu2QSIr.mjs.map +1 -1
- package/dist/telemetry-Xk7J829P.mjs.map +1 -1
- package/dist/type-source--ZNcV8RJ.mjs.map +1 -1
- package/dist/user-agent-vdHYF3QL.mjs.map +1 -1
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/setup.mjs.map +1 -1
- package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -1
- package/dist/wait-point-registry-B-ESkTZX.mjs.map +1 -1
- package/dist/workflow-Cs9ISw6j.mjs.map +1 -1
- package/dist/workspace_resource_pb-CaoM2npP.mjs.map +1 -1
- package/docs/cli/application.md +4 -0
- package/docs/cli/auth.md +4 -0
- package/docs/cli/completion.md +4 -0
- package/docs/cli/crashreport.md +4 -0
- package/docs/cli/data.md +4 -0
- package/docs/cli/executor.md +4 -0
- package/docs/cli/function.md +4 -0
- package/docs/cli/organization.md +4 -0
- package/docs/cli/plugin.md +4 -0
- package/docs/cli/query.md +4 -0
- package/docs/cli/secret.md +4 -0
- package/docs/cli/skills.md +4 -0
- package/docs/cli/staticwebsite.md +4 -0
- package/docs/cli/tailordb.md +4 -0
- package/docs/cli/upgrade.md +4 -0
- package/docs/cli/user.md +4 -0
- package/docs/cli/workflow.md +4 -0
- package/docs/cli/workspace.md +4 -0
- package/docs/cli-reference.md +4 -0
- package/docs/configuration.md +4 -0
- package/docs/data-clone.md +4 -0
- package/docs/github-actions.md +10 -0
- package/docs/migration/v2.md +4 -0
- package/docs/multi-environment.md +4 -0
- package/docs/plugin/custom.md +4 -0
- package/docs/plugin/frontend.md +4 -0
- package/docs/plugin/index.md +4 -0
- package/docs/quickstart.md +4 -0
- package/docs/runtime.md +4 -0
- package/docs/services/aigateway.md +4 -0
- package/docs/services/auth.md +4 -0
- package/docs/services/executor.md +4 -0
- package/docs/services/http-adapter.md +4 -0
- package/docs/services/idp.md +4 -0
- package/docs/services/resolver.md +4 -0
- package/docs/services/secret.md +4 -0
- package/docs/services/staticwebsite.md +4 -0
- package/docs/services/tailordb/index.md +4 -0
- package/docs/services/tailordb/migration.md +4 -0
- package/docs/services/workflow.md +4 -0
- package/docs/testing.md +4 -0
- package/package.json +3 -3
- package/dist/crashreport-BcXuocwI.mjs +0 -1
- package/dist/errors-D3qpNHR6.mjs +0 -7
- package/dist/errors-D3qpNHR6.mjs.map +0 -1
- package/dist/logger-DuaT2zY3.mjs.map +0 -1
- package/dist/register-ts-hook-B5ZbbJwS.mjs.map +0 -1
- package/dist/seed-C3P_T_Eh.mjs.map +0 -1
- package/dist/service-C_CogLQr.mjs +0 -1
- package/docs/migration/v3.md +0 -277
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"seed-C3P_T_Eh.mjs","names":["assertDefined","isPluginGeneratedTable","path","auth","tableName","idpNamespace","listIdpUsersFunction","options","schemaBody","includeUserProfileFK","userTableName","usernameField","source","type","field","optionalFields","omitFields","indexes","foreignKeys","fieldName","indexName","indexDef","schemaOptions","fk","index","option","tableVariable","metadata","params","schemaOptionsCode","configImportPath","exportName","typeImportPath","pluginSource","schemaTypeCode","originalImportPath","SeedGeneratorID","files","idpUser","ctx","idpUserSyncFKs","ns","linesDb","schemaOutputPath","relativePath","schemaContent"],"sources":["../src/plugin/builtin/seed/idp-user-processor.ts","../src/plugin/builtin/seed/lines-db-processor.ts","../src/plugin/builtin/seed/index.ts"],"sourcesContent":["import ml from \"#/utils/multiline\";\nimport type { GeneratorAuthInput } from \"#/plugin/types\";\n\nexport interface IdpUserMetadata {\n name: \"_User\";\n dependencies: string[];\n dataFile: string;\n idpNamespace: string;\n schema: {\n usernameField: string;\n userTableName: string;\n };\n}\n\n/**\n * Processes auth configuration to generate IdP user seed metadata\n * @param auth - Auth configuration from generator\n * @returns IdP user metadata or undefined if not applicable\n */\nexport function processIdpUser(auth: GeneratorAuthInput): IdpUserMetadata | undefined {\n // Only process if idProvider is BuiltInIdP and userProfile is defined\n if (auth.idProvider?.kind !== \"BuiltInIdP\" || !auth.userProfile) {\n return undefined;\n }\n\n const { tableName, usernameField } = auth.userProfile;\n\n return {\n name: \"_User\",\n dependencies: [tableName],\n dataFile: \"data/_User.jsonl\",\n idpNamespace: auth.idProvider.namespace,\n schema: {\n usernameField,\n userTableName: tableName,\n },\n };\n}\n\n/**\n * Generates the server-side IDP seed script code.\n * Uses the global tailor.idp.Client - no bundling required.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpSeedScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n export async function main(input) {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let processed = 0;\n let created = 0;\n let updated = 0;\n let skipped = 0;\n const upsert = input.upsert === true;\n // Rows may arrive as one chunk of a larger dataset; report row numbers\n // relative to the whole dataset so they match the source JSONL.\n const offset = typeof input.offset === \"number\" ? input.offset : 0;\n const total = typeof input.total === \"number\" ? input.total : input.users.length;\n\n for (let i = 0; i < input.users.length; i++) {\n try {\n if (upsert) {\n let existing;\n let lookupError;\n try {\n existing = await client.userByName(input.users[i].name);\n } catch (error) {\n existing = undefined;\n lookupError = error instanceof Error ? error.message : String(error);\n }\n\n if (existing) {\n const { name, ...attributes } = input.users[i];\n if (Object.keys(attributes).length === 0) {\n skipped++;\n } else {\n await client.updateUser({ id: existing.id, ...attributes });\n updated++;\n }\n } else {\n try {\n await client.createUser(input.users[i]);\n created++;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(\n lookupError ? \\`create failed (\\${message}); lookup failed (\\${lookupError})\\` : message,\n );\n }\n }\n } else {\n await client.createUser(input.users[i]);\n created++;\n }\n processed++;\n console.log(\\`[_User] \\${offset + i + 1}/\\${total}: \\${input.users[i].name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n errors.push(\\`Row \\${offset + i + 1} (\\${input.users[i].name}): \\${message}\\`);\n console.error(\\`[_User] Row \\${offset + i + 1} failed: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n processed,\n created,\n updated,\n skipped,\n errors,\n };\n }\n `;\n}\n\nconst listIdpUsersFunction = ml /* ts */ `\n async function listUsers(client) {\n let after = undefined;\n const users = [];\n do {\n const response = await client.users(after ? { after } : undefined);\n for (const user of response.users || []) {\n users.push({ id: user.id, name: user.name });\n }\n after = response.nextPageToken;\n } while (after);\n console.log(\\`Found \\${users.length} IDP users to delete\\`);\n return users;\n }\n`;\n\n/**\n * Generates the server-side script that lists every IdP user for truncation.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpListUsersScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n ${listIdpUsersFunction}\n\n export async function main() {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const users = await listUsers(client);\n return { success: true, users };\n }\n `;\n}\n\n/**\n * Generates the server-side IDP truncation script code.\n * Deletes the users passed in `input.users` (one chunk of the listing produced by\n * {@link generateIdpListUsersScriptCode}), or every user when no chunk is passed so\n * older seed plugins that call it without input keep working. A user that is already\n * gone counts as deleted.\n * @param idpNamespace - The IDP namespace name\n * @returns Script code string\n */\nexport function generateIdpTruncateScriptCode(idpNamespace: string): string {\n return ml /* ts */ `\n ${listIdpUsersFunction}\n\n export async function main(input) {\n const client = new tailor.idp.Client({ namespace: \"${idpNamespace}\" });\n const errors = [];\n let deleted = 0;\n let notFound = 0;\n const users = Array.isArray(input.users) ? input.users : await listUsers(client);\n const offset = typeof input.offset === \"number\" ? input.offset : 0;\n const total = typeof input.total === \"number\" ? input.total : users.length;\n\n for (let i = 0; i < users.length; i++) {\n const user = users[i];\n try {\n await client.deleteUser(user.id);\n deleted++;\n console.log(\\`[_User] Deleted \\${offset + i + 1}/\\${total}: \\${user.name}\\`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (/user not found/i.test(message)) {\n notFound++;\n console.log(\\`[_User] Already deleted \\${offset + i + 1}/\\${total}: \\${user.name}\\`);\n continue;\n }\n errors.push(\\`User \\${user.id} (\\${user.name}): \\${message}\\`);\n console.error(\\`[_User] Delete failed for \\${user.name}: \\${message}\\`);\n }\n }\n\n return {\n success: errors.length === 0,\n deleted,\n notFound,\n total: users.length,\n errors,\n };\n }\n `;\n}\n\ntype GenerateIdpUserSchemaFileOptions = {\n usernameField: string;\n userTableName: string;\n /**\n * When `true` (default), emit a foreign key from `_User.name` to the\n * userProfile table's username field so that seed validation rejects `_User`\n * rows without a matching userProfile row. Set to `false` to seed `_User`\n * rows that do not yet have a corresponding userProfile row.\n */\n includeUserProfileFK?: boolean;\n};\n\n/**\n * Generates the schema file content for IdP users. Emits the\n * `_User.name -> <userProfile>.<usernameField>` foreign key by default; pass\n * `includeUserProfileFK: false` to omit it (e.g. when seeding `_User` rows\n * that do not yet have a corresponding userProfile row).\n * @param options - Schema generation options\n * @param options.usernameField - Username field name\n * @param options.userTableName - TailorDB user table name\n * @param options.includeUserProfileFK - Whether to emit the `_User -> userProfile` foreign key (default `true`)\n * @returns Schema file contents\n */\nexport function generateIdpUserSchemaFile(options: GenerateIdpUserSchemaFileOptions): string {\n const { usernameField, userTableName, includeUserProfileFK = true } = options;\n const schemaBody = includeUserProfileFK\n ? ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n foreignKeys: [\n {\n column: \"name\",\n references: {\n table: \"${userTableName}\",\n column: \"${usernameField}\",\n },\n },\n ],\n `\n : ml`\n primaryKey: \"name\",\n indexes: [\n { name: \"_user_name_unique_idx\", columns: [\"name\"], unique: true },\n ],\n `;\n\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const schemaType = t.object({\n name: t.string(),\n password: t.string(),\n });\n\n // Simple identity hook for _User (no TailorDB backing table)\n export const hook = <T>(data: unknown) => data as T;\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook),\n {\n ${schemaBody}\n }\n );\n\n `;\n}\n","import { isPluginGeneratedTable } from \"#/parser/service/tailordb/type-source\";\nimport ml from \"#/utils/multiline\";\nimport type {\n ParsedField,\n PluginGeneratedTableSource,\n TailorDBType,\n TypeSourceInfoEntry,\n} from \"#/parser/service/tailordb/types\";\nimport type { LinesDbMetadata } from \"./types\";\nimport type { ForeignKeyDefinition, IndexDefinition } from \"lines-db\";\n\n/**\n * Processes TailorDB tables to generate lines-db metadata\n * @param type - Parsed TailorDB table\n * @param source - Source file info\n * @returns Generated lines-db metadata\n */\nexport function processLinesDb(type: TailorDBType, source: TypeSourceInfoEntry): LinesDbMetadata {\n if (isPluginGeneratedTable(source)) {\n // Plugin-generated table\n return processLinesDbForPluginTable(type, source);\n }\n\n // User-defined table\n if (!source.filePath) {\n throw new Error(`Missing source info for table ${type.name}`);\n }\n if (!source.exportName) {\n throw new Error(`Missing export name for table ${type.name}`);\n }\n\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n tableName: type.name,\n exportName: source.exportName,\n importPath: source.filePath,\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n };\n}\n\n/**\n * Process lines-db metadata for plugin-generated tables\n * @param type - Parsed TailorDB table\n * @param source - Plugin-generated table source info\n * @returns Generated lines-db metadata with plugin source\n */\nfunction processLinesDbForPluginTable(\n type: TailorDBType,\n source: PluginGeneratedTableSource,\n): LinesDbMetadata {\n const { optionalFields, omitFields, indexes, foreignKeys } = extractFieldMetadata(type);\n\n return {\n tableName: type.name,\n exportName: source.exportName,\n importPath: \"\",\n optionalFields,\n omitFields,\n foreignKeys,\n indexes,\n pluginSource: source,\n };\n}\n\n/**\n * Whether the platform produces a value for the field on create when a row omits it,\n * either from a create hook or from a schema default. Such fields stay optional in seed\n * data even when the table marks them required.\n * @param field - Parsed TailorDB field\n * @returns True when a seed row does not have to supply the field\n */\nfunction isGeneratedOnCreate(field: ParsedField): boolean {\n return field.config.hooks?.create !== undefined || field.config.default !== undefined;\n}\n\n/**\n * Extract field metadata from TailorDB table\n * @param type - Parsed TailorDB table\n * @returns Field metadata including optional fields, omit fields, indexes, and foreign keys\n */\nfunction extractFieldMetadata(type: TailorDBType): {\n optionalFields: string[];\n omitFields: string[];\n indexes: IndexDefinition[];\n foreignKeys: ForeignKeyDefinition[];\n} {\n const optionalFields = [\"id\"]; // id is always optional\n const omitFields: string[] = [];\n const indexes: IndexDefinition[] = [];\n const foreignKeys: ForeignKeyDefinition[] = [];\n\n // Find fields generated on create, or serial\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (isGeneratedOnCreate(field)) {\n optionalFields.push(fieldName);\n }\n // Serial fields are auto-generated, so they are excluded from the seed schema entirely\n if (field.config.serial) {\n omitFields.push(fieldName);\n }\n if (field.config.unique) {\n indexes.push({\n name: `${type.name.toLowerCase()}_${fieldName}_unique_idx`,\n columns: [fieldName],\n unique: true,\n });\n }\n }\n\n // Extract indexes\n if (type.indexes) {\n for (const [indexName, indexDef] of Object.entries(type.indexes)) {\n indexes.push({\n name: indexName,\n columns: indexDef.fields,\n unique: indexDef.unique,\n });\n }\n }\n\n // Extract foreign keys from relations\n for (const [fieldName, field] of Object.entries(type.fields)) {\n if (field.relation) {\n foreignKeys.push({\n column: fieldName,\n references: {\n table: field.relation.targetType,\n column: field.relation.key,\n },\n });\n }\n }\n\n return { optionalFields, omitFields, indexes, foreignKeys };\n}\n\n/**\n * Generate schema options code for lines-db\n * @param foreignKeys - Foreign key definitions\n * @param indexes - Index definitions\n * @returns Schema options code string\n */\nfunction generateSchemaOptions(\n foreignKeys: ForeignKeyDefinition[],\n indexes: IndexDefinition[],\n): string {\n const schemaOptions: string[] = [];\n\n if (foreignKeys.length > 0) {\n schemaOptions.push(`foreignKeys: [`);\n foreignKeys.forEach((fk) => {\n schemaOptions.push(` ${JSON.stringify(fk)},`);\n });\n schemaOptions.push(`],`);\n }\n\n if (indexes.length > 0) {\n schemaOptions.push(`indexes: [`);\n indexes.forEach((index) => {\n schemaOptions.push(` ${JSON.stringify(index)},`);\n });\n schemaOptions.push(\"],\");\n }\n\n return schemaOptions.length > 0\n ? [\"\\n {\", ...schemaOptions.map((option) => ` ${option}`), \" }\"].join(\"\\n\")\n : \"\";\n}\n\n/**\n * Parameters for generating a user-defined table's schema file\n */\nexport interface UserTableSchemaParams {\n /** Relative import path to the table's source file */\n typeImportPath: string;\n /**\n * Relative path from the schema output to tailor.config.ts. Set when plugins are\n * attached to the table: the schema then loads the table through `getExtendedTable`\n * so the fields those plugins add are part of the seed schema.\n */\n configImportPath?: string;\n}\n\nfunction generateSchemaTypeCode(\n tableVariable: string,\n optionalFields: string[],\n omitFields: string[],\n): string {\n return ml /* ts */ `\n const schemaType = t.object({\n ...${tableVariable}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${tableVariable}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n}\n\n/**\n * Generates the schema file content for lines-db (for user-defined tables with import)\n * @param metadata - lines-db metadata\n * @param params - Import paths for the table and, when plugins are attached, the config\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFile(\n metadata: LinesDbMetadata,\n params: UserTableSchemaParams,\n): string {\n const { exportName, optionalFields, omitFields, foreignKeys, indexes } = metadata;\n const { typeImportPath, configImportPath } = params;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n if (configImportPath === undefined) {\n return ml /* ts */ `\n import { t } from \"@tailor-platform/sdk\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${exportName} } from \"${typeImportPath}\";\n\n ${generateSchemaTypeCode(exportName, optionalFields, omitFields)}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n }\n\n // The source file exports the table without the fields its plugins add, so the\n // schema is built from the table `getExtendedTable` returns instead.\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getExtendedTable } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${exportName} as sourceTable } from ${JSON.stringify(typeImportPath)};\n\n const configPath = join(import.meta.dirname, ${JSON.stringify(configImportPath)});\n const table = await getExtendedTable(configPath, sourceTable);\n\n ${generateSchemaTypeCode(\"table\", optionalFields, omitFields)}\n\n export const hook = createTailorDBHook(table);\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, table),${schemaOptionsCode}\n );\n\n `;\n}\n\n/**\n * Parameters for generating a plugin-generated table's schema file\n */\nexport interface PluginSchemaParams {\n /** Relative path from schema output to tailor.config.ts */\n configImportPath: string;\n /** Relative import path to the original table file (for table-attached plugins) */\n originalImportPath?: string;\n}\n\n/**\n * Generates the schema file content using getGeneratedTable API\n * (for plugin-generated tables)\n * @param metadata - lines-db metadata (must have pluginSource)\n * @param params - Plugin import paths\n * @returns Schema file contents\n */\nexport function generateLinesDbSchemaFileWithPluginAPI(\n metadata: LinesDbMetadata,\n params: PluginSchemaParams,\n): string {\n const { tableName, exportName, optionalFields, omitFields, foreignKeys, indexes, pluginSource } =\n metadata;\n\n if (!pluginSource) {\n throw new Error(`pluginSource is required for plugin-generated table \"${tableName}\"`);\n }\n\n const { configImportPath, originalImportPath } = params;\n\n const schemaTypeCode = ml /* ts */ `\n const schemaType = t.object({\n ...${exportName}.pickFields(${JSON.stringify(optionalFields)}, { optional: true }),\n ...${exportName}.omitFields(${JSON.stringify([...optionalFields, ...omitFields])}),\n });\n `;\n\n const schemaOptionsCode = generateSchemaOptions(foreignKeys, indexes);\n\n // Table-attached plugin (e.g., changeset): import the original table and use getGeneratedTable(configPath, pluginId, table, kind)\n if (pluginSource.originalExportName && originalImportPath && pluginSource.generatedTableKind) {\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedTable } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n import { ${pluginSource.originalExportName} } from \"${originalImportPath}\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedTable(configPath, \"${pluginSource.pluginId}\", ${pluginSource.originalExportName}, \"${pluginSource.generatedTableKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n }\n\n // Namespace plugin (e.g., audit-log): use getGeneratedTable(configPath, pluginId, null, kind)\n // For namespace plugins, generatedTableKind is required\n if (!pluginSource.generatedTableKind) {\n throw new Error(\n `Namespace plugin \"${pluginSource.pluginId}\" must provide generatedTableKind for table \"${tableName}\"`,\n );\n }\n\n return ml /* ts */ `\n import { join } from \"node:path\";\n import { t } from \"@tailor-platform/sdk\";\n import { getGeneratedTable } from \"@tailor-platform/sdk/plugin\";\n import { defineSchema } from \"@tailor-platform/sdk/seed\";\n import { createTailorDBHook, createStandardSchema } from \"@tailor-platform/sdk/test\";\n\n const configPath = join(import.meta.dirname, \"${configImportPath}\");\n const ${exportName} = await getGeneratedTable(configPath, \"${pluginSource.pluginId}\", null, \"${pluginSource.generatedTableKind}\");\n\n ${schemaTypeCode}\n\n export const hook = createTailorDBHook(${exportName});\n\n export const schema = defineSchema(\n createStandardSchema(schemaType, hook, ${exportName}),${schemaOptionsCode}\n );\n\n `;\n}\n","import * as path from \"pathe\";\nimport { assertDefined } from \"#/utils/assert\";\nimport { processIdpUser, generateIdpUserSchemaFile } from \"./idp-user-processor\";\nimport {\n processLinesDb,\n generateLinesDbSchemaFile,\n generateLinesDbSchemaFileWithPluginAPI,\n type PluginSchemaParams,\n} from \"./lines-db-processor\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"#/plugin/types\";\n\n/** Unique identifier for the seed generator plugin. */\nexport const SeedGeneratorID = \"@tailor-platform/seed\";\n\ntype DisableIdpUserSyncDirections = {\n /**\n * Skip emitting the foreign key from `<userProfile>.<usernameField>` to\n * `_User.name`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed pre-registration states such as\n * invited-but-not-registered users.\n */\n userToIdp?: boolean;\n /**\n * Skip emitting the foreign key from `_User.name` to\n * `<userProfile>.<usernameField>`. Defaults to `false` (FK emitted).\n *\n * Set to `true` to seed `_User` rows that do not yet have a corresponding\n * userProfile row.\n */\n idpToUser?: boolean;\n};\n\nexport type SeedPluginOptions = {\n distPath: string;\n machineUserName?: string;\n /**\n * Disable individual `_User <-> userProfile` foreign keys emitted into\n * the generated seed schema. Both directions are emitted by default.\n *\n * Set a direction to `true` to relax it — for example to seed invited\n * users that do not yet have an IdP credential.\n */\n disableIdpUserSync?: DisableIdpUserSyncDirections;\n /**\n * Named combinations of datasets, so `tailor seed apply --dataset preview`\n * stands for every dataset directory the name lists. A dataset directory is\n * a directory under `<distPath>/data/` holding JSONL files for some of the\n * tables; its rows are applied on top of the rows in `<distPath>/data/`.\n * @example { preview: [\"cogs\", \"shipments\"], dev: [\"local\"] }\n */\n datasets?: Record<string, readonly string[]>;\n};\n\ndeclare module \"@tailor-platform/sdk/plugin\" {\n interface PluginConfigRegistry {\n \"@tailor-platform/seed\": SeedPluginOptions;\n }\n}\n\nfunction resolveIdpUserSyncFKs(option: SeedPluginOptions[\"disableIdpUserSync\"]): {\n emitUserToIdpFK: boolean;\n emitIdpToUserFK: boolean;\n} {\n return {\n emitUserToIdpFK: !(option?.userToIdp ?? false),\n emitIdpToUserFK: !(option?.idpToUser ?? false),\n };\n}\n/**\n * Plugin that generates seed data and schema files consumed by the\n * `tailor seed` commands (@tailor-platform/sdk-plugin-seed).\n * @param options - Plugin options\n * @param options.distPath - Output directory path for generated seed files\n * @param options.machineUserName - Default machine user name for authentication\n * @param options.disableIdpUserSync - Skip emitting individual `_User <-> userProfile` foreign keys. Both directions are emitted by default; set a direction to `true` to relax that side.\n * @param options.datasets - Named combinations of dataset directories under `<distPath>/data/`, selected with `tailor seed apply --dataset <name>`.\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function seedPlugin(options: SeedPluginOptions): Plugin<unknown, SeedPluginOptions> {\n return {\n id: SeedGeneratorID,\n description: \"Generates seed data and schema files for the tailor seed CLI plugin\",\n pluginConfig: options,\n\n async onTailorDBReady(ctx: TailorDBReadyContext<SeedPluginOptions>): Promise<GeneratorResult> {\n const files: GeneratorResult[\"files\"] = [];\n\n // Process IdP user early so we can add reverse FK to the user profile type\n const idpUser = ctx.auth ? (processIdpUser(ctx.auth) ?? null) : null;\n const idpUserSyncFKs = resolveIdpUserSyncFKs(ctx.pluginConfig.disableIdpUserSync);\n\n for (const ns of ctx.tailordb) {\n for (const [tableName, type] of Object.entries(ns.tables)) {\n const source = assertDefined(\n ns.sourceInfo.get(tableName),\n `source info missing for table: ${tableName}`,\n );\n const linesDb = processLinesDb(type, source);\n\n // Add reverse FK from userProfile table to _User (opt-out via disableIdpUserSync.userToIdp: true)\n if (\n idpUserSyncFKs.emitUserToIdpFK &&\n idpUser &&\n tableName === idpUser.schema.userTableName\n ) {\n linesDb.foreignKeys.push({\n column: idpUser.schema.usernameField,\n references: {\n table: \"_User\",\n column: \"name\",\n },\n });\n }\n\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${linesDb.tableName}.jsonl`),\n content: \"\",\n skipIfExists: true,\n });\n\n const schemaOutputPath = path.join(\n ctx.pluginConfig.distPath,\n \"data\",\n `${linesDb.tableName}.schema.ts`,\n );\n\n // Plugin-generated table: use getGeneratedTable API\n if (linesDb.pluginSource && linesDb.pluginSource.pluginImportPath) {\n // Build original type import path\n let originalImportPath: string | undefined;\n if (linesDb.pluginSource.originalFilePath && linesDb.pluginSource.originalExportName) {\n const relativePath = path.relative(\n path.dirname(schemaOutputPath),\n linesDb.pluginSource.originalFilePath,\n );\n originalImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n }\n\n // Compute relative path from schema output to config file\n const configImportPath = path.relative(path.dirname(schemaOutputPath), ctx.configPath);\n\n const params: PluginSchemaParams = {\n configImportPath,\n originalImportPath,\n };\n\n const schemaContent = generateLinesDbSchemaFileWithPluginAPI(linesDb, params);\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n } else {\n // User-defined type: import from source file\n const relativePath = path.relative(path.dirname(schemaOutputPath), linesDb.importPath);\n const typeImportPath = relativePath.replace(/\\.ts$/, \"\").startsWith(\".\")\n ? relativePath.replace(/\\.ts$/, \"\")\n : `./${relativePath.replace(/\\.ts$/, \"\")}`;\n // A table with plugins attached may carry fields the source file does not\n // declare, so its schema loads the table through the config.\n const hasPlugins = (ns.pluginAttachments.get(tableName)?.length ?? 0) > 0;\n const configImportPath = hasPlugins\n ? path.relative(path.dirname(schemaOutputPath), ctx.configPath)\n : undefined;\n const schemaContent = generateLinesDbSchemaFile(linesDb, {\n typeImportPath,\n configImportPath,\n });\n\n files.push({\n path: schemaOutputPath,\n content: schemaContent,\n });\n }\n }\n }\n\n if (idpUser) {\n // Generate empty JSONL data file\n files.push({\n path: path.join(ctx.pluginConfig.distPath, idpUser.dataFile),\n content: \"\",\n skipIfExists: true,\n });\n\n // Generate schema file with foreign key (opt-out via disableIdpUserSync.idpToUser: true)\n files.push({\n path: path.join(ctx.pluginConfig.distPath, \"data\", `${idpUser.name}.schema.ts`),\n content: generateIdpUserSchemaFile({\n usernameField: idpUser.schema.usernameField,\n userTableName: idpUser.schema.userTableName,\n includeUserProfileFK: idpUserSyncFKs.emitIdpToUserFK,\n }),\n });\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export{t as createExecutorService}from"./service-l_tEI8sS.mjs";
|
package/docs/migration/v3.md
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
# Migrating to v3
|
|
2
|
-
|
|
3
|
-
<!-- Generated from the sdk-codemod registry. Run `pnpm codemod:docs:update` and edit `packages/sdk-codemod/src/registry.ts` instead of this file. -->
|
|
4
|
-
|
|
5
|
-
Run the codemods, then finish anything reported as not migrated automatically:
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
npx @tailor-platform/sdk-codemod --from <current-version> --to <target-version>
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## workflow.execJobFunction (imported) removed — use job.start()
|
|
12
|
-
|
|
13
|
-
**Migration:** Manual
|
|
14
|
-
|
|
15
|
-
`execJobFunction` on the `workflow` value imported from @tailor-platform/sdk/runtime(/workflow) is removed in v3. Calling it directly from a workflow job body to reach another job is not detected as a build-time dependency and has no working use; the target job's own `.start()` method is the only supported way to call it. This does not affect the ambient `tailor.workflow.execJobFunction` global — that's what `.start()` itself compiles down to at build time, and it remains fully supported.
|
|
16
|
-
|
|
17
|
-
Before:
|
|
18
|
-
|
|
19
|
-
```ts
|
|
20
|
-
import { workflow } from "@tailor-platform/sdk/runtime";
|
|
21
|
-
|
|
22
|
-
await workflow.execJobFunction("worker", { id: 1 });
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
After:
|
|
26
|
-
|
|
27
|
-
```ts
|
|
28
|
-
import { worker } from "./jobs/worker";
|
|
29
|
-
|
|
30
|
-
await worker.start({ id: 1 });
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
<details>
|
|
34
|
-
<summary>Prompt for an AI agent (to perform this migration)</summary>
|
|
35
|
-
|
|
36
|
-
```text
|
|
37
|
-
workflow.execJobFunction — the value imported from
|
|
38
|
-
@tailor-platform/sdk/runtime or @tailor-platform/sdk/runtime/workflow — is
|
|
39
|
-
removed in v3. Replace each call with the target job's own .start() method:
|
|
40
|
-
import the WorkflowJob the call names and call <job>.start(args, options)
|
|
41
|
-
instead of workflow.execJobFunction("<job-name>", args, options).
|
|
42
|
-
|
|
43
|
-
This only removes the re-export from @tailor-platform/sdk/runtime. It does
|
|
44
|
-
not affect the ambient tailor.workflow.execJobFunction global, which stays
|
|
45
|
-
fully supported and is what .start() itself compiles down to at build time.
|
|
46
|
-
This codemod does not rewrite ambient tailor.workflow.execJobFunction(...)
|
|
47
|
-
call sites, since removing the import re-export does not affect them — but
|
|
48
|
-
if such a call site sits inside workflow job source and calls another job
|
|
49
|
-
by name, a separate build-time check already rejects it; migrate that call
|
|
50
|
-
to the target job's own .start() method too.
|
|
51
|
-
|
|
52
|
-
If the job name passed to execJobFunction is not a string literal (a truly
|
|
53
|
-
dynamic dispatch), there is currently no supported replacement — .start()
|
|
54
|
-
only targets a statically known job. Flag this case for a human instead of
|
|
55
|
-
guessing a rewrite.
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
</details>
|
|
59
|
-
|
|
60
|
-
## function test-run → function run
|
|
61
|
-
|
|
62
|
-
**Migration:** Partially automatic
|
|
63
|
-
|
|
64
|
-
Rename `tailor function test-run` invocations to `tailor function run`. `test-run` remains as a deprecated alias until it is removed in v3.
|
|
65
|
-
|
|
66
|
-
Before:
|
|
67
|
-
|
|
68
|
-
```sh
|
|
69
|
-
tailor function test-run resolvers/add.ts --arg '{"a":1,"b":2}'
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
After:
|
|
73
|
-
|
|
74
|
-
```sh
|
|
75
|
-
tailor function run resolvers/add.ts --arg '{"a":1,"b":2}'
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
<details>
|
|
79
|
-
<summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
|
|
80
|
-
|
|
81
|
-
```text
|
|
82
|
-
The `tailor function test-run` subcommand is renamed to `tailor function run`;
|
|
83
|
-
the old name is removed in v3. Replace any remaining `function test-run`
|
|
84
|
-
invocations the codemod did not rewrite (e.g. wrapped across lines or invoked
|
|
85
|
-
through a package runner such as `npx @tailor-platform/sdk`) with
|
|
86
|
-
`function run`. Leave prose that merely mentions the old subcommand name
|
|
87
|
-
unchanged unless it documents a command to type.
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
</details>
|
|
91
|
-
|
|
92
|
-
## relation() toward.type → toward.table
|
|
93
|
-
|
|
94
|
-
**Migration:** Partially automatic
|
|
95
|
-
|
|
96
|
-
Rename the `.relation()` option `toward.type` to `toward.table`, matching the `db.type()` → `db.table()` rename. The relation's own `type` (its cardinality, e.g. `"n-1"`) is unchanged — only the target-table reference nested under `toward` moves.
|
|
97
|
-
|
|
98
|
-
Before:
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
customerId: db.uuid().relation({
|
|
102
|
-
type: "n-1",
|
|
103
|
-
toward: { type: customer },
|
|
104
|
-
}),
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
After:
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
customerId: db.uuid().relation({
|
|
111
|
-
type: "n-1",
|
|
112
|
-
toward: { table: customer },
|
|
113
|
-
}),
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
<details>
|
|
117
|
-
<summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
|
|
118
|
-
|
|
119
|
-
```text
|
|
120
|
-
In Tailor SDK v3, `.relation()`'s `toward.type` option is renamed to
|
|
121
|
-
`toward.table` (it names a target table, not a TypeScript/GraphQL type).
|
|
122
|
-
Rename any remaining `toward.type` the codemod did not rewrite (e.g. a
|
|
123
|
-
`toward` object reached through a shared variable, spread, or computed
|
|
124
|
-
key) to `toward.table`. Do not touch the relation's own outer `type`
|
|
125
|
-
property, which is the relation's cardinality (e.g. "n-1", "1-1",
|
|
126
|
-
"keyOnly") and keeps its name.
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
</details>
|
|
130
|
-
|
|
131
|
-
## defineConfig inlineSourcemap / logLevel → buildOptions
|
|
132
|
-
|
|
133
|
-
**Migration:** Partially automatic
|
|
134
|
-
|
|
135
|
-
Move the top-level `inlineSourcemap` and `logLevel` of `defineConfig()` into `buildOptions`, which groups the settings that control how functions are bundled. The top-level fields keep working until they are removed in v3; setting the same option in both places is rejected.
|
|
136
|
-
|
|
137
|
-
Before:
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
export default defineConfig({
|
|
141
|
-
name: "my-app",
|
|
142
|
-
inlineSourcemap: false,
|
|
143
|
-
logLevel: "WARN",
|
|
144
|
-
});
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
After:
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
export default defineConfig({
|
|
151
|
-
name: "my-app",
|
|
152
|
-
buildOptions: {
|
|
153
|
-
inlineSourcemap: false,
|
|
154
|
-
logLevel: "WARN",
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
<details>
|
|
160
|
-
<summary>Prompt for an AI agent (to finish the cases the codemod could not migrate)</summary>
|
|
161
|
-
|
|
162
|
-
```text
|
|
163
|
-
In Tailor SDK v3, the top-level `inlineSourcemap` and `logLevel` options of
|
|
164
|
-
`defineConfig()` from `@tailor-platform/sdk` are removed in favor of
|
|
165
|
-
`buildOptions.inlineSourcemap` and `buildOptions.logLevel`. For each flagged
|
|
166
|
-
config, move those two properties into a `buildOptions` object (create it if
|
|
167
|
-
it does not exist) without changing their values. When the config is built
|
|
168
|
-
from a variable or a spread, move them in the object that actually defines
|
|
169
|
-
them. If an option is set both at the top level and in `buildOptions`, keep
|
|
170
|
-
the value that the deployed app should use and delete the other; the build
|
|
171
|
-
rejects a config that sets both. Leave `logLevel` options of other tools
|
|
172
|
-
(for example a Vite or Vitest config) unchanged.
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
</details>
|
|
176
|
-
|
|
177
|
-
## String file uploads → explicit encoding
|
|
178
|
-
|
|
179
|
-
**Migration:** Manual
|
|
180
|
-
|
|
181
|
-
String inputs to the SDK `file.upload` and generated `uploadFile` require an explicit `encoding` in v3. Add `encoding: "utf8"` to preserve the previous behavior; use `"base64"` only when decoding the input is intended. Byte inputs are unchanged. This migration requires checking the input type and regenerating file helpers, so it provides review guidance instead of rewriting calls automatically.
|
|
182
|
-
|
|
183
|
-
Before:
|
|
184
|
-
|
|
185
|
-
```ts
|
|
186
|
-
await file.upload(ns, table, field, id, text, { contentType: "text/plain" });
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
After:
|
|
190
|
-
|
|
191
|
-
```ts
|
|
192
|
-
await file.upload(ns, table, field, id, text, { contentType: "text/plain", encoding: "utf8" });
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
<details>
|
|
196
|
-
<summary>Prompt for an AI agent (to perform this migration)</summary>
|
|
197
|
-
|
|
198
|
-
```text
|
|
199
|
-
Inspect calls to the imported SDK file.upload (including aliases and destructured upload)
|
|
200
|
-
and generated uploadFile helpers, including shared wrappers and option objects.
|
|
201
|
-
For string inputs, add encoding: utf8 to preserve existing text storage behavior.
|
|
202
|
-
Choose encoding: base64 only if decoding is explicitly intended; never infer it from
|
|
203
|
-
the string contents or contentType. Preserve all existing upload options.
|
|
204
|
-
Leave byte-only inputs unchanged. For string | byte unions, supplying encoding: utf8
|
|
205
|
-
preserves behavior because byte input ignores encoding. Narrow shared options types
|
|
206
|
-
so TypeScript can see that encoding is present for strings.
|
|
207
|
-
Run tailor generate to regenerate uploadFile helpers instead of editing generated files.
|
|
208
|
-
The global tailordb.file.upload does not support this encoding option; switch to the
|
|
209
|
-
file import from @tailor-platform/sdk/runtime before using it.
|
|
210
|
-
Do not change unrelated upload APIs or already explicit encodings.
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
</details>
|
|
214
|
-
|
|
215
|
-
## secrets.get()/getAll() (defineSecretManager) removed — use secretmanager from @tailor-platform/sdk/runtime
|
|
216
|
-
|
|
217
|
-
**Migration:** Manual
|
|
218
|
-
|
|
219
|
-
The `get()`/`getAll()` methods on the object `defineSecretManager()` returns are removed in v3. Importing that object into a resolver, executor, or workflow file bundles the raw values passed to `defineSecretManager()` into that function's deployed code, which fails to build once any value comes from `process.env`. `secretmanager.getSecret()`/`getSecrets()` from `@tailor-platform/sdk/runtime` read the same secrets without importing the config object.
|
|
220
|
-
|
|
221
|
-
Before:
|
|
222
|
-
|
|
223
|
-
```ts
|
|
224
|
-
import { secrets } from "../tailor.config";
|
|
225
|
-
|
|
226
|
-
const apiKey = await secrets.get("api-keys", "stripe-secret-key");
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
After:
|
|
230
|
-
|
|
231
|
-
```ts
|
|
232
|
-
import { secretmanager } from "@tailor-platform/sdk/runtime";
|
|
233
|
-
|
|
234
|
-
const apiKey = await secretmanager.getSecret("api-keys", "stripe-secret-key");
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Before:
|
|
238
|
-
|
|
239
|
-
```ts
|
|
240
|
-
import { secrets } from "../tailor.config";
|
|
241
|
-
|
|
242
|
-
const [apiKey, webhookSecret] = await secrets.getAll("api-keys", [
|
|
243
|
-
"sendgrid-api-key",
|
|
244
|
-
"stripe-secret-key",
|
|
245
|
-
]);
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
After:
|
|
249
|
-
|
|
250
|
-
```ts
|
|
251
|
-
import { secretmanager } from "@tailor-platform/sdk/runtime";
|
|
252
|
-
|
|
253
|
-
const { "sendgrid-api-key": apiKey, "stripe-secret-key": webhookSecret } =
|
|
254
|
-
await secretmanager.getSecrets("api-keys", ["sendgrid-api-key", "stripe-secret-key"]);
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
<details>
|
|
258
|
-
<summary>Prompt for an AI agent (to perform this migration)</summary>
|
|
259
|
-
|
|
260
|
-
```text
|
|
261
|
-
`secrets.get()`/`getAll()` on the object `defineSecretManager()` returns are removed in v3.
|
|
262
|
-
Replace the import with `import { secretmanager } from "@tailor-platform/sdk/runtime";` and
|
|
263
|
-
call `secretmanager.getSecret(vault, name)` in place of `secrets.get(vault, name)`.
|
|
264
|
-
|
|
265
|
-
`getAll()` needs more than a rename: `secrets.getAll(vault, names)` returned an array of
|
|
266
|
-
values in the same order as `names`, while `secretmanager.getSecrets(vault, names)` returns
|
|
267
|
-
a partial record keyed by each requested name (a name with no value is omitted instead of
|
|
268
|
-
being `undefined` at its index). Rewrite positional destructuring (`const [a, b] = await
|
|
269
|
-
secrets.getAll(v, ["A", "B"])`) into keyed destructuring (`const { A: a, B: b } = await
|
|
270
|
-
secretmanager.getSecrets(v, ["A", "B"])`).
|
|
271
|
-
|
|
272
|
-
Also review: a `secrets` object re-exported or re-assigned to another name before use, and a
|
|
273
|
-
file that already imports something else named `secretmanager` (rename one of the two on
|
|
274
|
-
conflict).
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
</details>
|