@tailor-platform/sdk 1.66.1 → 1.67.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/application-Djeezk3m.mjs +4 -0
  3. package/dist/{client-F0a4cWUM.mjs → application-WpWwTyk9.mjs} +5734 -20
  4. package/dist/application-WpWwTyk9.mjs.map +1 -0
  5. package/dist/{authconnection-D8SJGMpj.mjs → authconnection-Ds2Ahpum.mjs} +2 -2
  6. package/dist/{authconnection-D8SJGMpj.mjs.map → authconnection-Ds2Ahpum.mjs.map} +1 -1
  7. package/dist/cli/index.mjs +18 -64
  8. package/dist/cli/index.mjs.map +1 -1
  9. package/dist/cli/lib.d.mts +7 -7
  10. package/dist/cli/lib.mjs +3 -4
  11. package/dist/cli/lib.mjs.map +1 -1
  12. package/dist/completion/zsh-worker.zsh +1 -1
  13. package/dist/configure/index.d.mts +5 -5
  14. package/dist/configure/index.mjs +2 -2
  15. package/dist/configure/index.mjs.map +1 -1
  16. package/dist/{context-s0lxhu8_.mjs → context-CDQqIv4u.mjs} +2 -2
  17. package/dist/{context-s0lxhu8_.mjs.map → context-CDQqIv4u.mjs.map} +1 -1
  18. package/dist/{crashreport-Bf6uT6mf.mjs → crashreport-6jpCceOF.mjs} +1 -1
  19. package/dist/{crashreport-0EHy-ayY.mjs → crashreport-u9y2npiy.mjs} +5 -7
  20. package/dist/{crashreport-0EHy-ayY.mjs.map → crashreport-u9y2npiy.mjs.map} +1 -1
  21. package/dist/enum-constants-C7DaWeQo.mjs.map +1 -1
  22. package/dist/field-C4zdJLW5.mjs.map +1 -1
  23. package/dist/{file-B58Dm-2P.mjs → file-BkxupbYP.mjs} +2 -2
  24. package/dist/{file-B58Dm-2P.mjs.map → file-BkxupbYP.mjs.map} +1 -1
  25. package/dist/file-utils-BHPxPXmn.mjs.map +1 -1
  26. package/dist/{iconv-DreIffeM.mjs → iconv-D1zmPjvi.mjs} +2 -2
  27. package/dist/{iconv-DreIffeM.mjs.map → iconv-D1zmPjvi.mjs.map} +1 -1
  28. package/dist/{idp-Ch95ag8h.mjs → idp-BZPqpcYY.mjs} +2 -2
  29. package/dist/{idp-Ch95ag8h.mjs.map → idp-BZPqpcYY.mjs.map} +1 -1
  30. package/dist/{index-Db2RvnEH.d.mts → index-CklcVeMG.d.mts} +2 -2
  31. package/dist/{index-CZ2r3qiO.d.mts → index-DYhnxXYR.d.mts} +2 -2
  32. package/dist/{index-QpC0TNbH.d.mts → index-DlDRSzFZ.d.mts} +2 -2
  33. package/dist/{index-BdLqzJDu.d.mts → index-DvEUb3pX.d.mts} +15 -9
  34. package/dist/{index-Bhjep8cS.d.mts → index-hXoO-AOC.d.mts} +2 -2
  35. package/dist/job-BpsFXPbi.mjs.map +1 -1
  36. package/dist/kysely-type-D1e0Vwkd.mjs.map +1 -1
  37. package/dist/mock-DMgIygjE.mjs.map +1 -1
  38. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  39. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  40. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  41. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  42. package/dist/plugin/builtin/seed/index.mjs +1 -1
  43. package/dist/plugin/index.d.mts +2 -3
  44. package/dist/plugin/index.mjs.map +1 -1
  45. package/dist/registry-D0uB0OrK.mjs.map +1 -1
  46. package/dist/runtime/authconnection.mjs +1 -1
  47. package/dist/runtime/context.mjs +1 -1
  48. package/dist/runtime/file.mjs +1 -1
  49. package/dist/runtime/iconv.mjs +1 -1
  50. package/dist/runtime/idp.mjs +1 -1
  51. package/dist/runtime/index.mjs +7 -7
  52. package/dist/runtime/secretmanager.mjs +1 -1
  53. package/dist/runtime/workflow.mjs +1 -1
  54. package/dist/{runtime-2nzOZCUb.mjs → runtime-BU6KtCvk.mjs} +9 -35
  55. package/dist/runtime-BU6KtCvk.mjs.map +1 -0
  56. package/dist/schema-1msIhXwA.mjs.map +1 -1
  57. package/dist/{secret-file-CWzF8rry.mjs → secret-file-eB3R3Fil.mjs} +27 -2
  58. package/dist/{secret-file-CWzF8rry.mjs.map → secret-file-eB3R3Fil.mjs.map} +1 -1
  59. package/dist/{secretmanager-B9h-U_8U.mjs → secretmanager-h3tBJV8f.mjs} +2 -2
  60. package/dist/{secretmanager-B9h-U_8U.mjs.map → secretmanager-h3tBJV8f.mjs.map} +1 -1
  61. package/dist/{seed-BH2FbrPV.mjs → seed-YAbtMy65.mjs} +2 -2
  62. package/dist/seed-YAbtMy65.mjs.map +1 -0
  63. package/dist/{service-DMohAx8a2.mjs → service-DMohAx8a.mjs} +1 -1
  64. package/dist/service-DMohAx8a.mjs.map +1 -0
  65. package/dist/service-wI3Hvrgx.mjs.map +1 -1
  66. package/dist/{plugin-DylAsA4Z.d.mts → types-Bzr0RQME.d.mts} +342 -36
  67. package/dist/types-CmzfQP_m.mjs.map +1 -1
  68. package/dist/types-DTcZ2Yax.d.mts +74 -0
  69. package/dist/{tailordb-C-ar4XCX.d.mts → types-DZrtN6-H.d.mts} +89 -239
  70. package/dist/utils/test/index.d.mts +3 -3
  71. package/dist/utils/test/index.mjs.map +1 -1
  72. package/dist/vitest/index.d.mts +1 -1
  73. package/dist/{workflow--aPbA8Uq.mjs → workflow-C8I7shjM.mjs} +2 -2
  74. package/dist/{workflow--aPbA8Uq.mjs.map → workflow-C8I7shjM.mjs.map} +1 -1
  75. package/dist/{workflow.generated--1Qc15Et.d.mts → workflow.generated-1S50BhEb.d.mts} +17 -241
  76. package/docs/cli-reference.md +18 -17
  77. package/docs/github-actions.md +2 -2
  78. package/package.json +12 -10
  79. package/dist/actor-D_2aJjYO.d.mts +0 -24
  80. package/dist/application-DGDmL8i_.mjs +0 -5620
  81. package/dist/application-DGDmL8i_.mjs.map +0 -1
  82. package/dist/application-nTydHJm8.mjs +0 -4
  83. package/dist/client-F0a4cWUM.mjs.map +0 -1
  84. package/dist/client-boxXYevx.mjs +0 -4
  85. package/dist/env-B-g-qgE4.d.mts +0 -7
  86. package/dist/runtime-2nzOZCUb.mjs.map +0 -1
  87. package/dist/seed-BH2FbrPV.mjs.map +0 -1
  88. package/dist/service-DMohAx8a2.mjs.map +0 -1
  89. /package/dist/{chunk-BkoGK1jX.mjs → rolldown-runtime-BkoGK1jX.mjs} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"kysely-type-D1e0Vwkd.mjs","names":[],"sources":["../src/plugin/builtin/kysely-type/type-processor.ts","../src/plugin/builtin/kysely-type/index.ts"],"sourcesContent":["import multiline from \"@/utils/multiline\";\nimport { type KyselyNamespaceMetadata, type KyselyTypeMetadata } from \"./types\";\nimport type { OperatorFieldConfig, TailorDBType } from \"@/types/tailordb\";\n\ntype UsedUtilityTypes = { Timestamp: boolean; Serial: boolean };\n\ntype FieldTypeResult = {\n type: string;\n usedUtilityTypes: UsedUtilityTypes;\n};\n\n/**\n * Get the enum type definition.\n * @param fieldConfig - The field configuration\n * @returns The enum type as a string union\n */\nfunction getEnumType(fieldConfig: OperatorFieldConfig): string {\n const allowedValues = fieldConfig.allowedValues;\n\n if (allowedValues && Array.isArray(allowedValues)) {\n return allowedValues\n .map((v: string | { value: string }) => {\n const value = typeof v === \"string\" ? v : v.value;\n return `\"${value}\"`;\n })\n .join(\" | \");\n }\n return \"string\";\n}\n\n/**\n * Get the nested object type definition.\n * @param fieldConfig - The field configuration\n * @returns The nested type with used utility types\n */\nfunction getNestedType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const fields = fieldConfig.fields;\n if (!fields || typeof fields !== \"object\") {\n return {\n type: \"string\",\n usedUtilityTypes: { Timestamp: false, Serial: false },\n };\n }\n\n const fieldResults = Object.entries(fields).map(([fieldName, config]) => {\n const result = generateFieldType(config);\n const optional = config.required !== true ? \"?\" : \"\";\n return {\n fieldType: `${fieldName}${optional}: ${result.type}`,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n });\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => ({\n Timestamp: acc.Timestamp || result.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || result.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const fieldTypes = fieldResults.map((r) => r.fieldType);\n const obj = `{\\n ${fieldTypes.join(\";\\n \")}${fieldTypes.length > 0 ? \";\" : \"\"}\\n}`;\n\n const hasOptionalFields = Object.values(fields).some((config) => config.required !== true);\n if (aggregatedUtilityTypes.Timestamp || hasOptionalFields) {\n return { type: `ObjectColumnType<${obj}>`, usedUtilityTypes: aggregatedUtilityTypes };\n }\n return { type: obj, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Get the base Kysely type for a field (without array/null modifiers).\n * @param fieldConfig - The field configuration\n * @returns The base type with used utility types\n */\nfunction getBaseType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const fieldType = fieldConfig.type;\n const usedUtilityTypes = { Timestamp: false, Serial: false };\n\n let type: string;\n switch (fieldType) {\n case \"uuid\":\n case \"string\":\n case \"decimal\":\n type = \"string\";\n break;\n case \"integer\":\n case \"float\":\n type = \"number\";\n break;\n case \"date\":\n case \"datetime\":\n usedUtilityTypes.Timestamp = true;\n type = \"Timestamp\";\n break;\n case \"bool\":\n case \"boolean\":\n type = \"boolean\";\n break;\n case \"enum\":\n type = getEnumType(fieldConfig);\n break;\n case \"nested\": {\n const nestedResult = getNestedType(fieldConfig);\n return nestedResult;\n }\n default:\n type = \"string\";\n break;\n }\n\n return { type, usedUtilityTypes };\n}\n\n/**\n * Generate the complete field type including array and null modifiers.\n * @param fieldConfig - The field configuration\n * @returns The complete field type with used utility types\n */\nfunction generateFieldType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const baseTypeResult = getBaseType(fieldConfig);\n const usedUtilityTypes = { ...baseTypeResult.usedUtilityTypes };\n\n const isArray = fieldConfig.array === true;\n const isNullable = fieldConfig.required !== true;\n\n // Types that use ColumnType internally (Timestamp, ObjectColumnType) cannot be\n // directly wrapped with [] for arrays, because Kysely only resolves ColumnType at\n // the top-level table property. Use ArrayColumnType/ObjectArrayColumnType to keep\n // the ColumnType at the top level with arrays inside.\n const columnTypeBaseTypes = new Set([\"Timestamp\"]);\n const isColumnTypeBase = columnTypeBaseTypes.has(baseTypeResult.type);\n\n let finalType = baseTypeResult.type;\n if (isArray) {\n if (isColumnTypeBase || finalType.startsWith(\"ObjectColumnType<\")) {\n finalType = `ArrayColumnType<${baseTypeResult.type}>`;\n } else {\n const needsParens = fieldConfig.type === \"enum\";\n finalType = needsParens ? `(${baseTypeResult.type})[]` : `${baseTypeResult.type}[]`;\n }\n }\n if (isNullable) {\n finalType = `${finalType} | null`;\n }\n\n if (fieldConfig.serial) {\n usedUtilityTypes.Serial = true;\n finalType = `Serial<${finalType}>`;\n }\n if (fieldConfig.hooks?.create) {\n finalType = `Generated<${finalType}>`;\n }\n\n return { type: finalType, usedUtilityTypes };\n}\n\n/**\n * Generate the table interface.\n * @param type - The parsed TailorDB type\n * @returns The type definition and used utility types\n */\nfunction generateTableInterface(type: TailorDBType): {\n typeDef: string;\n usedUtilityTypes: UsedUtilityTypes;\n} {\n const fieldEntries = Object.entries(type.fields).filter(([fieldName]) => fieldName !== \"id\");\n\n const fieldResults = fieldEntries.map(([fieldName, parsedField]) => ({\n fieldName,\n ...generateFieldType(parsedField.config),\n }));\n\n const fields = [\n \"id: Generated<string>;\",\n ...fieldResults.map((result) => `${result.fieldName}: ${result.type};`),\n ];\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => ({\n Timestamp: acc.Timestamp || result.usedUtilityTypes.Timestamp,\n\n Serial: acc.Serial || result.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const typeDef = multiline /* ts */ `\n ${type.name}: {\n ${fields.join(\"\\n\")}\n }\n `;\n\n return { typeDef, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Convert a TailorDBType into KyselyTypeMetadata.\n * @param type - Parsed TailorDB type\n * @returns Generated Kysely type metadata\n */\nexport async function processKyselyType(type: TailorDBType): Promise<KyselyTypeMetadata> {\n const result = generateTableInterface(type);\n\n return {\n name: type.name,\n typeDef: result.typeDef,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n}\n\n/**\n * Generate unified types file from multiple namespaces.\n * @param namespaceData - Namespace metadata\n * @returns Generated types file contents\n */\nexport function generateUnifiedKyselyTypes(namespaceData: KyselyNamespaceMetadata[]): string {\n if (namespaceData.length === 0) {\n return \"\";\n }\n\n // Aggregate used utility types from all namespaces\n const globalUsedUtilityTypes = namespaceData.reduce(\n (acc, ns) => ({\n Timestamp: acc.Timestamp || ns.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || ns.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const utilityTypeImports: string[] = [\"type Generated\"];\n if (globalUsedUtilityTypes.Timestamp) {\n utilityTypeImports.push(\"type Timestamp\");\n }\n const hasObjectColumnType = namespaceData.some((ns) =>\n ns.types.some((t) => t.typeDef.includes(\"ObjectColumnType<\")),\n );\n if (hasObjectColumnType) {\n utilityTypeImports.push(\"type ObjectColumnType\");\n }\n const hasArrayColumnType = namespaceData.some((ns) =>\n ns.types.some((t) => t.typeDef.includes(\"ArrayColumnType<\")),\n );\n if (hasArrayColumnType) {\n utilityTypeImports.push(\"type ArrayColumnType\");\n }\n if (globalUsedUtilityTypes.Serial) {\n utilityTypeImports.push(\"type Serial\");\n }\n\n const importsSection = multiline /* ts */ `\n import {\n createGetDB,\n ${utilityTypeImports.join(\",\\n\")},\n type NamespaceDB,\n type NamespaceInsertable,\n type NamespaceSelectable,\n type NamespaceTable,\n type NamespaceTableName,\n type NamespaceTransaction,\n type NamespaceUpdateable,\n } from \"@tailor-platform/sdk/kysely\";\n `;\n\n // Generate Namespace interface with multiple namespaces\n const namespaceInterfaces = namespaceData\n .map(({ namespace, types }) => {\n const typeDefsWithIndent = types\n .map((type) => {\n return type.typeDef\n .split(\"\\n\")\n .map((line) => (line.trim() ? ` ${line}` : \"\"))\n .join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return ` \"${namespace}\": {\\n${typeDefsWithIndent}\\n }`;\n })\n .join(\",\\n\");\n\n const namespaceInterface = `export interface Namespace {\\n${namespaceInterfaces}\\n}`;\n\n const getDBFunction = multiline /* ts */ `\n export const getDB = createGetDB<Namespace>();\n\n export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;\n `;\n\n const utilityTypeExports = multiline /* ts */ `\n export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =\n NamespaceTransaction<Namespace, K>;\n\n type TableName = NamespaceTableName<Namespace>;\n export type Table<T extends TableName> = NamespaceTable<Namespace, T>;\n\n export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;\n export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;\n export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;\n `;\n\n return (\n [importsSection, namespaceInterface, getDBFunction, utilityTypeExports].join(\"\\n\\n\") + \"\\n\"\n );\n}\n","import { processKyselyType, generateUnifiedKyselyTypes } from \"./type-processor\";\nimport type { KyselyTypeMetadata, KyselyNamespaceMetadata } from \"./types\";\nimport type { Plugin } from \"@/types/plugin\";\nimport type { GeneratorResult, TailorDBReadyContext } from \"@/types/plugin-generation\";\n\n/** Unique identifier for the Kysely type generator plugin. */\nexport const KyselyGeneratorID = \"@tailor-platform/kysely-type\";\n\ntype KyselyTypePluginOptions = {\n distPath: string;\n};\n\n/**\n * Plugin that generates Kysely type definitions for TailorDB types.\n * @param options - Plugin options\n * @param options.distPath - Output file path for generated types\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function kyselyTypePlugin(\n options: KyselyTypePluginOptions,\n): Plugin<unknown, KyselyTypePluginOptions> {\n return {\n id: KyselyGeneratorID,\n description: \"Generates Kysely type definitions for TailorDB types\",\n pluginConfig: options,\n\n async onTailorDBReady(\n ctx: TailorDBReadyContext<KyselyTypePluginOptions>,\n ): Promise<GeneratorResult> {\n const allNamespaceData: KyselyNamespaceMetadata[] = [];\n\n for (const ns of ctx.tailordb) {\n const typeMetadataList: KyselyTypeMetadata[] = [];\n\n for (const type of Object.values(ns.types)) {\n const metadata = await processKyselyType(type);\n typeMetadataList.push(metadata);\n }\n\n if (typeMetadataList.length === 0) continue;\n\n const usedUtilityTypes = typeMetadataList.reduce(\n (acc, type) => ({\n Timestamp: acc.Timestamp || type.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || type.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n allNamespaceData.push({\n namespace: ns.namespace,\n types: typeMetadataList,\n usedUtilityTypes,\n });\n }\n\n const files: GeneratorResult[\"files\"] = [];\n if (allNamespaceData.length > 0) {\n const content = generateUnifiedKyselyTypes(allNamespaceData);\n files.push({\n path: ctx.pluginConfig.distPath,\n content,\n });\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"kysely-type-D1e0Vwkd.mjs","names":[],"sources":["../src/plugin/builtin/kysely-type/type-processor.ts","../src/plugin/builtin/kysely-type/index.ts"],"sourcesContent":["import multiline from \"@/utils/multiline\";\nimport { type KyselyNamespaceMetadata, type KyselyTypeMetadata } from \"./types\";\nimport type { OperatorFieldConfig, TailorDBType } from \"@/parser/service/tailordb/types\";\n\ntype UsedUtilityTypes = { Timestamp: boolean; Serial: boolean };\n\ntype FieldTypeResult = {\n type: string;\n usedUtilityTypes: UsedUtilityTypes;\n};\n\n/**\n * Get the enum type definition.\n * @param fieldConfig - The field configuration\n * @returns The enum type as a string union\n */\nfunction getEnumType(fieldConfig: OperatorFieldConfig): string {\n const allowedValues = fieldConfig.allowedValues;\n\n if (allowedValues && Array.isArray(allowedValues)) {\n return allowedValues\n .map((v: string | { value: string }) => {\n const value = typeof v === \"string\" ? v : v.value;\n return `\"${value}\"`;\n })\n .join(\" | \");\n }\n return \"string\";\n}\n\n/**\n * Get the nested object type definition.\n * @param fieldConfig - The field configuration\n * @returns The nested type with used utility types\n */\nfunction getNestedType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const fields = fieldConfig.fields;\n if (!fields || typeof fields !== \"object\") {\n return {\n type: \"string\",\n usedUtilityTypes: { Timestamp: false, Serial: false },\n };\n }\n\n const fieldResults = Object.entries(fields).map(([fieldName, config]) => {\n const result = generateFieldType(config);\n const optional = config.required !== true ? \"?\" : \"\";\n return {\n fieldType: `${fieldName}${optional}: ${result.type}`,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n });\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => ({\n Timestamp: acc.Timestamp || result.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || result.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const fieldTypes = fieldResults.map((r) => r.fieldType);\n const obj = `{\\n ${fieldTypes.join(\";\\n \")}${fieldTypes.length > 0 ? \";\" : \"\"}\\n}`;\n\n const hasOptionalFields = Object.values(fields).some((config) => config.required !== true);\n if (aggregatedUtilityTypes.Timestamp || hasOptionalFields) {\n return { type: `ObjectColumnType<${obj}>`, usedUtilityTypes: aggregatedUtilityTypes };\n }\n return { type: obj, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Get the base Kysely type for a field (without array/null modifiers).\n * @param fieldConfig - The field configuration\n * @returns The base type with used utility types\n */\nfunction getBaseType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const fieldType = fieldConfig.type;\n const usedUtilityTypes = { Timestamp: false, Serial: false };\n\n let type: string;\n switch (fieldType) {\n case \"uuid\":\n case \"string\":\n case \"decimal\":\n type = \"string\";\n break;\n case \"integer\":\n case \"float\":\n type = \"number\";\n break;\n case \"date\":\n case \"datetime\":\n usedUtilityTypes.Timestamp = true;\n type = \"Timestamp\";\n break;\n case \"bool\":\n case \"boolean\":\n type = \"boolean\";\n break;\n case \"enum\":\n type = getEnumType(fieldConfig);\n break;\n case \"nested\": {\n const nestedResult = getNestedType(fieldConfig);\n return nestedResult;\n }\n default:\n type = \"string\";\n break;\n }\n\n return { type, usedUtilityTypes };\n}\n\n/**\n * Generate the complete field type including array and null modifiers.\n * @param fieldConfig - The field configuration\n * @returns The complete field type with used utility types\n */\nfunction generateFieldType(fieldConfig: OperatorFieldConfig): FieldTypeResult {\n const baseTypeResult = getBaseType(fieldConfig);\n const usedUtilityTypes = { ...baseTypeResult.usedUtilityTypes };\n\n const isArray = fieldConfig.array === true;\n const isNullable = fieldConfig.required !== true;\n\n // Types that use ColumnType internally (Timestamp, ObjectColumnType) cannot be\n // directly wrapped with [] for arrays, because Kysely only resolves ColumnType at\n // the top-level table property. Use ArrayColumnType/ObjectArrayColumnType to keep\n // the ColumnType at the top level with arrays inside.\n const columnTypeBaseTypes = new Set([\"Timestamp\"]);\n const isColumnTypeBase = columnTypeBaseTypes.has(baseTypeResult.type);\n\n let finalType = baseTypeResult.type;\n if (isArray) {\n if (isColumnTypeBase || finalType.startsWith(\"ObjectColumnType<\")) {\n finalType = `ArrayColumnType<${baseTypeResult.type}>`;\n } else {\n const needsParens = fieldConfig.type === \"enum\";\n finalType = needsParens ? `(${baseTypeResult.type})[]` : `${baseTypeResult.type}[]`;\n }\n }\n if (isNullable) {\n finalType = `${finalType} | null`;\n }\n\n if (fieldConfig.serial) {\n usedUtilityTypes.Serial = true;\n finalType = `Serial<${finalType}>`;\n }\n if (fieldConfig.hooks?.create) {\n finalType = `Generated<${finalType}>`;\n }\n\n return { type: finalType, usedUtilityTypes };\n}\n\n/**\n * Generate the table interface.\n * @param type - The parsed TailorDB type\n * @returns The type definition and used utility types\n */\nfunction generateTableInterface(type: TailorDBType): {\n typeDef: string;\n usedUtilityTypes: UsedUtilityTypes;\n} {\n const fieldEntries = Object.entries(type.fields).filter(([fieldName]) => fieldName !== \"id\");\n\n const fieldResults = fieldEntries.map(([fieldName, parsedField]) => ({\n fieldName,\n ...generateFieldType(parsedField.config),\n }));\n\n const fields = [\n \"id: Generated<string>;\",\n ...fieldResults.map((result) => `${result.fieldName}: ${result.type};`),\n ];\n\n const aggregatedUtilityTypes = fieldResults.reduce(\n (acc, result) => ({\n Timestamp: acc.Timestamp || result.usedUtilityTypes.Timestamp,\n\n Serial: acc.Serial || result.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const typeDef = multiline /* ts */ `\n ${type.name}: {\n ${fields.join(\"\\n\")}\n }\n `;\n\n return { typeDef, usedUtilityTypes: aggregatedUtilityTypes };\n}\n\n/**\n * Convert a TailorDBType into KyselyTypeMetadata.\n * @param type - Parsed TailorDB type\n * @returns Generated Kysely type metadata\n */\nexport async function processKyselyType(type: TailorDBType): Promise<KyselyTypeMetadata> {\n const result = generateTableInterface(type);\n\n return {\n name: type.name,\n typeDef: result.typeDef,\n usedUtilityTypes: result.usedUtilityTypes,\n };\n}\n\n/**\n * Generate unified types file from multiple namespaces.\n * @param namespaceData - Namespace metadata\n * @returns Generated types file contents\n */\nexport function generateUnifiedKyselyTypes(namespaceData: KyselyNamespaceMetadata[]): string {\n if (namespaceData.length === 0) {\n return \"\";\n }\n\n // Aggregate used utility types from all namespaces\n const globalUsedUtilityTypes = namespaceData.reduce(\n (acc, ns) => ({\n Timestamp: acc.Timestamp || ns.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || ns.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n const utilityTypeImports: string[] = [\"type Generated\"];\n if (globalUsedUtilityTypes.Timestamp) {\n utilityTypeImports.push(\"type Timestamp\");\n }\n const hasObjectColumnType = namespaceData.some((ns) =>\n ns.types.some((t) => t.typeDef.includes(\"ObjectColumnType<\")),\n );\n if (hasObjectColumnType) {\n utilityTypeImports.push(\"type ObjectColumnType\");\n }\n const hasArrayColumnType = namespaceData.some((ns) =>\n ns.types.some((t) => t.typeDef.includes(\"ArrayColumnType<\")),\n );\n if (hasArrayColumnType) {\n utilityTypeImports.push(\"type ArrayColumnType\");\n }\n if (globalUsedUtilityTypes.Serial) {\n utilityTypeImports.push(\"type Serial\");\n }\n\n const importsSection = multiline /* ts */ `\n import {\n createGetDB,\n ${utilityTypeImports.join(\",\\n\")},\n type NamespaceDB,\n type NamespaceInsertable,\n type NamespaceSelectable,\n type NamespaceTable,\n type NamespaceTableName,\n type NamespaceTransaction,\n type NamespaceUpdateable,\n } from \"@tailor-platform/sdk/kysely\";\n `;\n\n // Generate Namespace interface with multiple namespaces\n const namespaceInterfaces = namespaceData\n .map(({ namespace, types }) => {\n const typeDefsWithIndent = types\n .map((type) => {\n return type.typeDef\n .split(\"\\n\")\n .map((line) => (line.trim() ? ` ${line}` : \"\"))\n .join(\"\\n\");\n })\n .join(\"\\n\\n\");\n\n return ` \"${namespace}\": {\\n${typeDefsWithIndent}\\n }`;\n })\n .join(\",\\n\");\n\n const namespaceInterface = `export interface Namespace {\\n${namespaceInterfaces}\\n}`;\n\n const getDBFunction = multiline /* ts */ `\n export const getDB = createGetDB<Namespace>();\n\n export type DB<N extends keyof Namespace = keyof Namespace> = NamespaceDB<Namespace, N>;\n `;\n\n const utilityTypeExports = multiline /* ts */ `\n export type Transaction<K extends keyof Namespace | DB = keyof Namespace> =\n NamespaceTransaction<Namespace, K>;\n\n type TableName = NamespaceTableName<Namespace>;\n export type Table<T extends TableName> = NamespaceTable<Namespace, T>;\n\n export type Insertable<T extends TableName> = NamespaceInsertable<Namespace, T>;\n export type Selectable<T extends TableName> = NamespaceSelectable<Namespace, T>;\n export type Updateable<T extends TableName> = NamespaceUpdateable<Namespace, T>;\n `;\n\n return (\n [importsSection, namespaceInterface, getDBFunction, utilityTypeExports].join(\"\\n\\n\") + \"\\n\"\n );\n}\n","import { processKyselyType, generateUnifiedKyselyTypes } from \"./type-processor\";\nimport type { KyselyTypeMetadata, KyselyNamespaceMetadata } from \"./types\";\nimport type { Plugin, GeneratorResult, TailorDBReadyContext } from \"@/plugin/types\";\n\n/** Unique identifier for the Kysely type generator plugin. */\nexport const KyselyGeneratorID = \"@tailor-platform/kysely-type\";\n\ntype KyselyTypePluginOptions = {\n distPath: string;\n};\n\n/**\n * Plugin that generates Kysely type definitions for TailorDB types.\n * @param options - Plugin options\n * @param options.distPath - Output file path for generated types\n * @returns Plugin instance with onTailorDBReady hook\n */\nexport function kyselyTypePlugin(\n options: KyselyTypePluginOptions,\n): Plugin<unknown, KyselyTypePluginOptions> {\n return {\n id: KyselyGeneratorID,\n description: \"Generates Kysely type definitions for TailorDB types\",\n pluginConfig: options,\n\n async onTailorDBReady(\n ctx: TailorDBReadyContext<KyselyTypePluginOptions>,\n ): Promise<GeneratorResult> {\n const allNamespaceData: KyselyNamespaceMetadata[] = [];\n\n for (const ns of ctx.tailordb) {\n const typeMetadataList: KyselyTypeMetadata[] = [];\n\n for (const type of Object.values(ns.types)) {\n const metadata = await processKyselyType(type);\n typeMetadataList.push(metadata);\n }\n\n if (typeMetadataList.length === 0) continue;\n\n const usedUtilityTypes = typeMetadataList.reduce(\n (acc, type) => ({\n Timestamp: acc.Timestamp || type.usedUtilityTypes.Timestamp,\n Serial: acc.Serial || type.usedUtilityTypes.Serial,\n }),\n { Timestamp: false, Serial: false },\n );\n\n allNamespaceData.push({\n namespace: ns.namespace,\n types: typeMetadataList,\n usedUtilityTypes,\n });\n }\n\n const files: GeneratorResult[\"files\"] = [];\n if (allNamespaceData.length > 0) {\n const content = generateUnifiedKyselyTypes(allNamespaceData);\n files.push({\n path: ctx.pluginConfig.distPath,\n content,\n });\n }\n\n return { files };\n },\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mock-DMgIygjE.mjs","names":["#fromEncoding","#toEncoding"],"sources":["../src/vitest/mock.ts"],"sourcesContent":["/**\n * Mock controls for Tailor Platform APIs (vitest).\n *\n * Each `xMock()` factory installs `vi.fn()`-backed mocks for one platform\n * namespace onto `globalThis` when acquired, and restores the previous value\n * when the `using` scope exits. State lives in the per-acquisition vi.fns /\n * closures — there is no shared global state bag — so nested/sequential scopes\n * are isolated and namespaces never interfere with each other.\n *\n * Acquire a mock with a `using` declaration:\n *\n * ```ts\n * test(\"...\", () => {\n * using wf = mockWorkflow();\n * wf.setJobHandler(() => ({ ok: true }));\n * }); // previous workflow mock restored here\n * ```\n *\n * The friendly helpers (`setJobHandler`, `enqueueResult`, `triggeredJobs`, …)\n * are thin wrappers over the underlying vi.fns, which are also exposed directly\n * (`wf.triggerJobFunction`) for native matchers like\n * `expect(wf.triggerJobFunction).toHaveBeenCalledWith(...)`.\n */\n\nimport { type Mock, vi } from \"vitest\";\nimport {\n getRegisteredJob,\n getRegisteredWorkflow,\n TRIGGER_DEFAULT,\n} from \"@/configure/services/workflow/registry\";\nimport { assertDefined } from \"@/utils/assert\";\nimport { platformSerialize } from \"@/utils/test/platform-serialize\";\nimport {\n buildJobContext,\n clearWorkflowTestEnv,\n writeWorkflowTestEnv,\n} from \"../configure/services/workflow/test-env-key\";\nimport type { User as IdpUser } from \"../runtime/idp\";\nimport type { TailorEnv } from \"../types/env\";\n\nexport { RUNTIME_FLAG_KEY } from \"./globals\";\n\n// Re-export the base globals install/cleanup under their historical names so\n// non-environment tests (which run in the plain `node` environment) can set up\n// the base platform surface — `globalThis.tailor`, error classes — themselves.\nexport {\n installPlatformGlobals as injectMocks,\n cleanupPlatformGlobals as cleanupMocks,\n} from \"./globals\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype QueryResolver = (query: string, params: unknown[]) => unknown[];\ntype JobHandler = (jobName: string, args: unknown) => unknown;\ntype IdpResolver = (method: string, args: unknown[], namespace: string) => unknown;\ntype FileResolver = (method: string, call: FileCall) => unknown;\ntype IconvResolver = (method: string, args: unknown[]) => unknown;\n\ntype TriggerWorkflowOptions = {\n authInvoker?: { namespace: string; machineUserName: string };\n};\ntype TriggerHandlerFn = (\n workflowName: string,\n args: unknown,\n options?: TriggerWorkflowOptions,\n) => string;\ntype WaitHandlerFn = (key: string, payload: unknown) => unknown;\ntype ResolveHandler = (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n) => unknown | Promise<unknown>;\n\n// Overloaded so TypeScript narrows to WaitHandlerFn first (giving inferred\n// `(key: string, payload: unknown) => …` for callers) before falling back\n// to the static-value form. A union type would let `unknown` swallow the\n// function variant and break inference.\ntype SetWaitHandler = {\n (handler: WaitHandlerFn): void;\n (handler: unknown): void;\n};\n\ninterface ExecutedQuery {\n query: string;\n params: unknown[];\n}\n\ninterface CreatedClient {\n namespace: string | undefined;\n ended: boolean;\n}\n\ninterface TriggeredJob {\n jobName: string;\n args: unknown;\n}\n\ninterface SecretCall {\n method: \"getSecret\" | \"getSecrets\";\n vault: string;\n name?: string;\n names?: readonly string[];\n}\n\ninterface AuthConnectionCall {\n connectionName: string;\n}\n\ninterface IdpCall {\n method: string;\n args: unknown[];\n namespace: string;\n}\n\ninterface FileCall {\n method: string;\n namespace: string;\n typeName: string;\n fieldName: string;\n recordId: string;\n}\n\ninterface IconvCall {\n method: string;\n args: unknown[];\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n// Attach a non-enumerable `Symbol.dispose` to a facade so it works with `using`.\nfunction withDispose<T extends object>(facade: T, dispose: () => void): T & Disposable {\n Object.defineProperty(facade, Symbol.dispose, {\n value: dispose,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n return facade as T & Disposable;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction tailorRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailor) {\n // Ensure the container (and the always-present context stub) exists even if\n // the base globals were not installed (e.g. a unit test that only acquires\n // a single mock without the tailor-runtime environment).\n g.tailor = { context: { getInvoker: () => null } };\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailor as Record<string, any>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction tailordbRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailordb) {\n g.tailordb = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailordb as Record<string, any>;\n}\n\nclass MockQueryResult {\n command: string;\n rowCount: number;\n rows: unknown[];\n\n constructor(rows: unknown[]) {\n this.command = \"\";\n this.rowCount = rows.length;\n this.rows = rows;\n }\n}\n\n// ---------------------------------------------------------------------------\n// TailorDB Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for TailorDB operations. Installs a mock\n * `tailordb.Client` whose `queryObject` is a shared `vi.fn()` (so query\n * responses can be staged before the client is constructed). Restored on\n * dispose.\n * @returns Disposable TailorDB mock control object\n * @example\n * ```typescript\n * import { mockTailordb } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"order-based\", async () => {\n * using db = mockTailordb();\n * db.enqueueResults([], [{ age: 30 }], []); // BEGIN / SELECT / COMMIT\n * // …\n * expect(db.queryObject).toHaveBeenCalledTimes(3);\n * expect(db.Client).toHaveBeenCalledWith({ namespace: \"tailordb\" });\n * });\n * ```\n */\nexport function mockTailordb() {\n const root = tailordbRoot();\n const prevClient = root.Client;\n\n const queryObject = vi.fn(\n async (_query: string, _params: unknown[] = []): Promise<MockQueryResult> =>\n new MockQueryResult([]),\n );\n const connect = vi.fn(async (): Promise<void> => {});\n const createdClients: CreatedClient[] = [];\n\n const Client = vi.fn(function (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this: any,\n config?: { namespace?: string },\n ) {\n const record: CreatedClient = { namespace: config?.namespace, ended: false };\n createdClients.push(record);\n this.connect = connect;\n this.end = vi.fn(async (): Promise<void> => {\n record.ended = true;\n });\n this.queryObject = queryObject;\n this.createTransaction = (name: string) => {\n if (!name) {\n throw new Error(\"Transaction name must be a non-empty string\");\n }\n return {\n begin: async (): Promise<void> => {},\n commit: async (): Promise<void> => {},\n rollback: async (): Promise<void> => {},\n queryObject,\n };\n };\n });\n\n root.Client = Client;\n\n const facade = {\n /** The mock `tailordb.Client` constructor (`vi.fn`). */\n Client,\n /** The shared `queryObject` `vi.fn` used by every client and transaction. */\n queryObject,\n\n /**\n * Set a fallback query resolver. Called when the enqueue queue is empty.\n * @param resolver - Function that returns rows for a given query and params\n */\n setQueryResolver(resolver: QueryResolver): void {\n queryObject.mockImplementation(\n async (query: string, params: unknown[] = []) =>\n // user resolvers may return undefined\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n new MockQueryResult(resolver(query, params) ?? []),\n );\n },\n\n /**\n * Enqueue rows for the next `queryObject` call (FIFO; takes priority over\n * `setQueryResolver`). Call with no arguments for an empty result.\n * @param rows - Row objects to return from the next `queryObject` call\n */\n enqueueResult(...rows: unknown[]): void {\n queryObject.mockImplementationOnce(async () => new MockQueryResult(rows));\n },\n\n /**\n * Enqueue rows for multiple subsequent `queryObject` calls (FIFO).\n * @param rowsList - Rows arrays, one per upcoming query\n */\n enqueueResults(...rowsList: unknown[][]): void {\n for (const rows of rowsList) {\n queryObject.mockImplementationOnce(async () => new MockQueryResult(rows));\n }\n },\n\n /**\n * All queries executed via `queryObject`, in order, derived from the vi.fn\n * call records.\n * @returns Executed queries array\n */\n get executedQueries(): ExecutedQuery[] {\n return queryObject.mock.calls.map(([query, params]) => ({\n query: query as string,\n // vitest records an omitted argument as undefined\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n params: (params as unknown[]) ?? [],\n }));\n },\n\n /**\n * All TailorDB clients created, with their namespace and end state.\n * @returns Created clients array\n */\n get createdClients(): CreatedClient[] {\n return createdClients;\n },\n\n /** Reset query responses and recorded calls (keeps the mock installed). */\n reset(): void {\n queryObject.mockReset();\n queryObject.mockImplementation(async () => new MockQueryResult([]));\n connect.mockClear();\n Client.mockClear();\n createdClients.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.Client = prevClient;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Workflow Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for workflow operations (`tailor.workflow`).\n * Restored on dispose.\n * @returns Disposable workflow mock control object\n * @example\n * ```typescript\n * import { mockWorkflow } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"job handler\", async () => {\n * using wf = mockWorkflow();\n * wf.setJobHandler((name) => (name === \"validate\" ? { valid: true } : null));\n * await runWorkflowUnderTest(); // calls tailor.workflow.triggerJobFunction(\"validate\", {})\n * expect(wf.triggerJobFunction).toHaveBeenCalledWith(\"validate\", {});\n * });\n * ```\n */\nexport function mockWorkflow() {\n const root = tailorRoot();\n const prev = root.workflow;\n\n // Default impls (also restored by reset): run the registered body by name so a\n // `.trigger()` with no handler/result executes the real job locally.\n const defaultTriggerJob = (jobName: string, args?: unknown): unknown => {\n const body = getRegisteredJob(jobName);\n return body ? body(args, buildJobContext()) : null;\n };\n const defaultTriggerWorkflow = async (\n workflowName: string,\n args?: unknown,\n _options?: TriggerWorkflowOptions,\n ): Promise<string> => {\n const wf = getRegisteredWorkflow(workflowName);\n if (wf) await installedTriggerJobFunction(wf.mainJobName, args);\n return TRIGGER_DEFAULT;\n };\n\n // Inner vi.fns hold the overridable behavior + call recording; the installed\n // shims below cross the platform JSON boundary (serialize args + results) once\n // so every path (default body, setJobHandler, enqueueResult) is covered.\n const triggerJobFunction = vi.fn(defaultTriggerJob);\n const triggerWorkflow = vi.fn(defaultTriggerWorkflow);\n const wait = vi.fn((_key: string, _payload?: unknown): unknown => null);\n const resolve = vi.fn(\n async (\n _executionId: string,\n _key: string,\n _callback: (payload: unknown) => unknown,\n ): Promise<void> => {},\n );\n\n const installedTriggerJobFunction = (jobName: string, args?: unknown): unknown => {\n const out = triggerJobFunction(jobName, platformSerialize(args));\n return out instanceof Promise ? out.then((v) => platformSerialize(v)) : platformSerialize(out);\n };\n\n root.workflow = {\n triggerJobFunction: installedTriggerJobFunction,\n // Preserve arity so a forwarded third `options` arg — even `undefined` — is\n // recorded, matching the real `.trigger(args, options)` call shape.\n triggerWorkflow: (...call: [string, unknown?, TriggerWorkflowOptions?]) =>\n call.length >= 3\n ? triggerWorkflow(call[0], platformSerialize(call[1]), call[2])\n : triggerWorkflow(call[0], platformSerialize(call[1])),\n wait: (key: string, payload?: unknown) => wait(key, platformSerialize(payload)),\n resolve: (executionId: string, key: string, callback: (payload: unknown) => unknown) =>\n resolve(executionId, key, (payload: unknown) => {\n const out = callback(payload);\n return out instanceof Promise\n ? out.then((v) => platformSerialize(v))\n : platformSerialize(out);\n }),\n };\n\n const facade = {\n /** The `triggerJobFunction` `vi.fn`. */\n triggerJobFunction,\n /** The `triggerWorkflow` `vi.fn`. */\n triggerWorkflow,\n /** The `wait` `vi.fn`. */\n wait,\n /** The `resolve` `vi.fn`. */\n resolve,\n\n /**\n * Set a fallback job handler. Called when the enqueue queue is empty.\n * @param handler - Function returning a result for a job name and args\n */\n setJobHandler(handler: JobHandler): void {\n triggerJobFunction.mockImplementation((name, args) => handler(name, args));\n },\n\n /**\n * Enqueue a single result for the next `triggerJobFunction` call (FIFO;\n * takes priority over `setJobHandler`).\n * @param result - Result to return from the next call\n */\n enqueueResult(result: unknown): void {\n triggerJobFunction.mockImplementationOnce(() => result);\n },\n\n /**\n * Enqueue results for multiple subsequent `triggerJobFunction` calls (FIFO).\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n for (const result of results) {\n triggerJobFunction.mockImplementationOnce(() => result);\n }\n },\n\n /**\n * All jobs triggered via `triggerJobFunction`, in order.\n * @returns Triggered jobs array\n */\n get triggeredJobs(): TriggeredJob[] {\n return triggerJobFunction.mock.calls.map(([jobName, args]) => ({\n jobName: jobName as string,\n args,\n }));\n },\n\n /**\n * Configure what `triggerWorkflow` returns. Pass a string (same id every\n * call) or `(name, args, options) => string`. Default: a placeholder UUID.\n * @param handler - Static execution ID or a function returning one\n */\n setTriggerHandler(handler: string | TriggerHandlerFn): void {\n triggerWorkflow.mockImplementation(\n typeof handler === \"function\"\n ? async (name, args, options) => handler(name, args, options)\n : async () => handler,\n );\n },\n\n /**\n * Configure what `wait` returns. Pass `(key, payload) => unknown` or any\n * other value to return it for every call. Default: `null`.\n * @param handler - Static value or a function returning one\n */\n setWaitHandler: ((handler: unknown) => {\n wait.mockImplementation(\n typeof handler === \"function\"\n ? (key, payload) => (handler as WaitHandlerFn)(key, payload)\n : () => handler,\n );\n }) as SetWaitHandler,\n\n /**\n * Set the `env` passed to job bodies invoked via `createWorkflowJob().trigger()`.\n * Cleared on dispose / reset.\n * @param env - Env passed to job bodies.\n */\n setEnv(env: TailorEnv): void {\n writeWorkflowTestEnv({ ...env });\n },\n\n /**\n * Configure how `resolve` runs the user-supplied callback. Default: callback\n * is not invoked (records the call only).\n * @param handler - Function invoked per `resolve` call\n */\n setResolveHandler(handler: ResolveHandler): void {\n resolve.mockImplementation(async (executionId, key, callback) => {\n await handler(executionId, key, callback);\n });\n },\n\n /**\n * `wait` calls reshaped as `{ key, payload }` for assertions.\n * @returns Wait call records\n */\n get waitCalls(): { key: string; payload: unknown }[] {\n return wait.mock.calls.map(([key, payload]) => ({ key: key as string, payload }));\n },\n\n /**\n * `resolve` calls reshaped as `{ executionId, key }` for assertions.\n * @returns Resolve call records\n */\n get resolveCalls(): { executionId: string; key: string }[] {\n return resolve.mock.calls.map(([executionId, key]) => ({\n executionId: executionId as string,\n key: key as string,\n }));\n },\n\n /** Reset all workflow responses and recorded calls (keeps the mock installed). */\n reset(): void {\n triggerJobFunction.mockReset();\n triggerJobFunction.mockImplementation(defaultTriggerJob);\n triggerWorkflow.mockReset();\n triggerWorkflow.mockImplementation(defaultTriggerWorkflow);\n wait.mockReset();\n wait.mockImplementation(() => null);\n resolve.mockReset();\n resolve.mockImplementation(async () => {});\n clearWorkflowTestEnv();\n },\n };\n\n return withDispose(facade, () => {\n root.workflow = prev;\n clearWorkflowTestEnv();\n });\n}\n\n// ---------------------------------------------------------------------------\n// SecretManager Mock\n// ---------------------------------------------------------------------------\n\n// Hidden accessor key used to inherit the previous scope's secret store on\n// acquisition (so secrets seeded once outside tests — e.g. from tailor.config.ts\n// via setup.ts — remain visible) while still isolating per-test overrides.\nconst SECRET_STORE = Symbol(\"tailorSecretStore\");\n\n/**\n * Acquire a disposable mock for `tailor.secretmanager`. The secret store is\n * inherited (cloned) from the currently-installed mock on acquisition and\n * restored on dispose, so secrets seeded outside the test survive across\n * `using` scopes while per-test `setSecrets()` overrides stay isolated.\n * @returns Disposable SecretManager mock control object\n * @example\n * ```typescript\n * import { mockSecretmanager } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"reads secrets from vault\", async () => {\n * using sm = mockSecretmanager();\n * sm.setSecrets({ \"my-vault\": { API_KEY: \"sk-123\" } });\n * // …\n * });\n * ```\n */\nexport function mockSecretmanager() {\n const root = tailorRoot();\n const prev = root.secretmanager;\n\n const holder: { store: Record<string, Record<string, string>> } = {\n // prior mock state may be absent\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n store: structuredClone((prev?.[SECRET_STORE]?.store as typeof holder.store) ?? {}),\n };\n\n const getSecret = vi.fn(\n async (vault: string, name: string): Promise<string | undefined> => holder.store[vault]?.[name],\n );\n const getSecrets = vi.fn(\n async <const T extends readonly string[]>(\n vault: string,\n names: T,\n ): Promise<Partial<Record<T[number], string>>> => {\n const vaultData = holder.store[vault] ?? {};\n const result: Record<string, string> = {};\n for (const name of names) {\n if (name in vaultData) {\n result[name] = assertDefined(vaultData[name], `vault entry missing for: ${name}`);\n }\n }\n return result as Partial<Record<T[number], string>>;\n },\n );\n\n root.secretmanager = { getSecret, getSecrets, [SECRET_STORE]: holder };\n\n const facade = {\n /** The `getSecret` `vi.fn`. */\n getSecret,\n /** The `getSecrets` `vi.fn`. */\n getSecrets,\n\n setSecrets(secrets: Record<string, Record<string, string>>): void {\n holder.store = secrets;\n },\n\n get calls(): SecretCall[] {\n // Merge both methods' calls back into chronological order via vi.fn's\n // global invocationCallOrder, so a test mixing getSecret/getSecrets sees\n // them in the order they actually ran (not all getSecret, then all getSecrets).\n const entries: { order: number; call: SecretCall }[] = [\n ...getSecret.mock.calls.map((args, i) => ({\n order: getSecret.mock.invocationCallOrder[i] ?? 0,\n call: { method: \"getSecret\" as const, vault: args[0] as string, name: args[1] as string },\n })),\n ...getSecrets.mock.calls.map((args, i) => ({\n order: getSecrets.mock.invocationCallOrder[i] ?? 0,\n call: {\n method: \"getSecrets\" as const,\n vault: args[0] as string,\n names: args[1] as readonly string[],\n },\n })),\n ];\n return entries.toSorted((a, b) => a.order - b.order).map((e) => e.call);\n },\n\n reset(): void {\n holder.store = {};\n getSecret.mockClear();\n getSecrets.mockClear();\n },\n };\n\n return withDispose(facade, () => {\n root.secretmanager = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// AuthConnection Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for `tailor.authconnection`. Restored on dispose.\n * @returns Disposable AuthConnection mock control object\n * @example\n * ```typescript\n * import { mockAuthconnection } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"returns configured token\", async () => {\n * using ac = mockAuthconnection();\n * ac.setTokens({ google: { access_token: \"ya29.xxx\" } });\n * // …\n * });\n * ```\n */\nexport function mockAuthconnection() {\n const root = tailorRoot();\n const prev = root.authconnection;\n\n let tokens: Record<string, unknown> = {};\n const getConnectionToken = vi.fn(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (connectionName: string): Promise<any> =>\n tokens[connectionName] ?? { access_token: \"mock-token\" },\n );\n\n root.authconnection = { getConnectionToken };\n\n const facade = {\n /** The `getConnectionToken` `vi.fn`. */\n getConnectionToken,\n\n setTokens(value: Record<string, unknown>): void {\n tokens = value;\n },\n\n get calls(): AuthConnectionCall[] {\n return getConnectionToken.mock.calls.map(([connectionName]) => ({\n connectionName: connectionName as string,\n }));\n },\n\n reset(): void {\n tokens = {};\n getConnectionToken.mockClear();\n },\n };\n\n return withDispose(facade, () => {\n root.authconnection = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// IDP Mock\n// ---------------------------------------------------------------------------\n\nconst IDP_DEFAULTS: Record<string, unknown> = {\n users: { users: [], nextPageToken: null, totalCount: 0 },\n user: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n userByName: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n createUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n updateUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n deleteUser: true,\n sendPasswordResetEmail: true,\n};\n\n/**\n * Acquire a disposable mock for `tailor.idp`. Restored on dispose.\n * @returns Disposable IDP mock control object\n * @example\n * ```typescript\n * import { mockIdp } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"resolver-based\", async () => {\n * using idp = mockIdp();\n * idp.setResolver((method) =>\n * method === \"user\" ? { id: \"u-1\", name: \"alice\", disabled: false } : null,\n * );\n * // …\n * });\n * ```\n */\nexport function mockIdp() {\n const root = tailorRoot();\n const prev = root.idp;\n\n const queue: unknown[] = [];\n let resolver: IdpResolver = () => null;\n const calls: IdpCall[] = [];\n\n function handle(method: string, args: unknown[], namespace: string): unknown {\n calls.push({ method, args, namespace });\n if (queue.length > 0) return queue.shift();\n const resolved = resolver(method, args, namespace);\n // Treat null and undefined alike as \"no override\".\n if (resolved != null) return resolved;\n // Clone the default so a test mutating the returned value cannot corrupt\n // the shared module-level object for subsequent tests.\n const fallback = IDP_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n }\n\n const Client = vi.fn(function (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this: any,\n config: { namespace: string },\n ) {\n const namespace = config.namespace;\n this.users = async (options?: unknown) => handle(\"users\", [options], namespace);\n this.user = async (userId: string) => handle(\"user\", [userId], namespace);\n this.userByName = async (name: string) => handle(\"userByName\", [name], namespace);\n this.createUser = async (input: unknown) => handle(\"createUser\", [input], namespace);\n this.updateUser = async (input: unknown) => handle(\"updateUser\", [input], namespace);\n this.deleteUser = async (userId: string) => handle(\"deleteUser\", [userId], namespace);\n this.sendPasswordResetEmail = async (input: unknown) =>\n handle(\"sendPasswordResetEmail\", [input], namespace);\n }) as unknown as new (config: { namespace: string }) => {\n users(options?: {\n first?: number;\n after?: string;\n query?: { ids?: string[]; names?: string[] };\n }): Promise<{ users: IdpUser[]; nextPageToken: string | null; totalCount: number }>;\n user(userId: string): Promise<IdpUser>;\n userByName(name: string): Promise<IdpUser>;\n createUser(input: { name: string; password?: string; disabled?: boolean }): Promise<IdpUser>;\n updateUser(input: {\n id: string;\n name?: string;\n password?: string;\n clearPassword?: boolean;\n disabled?: boolean;\n }): Promise<IdpUser>;\n deleteUser(userId: string): Promise<boolean>;\n sendPasswordResetEmail(input: { userId: string; redirectUri: string }): Promise<boolean>;\n };\n\n root.idp = { Client };\n\n const facade = {\n /** The mock IDP `Client` constructor (`vi.fn`). */\n Client: Client as unknown as Mock,\n\n setResolver(value: IdpResolver): void {\n resolver = value;\n },\n\n /**\n * Enqueue a single result for the next IDP call (FIFO; falls back to\n * `setResolver` when exhausted).\n * @param result - Result to return from the next IDP call\n */\n enqueueResult(result: unknown): void {\n queue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent IDP calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n queue.push(...results);\n },\n\n get calls(): IdpCall[] {\n return calls;\n },\n\n reset(): void {\n queue.length = 0;\n resolver = () => null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.idp = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Iconv Mock\n// ---------------------------------------------------------------------------\n\n// Iconv methods return `string` for UTF-8 target encodings and `Uint8Array`\n// for any other byte-producing encoding (the platform API mirrors this).\nfunction isUtf8(encoding: unknown): boolean {\n return encoding === \"UTF8\" || encoding === \"UTF-8\";\n}\n\nfunction defaultIconvResult(method: string, args: unknown[]): unknown {\n switch (method) {\n case \"convert\":\n case \"convertBuffer\":\n return isUtf8(args[2]) ? \"\" : new Uint8Array();\n case \"decode\":\n return \"\";\n case \"encode\":\n return isUtf8(args[1]) ? \"\" : new Uint8Array();\n case \"encodings\":\n return [];\n default:\n return undefined;\n }\n}\n\n/**\n * Acquire a disposable mock for `tailor.iconv`. Restored on dispose.\n * @returns Disposable Iconv mock control object\n * @example\n * ```typescript\n * import { mockIconv } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"mock encoding conversion\", () => {\n * using iconv = mockIconv();\n * iconv.setResolver((method) => (method === \"decode\" ? \"decoded-text\" : null));\n * // …\n * });\n * ```\n */\nexport function mockIconv() {\n const root = tailorRoot();\n const prev = root.iconv;\n\n let resolver: IconvResolver | null = null;\n const calls: IconvCall[] = [];\n\n function handle(method: string, args: unknown[]): unknown {\n calls.push({ method, args: [...args] });\n if (resolver) {\n const result = resolver(method, args);\n if (result != null) return result;\n }\n return defaultIconvResult(method, args);\n }\n\n class MockIconv {\n #fromEncoding: string;\n #toEncoding: string;\n constructor(fromEncoding: string, toEncoding: string) {\n this.#fromEncoding = fromEncoding;\n this.#toEncoding = toEncoding;\n }\n convert(input: string | Uint8Array | ArrayBuffer): string | Uint8Array {\n return handle(\"convert\", [input, this.#fromEncoding, this.#toEncoding]) as\n | string\n | Uint8Array;\n }\n }\n\n root.iconv = {\n convert: (str: unknown, from: string, to: string) => handle(\"convert\", [str, from, to]),\n convertBuffer: (buf: unknown, from: string, to: string) =>\n handle(\"convertBuffer\", [buf, from, to]),\n decode: (buf: unknown, encoding: string) => handle(\"decode\", [buf, encoding]),\n encode: (str: string, encoding: string) => handle(\"encode\", [str, encoding]),\n encodings: () => handle(\"encodings\", []),\n Iconv: MockIconv,\n };\n\n const facade = {\n setResolver(value: IconvResolver): void {\n resolver = value;\n },\n\n get calls(): IconvCall[] {\n return calls;\n },\n\n reset(): void {\n resolver = null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.iconv = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// File Mock (tailordb.file)\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst FILE_DEFAULTS: Record<string, any> = {\n upload: { metadata: { fileSize: 0, sha256sum: \"\" } },\n download: {\n data: new Uint8Array(),\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n downloadAsBase64: {\n data: \"\",\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n delete: undefined,\n getMetadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", urlPath: \"\" },\n downloadStream: null,\n uploadStream: { metadata: { fileSize: 0, sha256sum: \"\" } },\n};\n\ntype FileStream = AsyncIterableIterator<unknown> & { close(): Promise<void> };\n\nfunction toFileStream(value: unknown): FileStream {\n if (\n value !== null &&\n typeof value === \"object\" &&\n Symbol.asyncIterator in value &&\n typeof (value as { close?: unknown }).close === \"function\"\n ) {\n return value as FileStream;\n }\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n throw new TypeError(\n \"openDownloadStream expects an iterable of StreamValue items \" +\n '(e.g. [{ type: \"chunk\", data, position }, { type: \"complete\" }]); ' +\n \"got raw bytes. Wrap the bytes in a structured chunk first.\",\n );\n }\n if (\n value !== null &&\n typeof value === \"object\" &&\n (Symbol.iterator in value || Symbol.asyncIterator in value)\n ) {\n const source = value as Iterable<unknown> | AsyncIterable<unknown>;\n const inner =\n Symbol.asyncIterator in source\n ? (source as AsyncIterable<unknown>)[Symbol.asyncIterator]()\n : (source as Iterable<unknown>)[Symbol.iterator]();\n const stream: FileStream = {\n async next() {\n const r = await inner.next();\n if (!r.done) {\n assertStreamValue(r.value);\n }\n return r.done ? { done: true as const, value: undefined } : r;\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return stream;\n },\n };\n return stream;\n }\n const empty: FileStream = {\n async next() {\n return { done: true as const, value: undefined };\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return empty;\n },\n };\n return empty;\n}\n\nfunction assertStreamValue(v: unknown): void {\n if (v === null || typeof v !== \"object\") {\n throw new TypeError(\n 'openDownloadStream expected a StreamValue item ({ type: \"metadata\" | \"chunk\" | \"complete\", ... }); ' +\n `got ${typeof v === \"object\" ? \"null\" : typeof v}.`,\n );\n }\n if (v instanceof ArrayBuffer || ArrayBuffer.isView(v)) {\n throw new TypeError(\n \"openDownloadStream expected a StreamValue item, got raw bytes. \" +\n 'Wrap the bytes in a structured chunk first (e.g. { type: \"chunk\", data, position }).',\n );\n }\n const type = (v as { type?: unknown }).type;\n if (type !== \"metadata\" && type !== \"chunk\" && type !== \"complete\") {\n throw new TypeError(\n 'openDownloadStream expected a StreamValue item with type \"metadata\" | \"chunk\" | \"complete\"; ' +\n `got ${JSON.stringify(type)}.`,\n );\n }\n}\n\n/**\n * Acquire a disposable mock for `tailordb.file`. Restored on dispose.\n * @returns Disposable File mock control object\n * @example\n * ```typescript\n * import { mockFile } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"mock file download\", async () => {\n * using file = mockFile();\n * file.enqueueResult({ data: new Uint8Array([1, 2, 3]), metadata: { ... } });\n * // …\n * });\n * ```\n */\nexport function mockFile() {\n const root = tailordbRoot();\n const prev = root.file;\n\n const queue: unknown[] = [];\n let resolver: FileResolver = () => null;\n const calls: FileCall[] = [];\n\n function handle(\n method: string,\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): unknown {\n const call: FileCall = { method, namespace, typeName, fieldName, recordId };\n calls.push(call);\n if (queue.length > 0) return queue.shift();\n const resolved = resolver(method, call);\n if (resolved != null) return resolved;\n const fallback = FILE_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n }\n\n root.file = {\n async upload(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"upload\", namespace, typeName, fieldName, recordId);\n },\n async download(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"download\", namespace, typeName, fieldName, recordId);\n },\n async downloadAsBase64(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ) {\n return handle(\"downloadAsBase64\", namespace, typeName, fieldName, recordId);\n },\n async delete(namespace: string, typeName: string, fieldName: string, recordId: string) {\n handle(\"delete\", namespace, typeName, fieldName, recordId);\n },\n async getMetadata(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"getMetadata\", namespace, typeName, fieldName, recordId);\n },\n async openDownloadStream(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ) {\n return toFileStream(handle(\"openDownloadStream\", namespace, typeName, fieldName, recordId));\n },\n async downloadStream(namespace: string, typeName: string, fieldName: string, recordId: string) {\n const resolved = handle(\"downloadStream\", namespace, typeName, fieldName, recordId);\n if (resolved != null) return resolved;\n return {\n body: new ReadableStream({\n start(c) {\n c.close();\n },\n }),\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n };\n },\n async uploadStream(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"uploadStream\", namespace, typeName, fieldName, recordId);\n },\n };\n\n const facade = {\n setResolver(value: FileResolver): void {\n resolver = value;\n },\n\n /**\n * Enqueue a single result for the next `tailordb.file` call (FIFO; falls\n * back to `setResolver` when exhausted).\n * @param result - Result to return from the next file call\n */\n enqueueResult(result: unknown): void {\n queue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent `tailordb.file` calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n queue.push(...results);\n },\n\n get calls(): FileCall[] {\n return calls;\n },\n\n reset(): void {\n queue.length = 0;\n resolver = () => null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.file = prev;\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mock-DMgIygjE.mjs","names":["#fromEncoding","#toEncoding"],"sources":["../src/vitest/mock.ts"],"sourcesContent":["/**\n * Mock controls for Tailor Platform APIs (vitest).\n *\n * Each `xMock()` factory installs `vi.fn()`-backed mocks for one platform\n * namespace onto `globalThis` when acquired, and restores the previous value\n * when the `using` scope exits. State lives in the per-acquisition vi.fns /\n * closures — there is no shared global state bag — so nested/sequential scopes\n * are isolated and namespaces never interfere with each other.\n *\n * Acquire a mock with a `using` declaration:\n *\n * ```ts\n * test(\"...\", () => {\n * using wf = mockWorkflow();\n * wf.setJobHandler(() => ({ ok: true }));\n * }); // previous workflow mock restored here\n * ```\n *\n * The friendly helpers (`setJobHandler`, `enqueueResult`, `triggeredJobs`, …)\n * are thin wrappers over the underlying vi.fns, which are also exposed directly\n * (`wf.triggerJobFunction`) for native matchers like\n * `expect(wf.triggerJobFunction).toHaveBeenCalledWith(...)`.\n */\n\nimport { type Mock, vi } from \"vitest\";\nimport {\n getRegisteredJob,\n getRegisteredWorkflow,\n TRIGGER_DEFAULT,\n} from \"@/configure/services/workflow/registry\";\nimport { assertDefined } from \"@/utils/assert\";\nimport { platformSerialize } from \"@/utils/test/platform-serialize\";\nimport {\n buildJobContext,\n clearWorkflowTestEnv,\n writeWorkflowTestEnv,\n} from \"../configure/services/workflow/test-env-key\";\nimport type { User as IdpUser } from \"../runtime/idp\";\nimport type { TailorEnv } from \"@/runtime/types\";\n\nexport { RUNTIME_FLAG_KEY } from \"./globals\";\n\n// Re-export the base globals install/cleanup under their historical names so\n// non-environment tests (which run in the plain `node` environment) can set up\n// the base platform surface — `globalThis.tailor`, error classes — themselves.\nexport {\n installPlatformGlobals as injectMocks,\n cleanupPlatformGlobals as cleanupMocks,\n} from \"./globals\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype QueryResolver = (query: string, params: unknown[]) => unknown[];\ntype JobHandler = (jobName: string, args: unknown) => unknown;\ntype IdpResolver = (method: string, args: unknown[], namespace: string) => unknown;\ntype FileResolver = (method: string, call: FileCall) => unknown;\ntype IconvResolver = (method: string, args: unknown[]) => unknown;\n\ntype TriggerWorkflowOptions = {\n authInvoker?: { namespace: string; machineUserName: string };\n};\ntype TriggerHandlerFn = (\n workflowName: string,\n args: unknown,\n options?: TriggerWorkflowOptions,\n) => string;\ntype WaitHandlerFn = (key: string, payload: unknown) => unknown;\ntype ResolveHandler = (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n) => unknown | Promise<unknown>;\n\n// Overloaded so TypeScript narrows to WaitHandlerFn first (giving inferred\n// `(key: string, payload: unknown) => …` for callers) before falling back\n// to the static-value form. A union type would let `unknown` swallow the\n// function variant and break inference.\ntype SetWaitHandler = {\n (handler: WaitHandlerFn): void;\n (handler: unknown): void;\n};\n\ninterface ExecutedQuery {\n query: string;\n params: unknown[];\n}\n\ninterface CreatedClient {\n namespace: string | undefined;\n ended: boolean;\n}\n\ninterface TriggeredJob {\n jobName: string;\n args: unknown;\n}\n\ninterface SecretCall {\n method: \"getSecret\" | \"getSecrets\";\n vault: string;\n name?: string;\n names?: readonly string[];\n}\n\ninterface AuthConnectionCall {\n connectionName: string;\n}\n\ninterface IdpCall {\n method: string;\n args: unknown[];\n namespace: string;\n}\n\ninterface FileCall {\n method: string;\n namespace: string;\n typeName: string;\n fieldName: string;\n recordId: string;\n}\n\ninterface IconvCall {\n method: string;\n args: unknown[];\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\n// Attach a non-enumerable `Symbol.dispose` to a facade so it works with `using`.\nfunction withDispose<T extends object>(facade: T, dispose: () => void): T & Disposable {\n Object.defineProperty(facade, Symbol.dispose, {\n value: dispose,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n return facade as T & Disposable;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction tailorRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailor) {\n // Ensure the container (and the always-present context stub) exists even if\n // the base globals were not installed (e.g. a unit test that only acquires\n // a single mock without the tailor-runtime environment).\n g.tailor = { context: { getInvoker: () => null } };\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailor as Record<string, any>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction tailordbRoot(): Record<string, any> {\n const g = globalThis as Record<string, unknown>;\n if (!g.tailordb) {\n g.tailordb = {};\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return g.tailordb as Record<string, any>;\n}\n\nclass MockQueryResult {\n command: string;\n rowCount: number;\n rows: unknown[];\n\n constructor(rows: unknown[]) {\n this.command = \"\";\n this.rowCount = rows.length;\n this.rows = rows;\n }\n}\n\n// ---------------------------------------------------------------------------\n// TailorDB Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for TailorDB operations. Installs a mock\n * `tailordb.Client` whose `queryObject` is a shared `vi.fn()` (so query\n * responses can be staged before the client is constructed). Restored on\n * dispose.\n * @returns Disposable TailorDB mock control object\n * @example\n * ```typescript\n * import { mockTailordb } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"order-based\", async () => {\n * using db = mockTailordb();\n * db.enqueueResults([], [{ age: 30 }], []); // BEGIN / SELECT / COMMIT\n * // …\n * expect(db.queryObject).toHaveBeenCalledTimes(3);\n * expect(db.Client).toHaveBeenCalledWith({ namespace: \"tailordb\" });\n * });\n * ```\n */\nexport function mockTailordb() {\n const root = tailordbRoot();\n const prevClient = root.Client;\n\n const queryObject = vi.fn(\n async (_query: string, _params: unknown[] = []): Promise<MockQueryResult> =>\n new MockQueryResult([]),\n );\n const connect = vi.fn(async (): Promise<void> => {});\n const createdClients: CreatedClient[] = [];\n\n const Client = vi.fn(function (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this: any,\n config?: { namespace?: string },\n ) {\n const record: CreatedClient = { namespace: config?.namespace, ended: false };\n createdClients.push(record);\n this.connect = connect;\n this.end = vi.fn(async (): Promise<void> => {\n record.ended = true;\n });\n this.queryObject = queryObject;\n this.createTransaction = (name: string) => {\n if (!name) {\n throw new Error(\"Transaction name must be a non-empty string\");\n }\n return {\n begin: async (): Promise<void> => {},\n commit: async (): Promise<void> => {},\n rollback: async (): Promise<void> => {},\n queryObject,\n };\n };\n });\n\n root.Client = Client;\n\n const facade = {\n /** The mock `tailordb.Client` constructor (`vi.fn`). */\n Client,\n /** The shared `queryObject` `vi.fn` used by every client and transaction. */\n queryObject,\n\n /**\n * Set a fallback query resolver. Called when the enqueue queue is empty.\n * @param resolver - Function that returns rows for a given query and params\n */\n setQueryResolver(resolver: QueryResolver): void {\n queryObject.mockImplementation(\n async (query: string, params: unknown[] = []) =>\n // user resolvers may return undefined\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n new MockQueryResult(resolver(query, params) ?? []),\n );\n },\n\n /**\n * Enqueue rows for the next `queryObject` call (FIFO; takes priority over\n * `setQueryResolver`). Call with no arguments for an empty result.\n * @param rows - Row objects to return from the next `queryObject` call\n */\n enqueueResult(...rows: unknown[]): void {\n queryObject.mockImplementationOnce(async () => new MockQueryResult(rows));\n },\n\n /**\n * Enqueue rows for multiple subsequent `queryObject` calls (FIFO).\n * @param rowsList - Rows arrays, one per upcoming query\n */\n enqueueResults(...rowsList: unknown[][]): void {\n for (const rows of rowsList) {\n queryObject.mockImplementationOnce(async () => new MockQueryResult(rows));\n }\n },\n\n /**\n * All queries executed via `queryObject`, in order, derived from the vi.fn\n * call records.\n * @returns Executed queries array\n */\n get executedQueries(): ExecutedQuery[] {\n return queryObject.mock.calls.map(([query, params]) => ({\n query: query as string,\n // vitest records an omitted argument as undefined\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n params: (params as unknown[]) ?? [],\n }));\n },\n\n /**\n * All TailorDB clients created, with their namespace and end state.\n * @returns Created clients array\n */\n get createdClients(): CreatedClient[] {\n return createdClients;\n },\n\n /** Reset query responses and recorded calls (keeps the mock installed). */\n reset(): void {\n queryObject.mockReset();\n queryObject.mockImplementation(async () => new MockQueryResult([]));\n connect.mockClear();\n Client.mockClear();\n createdClients.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.Client = prevClient;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Workflow Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for workflow operations (`tailor.workflow`).\n * Restored on dispose.\n * @returns Disposable workflow mock control object\n * @example\n * ```typescript\n * import { mockWorkflow } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"job handler\", async () => {\n * using wf = mockWorkflow();\n * wf.setJobHandler((name) => (name === \"validate\" ? { valid: true } : null));\n * await runWorkflowUnderTest(); // calls tailor.workflow.triggerJobFunction(\"validate\", {})\n * expect(wf.triggerJobFunction).toHaveBeenCalledWith(\"validate\", {});\n * });\n * ```\n */\nexport function mockWorkflow() {\n const root = tailorRoot();\n const prev = root.workflow;\n\n // Default impls (also restored by reset): run the registered body by name so a\n // `.trigger()` with no handler/result executes the real job locally.\n const defaultTriggerJob = (jobName: string, args?: unknown): unknown => {\n const body = getRegisteredJob(jobName);\n return body ? body(args, buildJobContext()) : null;\n };\n const defaultTriggerWorkflow = async (\n workflowName: string,\n args?: unknown,\n _options?: TriggerWorkflowOptions,\n ): Promise<string> => {\n const wf = getRegisteredWorkflow(workflowName);\n if (wf) await installedTriggerJobFunction(wf.mainJobName, args);\n return TRIGGER_DEFAULT;\n };\n\n // Inner vi.fns hold the overridable behavior + call recording; the installed\n // shims below cross the platform JSON boundary (serialize args + results) once\n // so every path (default body, setJobHandler, enqueueResult) is covered.\n const triggerJobFunction = vi.fn(defaultTriggerJob);\n const triggerWorkflow = vi.fn(defaultTriggerWorkflow);\n const wait = vi.fn((_key: string, _payload?: unknown): unknown => null);\n const resolve = vi.fn(\n async (\n _executionId: string,\n _key: string,\n _callback: (payload: unknown) => unknown,\n ): Promise<void> => {},\n );\n\n const installedTriggerJobFunction = (jobName: string, args?: unknown): unknown => {\n const out = triggerJobFunction(jobName, platformSerialize(args));\n return out instanceof Promise ? out.then((v) => platformSerialize(v)) : platformSerialize(out);\n };\n\n root.workflow = {\n triggerJobFunction: installedTriggerJobFunction,\n // Preserve arity so a forwarded third `options` arg — even `undefined` — is\n // recorded, matching the real `.trigger(args, options)` call shape.\n triggerWorkflow: (...call: [string, unknown?, TriggerWorkflowOptions?]) =>\n call.length >= 3\n ? triggerWorkflow(call[0], platformSerialize(call[1]), call[2])\n : triggerWorkflow(call[0], platformSerialize(call[1])),\n wait: (key: string, payload?: unknown) => wait(key, platformSerialize(payload)),\n resolve: (executionId: string, key: string, callback: (payload: unknown) => unknown) =>\n resolve(executionId, key, (payload: unknown) => {\n const out = callback(payload);\n return out instanceof Promise\n ? out.then((v) => platformSerialize(v))\n : platformSerialize(out);\n }),\n };\n\n const facade = {\n /** The `triggerJobFunction` `vi.fn`. */\n triggerJobFunction,\n /** The `triggerWorkflow` `vi.fn`. */\n triggerWorkflow,\n /** The `wait` `vi.fn`. */\n wait,\n /** The `resolve` `vi.fn`. */\n resolve,\n\n /**\n * Set a fallback job handler. Called when the enqueue queue is empty.\n * @param handler - Function returning a result for a job name and args\n */\n setJobHandler(handler: JobHandler): void {\n triggerJobFunction.mockImplementation((name, args) => handler(name, args));\n },\n\n /**\n * Enqueue a single result for the next `triggerJobFunction` call (FIFO;\n * takes priority over `setJobHandler`).\n * @param result - Result to return from the next call\n */\n enqueueResult(result: unknown): void {\n triggerJobFunction.mockImplementationOnce(() => result);\n },\n\n /**\n * Enqueue results for multiple subsequent `triggerJobFunction` calls (FIFO).\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n for (const result of results) {\n triggerJobFunction.mockImplementationOnce(() => result);\n }\n },\n\n /**\n * All jobs triggered via `triggerJobFunction`, in order.\n * @returns Triggered jobs array\n */\n get triggeredJobs(): TriggeredJob[] {\n return triggerJobFunction.mock.calls.map(([jobName, args]) => ({\n jobName: jobName as string,\n args,\n }));\n },\n\n /**\n * Configure what `triggerWorkflow` returns. Pass a string (same id every\n * call) or `(name, args, options) => string`. Default: a placeholder UUID.\n * @param handler - Static execution ID or a function returning one\n */\n setTriggerHandler(handler: string | TriggerHandlerFn): void {\n triggerWorkflow.mockImplementation(\n typeof handler === \"function\"\n ? async (name, args, options) => handler(name, args, options)\n : async () => handler,\n );\n },\n\n /**\n * Configure what `wait` returns. Pass `(key, payload) => unknown` or any\n * other value to return it for every call. Default: `null`.\n * @param handler - Static value or a function returning one\n */\n setWaitHandler: ((handler: unknown) => {\n wait.mockImplementation(\n typeof handler === \"function\"\n ? (key, payload) => (handler as WaitHandlerFn)(key, payload)\n : () => handler,\n );\n }) as SetWaitHandler,\n\n /**\n * Set the `env` passed to job bodies invoked via `createWorkflowJob().trigger()`.\n * Cleared on dispose / reset.\n * @param env - Env passed to job bodies.\n */\n setEnv(env: TailorEnv): void {\n writeWorkflowTestEnv({ ...env });\n },\n\n /**\n * Configure how `resolve` runs the user-supplied callback. Default: callback\n * is not invoked (records the call only).\n * @param handler - Function invoked per `resolve` call\n */\n setResolveHandler(handler: ResolveHandler): void {\n resolve.mockImplementation(async (executionId, key, callback) => {\n await handler(executionId, key, callback);\n });\n },\n\n /**\n * `wait` calls reshaped as `{ key, payload }` for assertions.\n * @returns Wait call records\n */\n get waitCalls(): { key: string; payload: unknown }[] {\n return wait.mock.calls.map(([key, payload]) => ({ key: key as string, payload }));\n },\n\n /**\n * `resolve` calls reshaped as `{ executionId, key }` for assertions.\n * @returns Resolve call records\n */\n get resolveCalls(): { executionId: string; key: string }[] {\n return resolve.mock.calls.map(([executionId, key]) => ({\n executionId: executionId as string,\n key: key as string,\n }));\n },\n\n /** Reset all workflow responses and recorded calls (keeps the mock installed). */\n reset(): void {\n triggerJobFunction.mockReset();\n triggerJobFunction.mockImplementation(defaultTriggerJob);\n triggerWorkflow.mockReset();\n triggerWorkflow.mockImplementation(defaultTriggerWorkflow);\n wait.mockReset();\n wait.mockImplementation(() => null);\n resolve.mockReset();\n resolve.mockImplementation(async () => {});\n clearWorkflowTestEnv();\n },\n };\n\n return withDispose(facade, () => {\n root.workflow = prev;\n clearWorkflowTestEnv();\n });\n}\n\n// ---------------------------------------------------------------------------\n// SecretManager Mock\n// ---------------------------------------------------------------------------\n\n// Hidden accessor key used to inherit the previous scope's secret store on\n// acquisition (so secrets seeded once outside tests — e.g. from tailor.config.ts\n// via setup.ts — remain visible) while still isolating per-test overrides.\nconst SECRET_STORE = Symbol(\"tailorSecretStore\");\n\n/**\n * Acquire a disposable mock for `tailor.secretmanager`. The secret store is\n * inherited (cloned) from the currently-installed mock on acquisition and\n * restored on dispose, so secrets seeded outside the test survive across\n * `using` scopes while per-test `setSecrets()` overrides stay isolated.\n * @returns Disposable SecretManager mock control object\n * @example\n * ```typescript\n * import { mockSecretmanager } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"reads secrets from vault\", async () => {\n * using sm = mockSecretmanager();\n * sm.setSecrets({ \"my-vault\": { API_KEY: \"sk-123\" } });\n * // …\n * });\n * ```\n */\nexport function mockSecretmanager() {\n const root = tailorRoot();\n const prev = root.secretmanager;\n\n const holder: { store: Record<string, Record<string, string>> } = {\n // prior mock state may be absent\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n store: structuredClone((prev?.[SECRET_STORE]?.store as typeof holder.store) ?? {}),\n };\n\n const getSecret = vi.fn(\n async (vault: string, name: string): Promise<string | undefined> => holder.store[vault]?.[name],\n );\n const getSecrets = vi.fn(\n async <const T extends readonly string[]>(\n vault: string,\n names: T,\n ): Promise<Partial<Record<T[number], string>>> => {\n const vaultData = holder.store[vault] ?? {};\n const result: Record<string, string> = {};\n for (const name of names) {\n if (name in vaultData) {\n result[name] = assertDefined(vaultData[name], `vault entry missing for: ${name}`);\n }\n }\n return result as Partial<Record<T[number], string>>;\n },\n );\n\n root.secretmanager = { getSecret, getSecrets, [SECRET_STORE]: holder };\n\n const facade = {\n /** The `getSecret` `vi.fn`. */\n getSecret,\n /** The `getSecrets` `vi.fn`. */\n getSecrets,\n\n setSecrets(secrets: Record<string, Record<string, string>>): void {\n holder.store = secrets;\n },\n\n get calls(): SecretCall[] {\n // Merge both methods' calls back into chronological order via vi.fn's\n // global invocationCallOrder, so a test mixing getSecret/getSecrets sees\n // them in the order they actually ran (not all getSecret, then all getSecrets).\n const entries: { order: number; call: SecretCall }[] = [\n ...getSecret.mock.calls.map((args, i) => ({\n order: getSecret.mock.invocationCallOrder[i] ?? 0,\n call: { method: \"getSecret\" as const, vault: args[0] as string, name: args[1] as string },\n })),\n ...getSecrets.mock.calls.map((args, i) => ({\n order: getSecrets.mock.invocationCallOrder[i] ?? 0,\n call: {\n method: \"getSecrets\" as const,\n vault: args[0] as string,\n names: args[1] as readonly string[],\n },\n })),\n ];\n return entries.toSorted((a, b) => a.order - b.order).map((e) => e.call);\n },\n\n reset(): void {\n holder.store = {};\n getSecret.mockClear();\n getSecrets.mockClear();\n },\n };\n\n return withDispose(facade, () => {\n root.secretmanager = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// AuthConnection Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Acquire a disposable mock for `tailor.authconnection`. Restored on dispose.\n * @returns Disposable AuthConnection mock control object\n * @example\n * ```typescript\n * import { mockAuthconnection } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"returns configured token\", async () => {\n * using ac = mockAuthconnection();\n * ac.setTokens({ google: { access_token: \"ya29.xxx\" } });\n * // …\n * });\n * ```\n */\nexport function mockAuthconnection() {\n const root = tailorRoot();\n const prev = root.authconnection;\n\n let tokens: Record<string, unknown> = {};\n const getConnectionToken = vi.fn(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n async (connectionName: string): Promise<any> =>\n tokens[connectionName] ?? { access_token: \"mock-token\" },\n );\n\n root.authconnection = { getConnectionToken };\n\n const facade = {\n /** The `getConnectionToken` `vi.fn`. */\n getConnectionToken,\n\n setTokens(value: Record<string, unknown>): void {\n tokens = value;\n },\n\n get calls(): AuthConnectionCall[] {\n return getConnectionToken.mock.calls.map(([connectionName]) => ({\n connectionName: connectionName as string,\n }));\n },\n\n reset(): void {\n tokens = {};\n getConnectionToken.mockClear();\n },\n };\n\n return withDispose(facade, () => {\n root.authconnection = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// IDP Mock\n// ---------------------------------------------------------------------------\n\nconst IDP_DEFAULTS: Record<string, unknown> = {\n users: { users: [], nextPageToken: null, totalCount: 0 },\n user: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n userByName: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n createUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n updateUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n deleteUser: true,\n sendPasswordResetEmail: true,\n};\n\n/**\n * Acquire a disposable mock for `tailor.idp`. Restored on dispose.\n * @returns Disposable IDP mock control object\n * @example\n * ```typescript\n * import { mockIdp } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"resolver-based\", async () => {\n * using idp = mockIdp();\n * idp.setResolver((method) =>\n * method === \"user\" ? { id: \"u-1\", name: \"alice\", disabled: false } : null,\n * );\n * // …\n * });\n * ```\n */\nexport function mockIdp() {\n const root = tailorRoot();\n const prev = root.idp;\n\n const queue: unknown[] = [];\n let resolver: IdpResolver = () => null;\n const calls: IdpCall[] = [];\n\n function handle(method: string, args: unknown[], namespace: string): unknown {\n calls.push({ method, args, namespace });\n if (queue.length > 0) return queue.shift();\n const resolved = resolver(method, args, namespace);\n // Treat null and undefined alike as \"no override\".\n if (resolved != null) return resolved;\n // Clone the default so a test mutating the returned value cannot corrupt\n // the shared module-level object for subsequent tests.\n const fallback = IDP_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n }\n\n const Client = vi.fn(function (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this: any,\n config: { namespace: string },\n ) {\n const namespace = config.namespace;\n this.users = async (options?: unknown) => handle(\"users\", [options], namespace);\n this.user = async (userId: string) => handle(\"user\", [userId], namespace);\n this.userByName = async (name: string) => handle(\"userByName\", [name], namespace);\n this.createUser = async (input: unknown) => handle(\"createUser\", [input], namespace);\n this.updateUser = async (input: unknown) => handle(\"updateUser\", [input], namespace);\n this.deleteUser = async (userId: string) => handle(\"deleteUser\", [userId], namespace);\n this.sendPasswordResetEmail = async (input: unknown) =>\n handle(\"sendPasswordResetEmail\", [input], namespace);\n }) as unknown as new (config: { namespace: string }) => {\n users(options?: {\n first?: number;\n after?: string;\n query?: { ids?: string[]; names?: string[] };\n }): Promise<{ users: IdpUser[]; nextPageToken: string | null; totalCount: number }>;\n user(userId: string): Promise<IdpUser>;\n userByName(name: string): Promise<IdpUser>;\n createUser(input: { name: string; password?: string; disabled?: boolean }): Promise<IdpUser>;\n updateUser(input: {\n id: string;\n name?: string;\n password?: string;\n clearPassword?: boolean;\n disabled?: boolean;\n }): Promise<IdpUser>;\n deleteUser(userId: string): Promise<boolean>;\n sendPasswordResetEmail(input: { userId: string; redirectUri: string }): Promise<boolean>;\n };\n\n root.idp = { Client };\n\n const facade = {\n /** The mock IDP `Client` constructor (`vi.fn`). */\n Client: Client as unknown as Mock,\n\n setResolver(value: IdpResolver): void {\n resolver = value;\n },\n\n /**\n * Enqueue a single result for the next IDP call (FIFO; falls back to\n * `setResolver` when exhausted).\n * @param result - Result to return from the next IDP call\n */\n enqueueResult(result: unknown): void {\n queue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent IDP calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n queue.push(...results);\n },\n\n get calls(): IdpCall[] {\n return calls;\n },\n\n reset(): void {\n queue.length = 0;\n resolver = () => null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.idp = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Iconv Mock\n// ---------------------------------------------------------------------------\n\n// Iconv methods return `string` for UTF-8 target encodings and `Uint8Array`\n// for any other byte-producing encoding (the platform API mirrors this).\nfunction isUtf8(encoding: unknown): boolean {\n return encoding === \"UTF8\" || encoding === \"UTF-8\";\n}\n\nfunction defaultIconvResult(method: string, args: unknown[]): unknown {\n switch (method) {\n case \"convert\":\n case \"convertBuffer\":\n return isUtf8(args[2]) ? \"\" : new Uint8Array();\n case \"decode\":\n return \"\";\n case \"encode\":\n return isUtf8(args[1]) ? \"\" : new Uint8Array();\n case \"encodings\":\n return [];\n default:\n return undefined;\n }\n}\n\n/**\n * Acquire a disposable mock for `tailor.iconv`. Restored on dispose.\n * @returns Disposable Iconv mock control object\n * @example\n * ```typescript\n * import { mockIconv } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"mock encoding conversion\", () => {\n * using iconv = mockIconv();\n * iconv.setResolver((method) => (method === \"decode\" ? \"decoded-text\" : null));\n * // …\n * });\n * ```\n */\nexport function mockIconv() {\n const root = tailorRoot();\n const prev = root.iconv;\n\n let resolver: IconvResolver | null = null;\n const calls: IconvCall[] = [];\n\n function handle(method: string, args: unknown[]): unknown {\n calls.push({ method, args: [...args] });\n if (resolver) {\n const result = resolver(method, args);\n if (result != null) return result;\n }\n return defaultIconvResult(method, args);\n }\n\n class MockIconv {\n #fromEncoding: string;\n #toEncoding: string;\n constructor(fromEncoding: string, toEncoding: string) {\n this.#fromEncoding = fromEncoding;\n this.#toEncoding = toEncoding;\n }\n convert(input: string | Uint8Array | ArrayBuffer): string | Uint8Array {\n return handle(\"convert\", [input, this.#fromEncoding, this.#toEncoding]) as\n | string\n | Uint8Array;\n }\n }\n\n root.iconv = {\n convert: (str: unknown, from: string, to: string) => handle(\"convert\", [str, from, to]),\n convertBuffer: (buf: unknown, from: string, to: string) =>\n handle(\"convertBuffer\", [buf, from, to]),\n decode: (buf: unknown, encoding: string) => handle(\"decode\", [buf, encoding]),\n encode: (str: string, encoding: string) => handle(\"encode\", [str, encoding]),\n encodings: () => handle(\"encodings\", []),\n Iconv: MockIconv,\n };\n\n const facade = {\n setResolver(value: IconvResolver): void {\n resolver = value;\n },\n\n get calls(): IconvCall[] {\n return calls;\n },\n\n reset(): void {\n resolver = null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.iconv = prev;\n });\n}\n\n// ---------------------------------------------------------------------------\n// File Mock (tailordb.file)\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst FILE_DEFAULTS: Record<string, any> = {\n upload: { metadata: { fileSize: 0, sha256sum: \"\" } },\n download: {\n data: new Uint8Array(),\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n downloadAsBase64: {\n data: \"\",\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n delete: undefined,\n getMetadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", urlPath: \"\" },\n downloadStream: null,\n uploadStream: { metadata: { fileSize: 0, sha256sum: \"\" } },\n};\n\ntype FileStream = AsyncIterableIterator<unknown> & { close(): Promise<void> };\n\nfunction toFileStream(value: unknown): FileStream {\n if (\n value !== null &&\n typeof value === \"object\" &&\n Symbol.asyncIterator in value &&\n typeof (value as { close?: unknown }).close === \"function\"\n ) {\n return value as FileStream;\n }\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n throw new TypeError(\n \"openDownloadStream expects an iterable of StreamValue items \" +\n '(e.g. [{ type: \"chunk\", data, position }, { type: \"complete\" }]); ' +\n \"got raw bytes. Wrap the bytes in a structured chunk first.\",\n );\n }\n if (\n value !== null &&\n typeof value === \"object\" &&\n (Symbol.iterator in value || Symbol.asyncIterator in value)\n ) {\n const source = value as Iterable<unknown> | AsyncIterable<unknown>;\n const inner =\n Symbol.asyncIterator in source\n ? (source as AsyncIterable<unknown>)[Symbol.asyncIterator]()\n : (source as Iterable<unknown>)[Symbol.iterator]();\n const stream: FileStream = {\n async next() {\n const r = await inner.next();\n if (!r.done) {\n assertStreamValue(r.value);\n }\n return r.done ? { done: true as const, value: undefined } : r;\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return stream;\n },\n };\n return stream;\n }\n const empty: FileStream = {\n async next() {\n return { done: true as const, value: undefined };\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return empty;\n },\n };\n return empty;\n}\n\nfunction assertStreamValue(v: unknown): void {\n if (v === null || typeof v !== \"object\") {\n throw new TypeError(\n 'openDownloadStream expected a StreamValue item ({ type: \"metadata\" | \"chunk\" | \"complete\", ... }); ' +\n `got ${typeof v === \"object\" ? \"null\" : typeof v}.`,\n );\n }\n if (v instanceof ArrayBuffer || ArrayBuffer.isView(v)) {\n throw new TypeError(\n \"openDownloadStream expected a StreamValue item, got raw bytes. \" +\n 'Wrap the bytes in a structured chunk first (e.g. { type: \"chunk\", data, position }).',\n );\n }\n const type = (v as { type?: unknown }).type;\n if (type !== \"metadata\" && type !== \"chunk\" && type !== \"complete\") {\n throw new TypeError(\n 'openDownloadStream expected a StreamValue item with type \"metadata\" | \"chunk\" | \"complete\"; ' +\n `got ${JSON.stringify(type)}.`,\n );\n }\n}\n\n/**\n * Acquire a disposable mock for `tailordb.file`. Restored on dispose.\n * @returns Disposable File mock control object\n * @example\n * ```typescript\n * import { mockFile } from \"@tailor-platform/sdk/vitest\";\n *\n * test(\"mock file download\", async () => {\n * using file = mockFile();\n * file.enqueueResult({ data: new Uint8Array([1, 2, 3]), metadata: { ... } });\n * // …\n * });\n * ```\n */\nexport function mockFile() {\n const root = tailordbRoot();\n const prev = root.file;\n\n const queue: unknown[] = [];\n let resolver: FileResolver = () => null;\n const calls: FileCall[] = [];\n\n function handle(\n method: string,\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): unknown {\n const call: FileCall = { method, namespace, typeName, fieldName, recordId };\n calls.push(call);\n if (queue.length > 0) return queue.shift();\n const resolved = resolver(method, call);\n if (resolved != null) return resolved;\n const fallback = FILE_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n }\n\n root.file = {\n async upload(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"upload\", namespace, typeName, fieldName, recordId);\n },\n async download(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"download\", namespace, typeName, fieldName, recordId);\n },\n async downloadAsBase64(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ) {\n return handle(\"downloadAsBase64\", namespace, typeName, fieldName, recordId);\n },\n async delete(namespace: string, typeName: string, fieldName: string, recordId: string) {\n handle(\"delete\", namespace, typeName, fieldName, recordId);\n },\n async getMetadata(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"getMetadata\", namespace, typeName, fieldName, recordId);\n },\n async openDownloadStream(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ) {\n return toFileStream(handle(\"openDownloadStream\", namespace, typeName, fieldName, recordId));\n },\n async downloadStream(namespace: string, typeName: string, fieldName: string, recordId: string) {\n const resolved = handle(\"downloadStream\", namespace, typeName, fieldName, recordId);\n if (resolved != null) return resolved;\n return {\n body: new ReadableStream({\n start(c) {\n c.close();\n },\n }),\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n };\n },\n async uploadStream(namespace: string, typeName: string, fieldName: string, recordId: string) {\n return handle(\"uploadStream\", namespace, typeName, fieldName, recordId);\n },\n };\n\n const facade = {\n setResolver(value: FileResolver): void {\n resolver = value;\n },\n\n /**\n * Enqueue a single result for the next `tailordb.file` call (FIFO; falls\n * back to `setResolver` when exhausted).\n * @param result - Result to return from the next file call\n */\n enqueueResult(result: unknown): void {\n queue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent `tailordb.file` calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n queue.push(...results);\n },\n\n get calls(): FileCall[] {\n return calls;\n },\n\n reset(): void {\n queue.length = 0;\n resolver = () => null;\n calls.length = 0;\n },\n };\n\n return withDispose(facade, () => {\n root.file = prev;\n });\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-Db2RvnEH.mjs";
1
+ import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-CklcVeMG.mjs";
2
2
  export { EnumConstantsGeneratorID, enumConstantsPlugin };
@@ -1,2 +1,2 @@
1
- import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-CZ2r3qiO.mjs";
1
+ import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-DYhnxXYR.mjs";
2
2
  export { FileUtilsGeneratorID, fileUtilsPlugin };
@@ -1,2 +1,2 @@
1
- import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-QpC0TNbH.mjs";
1
+ import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-DlDRSzFZ.mjs";
2
2
  export { KyselyGeneratorID, kyselyTypePlugin };
@@ -1,2 +1,2 @@
1
- import { n as seedPlugin, t as SeedGeneratorID } from "../../../index-Bhjep8cS.mjs";
1
+ import { n as seedPlugin, t as SeedGeneratorID } from "../../../index-hXoO-AOC.mjs";
2
2
  export { SeedGeneratorID, seedPlugin };
@@ -1,4 +1,4 @@
1
1
 
2
- import { n as seedPlugin, t as SeedGeneratorID } from "../../../seed-BH2FbrPV.mjs";
2
+ import { n as seedPlugin, t as SeedGeneratorID } from "../../../seed-YAbtMy65.mjs";
3
3
 
4
4
  export { SeedGeneratorID, seedPlugin };
@@ -1,6 +1,5 @@
1
- import { c as TailorAnyDBType } from "../tailordb-C-ar4XCX.mjs";
2
- import { n as TailorEnv } from "../env-B-g-qgE4.mjs";
3
- import { t as TailorActor } from "../actor-D_2aJjYO.mjs";
1
+ import { a as TailorActor, o as TailorEnv } from "../types-DTcZ2Yax.mjs";
2
+ import { f as TailorAnyDBType } from "../types-DZrtN6-H.mjs";
4
3
 
5
4
  //#region src/plugin/with-context.d.ts
6
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/plugin/with-context.ts","../../src/plugin/get-generated-type.ts"],"sourcesContent":["/**\n * Plugin executor context support for defining plugin executors in separate files.\n * This module provides utilities for creating type-safe plugin executors that receive\n * context (like type references and namespace) at runtime.\n */\n\nimport type { TailorActor, TailorEnv } from \"@/types/runtime\";\n\n/**\n * Plugin executor factory function type.\n * Takes context and returns an executor configuration.\n * Returns unknown since the exact return type depends on createExecutor's generic params.\n */\nexport type PluginExecutorFactory<Ctx> = (ctx: Ctx) => unknown;\n\n// ============================================================================\n// Plugin Executor Args Types\n// ============================================================================\n\n/**\n * Base args for plugin executor function operations.\n * Provides typed access to runtime context without requiring specific record types.\n */\nexport interface PluginFunctionArgs {\n /** Workspace ID where the executor runs */\n workspaceId: string;\n /** Application namespace */\n appNamespace: string;\n /** Environment variables */\n env: TailorEnv;\n /** Actor (user) who triggered the event, null for system events */\n actor: TailorActor | null;\n /** Name of the TailorDB type */\n typeName: string;\n /** TailorDB connections by namespace */\n tailordb: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record creation.\n */\nexport interface PluginRecordCreatedArgs extends PluginFunctionArgs {\n /** The newly created record */\n newRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record update.\n */\nexport interface PluginRecordUpdatedArgs extends PluginFunctionArgs {\n /** The record after update */\n newRecord: Record<string, unknown>;\n /** The record before update */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record deletion.\n */\nexport interface PluginRecordDeletedArgs extends PluginFunctionArgs {\n /** The deleted record */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Database schema type for plugins.\n * Since plugins work with dynamic types, the schema uses Record types.\n */\nexport type PluginDBSchema = Record<string, Record<string, unknown>>;\n\n/**\n * Base record type for TailorDB records.\n * All records have an id field.\n */\nexport type PluginRecord = { id: string } & Record<string, unknown>;\n\n/**\n * Define a plugin executor that receives context at runtime.\n * This allows executor definitions to be in separate files while\n * still receiving dynamic values like typeName, generated types, and namespace.\n * @param factory - Function that takes context and returns executor configuration\n * @returns The same factory function (for type inference)\n * @example\n * ```typescript\n * // executors/on-create.ts\n * import { withPluginContext } from \"@tailor-platform/sdk/plugin\";\n * import { createExecutor, recordCreatedTrigger } from \"@tailor-platform/sdk\";\n * import { getDB } from \"@tailor-platform/function-kysely-tailordb\";\n *\n * interface MyContext {\n * sourceType: TailorAnyDBType;\n * historyType: TailorAnyDBType;\n * namespace: string;\n * }\n *\n * export default withPluginContext<MyContext>((ctx) =>\n * createExecutor({\n * name: `${ctx.sourceType.name.toLowerCase()}-on-create`,\n * trigger: recordCreatedTrigger({ type: ctx.sourceType }),\n * operation: {\n * kind: \"function\",\n * body: async (args) => {\n * const db = getDB(ctx.namespace);\n * await db.insertInto(ctx.historyType.name).values({\n * recordId: args.newRecord.id,\n * // ...\n * }).execute();\n * },\n * },\n * })\n * );\n * ```\n */\nexport function withPluginContext<Ctx>(\n factory: PluginExecutorFactory<Ctx>,\n): PluginExecutorFactory<Ctx> {\n return factory;\n}\n","import * as fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport * as path from \"pathe\";\nimport type { Plugin, PluginOutput, TypePluginOutput } from \"@/types/plugin\";\nimport type { TailorAnyDBType } from \"@/types/tailordb\";\n\n// ========================================\n// Config loading and caching\n// ========================================\n\ninterface PluginEntry {\n plugin: Plugin;\n pluginConfig: unknown;\n}\n\ninterface ConfigCache {\n config: { db?: Record<string, unknown> };\n plugins: Map<string, PluginEntry>;\n configDir: string;\n}\n\n/** Cache: resolved config path -> loaded config data */\nconst configCacheMap = new Map<string, ConfigCache>();\n\n/**\n * Check if a value is a Plugin instance.\n * @param value - Value to check\n * @returns True if value has the shape of Plugin\n */\nfunction isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as Record<string, unknown>).id === \"string\" &&\n typeof (value as Record<string, unknown>).description === \"string\"\n );\n}\n\n/**\n * Load and cache config module from the given path.\n * Extracts plugins from all array exports using definePlugins() format.\n * Returns null if the config file does not exist (e.g., in bundled executor on platform server).\n * @param configPath - Absolute or relative path to tailor.config.ts\n * @returns Cached config data with plugins map, or null if config file is not available\n */\nasync function loadAndCacheConfig(configPath: string): Promise<ConfigCache | null> {\n const resolvedPath = path.resolve(configPath);\n\n const cached = configCacheMap.get(resolvedPath);\n if (cached) return cached;\n\n // Config file may not exist in bundled environments (e.g., platform server)\n if (!fs.existsSync(resolvedPath)) {\n return null;\n }\n\n const configModule = await import(pathToFileURL(resolvedPath).href);\n if (!configModule?.default) {\n throw new Error(`Invalid config module at \"${resolvedPath}\": default export not found`);\n }\n\n const config = configModule.default as { db?: Record<string, unknown> };\n const configDir = path.dirname(resolvedPath);\n const plugins = new Map<string, PluginEntry>();\n\n // Find plugin arrays from exports (definePlugins returns PluginConfig[])\n for (const value of Object.values(configModule)) {\n if (!Array.isArray(value)) continue;\n\n for (const item of value) {\n if (isPlugin(item)) {\n plugins.set(item.id, { plugin: item, pluginConfig: item.pluginConfig });\n }\n }\n }\n\n const result: ConfigCache = { config, plugins, configDir };\n configCacheMap.set(resolvedPath, result);\n return result;\n}\n\n// ========================================\n// Namespace resolution\n// ========================================\n\ninterface DbNamespaceConfig {\n files?: string[];\n external?: boolean;\n}\n\n/**\n * Resolve the namespace for a type-attached sourceType by checking config.db file patterns.\n * Uses ESM module cache identity: same file path yields same object references.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param configDir - Directory containing the config file\n * @param sourceType - The TailorDB type to look up\n * @returns The namespace name\n */\nasync function resolveNamespaceForType(\n config: { db?: Record<string, unknown> },\n configDir: string,\n sourceType: TailorAnyDBType,\n): Promise<string> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n for (const [namespace, nsConfig] of Object.entries(config.db)) {\n const dbConfig = nsConfig as DbNamespaceConfig;\n // Skip external namespaces (no files to resolve)\n if (dbConfig.external || !dbConfig.files) continue;\n\n for (const pattern of dbConfig.files) {\n const absolutePattern = path.resolve(configDir, pattern);\n let matchedFiles: string[];\n try {\n matchedFiles = fs.globSync(absolutePattern);\n } catch {\n continue;\n }\n\n for (const file of matchedFiles) {\n const mod = await import(pathToFileURL(file).href);\n for (const exported of Object.values(mod)) {\n if (exported === sourceType) {\n return namespace;\n }\n }\n }\n }\n }\n\n throw new Error(\n `Could not resolve namespace for type \"${sourceType.name}\". ` +\n `Ensure the type file is included in a db namespace's files pattern.`,\n );\n}\n\n/**\n * Resolve the namespace for a namespace plugin by trying each namespace.\n * Calls onNamespaceLoaded() for each and returns the first whose output contains the requested kind.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - Plugin instance\n * @param kind - The generated type kind to look for\n * @param pluginConfig - Plugin-level configuration\n * @returns The namespace name\n */\nasync function resolveNamespaceForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<{ namespace: string; output: PluginOutput }> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const output = await plugin.onNamespaceLoaded({\n pluginConfig,\n namespace,\n });\n\n if (output.types?.[kind]) {\n return { namespace, output };\n }\n }\n\n throw new Error(\n `Could not resolve namespace for plugin \"${plugin.id}\" with kind \"${kind}\". ` +\n `No namespace produced a type with that kind.`,\n );\n}\n\n// ========================================\n// Process caching\n// ========================================\n\n// Cache: plugin -> cacheKey -> TypePluginOutput\nconst processCache = new WeakMap<Plugin, Map<string, TypePluginOutput>>();\n\n// Cache for namespace plugins: plugin -> cacheKey -> PluginOutput\nconst namespaceProcessCache = new WeakMap<Plugin, Map<string, PluginOutput>>();\n\n/**\n * Generate a cache key that includes pluginConfig.\n * @param baseKey - Base key for the cache\n * @param pluginConfig - Plugin configuration to include in the key\n * @returns Cache key string\n */\nfunction getCacheKey(baseKey: string, pluginConfig: unknown): string {\n if (pluginConfig === undefined) {\n return baseKey;\n }\n try {\n return `${baseKey}:${JSON.stringify(pluginConfig)}`;\n } catch {\n throw new Error(\n `pluginConfig must be JSON-serializable for caching. Received non-serializable value.`,\n );\n }\n}\n\n// ========================================\n// Main API\n// ========================================\n\n/**\n * Get a generated type from a plugin by loading the config and resolving everything automatically.\n * For type-attached plugins, calls onTypeLoaded() with the sourceType.\n * For namespace plugins, calls onNamespaceLoaded() with auto-resolved namespace.\n * Results are cached per config path, plugin, namespace, and pluginConfig to avoid redundant processing.\n * @param configPath - Path to tailor.config.ts (absolute or relative to cwd)\n * @param pluginId - The plugin's unique identifier\n * @param sourceType - The source TailorDB type (null for namespace plugins)\n * @param kind - The generated type kind (e.g., \"request\", \"step\")\n * @returns The generated TailorDB type\n */\nexport async function getGeneratedType(\n configPath: string,\n pluginId: string,\n sourceType: TailorAnyDBType | null,\n kind: string,\n): Promise<TailorAnyDBType> {\n const cache = await loadAndCacheConfig(configPath);\n\n if (!cache) {\n // Config not available (e.g., running in bundled executor on platform server).\n // Return a placeholder. The actual type is resolved at generate/apply time.\n return { name: `__placeholder_${kind}__`, fields: {} } as TailorAnyDBType;\n }\n\n const { config, configDir, plugins } = cache;\n\n const pluginEntry = plugins.get(pluginId);\n if (!pluginEntry) {\n throw new Error(\n `Plugin \"${pluginId}\" not found in config at \"${configPath}\". ` +\n `Ensure the plugin is registered via definePlugins().`,\n );\n }\n\n const { plugin, pluginConfig } = pluginEntry;\n\n if (sourceType === null) {\n return getGeneratedTypeForNamespacePlugin(config, plugin, kind, pluginConfig);\n }\n\n const namespace = await resolveNamespaceForType(config, configDir, sourceType);\n return getGeneratedTypeForTypeAttachedPlugin(plugin, sourceType, kind, pluginConfig, namespace);\n}\n\n/**\n * Get a generated type from a type-attached plugin.\n * @param plugin - The plugin instance (must have onTypeLoaded() method)\n * @param sourceType - The source TailorDB type\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @param namespace - Resolved namespace\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForTypeAttachedPlugin(\n plugin: Plugin,\n sourceType: TailorAnyDBType,\n kind: string,\n pluginConfig: unknown,\n namespace: string,\n): Promise<TailorAnyDBType> {\n if (!plugin.onTypeLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onTypeLoaded() method`);\n }\n\n // Check cache first\n let pluginCache = processCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n processCache.set(plugin, pluginCache);\n }\n\n const cacheKey = getCacheKey(`${sourceType.name}:ns=${namespace}`, pluginConfig);\n let output = pluginCache.get(cacheKey);\n\n if (!output) {\n const typeConfig = sourceType.plugins.find((p) => p.pluginId === plugin.id)?.config;\n output = await plugin.onTypeLoaded({\n type: sourceType,\n typeConfig: typeConfig ?? {},\n pluginConfig,\n namespace,\n });\n pluginCache.set(cacheKey, output);\n }\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(\n `Generated type not found: plugin=${plugin.id}, sourceType=${sourceType.name}, kind=${kind}`,\n );\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Get a generated type from a namespace plugin.\n * Auto-resolves the namespace by trying each one.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - The plugin instance (must have onNamespaceLoaded() method)\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<TailorAnyDBType> {\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n // Check cache first - try all namespaces\n let pluginCache = namespaceProcessCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n namespaceProcessCache.set(plugin, pluginCache);\n }\n\n // Try cached results first\n if (config.db) {\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n const cached = pluginCache.get(cacheKey);\n if (cached?.types?.[kind]) {\n return cached.types[kind] as TailorAnyDBType;\n }\n }\n }\n\n // Not in cache - resolve namespace and process\n const { namespace, output } = await resolveNamespaceForNamespacePlugin(\n config,\n plugin,\n kind,\n pluginConfig,\n );\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n pluginCache.set(cacheKey, output);\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(`Generated type not found: plugin=${plugin.id}, kind=${kind}`);\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Clear all internal caches. For testing only.\n */\nexport function _clearCacheForTesting(): void {\n configCacheMap.clear();\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/plugin/with-context.ts","../../src/plugin/get-generated-type.ts"],"sourcesContent":["/**\n * Plugin executor context support for defining plugin executors in separate files.\n * This module provides utilities for creating type-safe plugin executors that receive\n * context (like type references and namespace) at runtime.\n */\n\nimport type { TailorActor, TailorEnv } from \"@/runtime/types\";\n\n/**\n * Plugin executor factory function type.\n * Takes context and returns an executor configuration.\n * Returns unknown since the exact return type depends on createExecutor's generic params.\n */\nexport type PluginExecutorFactory<Ctx> = (ctx: Ctx) => unknown;\n\n// ============================================================================\n// Plugin Executor Args Types\n// ============================================================================\n\n/**\n * Base args for plugin executor function operations.\n * Provides typed access to runtime context without requiring specific record types.\n */\nexport interface PluginFunctionArgs {\n /** Workspace ID where the executor runs */\n workspaceId: string;\n /** Application namespace */\n appNamespace: string;\n /** Environment variables */\n env: TailorEnv;\n /** Actor (user) who triggered the event, null for system events */\n actor: TailorActor | null;\n /** Name of the TailorDB type */\n typeName: string;\n /** TailorDB connections by namespace */\n tailordb: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record creation.\n */\nexport interface PluginRecordCreatedArgs extends PluginFunctionArgs {\n /** The newly created record */\n newRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record update.\n */\nexport interface PluginRecordUpdatedArgs extends PluginFunctionArgs {\n /** The record after update */\n newRecord: Record<string, unknown>;\n /** The record before update */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record deletion.\n */\nexport interface PluginRecordDeletedArgs extends PluginFunctionArgs {\n /** The deleted record */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Database schema type for plugins.\n * Since plugins work with dynamic types, the schema uses Record types.\n */\nexport type PluginDBSchema = Record<string, Record<string, unknown>>;\n\n/**\n * Base record type for TailorDB records.\n * All records have an id field.\n */\nexport type PluginRecord = { id: string } & Record<string, unknown>;\n\n/**\n * Define a plugin executor that receives context at runtime.\n * This allows executor definitions to be in separate files while\n * still receiving dynamic values like typeName, generated types, and namespace.\n * @param factory - Function that takes context and returns executor configuration\n * @returns The same factory function (for type inference)\n * @example\n * ```typescript\n * // executors/on-create.ts\n * import { withPluginContext } from \"@tailor-platform/sdk/plugin\";\n * import { createExecutor, recordCreatedTrigger } from \"@tailor-platform/sdk\";\n * import { getDB } from \"@tailor-platform/function-kysely-tailordb\";\n *\n * interface MyContext {\n * sourceType: TailorAnyDBType;\n * historyType: TailorAnyDBType;\n * namespace: string;\n * }\n *\n * export default withPluginContext<MyContext>((ctx) =>\n * createExecutor({\n * name: `${ctx.sourceType.name.toLowerCase()}-on-create`,\n * trigger: recordCreatedTrigger({ type: ctx.sourceType }),\n * operation: {\n * kind: \"function\",\n * body: async (args) => {\n * const db = getDB(ctx.namespace);\n * await db.insertInto(ctx.historyType.name).values({\n * recordId: args.newRecord.id,\n * // ...\n * }).execute();\n * },\n * },\n * })\n * );\n * ```\n */\nexport function withPluginContext<Ctx>(\n factory: PluginExecutorFactory<Ctx>,\n): PluginExecutorFactory<Ctx> {\n return factory;\n}\n","import * as fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport * as path from \"pathe\";\nimport type { TailorAnyDBType } from \"@/configure/services/tailordb/types\";\nimport type { Plugin, PluginOutput, TypePluginOutput } from \"@/plugin/types\";\n\n// ========================================\n// Config loading and caching\n// ========================================\n\ninterface PluginEntry {\n plugin: Plugin;\n pluginConfig: unknown;\n}\n\ninterface ConfigCache {\n config: { db?: Record<string, unknown> };\n plugins: Map<string, PluginEntry>;\n configDir: string;\n}\n\n/** Cache: resolved config path -> loaded config data */\nconst configCacheMap = new Map<string, ConfigCache>();\n\n/**\n * Check if a value is a Plugin instance.\n * @param value - Value to check\n * @returns True if value has the shape of Plugin\n */\nfunction isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as Record<string, unknown>).id === \"string\" &&\n typeof (value as Record<string, unknown>).description === \"string\"\n );\n}\n\n/**\n * Load and cache config module from the given path.\n * Extracts plugins from all array exports using definePlugins() format.\n * Returns null if the config file does not exist (e.g., in bundled executor on platform server).\n * @param configPath - Absolute or relative path to tailor.config.ts\n * @returns Cached config data with plugins map, or null if config file is not available\n */\nasync function loadAndCacheConfig(configPath: string): Promise<ConfigCache | null> {\n const resolvedPath = path.resolve(configPath);\n\n const cached = configCacheMap.get(resolvedPath);\n if (cached) return cached;\n\n // Config file may not exist in bundled environments (e.g., platform server)\n if (!fs.existsSync(resolvedPath)) {\n return null;\n }\n\n const configModule = await import(pathToFileURL(resolvedPath).href);\n if (!configModule?.default) {\n throw new Error(`Invalid config module at \"${resolvedPath}\": default export not found`);\n }\n\n const config = configModule.default as { db?: Record<string, unknown> };\n const configDir = path.dirname(resolvedPath);\n const plugins = new Map<string, PluginEntry>();\n\n // Find plugin arrays from exports (definePlugins returns PluginConfig[])\n for (const value of Object.values(configModule)) {\n if (!Array.isArray(value)) continue;\n\n for (const item of value) {\n if (isPlugin(item)) {\n plugins.set(item.id, { plugin: item, pluginConfig: item.pluginConfig });\n }\n }\n }\n\n const result: ConfigCache = { config, plugins, configDir };\n configCacheMap.set(resolvedPath, result);\n return result;\n}\n\n// ========================================\n// Namespace resolution\n// ========================================\n\ninterface DbNamespaceConfig {\n files?: string[];\n external?: boolean;\n}\n\n/**\n * Resolve the namespace for a type-attached sourceType by checking config.db file patterns.\n * Uses ESM module cache identity: same file path yields same object references.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param configDir - Directory containing the config file\n * @param sourceType - The TailorDB type to look up\n * @returns The namespace name\n */\nasync function resolveNamespaceForType(\n config: { db?: Record<string, unknown> },\n configDir: string,\n sourceType: TailorAnyDBType,\n): Promise<string> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n for (const [namespace, nsConfig] of Object.entries(config.db)) {\n const dbConfig = nsConfig as DbNamespaceConfig;\n // Skip external namespaces (no files to resolve)\n if (dbConfig.external || !dbConfig.files) continue;\n\n for (const pattern of dbConfig.files) {\n const absolutePattern = path.resolve(configDir, pattern);\n let matchedFiles: string[];\n try {\n matchedFiles = fs.globSync(absolutePattern);\n } catch {\n continue;\n }\n\n for (const file of matchedFiles) {\n const mod = await import(pathToFileURL(file).href);\n for (const exported of Object.values(mod)) {\n if (exported === sourceType) {\n return namespace;\n }\n }\n }\n }\n }\n\n throw new Error(\n `Could not resolve namespace for type \"${sourceType.name}\". ` +\n `Ensure the type file is included in a db namespace's files pattern.`,\n );\n}\n\n/**\n * Resolve the namespace for a namespace plugin by trying each namespace.\n * Calls onNamespaceLoaded() for each and returns the first whose output contains the requested kind.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - Plugin instance\n * @param kind - The generated type kind to look for\n * @param pluginConfig - Plugin-level configuration\n * @returns The namespace name\n */\nasync function resolveNamespaceForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<{ namespace: string; output: PluginOutput }> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const output = await plugin.onNamespaceLoaded({\n pluginConfig,\n namespace,\n });\n\n if (output.types?.[kind]) {\n return { namespace, output };\n }\n }\n\n throw new Error(\n `Could not resolve namespace for plugin \"${plugin.id}\" with kind \"${kind}\". ` +\n `No namespace produced a type with that kind.`,\n );\n}\n\n// ========================================\n// Process caching\n// ========================================\n\n// Cache: plugin -> cacheKey -> TypePluginOutput\nconst processCache = new WeakMap<Plugin, Map<string, TypePluginOutput>>();\n\n// Cache for namespace plugins: plugin -> cacheKey -> PluginOutput\nconst namespaceProcessCache = new WeakMap<Plugin, Map<string, PluginOutput>>();\n\n/**\n * Generate a cache key that includes pluginConfig.\n * @param baseKey - Base key for the cache\n * @param pluginConfig - Plugin configuration to include in the key\n * @returns Cache key string\n */\nfunction getCacheKey(baseKey: string, pluginConfig: unknown): string {\n if (pluginConfig === undefined) {\n return baseKey;\n }\n try {\n return `${baseKey}:${JSON.stringify(pluginConfig)}`;\n } catch {\n throw new Error(\n `pluginConfig must be JSON-serializable for caching. Received non-serializable value.`,\n );\n }\n}\n\n// ========================================\n// Main API\n// ========================================\n\n/**\n * Get a generated type from a plugin by loading the config and resolving everything automatically.\n * For type-attached plugins, calls onTypeLoaded() with the sourceType.\n * For namespace plugins, calls onNamespaceLoaded() with auto-resolved namespace.\n * Results are cached per config path, plugin, namespace, and pluginConfig to avoid redundant processing.\n * @param configPath - Path to tailor.config.ts (absolute or relative to cwd)\n * @param pluginId - The plugin's unique identifier\n * @param sourceType - The source TailorDB type (null for namespace plugins)\n * @param kind - The generated type kind (e.g., \"request\", \"step\")\n * @returns The generated TailorDB type\n */\nexport async function getGeneratedType(\n configPath: string,\n pluginId: string,\n sourceType: TailorAnyDBType | null,\n kind: string,\n): Promise<TailorAnyDBType> {\n const cache = await loadAndCacheConfig(configPath);\n\n if (!cache) {\n // Config not available (e.g., running in bundled executor on platform server).\n // Return a placeholder. The actual type is resolved at generate/apply time.\n return { name: `__placeholder_${kind}__`, fields: {} } as TailorAnyDBType;\n }\n\n const { config, configDir, plugins } = cache;\n\n const pluginEntry = plugins.get(pluginId);\n if (!pluginEntry) {\n throw new Error(\n `Plugin \"${pluginId}\" not found in config at \"${configPath}\". ` +\n `Ensure the plugin is registered via definePlugins().`,\n );\n }\n\n const { plugin, pluginConfig } = pluginEntry;\n\n if (sourceType === null) {\n return getGeneratedTypeForNamespacePlugin(config, plugin, kind, pluginConfig);\n }\n\n const namespace = await resolveNamespaceForType(config, configDir, sourceType);\n return getGeneratedTypeForTypeAttachedPlugin(plugin, sourceType, kind, pluginConfig, namespace);\n}\n\n/**\n * Get a generated type from a type-attached plugin.\n * @param plugin - The plugin instance (must have onTypeLoaded() method)\n * @param sourceType - The source TailorDB type\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @param namespace - Resolved namespace\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForTypeAttachedPlugin(\n plugin: Plugin,\n sourceType: TailorAnyDBType,\n kind: string,\n pluginConfig: unknown,\n namespace: string,\n): Promise<TailorAnyDBType> {\n if (!plugin.onTypeLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onTypeLoaded() method`);\n }\n\n // Check cache first\n let pluginCache = processCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n processCache.set(plugin, pluginCache);\n }\n\n const cacheKey = getCacheKey(`${sourceType.name}:ns=${namespace}`, pluginConfig);\n let output = pluginCache.get(cacheKey);\n\n if (!output) {\n const typeConfig = sourceType.plugins.find((p) => p.pluginId === plugin.id)?.config;\n output = await plugin.onTypeLoaded({\n type: sourceType,\n typeConfig: typeConfig ?? {},\n pluginConfig,\n namespace,\n });\n pluginCache.set(cacheKey, output);\n }\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(\n `Generated type not found: plugin=${plugin.id}, sourceType=${sourceType.name}, kind=${kind}`,\n );\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Get a generated type from a namespace plugin.\n * Auto-resolves the namespace by trying each one.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - The plugin instance (must have onNamespaceLoaded() method)\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<TailorAnyDBType> {\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n // Check cache first - try all namespaces\n let pluginCache = namespaceProcessCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n namespaceProcessCache.set(plugin, pluginCache);\n }\n\n // Try cached results first\n if (config.db) {\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n const cached = pluginCache.get(cacheKey);\n if (cached?.types?.[kind]) {\n return cached.types[kind] as TailorAnyDBType;\n }\n }\n }\n\n // Not in cache - resolve namespace and process\n const { namespace, output } = await resolveNamespaceForNamespacePlugin(\n config,\n plugin,\n kind,\n pluginConfig,\n );\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n pluginCache.set(cacheKey, output);\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(`Generated type not found: plugin=${plugin.id}, kind=${kind}`);\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Clear all internal caches. For testing only.\n */\nexport function _clearCacheForTesting(): void {\n configCacheMap.clear();\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry-D0uB0OrK.mjs","names":[],"sources":["../src/utils/test/platform-serialize.ts","../src/configure/services/workflow/test-env-key.ts","../src/configure/services/workflow/registry.ts"],"sourcesContent":["/**\n * Validate and serialize a value as it would cross the Platform JSON boundary.\n *\n * Mirrors the runtime checks the platform performs on workflow arguments,\n * wait payloads, and trigger inputs so that local tests fail in the same\n * places production fails.\n *\n * Throws on:\n * - `NaN` / `Infinity` / `-Infinity` (`JSON.stringify` would silently emit `null`)\n * - `BigInt` (TypeError is thrown by `JSON.stringify`; we emit a clearer message)\n * - Non-plain objects (class instances, including `Date`, `Map`, `Set`, `Error`,\n * and user-defined DTOs whose prototype is not `Object.prototype`)\n *\n * The replacer reads `this[key]` so the check sees the original value before\n * any `toJSON` conversion (e.g. `Date.prototype.toJSON`).\n * @param value - Value to validate and round-trip\n * @returns The JSON-normalized value (undefined/function properties stripped, etc.)\n */\nexport function platformSerialize<T>(value: T): T {\n // Top-level undefined is allowed (jobs may take no input).\n if (value === undefined) return undefined as T;\n\n // Root function/symbol stringify to `undefined`; throw a specific message here.\n if (typeof value === \"function\") {\n throw new TypeError(\"platformSerialize: function is not JSON-serializable at <root>\");\n }\n if (typeof value === \"symbol\") {\n throw new TypeError(\"platformSerialize: Symbol is not JSON-serializable at <root>\");\n }\n\n const serialized = JSON.stringify(value, function (key, val) {\n if (typeof val === \"number\" && !Number.isFinite(val)) {\n throw new TypeError(\n `platformSerialize: non-finite number at ${formatPath(key)}: ${String(val)}`,\n );\n }\n if (typeof val === \"bigint\") {\n throw new TypeError(\n `platformSerialize: BigInt is not JSON-serializable at ${formatPath(key)}`,\n );\n }\n // Look at the pre-toJSON value so Date/Map/Set/etc. can be detected.\n const raw = (this as Record<string, unknown>)[key];\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n const proto = Object.getPrototypeOf(raw);\n if (proto !== Object.prototype && proto !== null) {\n const ctor = (raw as { constructor?: { name?: string } }).constructor?.name ?? \"anonymous\";\n throw new TypeError(\n `platformSerialize: non-plain object at ${formatPath(key)} (${ctor} instance)`,\n );\n }\n }\n return val;\n });\n\n // `JSON.stringify` returns `undefined` when the root collapses (e.g. a `toJSON`\n // returning `undefined`); parsing that would throw opaquely.\n // JSON.stringify returns undefined for non-serializable values\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n if (serialized === undefined) {\n throw new TypeError(\"platformSerialize: value is not JSON-serializable at <root>\");\n }\n\n return JSON.parse(serialized) as T;\n}\n\nfunction formatPath(key: string): string {\n return key === \"\" ? \"<root>\" : `\"${key}\"`;\n}\n","/**\n * Typed accessors for the test-time globalThis slot used to pass `env` from\n * `mockWorkflow().setEnv()` (in `@tailor-platform/sdk/vitest`) to\n * `createWorkflowJob().trigger()` bodies. The slot key is private to this\n * module; callers go through the get/set/clear functions below so both sides\n * share the same access path.\n *\n * Lives in its own file (with no `@/` imports) so `vitest/mock.ts` can load\n * it from nested Vitest configs that do not resolve `@/` aliases.\n * @internal\n */\nimport type { TailorEnv } from \"../../../types/env\";\nimport type { TailorInvoker } from \"../../../types/user\";\n\nconst SLOT_KEY = \"__tailorWorkflowTestEnv\";\n\n/**\n * Read the test-time env slot.\n * @returns Current env, or `undefined` when unset.\n * @internal\n */\nexport function readWorkflowTestEnv(): TailorEnv | undefined {\n return (globalThis as unknown as Record<string, TailorEnv | undefined>)[SLOT_KEY];\n}\n\n/**\n * Write the test-time env slot.\n * @param env - Env value to expose to `.trigger()` bodies.\n * @internal\n */\nexport function writeWorkflowTestEnv(env: TailorEnv): void {\n (globalThis as unknown as Record<string, TailorEnv>)[SLOT_KEY] = env;\n}\n\n/**\n * Clear the test-time env slot.\n * @internal\n */\nexport function clearWorkflowTestEnv(): void {\n delete (globalThis as unknown as Record<string, unknown>)[SLOT_KEY];\n}\n\n/**\n * Env-var fallback read by `.trigger()` when `mockWorkflow().setEnv()` is unset.\n * @deprecated Use `mockWorkflow().setEnv()` from `@tailor-platform/sdk/vitest`.\n * @internal\n */\nexport const WORKFLOW_TEST_ENV_KEY = \"TAILOR_TEST_WORKFLOW_ENV\";\n\n// env from `mockWorkflow().setEnv()`, else the deprecated env-var. Shallow-copied\n// to isolate against cross-trigger mutation.\nexport function buildJobContext(): { env: TailorEnv; invoker?: TailorInvoker } {\n const fromGlobal = readWorkflowTestEnv();\n if (fromGlobal !== undefined) return { env: { ...fromGlobal } };\n const raw = process.env[WORKFLOW_TEST_ENV_KEY];\n if (!raw) return { env: {} as TailorEnv };\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new Error(\n `Invalid JSON in ${WORKFLOW_TEST_ENV_KEY}; provide valid JSON or use mockWorkflow().setEnv().`,\n { cause },\n );\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\n `${WORKFLOW_TEST_ENV_KEY} must be a JSON object; provide a record or use mockWorkflow().setEnv().`,\n );\n }\n return { env: { ...(parsed as TailorEnv) } };\n}\n","import { platformSerialize } from \"@/utils/test/platform-serialize\";\nimport { buildJobContext } from \"./test-env-key\";\nimport type { TailorEnv } from \"@/types/env\";\nimport type { TailorInvoker } from \"@/types/user\";\n\n/**\n * Body signature shared by workflow jobs at registry-write time.\n * The user's `createWorkflowJob`/`createWorkflow` body uses concrete types,\n * but the registry erases them for storage.\n */\nexport type RegisteredJobBody = (\n args: unknown,\n context: { env: TailorEnv; invoker?: TailorInvoker },\n) => unknown | Promise<unknown>;\n\nexport interface RegisteredWorkflow {\n mainJobName: string;\n}\n\nconst JOB_REGISTRY_KEY: unique symbol = Symbol.for(\"tailor-platform/sdk:job-registry\");\nconst WORKFLOW_REGISTRY_KEY: unique symbol = Symbol.for(\"tailor-platform/sdk:workflow-registry\");\n\ntype PlatformWorkflow = {\n triggerWorkflow: (name: string, args?: unknown, options?: unknown) => Promise<string>;\n triggerJobFunction: (name: string, args?: unknown) => unknown;\n};\n\ntype GlobalWithRegistry = typeof globalThis & {\n [JOB_REGISTRY_KEY]?: Map<string, RegisteredJobBody>;\n [WORKFLOW_REGISTRY_KEY]?: Map<string, RegisteredWorkflow>;\n tailor?: { workflow?: PlatformWorkflow };\n};\n\nfunction jobs(): Map<string, RegisteredJobBody> {\n const g = globalThis as GlobalWithRegistry;\n let map = g[JOB_REGISTRY_KEY];\n if (!map) {\n map = new Map();\n g[JOB_REGISTRY_KEY] = map;\n }\n return map;\n}\n\nfunction workflows(): Map<string, RegisteredWorkflow> {\n const g = globalThis as GlobalWithRegistry;\n let map = g[WORKFLOW_REGISTRY_KEY];\n if (!map) {\n map = new Map();\n g[WORKFLOW_REGISTRY_KEY] = map;\n }\n return map;\n}\n\n/**\n * Register a job body keyed by job name. Called as a side effect by\n * `createWorkflowJob` so the vitest mock can execute the body when\n * `globalThis.tailor.workflow.triggerJobFunction(name, args)` is invoked.\n *\n * In production builds the bundler rewrites `.trigger()` calls so this registry\n * is never read; the gated write is dropped as dead code.\n * @param name - Job name\n * @param body - Job body function\n */\nexport function registerJob(name: string, body: RegisteredJobBody): void {\n jobs().set(name, body);\n}\n\n/**\n * Look up a registered job body by name.\n * @param name - Job name\n * @returns The registered body, or undefined when no job is registered\n */\nexport function getRegisteredJob(name: string): RegisteredJobBody | undefined {\n return jobs().get(name);\n}\n\n/**\n * Register a workflow's main job name so the mock can run the workflow locally.\n * @param name - Workflow name\n * @param mainJobName - Name of the workflow's main job\n */\nexport function registerWorkflow(name: string, mainJobName: string): void {\n workflows().set(name, { mainJobName });\n}\n\n/**\n * Look up a registered workflow by name.\n * @param name - Workflow name\n * @returns The registered workflow, or undefined\n */\nexport function getRegisteredWorkflow(name: string): RegisteredWorkflow | undefined {\n return workflows().get(name);\n}\n\nfunction currentPlatformWorkflow(): PlatformWorkflow | undefined {\n // globalThis may not have the tailor property at runtime\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n return (globalThis as GlobalWithRegistry).tailor?.workflow;\n}\n\n// A valid placeholder UUID, so callers that validate the execution id behave the\n// same locally as against the platform.\nexport const TRIGGER_DEFAULT = \"00000000-0000-4000-8000-000000000000\";\n\nfunction serializeReturn(out: unknown): unknown {\n return out instanceof Promise ? out.then((v) => platformSerialize(v)) : platformSerialize(out);\n}\n\n// Runs the registered body across the platform JSON boundary. Shared by the\n// `tailor-runtime` default runner and the no-shim `.trigger()` fallback below.\nexport function runRegisteredJob(name: string, args?: unknown): unknown {\n const body = getRegisteredJob(name);\n const out = body ? body(platformSerialize(args), buildJobContext()) : null;\n return serializeReturn(out);\n}\n\nexport async function runRegisteredWorkflow(name: string, args?: unknown): Promise<string> {\n const workflow = getRegisteredWorkflow(name);\n if (workflow) await runRegisteredJob(workflow.mainJobName, args);\n return TRIGGER_DEFAULT;\n}\n\n// `.trigger()` routes through the installed `tailor.workflow` shim, falling back\n// to running the registered body/workflow locally when none is installed.\nexport function dispatchTriggerJob(name: string, args?: unknown): unknown {\n const workflow = currentPlatformWorkflow();\n return workflow ? workflow.triggerJobFunction(name, args) : runRegisteredJob(name, args);\n}\n\nexport function dispatchTriggerWorkflow(\n name: string,\n args?: unknown,\n options?: unknown,\n): Promise<string> {\n const workflow = currentPlatformWorkflow();\n return workflow\n ? workflow.triggerWorkflow(name, args, options)\n : runRegisteredWorkflow(name, args);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry-D0uB0OrK.mjs","names":[],"sources":["../src/utils/test/platform-serialize.ts","../src/configure/services/workflow/test-env-key.ts","../src/configure/services/workflow/registry.ts"],"sourcesContent":["/**\n * Validate and serialize a value as it would cross the Platform JSON boundary.\n *\n * Mirrors the runtime checks the platform performs on workflow arguments,\n * wait payloads, and trigger inputs so that local tests fail in the same\n * places production fails.\n *\n * Throws on:\n * - `NaN` / `Infinity` / `-Infinity` (`JSON.stringify` would silently emit `null`)\n * - `BigInt` (TypeError is thrown by `JSON.stringify`; we emit a clearer message)\n * - Non-plain objects (class instances, including `Date`, `Map`, `Set`, `Error`,\n * and user-defined DTOs whose prototype is not `Object.prototype`)\n *\n * The replacer reads `this[key]` so the check sees the original value before\n * any `toJSON` conversion (e.g. `Date.prototype.toJSON`).\n * @param value - Value to validate and round-trip\n * @returns The JSON-normalized value (undefined/function properties stripped, etc.)\n */\nexport function platformSerialize<T>(value: T): T {\n // Top-level undefined is allowed (jobs may take no input).\n if (value === undefined) return undefined as T;\n\n // Root function/symbol stringify to `undefined`; throw a specific message here.\n if (typeof value === \"function\") {\n throw new TypeError(\"platformSerialize: function is not JSON-serializable at <root>\");\n }\n if (typeof value === \"symbol\") {\n throw new TypeError(\"platformSerialize: Symbol is not JSON-serializable at <root>\");\n }\n\n const serialized = JSON.stringify(value, function (key, val) {\n if (typeof val === \"number\" && !Number.isFinite(val)) {\n throw new TypeError(\n `platformSerialize: non-finite number at ${formatPath(key)}: ${String(val)}`,\n );\n }\n if (typeof val === \"bigint\") {\n throw new TypeError(\n `platformSerialize: BigInt is not JSON-serializable at ${formatPath(key)}`,\n );\n }\n // Look at the pre-toJSON value so Date/Map/Set/etc. can be detected.\n const raw = (this as Record<string, unknown>)[key];\n if (raw !== null && typeof raw === \"object\" && !Array.isArray(raw)) {\n const proto = Object.getPrototypeOf(raw);\n if (proto !== Object.prototype && proto !== null) {\n const ctor = (raw as { constructor?: { name?: string } }).constructor?.name ?? \"anonymous\";\n throw new TypeError(\n `platformSerialize: non-plain object at ${formatPath(key)} (${ctor} instance)`,\n );\n }\n }\n return val;\n });\n\n // `JSON.stringify` returns `undefined` when the root collapses (e.g. a `toJSON`\n // returning `undefined`); parsing that would throw opaquely.\n // JSON.stringify returns undefined for non-serializable values\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n if (serialized === undefined) {\n throw new TypeError(\"platformSerialize: value is not JSON-serializable at <root>\");\n }\n\n return JSON.parse(serialized) as T;\n}\n\nfunction formatPath(key: string): string {\n return key === \"\" ? \"<root>\" : `\"${key}\"`;\n}\n","/**\n * Typed accessors for the test-time globalThis slot used to pass `env` from\n * `mockWorkflow().setEnv()` (in `@tailor-platform/sdk/vitest`) to\n * `createWorkflowJob().trigger()` bodies. The slot key is private to this\n * module; callers go through the get/set/clear functions below so both sides\n * share the same access path.\n *\n * Lives in its own file (with no `@/` imports) so `vitest/mock.ts` can load\n * it from nested Vitest configs that do not resolve `@/` aliases.\n * @internal\n */\nimport type { TailorEnv, TailorInvoker } from \"../../../runtime/types\";\n\nconst SLOT_KEY = \"__tailorWorkflowTestEnv\";\n\n/**\n * Read the test-time env slot.\n * @returns Current env, or `undefined` when unset.\n * @internal\n */\nexport function readWorkflowTestEnv(): TailorEnv | undefined {\n return (globalThis as unknown as Record<string, TailorEnv | undefined>)[SLOT_KEY];\n}\n\n/**\n * Write the test-time env slot.\n * @param env - Env value to expose to `.trigger()` bodies.\n * @internal\n */\nexport function writeWorkflowTestEnv(env: TailorEnv): void {\n (globalThis as unknown as Record<string, TailorEnv>)[SLOT_KEY] = env;\n}\n\n/**\n * Clear the test-time env slot.\n * @internal\n */\nexport function clearWorkflowTestEnv(): void {\n delete (globalThis as unknown as Record<string, unknown>)[SLOT_KEY];\n}\n\n/**\n * Env-var fallback read by `.trigger()` when `mockWorkflow().setEnv()` is unset.\n * @deprecated Use `mockWorkflow().setEnv()` from `@tailor-platform/sdk/vitest`.\n * @internal\n */\nexport const WORKFLOW_TEST_ENV_KEY = \"TAILOR_TEST_WORKFLOW_ENV\";\n\n// env from `mockWorkflow().setEnv()`, else the deprecated env-var. Shallow-copied\n// to isolate against cross-trigger mutation.\nexport function buildJobContext(): { env: TailorEnv; invoker?: TailorInvoker } {\n const fromGlobal = readWorkflowTestEnv();\n if (fromGlobal !== undefined) return { env: { ...fromGlobal } };\n const raw = process.env[WORKFLOW_TEST_ENV_KEY];\n if (!raw) return { env: {} as TailorEnv };\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (cause) {\n throw new Error(\n `Invalid JSON in ${WORKFLOW_TEST_ENV_KEY}; provide valid JSON or use mockWorkflow().setEnv().`,\n { cause },\n );\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\n `${WORKFLOW_TEST_ENV_KEY} must be a JSON object; provide a record or use mockWorkflow().setEnv().`,\n );\n }\n return { env: { ...(parsed as TailorEnv) } };\n}\n","import { platformSerialize } from \"@/utils/test/platform-serialize\";\nimport { buildJobContext } from \"./test-env-key\";\nimport type { TailorEnv, TailorInvoker } from \"@/runtime/types\";\n\n/**\n * Body signature shared by workflow jobs at registry-write time.\n * The user's `createWorkflowJob`/`createWorkflow` body uses concrete types,\n * but the registry erases them for storage.\n */\nexport type RegisteredJobBody = (\n args: unknown,\n context: { env: TailorEnv; invoker?: TailorInvoker },\n) => unknown | Promise<unknown>;\n\nexport interface RegisteredWorkflow {\n mainJobName: string;\n}\n\nconst JOB_REGISTRY_KEY: unique symbol = Symbol.for(\"tailor-platform/sdk:job-registry\");\nconst WORKFLOW_REGISTRY_KEY: unique symbol = Symbol.for(\"tailor-platform/sdk:workflow-registry\");\n\ntype PlatformWorkflow = {\n triggerWorkflow: (name: string, args?: unknown, options?: unknown) => Promise<string>;\n triggerJobFunction: (name: string, args?: unknown) => unknown;\n};\n\ntype GlobalWithRegistry = typeof globalThis & {\n [JOB_REGISTRY_KEY]?: Map<string, RegisteredJobBody>;\n [WORKFLOW_REGISTRY_KEY]?: Map<string, RegisteredWorkflow>;\n tailor?: { workflow?: PlatformWorkflow };\n};\n\nfunction jobs(): Map<string, RegisteredJobBody> {\n const g = globalThis as GlobalWithRegistry;\n let map = g[JOB_REGISTRY_KEY];\n if (!map) {\n map = new Map();\n g[JOB_REGISTRY_KEY] = map;\n }\n return map;\n}\n\nfunction workflows(): Map<string, RegisteredWorkflow> {\n const g = globalThis as GlobalWithRegistry;\n let map = g[WORKFLOW_REGISTRY_KEY];\n if (!map) {\n map = new Map();\n g[WORKFLOW_REGISTRY_KEY] = map;\n }\n return map;\n}\n\n/**\n * Register a job body keyed by job name. Called as a side effect by\n * `createWorkflowJob` so the vitest mock can execute the body when\n * `globalThis.tailor.workflow.triggerJobFunction(name, args)` is invoked.\n *\n * In production builds the bundler rewrites `.trigger()` calls so this registry\n * is never read; the gated write is dropped as dead code.\n * @param name - Job name\n * @param body - Job body function\n */\nexport function registerJob(name: string, body: RegisteredJobBody): void {\n jobs().set(name, body);\n}\n\n/**\n * Look up a registered job body by name.\n * @param name - Job name\n * @returns The registered body, or undefined when no job is registered\n */\nexport function getRegisteredJob(name: string): RegisteredJobBody | undefined {\n return jobs().get(name);\n}\n\n/**\n * Register a workflow's main job name so the mock can run the workflow locally.\n * @param name - Workflow name\n * @param mainJobName - Name of the workflow's main job\n */\nexport function registerWorkflow(name: string, mainJobName: string): void {\n workflows().set(name, { mainJobName });\n}\n\n/**\n * Look up a registered workflow by name.\n * @param name - Workflow name\n * @returns The registered workflow, or undefined\n */\nexport function getRegisteredWorkflow(name: string): RegisteredWorkflow | undefined {\n return workflows().get(name);\n}\n\nfunction currentPlatformWorkflow(): PlatformWorkflow | undefined {\n // globalThis may not have the tailor property at runtime\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n return (globalThis as GlobalWithRegistry).tailor?.workflow;\n}\n\n// A valid placeholder UUID, so callers that validate the execution id behave the\n// same locally as against the platform.\nexport const TRIGGER_DEFAULT = \"00000000-0000-4000-8000-000000000000\";\n\nfunction serializeReturn(out: unknown): unknown {\n return out instanceof Promise ? out.then((v) => platformSerialize(v)) : platformSerialize(out);\n}\n\n// Runs the registered body across the platform JSON boundary. Shared by the\n// `tailor-runtime` default runner and the no-shim `.trigger()` fallback below.\nexport function runRegisteredJob(name: string, args?: unknown): unknown {\n const body = getRegisteredJob(name);\n const out = body ? body(platformSerialize(args), buildJobContext()) : null;\n return serializeReturn(out);\n}\n\nexport async function runRegisteredWorkflow(name: string, args?: unknown): Promise<string> {\n const workflow = getRegisteredWorkflow(name);\n if (workflow) await runRegisteredJob(workflow.mainJobName, args);\n return TRIGGER_DEFAULT;\n}\n\n// `.trigger()` routes through the installed `tailor.workflow` shim, falling back\n// to running the registered body/workflow locally when none is installed.\nexport function dispatchTriggerJob(name: string, args?: unknown): unknown {\n const workflow = currentPlatformWorkflow();\n return workflow ? workflow.triggerJobFunction(name, args) : runRegisteredJob(name, args);\n}\n\nexport function dispatchTriggerWorkflow(\n name: string,\n args?: unknown,\n options?: unknown,\n): Promise<string> {\n const workflow = currentPlatformWorkflow();\n return workflow\n ? workflow.triggerWorkflow(name, args, options)\n : runRegisteredWorkflow(name, args);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
 
2
- import { n as getConnectionToken } from "../authconnection-D8SJGMpj.mjs";
2
+ import { n as getConnectionToken } from "../authconnection-Ds2Ahpum.mjs";
3
3
 
4
4
  export { getConnectionToken };
@@ -1,4 +1,4 @@
1
1
 
2
- import { n as getInvoker } from "../context-s0lxhu8_.mjs";
2
+ import { n as getInvoker } from "../context-CDQqIv4u.mjs";
3
3
 
4
4
  export { getInvoker };
@@ -1,4 +1,4 @@
1
1
 
2
- import { c as upload, i as downloadStream, l as uploadStream, n as download, o as getMetadata, r as downloadAsBase64, s as openDownloadStream, t as deleteFile } from "../file-B58Dm-2P.mjs";
2
+ import { c as upload, i as downloadStream, l as uploadStream, n as download, o as getMetadata, r as downloadAsBase64, s as openDownloadStream, t as deleteFile } from "../file-BkxupbYP.mjs";
3
3
 
4
4
  export { deleteFile as delete, deleteFile, download, downloadAsBase64, downloadStream, getMetadata, openDownloadStream, upload, uploadStream };
@@ -1,4 +1,4 @@
1
1
 
2
- import { a as encode, i as decode, n as convert, o as encodings, r as convertBuffer, t as Iconv } from "../iconv-DreIffeM.mjs";
2
+ import { a as encode, i as decode, n as convert, o as encodings, r as convertBuffer, t as Iconv } from "../iconv-D1zmPjvi.mjs";
3
3
 
4
4
  export { Iconv, convert, convertBuffer, decode, encode, encodings };
@@ -1,4 +1,4 @@
1
1
 
2
- import { t as Client } from "../idp-Ch95ag8h.mjs";
2
+ import { t as Client } from "../idp-BZPqpcYY.mjs";
3
3
 
4
4
  export { Client };