@powerhousedao/codegen 6.2.2-dev.42 → 6.2.2-dev.44

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.
@@ -17,8 +17,8 @@ import { writeJsonFile } from "write-json-file";
17
17
  import { stripVTControlCharacters } from "node:util";
18
18
  import path$1, { join as join$1, relative } from "node:path";
19
19
  import { generate } from "@graphql-codegen/cli";
20
- import { generatorTypeDefs, validationSchema } from "@powerhousedao/document-engineering/graphql";
21
- import { Kind, parse } from "graphql";
20
+ import { generatorTypeDefs, getPHCustomScalarByTypeName, validationSchema } from "@powerhousedao/document-engineering/graphql";
21
+ import { Kind, parse, print } from "graphql";
22
22
  import { realpathSync } from "node:fs";
23
23
  import { fileURLToPath, pathToFileURL } from "node:url";
24
24
  function isEOL(c) {
@@ -5185,36 +5185,88 @@ ${buildCreatorsExports(v.specification.modules, v.camelCaseDocumentType)}
5185
5185
  `.raw;
5186
5186
  //#endregion
5187
5187
  //#region src/templates/document-model/gen/document-schema.ts
5188
- const documentModelDocumentSchemaFileTemplate = (v) => ts$1`
5188
+ function priorVersions(versions, currentVersion) {
5189
+ return versions.filter((k) => k < currentVersion);
5190
+ }
5191
+ function makeOlderStateSchemaImports(versions, currentVersion, phStateName) {
5192
+ return priorVersions(versions, currentVersion).map((k) => `import { ${phStateName}Schema as ${phStateName}SchemaV${k} } from "../../v${k}/gen/document-schema.js";`).join("\n");
5193
+ }
5194
+ function makeStateSchemasByVersion(versions, currentVersion, phStateName) {
5195
+ return `{ ${versions.filter((k) => k <= currentVersion).map((k) => {
5196
+ return `${k}: ${k === currentVersion ? `${phStateName}Schema` : `${phStateName}SchemaV${k}`}`;
5197
+ }).join(", ")} }`;
5198
+ }
5199
+ function makeDocumentSchemasByVersion(versions, currentVersion, v) {
5200
+ return `{ ${versions.filter((k) => k <= currentVersion).map((k) => {
5201
+ if (k === currentVersion) return `${k}: ${v.phDocumentSchemaName}`;
5202
+ return `${k}: z.object({ header: ${v.phDocumentTypeName}HeaderSchema, state: ${v.phStateName}SchemaV${k}, initialState: ${v.phStateName}SchemaV${k} })`;
5203
+ }).join(", ")} }`;
5204
+ }
5189
5205
  /**
5190
- * WARNING: DO NOT EDIT
5191
- * This file is auto-generated and updated by codegen
5192
- */
5193
- import {
5194
- BaseDocumentHeaderSchema,
5195
- BaseDocumentStateSchema,
5196
- } from "document-model";
5197
- import { z } from "zod";
5198
- import { ${v.documentTypeVariableName} } from "./document-type.js";
5199
- import { ${v.stateSchemaName} } from "./schema/zod.js";
5200
- import type { ${v.phDocumentTypeName}, ${v.phStateName} } from "./types.js";
5206
+ * Version-aware validators are only emitted for versions with released
5207
+ * predecessors: a document is validated against the schema of the version it
5208
+ * is stamped with, so a later version may add non-nullable fields without
5209
+ * rejecting documents that have not been upgraded yet.
5210
+ */
5211
+ function makeVersionAwareValidators(v) {
5212
+ return `
5213
+ const ${v.phStateName}SchemasByVersion: Record<number, z.ZodType> = ${makeStateSchemasByVersion(v.versions, v.version, v.phStateName)};
5201
5214
 
5202
- /** Schema for validating the header object of a ${v.pascalCaseDocumentType} document */
5203
- export const ${v.phDocumentTypeName}HeaderSchema = BaseDocumentHeaderSchema.extend({
5204
- documentType: z.literal(${v.documentTypeVariableName}),
5205
- });
5215
+ const ${v.phDocumentSchemaName}sByVersion: Record<number, z.ZodType> = ${makeDocumentSchemasByVersion(v.versions, v.version, v)};
5206
5216
 
5207
- /** Schema for validating the state object of a ${v.pascalCaseDocumentType} document */
5208
- export const ${v.phStateName}Schema = BaseDocumentStateSchema.extend({
5209
- global: ${v.stateSchemaName}(),
5210
- });
5217
+ /** The document model version stamped in a state's document scope. States stamped with 0 or nothing predate versioning and are treated as version 1. */
5218
+ function stampedDocumentModelVersion(state: unknown): number {
5219
+ if (typeof state !== "object" || state === null) return 1;
5220
+ const documentScope = (state as { document?: unknown }).document;
5221
+ if (typeof documentScope !== "object" || documentScope === null) return 1;
5222
+ const version = (documentScope as { version?: unknown }).version;
5223
+ return normalizeDocumentModelVersion(typeof version === "number" ? version : undefined);
5224
+ }
5211
5225
 
5212
- export const ${v.phDocumentSchemaName} = z.object({
5213
- header: ${v.phDocumentTypeName}HeaderSchema,
5214
- state: ${v.phStateName}Schema,
5215
- initialState: ${v.phStateName}Schema,
5216
- });
5226
+ function resolve${v.phStateName}Schema(state: unknown): z.ZodType {
5227
+ const schema = ${v.phStateName}SchemasByVersion[stampedDocumentModelVersion(state)];
5228
+ return schema ?? ${v.phStateName}Schema;
5229
+ }
5230
+
5231
+ function resolve${v.phDocumentSchemaName}(document: unknown): z.ZodType {
5232
+ const state = typeof document === "object" && document !== null
5233
+ ? (document as { state?: unknown }).state
5234
+ : undefined;
5235
+ const schema = ${v.phDocumentSchemaName}sByVersion[stampedDocumentModelVersion(state)];
5236
+ return schema ?? ${v.phDocumentSchemaName};
5237
+ }
5238
+
5239
+ /** Simple helper function to check if a state object is a ${v.pascalCaseDocumentType} document state object. Validates against the schema of the version the state is stamped with. */
5240
+ export function ${v.isPhStateOfTypeFunctionName}(
5241
+ state: unknown,
5242
+ ): state is ${v.phStateName} {
5243
+ return resolve${v.phStateName}Schema(state).safeParse(state).success;
5244
+ }
5245
+
5246
+ /** Simple helper function to assert that a document state object is a ${v.pascalCaseDocumentType} document state object. Validates against the schema of the version the state is stamped with. */
5247
+ export function ${v.assertIsPhStateOfTypeFunctionName}(
5248
+ state: unknown,
5249
+ ): asserts state is ${v.phStateName} {
5250
+ resolve${v.phStateName}Schema(state).parse(state);
5251
+ }
5252
+
5253
+ /** Simple helper function to check if a document is a ${v.pascalCaseDocumentType} document. Validates against the schema of the version the document is stamped with, so documents on older versions remain valid until they are upgraded. */
5254
+ export function ${v.isPhDocumentOfTypeFunctionName}(
5255
+ document: unknown,
5256
+ ): document is ${v.phDocumentTypeName} {
5257
+ return resolve${v.phDocumentSchemaName}(document).safeParse(document).success;
5258
+ }
5217
5259
 
5260
+ /** Simple helper function to assert that a document is a ${v.pascalCaseDocumentType} document. Validates against the schema of the version the document is stamped with, so documents on older versions remain valid until they are upgraded. */
5261
+ export function ${v.assertIsPhDocumentOfTypeFunctionName}(
5262
+ document: unknown,
5263
+ ): asserts document is ${v.phDocumentTypeName} {
5264
+ resolve${v.phDocumentSchemaName}(document).parse(document);
5265
+ }
5266
+ `;
5267
+ }
5268
+ function makeSingleVersionValidators(v) {
5269
+ return `
5218
5270
  /** Simple helper function to check if a state object is a ${v.pascalCaseDocumentType} document state object */
5219
5271
  export function ${v.isPhStateOfTypeFunctionName}(
5220
5272
  state: unknown,
@@ -5242,7 +5294,42 @@ export function ${v.assertIsPhDocumentOfTypeFunctionName}(
5242
5294
  ): asserts document is ${v.phDocumentTypeName} {
5243
5295
  ${v.phDocumentSchemaName}.parse(document);
5244
5296
  }
5245
- `.raw;
5297
+ `;
5298
+ }
5299
+ const documentModelDocumentSchemaFileTemplate = (v) => {
5300
+ const olderImports = makeOlderStateSchemaImports(v.versions, v.version, v.phStateName);
5301
+ const hasPriorVersions = olderImports.length > 0;
5302
+ return ts$1`
5303
+ /**
5304
+ * WARNING: DO NOT EDIT
5305
+ * This file is auto-generated and updated by codegen
5306
+ */
5307
+ import {
5308
+ BaseDocumentHeaderSchema,
5309
+ BaseDocumentStateSchema,${hasPriorVersions ? "\n normalizeDocumentModelVersion," : ""}
5310
+ } from "document-model";
5311
+ import { z } from "zod";
5312
+ import { ${v.documentTypeVariableName} } from "./document-type.js";
5313
+ import { ${v.stateSchemaName} } from "./schema/zod.js";
5314
+ import type { ${v.phDocumentTypeName}, ${v.phStateName} } from "./types.js";
5315
+ ${hasPriorVersions ? olderImports + "\n" : ""}
5316
+ /** Schema for validating the header object of a ${v.pascalCaseDocumentType} document */
5317
+ export const ${v.phDocumentTypeName}HeaderSchema = BaseDocumentHeaderSchema.extend({
5318
+ documentType: z.literal(${v.documentTypeVariableName}),
5319
+ });
5320
+
5321
+ /** Schema for validating the state object of a ${v.pascalCaseDocumentType} document */
5322
+ export const ${v.phStateName}Schema = BaseDocumentStateSchema.extend({
5323
+ global: ${v.stateSchemaName}(),
5324
+ });
5325
+
5326
+ export const ${v.phDocumentSchemaName} = z.object({
5327
+ header: ${v.phDocumentTypeName}HeaderSchema,
5328
+ state: ${v.phStateName}Schema,
5329
+ initialState: ${v.phStateName}Schema,
5330
+ });
5331
+ ${hasPriorVersions ? makeVersionAwareValidators(v) : makeSingleVersionValidators(v)}`.raw;
5332
+ };
5246
5333
  //#endregion
5247
5334
  //#region src/templates/document-model/gen/document-type.ts
5248
5335
  const documentModelDocumentTypeTemplate = (v) => ts$1`
@@ -6231,11 +6318,66 @@ const upgradeManifestTemplate = (v) => ts$1`
6231
6318
  `.raw;
6232
6319
  //#endregion
6233
6320
  //#region src/templates/document-model/upgrades/upgrade-transition.ts
6234
- const upgradeTransitionTemplate = (v) => ts$1`
6321
+ /**
6322
+ * The generated v{N}.ts upgrade transition. Written once and never
6323
+ * overwritten, so hand edits survive regeneration.
6324
+ *
6325
+ * For mechanical schema changes the migration is derived: fields added in
6326
+ * the new version are initialized (from the new version's initial value or
6327
+ * the schema's zero value) and existing data is preserved. When the change
6328
+ * cannot be derived — a field changed type, a nested type changed shape —
6329
+ * the reducer throws until the migration is hand-written: silently running
6330
+ * a no-op migration would stamp documents with a version whose schema their
6331
+ * state does not satisfy, crashing every consumer that validates them.
6332
+ */
6333
+ const upgradeTransitionTemplate = (v) => {
6334
+ const body = v.plan.kind === "manual" ? manualReducer(v, v.plan.reason) : fillReducer(v, v.plan.fills);
6335
+ return ts$1`
6336
+ /**
6337
+ * WARNING: DO NOT EDIT
6338
+ * This file is auto-generated and updated by codegen
6339
+ */
6235
6340
  import type { Action, PHDocument, UpgradeTransition } from "document-model";
6236
6341
  import type { ${v.phStateName} as StateV${v.version - 1} } from "${v.documentModelImportPath}/v${v.version - 1}";
6237
6342
  import type { ${v.phStateName} as StateV${v.version} } from "${v.documentModelImportPath}/v${v.version}";
6238
6343
 
6344
+ ${body}
6345
+
6346
+ export const v${v.version}: UpgradeTransition = {
6347
+ toVersion: ${v.version},
6348
+ upgradeReducer,
6349
+ description: "",
6350
+ };
6351
+ `.raw;
6352
+ };
6353
+ function manualReducer(v, reason) {
6354
+ const message = `The ${v.documentModelState.id} v${v.version} migration is not implemented: ${reason}. Implement it in document-models/${v.documentModelDirName}/upgrades/v${v.version}.ts.`;
6355
+ return `
6356
+ /*
6357
+ * This migration could not be derived automatically: ${reason}.
6358
+ * Implement it (migrate BOTH state and initialState), then remove the throw.
6359
+ */
6360
+ function upgradeReducer(
6361
+ document: PHDocument<StateV${v.version - 1}>,
6362
+ action: Action,
6363
+ ): PHDocument<StateV${v.version}> {
6364
+ throw new Error(${JSON.stringify(message)});
6365
+ }
6366
+ `;
6367
+ }
6368
+ function fillReducer(v, fills) {
6369
+ const fillConsts = [];
6370
+ const scopeLines = (source) => ["global", "local"].filter((scope) => fills[scope]).map((scope) => ` ${scope}: { ...added${capitalize$1(scope)}Fields, ...document.${source}.${scope} },`).join("\n");
6371
+ for (const scope of ["global", "local"]) {
6372
+ const fill = fills[scope];
6373
+ if (!fill) continue;
6374
+ fillConsts.push(`const added${capitalize$1(scope)}Fields = ${JSON.stringify(fill, null, 2)} satisfies Partial<StateV${v.version}["${scope}"]>;`);
6375
+ }
6376
+ if (fillConsts.length === 0) return `
6377
+ /*
6378
+ * No fields were added between v${v.version - 1} and v${v.version}, so existing state
6379
+ * carries over unchanged.
6380
+ */
6239
6381
  function upgradeReducer(
6240
6382
  document: PHDocument<StateV${v.version - 1}>,
6241
6383
  action: Action,
@@ -6244,13 +6386,37 @@ function upgradeReducer(
6244
6386
  ...document,
6245
6387
  };
6246
6388
  }
6389
+ `;
6390
+ return `
6391
+ ${fillConsts.join("\n\n")}
6247
6392
 
6248
- export const v${v.version}: UpgradeTransition = {
6249
- toVersion: ${v.version},
6250
- upgradeReducer,
6251
- description: "",
6252
- };
6253
- `.raw;
6393
+ /*
6394
+ * Fields added in v${v.version} are initialized from the new version's initial
6395
+ * value (or the schema's zero value); existing data wins for every field
6396
+ * that already existed. Both state and initialState are migrated so a
6397
+ * rebuild from the operation log converges with the stored state.
6398
+ */
6399
+ function upgradeReducer(
6400
+ document: PHDocument<StateV${v.version - 1}>,
6401
+ action: Action,
6402
+ ): PHDocument<StateV${v.version}> {
6403
+ return {
6404
+ ...document,
6405
+ state: {
6406
+ ...document.state,
6407
+ ${scopeLines("state")}
6408
+ },
6409
+ initialState: {
6410
+ ...document.initialState,
6411
+ ${scopeLines("initialState")}
6412
+ },
6413
+ };
6414
+ }
6415
+ `;
6416
+ }
6417
+ function capitalize$1(value) {
6418
+ return value.charAt(0).toUpperCase() + value.slice(1);
6419
+ }
6254
6420
  //#endregion
6255
6421
  //#region src/templates/document-model/utils.ts
6256
6422
  const documentModelUtilsTemplate = ({ phStateName, pascalCaseDocumentType }) => ts$1`
@@ -8052,13 +8218,253 @@ async function makeDocumentModelTestFile(args) {
8052
8218
  await formatSourceFileWithPrettier(sourceFile);
8053
8219
  }
8054
8220
  //#endregion
8221
+ //#region src/file-builders/document-model/upgrade-migration.ts
8222
+ /**
8223
+ * Derives the migration between two consecutive spec versions. Mechanical
8224
+ * changes — field additions on the scope's state type (initialized from the
8225
+ * new version's initial value, falling back to the schema's zero value) and
8226
+ * field removals — produce a "fill" plan. Anything else (changed field
8227
+ * types, edits to nested types that pre-existing documents reference,
8228
+ * additions codegen cannot synthesize a value for) produces a "manual" plan.
8229
+ */
8230
+ function buildMigrationPlan(args) {
8231
+ const { previousSpec, specification, stateName, localStateName } = args;
8232
+ if (!previousSpec) return {
8233
+ kind: "manual",
8234
+ reason: "the previous specification version is not available"
8235
+ };
8236
+ const fills = {};
8237
+ const scopes = [{
8238
+ scope: "global",
8239
+ typeName: stateName
8240
+ }, {
8241
+ scope: "local",
8242
+ typeName: localStateName
8243
+ }];
8244
+ for (const { scope, typeName } of scopes) {
8245
+ const oldState = previousSpec.state[scope];
8246
+ const newState = specification.state[scope];
8247
+ const analysis = analyzeScope({
8248
+ oldSchema: oldState?.schema ?? "",
8249
+ newSchema: newState?.schema ?? "",
8250
+ newInitialValue: newState?.initialValue ?? "",
8251
+ typeName,
8252
+ scope
8253
+ });
8254
+ if (analysis.kind === "manual") return analysis;
8255
+ if (analysis.fill && Object.keys(analysis.fill).length > 0) fills[scope] = analysis.fill;
8256
+ }
8257
+ return {
8258
+ kind: "fill",
8259
+ fills
8260
+ };
8261
+ }
8262
+ function analyzeScope(args) {
8263
+ const { oldSchema, newSchema, newInitialValue, typeName, scope } = args;
8264
+ const oldDoc = safeParseSdl(oldSchema);
8265
+ const newDoc = safeParseSdl(newSchema);
8266
+ if (oldSchema.trim() && !oldDoc) return {
8267
+ kind: "manual",
8268
+ reason: `the previous ${scope} state schema could not be parsed`
8269
+ };
8270
+ if (newSchema.trim() && !newDoc) return {
8271
+ kind: "manual",
8272
+ reason: `the new ${scope} state schema could not be parsed`
8273
+ };
8274
+ const oldType = oldDoc ? findObjectType(oldDoc, typeName) : void 0;
8275
+ const newType = newDoc ? findObjectType(newDoc, typeName) : void 0;
8276
+ if (!newType || !newDoc) return {
8277
+ kind: "fill",
8278
+ fill: void 0
8279
+ };
8280
+ if (oldType && oldDoc) {
8281
+ const oldReachable = collectReachableTypes(oldDoc, typeName);
8282
+ for (const [name, oldDefinition] of oldReachable) {
8283
+ if (name === typeName) continue;
8284
+ const newDefinition = findTypeDefinition(newDoc, name);
8285
+ if (!newDefinition) continue;
8286
+ if (print(oldDefinition) !== print(newDefinition)) return {
8287
+ kind: "manual",
8288
+ reason: `the ${scope} state type "${name}" changed between versions`
8289
+ };
8290
+ }
8291
+ }
8292
+ const oldFields = new Map((oldType?.fields ?? []).map((field) => [field.name.value, field]));
8293
+ const newFields = newType.fields ?? [];
8294
+ const initialValueObject = safeParseJsonRecord(newInitialValue);
8295
+ const fill = {};
8296
+ for (const field of newFields) {
8297
+ const fieldName = field.name.value;
8298
+ const oldField = oldFields.get(fieldName);
8299
+ if (oldField) {
8300
+ if (print(oldField.type) !== print(field.type)) return {
8301
+ kind: "manual",
8302
+ reason: `the ${scope} state field "${fieldName}" changed type between versions`
8303
+ };
8304
+ continue;
8305
+ }
8306
+ if (initialValueObject && fieldName in initialValueObject) {
8307
+ fill[fieldName] = initialValueObject[fieldName];
8308
+ continue;
8309
+ }
8310
+ const zero = zeroValueForType(field.type, newDoc, /* @__PURE__ */ new Set());
8311
+ if (!zero.ok) return {
8312
+ kind: "manual",
8313
+ reason: `no initial value could be derived for the added ${scope} state field "${fieldName}"`
8314
+ };
8315
+ fill[fieldName] = zero.value;
8316
+ }
8317
+ return {
8318
+ kind: "fill",
8319
+ fill
8320
+ };
8321
+ }
8322
+ function zeroValueForType(typeNode, schemaDoc, visitedTypes) {
8323
+ if (typeNode.kind !== Kind.NON_NULL_TYPE) return {
8324
+ ok: true,
8325
+ value: null
8326
+ };
8327
+ const inner = typeNode.type;
8328
+ if (inner.kind === Kind.LIST_TYPE) return {
8329
+ ok: true,
8330
+ value: []
8331
+ };
8332
+ const name = inner.name.value;
8333
+ switch (name) {
8334
+ case "String":
8335
+ case "ID": return {
8336
+ ok: true,
8337
+ value: ""
8338
+ };
8339
+ case "Int":
8340
+ case "Float": return {
8341
+ ok: true,
8342
+ value: 0
8343
+ };
8344
+ case "Boolean": return {
8345
+ ok: true,
8346
+ value: false
8347
+ };
8348
+ }
8349
+ const definition = findTypeDefinition(schemaDoc, name);
8350
+ if (!definition) {
8351
+ const defaultValue = getPHCustomScalarByTypeName(name)?.getDefaultValue?.();
8352
+ if (defaultValue !== void 0) return {
8353
+ ok: true,
8354
+ value: defaultValue
8355
+ };
8356
+ return { ok: false };
8357
+ }
8358
+ if (definition.kind === Kind.ENUM_TYPE_DEFINITION) return zeroValueForEnum(definition);
8359
+ if (definition.kind === Kind.OBJECT_TYPE_DEFINITION) {
8360
+ if (visitedTypes.has(name)) return { ok: false };
8361
+ visitedTypes.add(name);
8362
+ const value = {};
8363
+ for (const field of definition.fields ?? []) {
8364
+ const fieldZero = zeroValueForType(field.type, schemaDoc, visitedTypes);
8365
+ if (!fieldZero.ok) return { ok: false };
8366
+ value[field.name.value] = fieldZero.value;
8367
+ }
8368
+ visitedTypes.delete(name);
8369
+ return {
8370
+ ok: true,
8371
+ value
8372
+ };
8373
+ }
8374
+ if (definition.kind === Kind.SCALAR_TYPE_DEFINITION) {
8375
+ const defaultValue = getPHCustomScalarByTypeName(name)?.getDefaultValue?.();
8376
+ if (defaultValue !== void 0) return {
8377
+ ok: true,
8378
+ value: defaultValue
8379
+ };
8380
+ return { ok: false };
8381
+ }
8382
+ return { ok: false };
8383
+ }
8384
+ function zeroValueForEnum(definition) {
8385
+ const first = definition.values?.[0]?.name.value;
8386
+ if (first === void 0) return { ok: false };
8387
+ return {
8388
+ ok: true,
8389
+ value: first
8390
+ };
8391
+ }
8392
+ function collectReachableTypes(schemaDoc, rootTypeName) {
8393
+ const reachable = /* @__PURE__ */ new Map();
8394
+ const queue = [rootTypeName];
8395
+ while (queue.length > 0) {
8396
+ const name = queue.shift();
8397
+ if (reachable.has(name)) continue;
8398
+ const definition = findTypeDefinition(schemaDoc, name);
8399
+ if (!definition) continue;
8400
+ reachable.set(name, definition);
8401
+ if (definition.kind === Kind.OBJECT_TYPE_DEFINITION) for (const field of definition.fields ?? []) queue.push(namedTypeOf(field.type));
8402
+ else if (definition.kind === Kind.UNION_TYPE_DEFINITION) for (const member of definition.types ?? []) queue.push(member.name.value);
8403
+ }
8404
+ return reachable;
8405
+ }
8406
+ function namedTypeOf(typeNode) {
8407
+ let node = typeNode;
8408
+ while (node.kind !== Kind.NAMED_TYPE) node = node.type;
8409
+ return node.name.value;
8410
+ }
8411
+ function findObjectType(schemaDoc, name) {
8412
+ const definition = findTypeDefinition(schemaDoc, name);
8413
+ return definition?.kind === Kind.OBJECT_TYPE_DEFINITION ? definition : void 0;
8414
+ }
8415
+ function findTypeDefinition(schemaDoc, name) {
8416
+ for (const definition of schemaDoc.definitions) switch (definition.kind) {
8417
+ case Kind.OBJECT_TYPE_DEFINITION:
8418
+ case Kind.ENUM_TYPE_DEFINITION:
8419
+ case Kind.SCALAR_TYPE_DEFINITION:
8420
+ case Kind.UNION_TYPE_DEFINITION:
8421
+ case Kind.INTERFACE_TYPE_DEFINITION:
8422
+ case Kind.INPUT_OBJECT_TYPE_DEFINITION: if (definition.name.value === name) return definition;
8423
+ }
8424
+ }
8425
+ function safeParseSdl(sdl) {
8426
+ if (!sdl.trim()) return null;
8427
+ try {
8428
+ return parse(sdl);
8429
+ } catch {
8430
+ return null;
8431
+ }
8432
+ }
8433
+ function safeParseJsonRecord(json) {
8434
+ if (!json.trim()) return null;
8435
+ try {
8436
+ const parsed = JSON.parse(json);
8437
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) return parsed;
8438
+ return null;
8439
+ } catch {
8440
+ return null;
8441
+ }
8442
+ }
8443
+ /**
8444
+ * Serializes a fill value to TypeScript source. Fill values come from JSON
8445
+ * (initial values) or the zero-value synthesizer, so JSON serialization is
8446
+ * sufficient.
8447
+ */
8448
+ function fillToTsLiteral(fill) {
8449
+ return JSON.stringify(fill, null, 2);
8450
+ }
8451
+ //#endregion
8055
8452
  //#region src/file-builders/document-model/upgrades-dir.ts
8056
8453
  async function makeUpgradeFile(args) {
8057
8454
  const { project, version, upgradesDirPath } = args;
8058
8455
  if (version < 2) return;
8059
8456
  const { alreadyExists, sourceFile } = getOrCreateSourceFile(project, path.join(upgradesDirPath, `v${version}.ts`));
8060
8457
  if (alreadyExists) return;
8061
- const template = upgradeTransitionTemplate(args);
8458
+ const plan = buildMigrationPlan({
8459
+ previousSpec: args.documentModelState.specifications.find((specification) => specification.version === version - 1),
8460
+ specification: args.specification,
8461
+ stateName: args.stateName,
8462
+ localStateName: args.localStateName
8463
+ });
8464
+ const template = upgradeTransitionTemplate({
8465
+ ...args,
8466
+ plan
8467
+ });
8062
8468
  sourceFile.replaceWithText(template);
8063
8469
  await formatSourceFileWithPrettier(sourceFile);
8064
8470
  }
@@ -8340,6 +8746,10 @@ async function makeDocumentModelsIndexFile(args) {
8340
8746
  moduleSpecifier
8341
8747
  });
8342
8748
  }));
8749
+ sourceFile.addExportDeclaration({
8750
+ namedExports: ["upgradeManifests"],
8751
+ moduleSpecifier: "./upgrade-manifests.js"
8752
+ });
8343
8753
  await formatSourceFileWithPrettier(sourceFile);
8344
8754
  }
8345
8755
  /** Writes a json file derived from a `documentModelState` */
@@ -8718,6 +9128,6 @@ async function makeSubgraphsIndexFile(args) {
8718
9128
  await formatSourceFileWithPrettier(sourceFile);
8719
9129
  }
8720
9130
  //#endregion
8721
- export { getVariableDeclarationByTypeName as $, upgradeManifestsTemplate as $n, documentModelPhFactoriesFileTemplate as $t, writeGeneratedProcessorsFiles as A, readmeTemplate as An, factoryBuildersTemplate as At, updateVersionedImports as B, mainTsxTemplate as Bn, makeOperationImportNames as Bt, buildBoilerplatePackageJson as C, documentEditorEditorFileTemplate as Cn, relationalDbSchemaTemplate as Ct, writeCIFiles as D, tsconfigPathsTemplate as Dn, relationalDbFactoryTemplate as Dt, writeAllGeneratedProjectFiles as E, tsConfigTemplate as En, relationalDbIndexTemplate as Et, tsMorphGenerateApp as F, pnpmWorkspaceTemplate as Fn, renderProcessorFilter as Ft, getAllImportModuleSpecifiers as G, indexHtmlTemplate as Gn, documentModelSrcIndexFileTemplate as Gt, DEFAULT_PROJECT_OPTIONS as H, reactorTsTemplate as Hn, makeTestCaseForOperation as Ht, makeEditorModuleFile as I, exportsTemplate as In, documentModelUtilsTemplate as It, getObjectLiteral as J, geminiSettingsTemplate as Jn, documentModelHooksFileTemplate as Jt, getAllImportNames as K, gitIgnoreTemplate as Kn, documentModelModuleFileTemplate as Kt, makeEditorsFile as L, packageJsonTemplate as Ln, upgradeTransitionTemplate as Lt, writeGeneratedSubgraphsFiles as M, buildPowerhouseConfigTemplate as Mn, analyticsIndexTemplate as Mt, writeModuleFiles as N, packageJsonExportsTemplate as Nn, analyticsFactoryTemplate as Nt, writeGeneratedDocumentModelsFiles as O, subgraphsIndexTemplate as On, processorsIndexTemplate as Ot, writeProjectRootFiles as P, packageJsonScriptsTemplate as Pn, parseFilterValues as Pt, getStringPropertyValue as Q, editorsTemplate as Qn, documentModelGenReducerFileTemplate as Qt, makeEditorsIndexFile as R, npmrcTemplate as Rn, upgradeManifestTemplate as Rt, writeCliDocsMarkdownFile as S, documentEditorModuleFileTemplate as Sn, subgraphIndexFileTemplate as St, writeAiConfigFiles as T, vitestConfigTemplate as Tn, relationalDbMigrationsTemplate as Tt, buildTsMorphProject as U, indexTsTemplate as Un, documentModelTestFileTemplate as Ut, getInitialStates as V, licenseTemplate as Vn, makeOperationsImports as Vt, getDefaultProjectOptions as W, legacyIndexHtmlTemplate as Wn, documentModelSrcUtilsTemplate as Wt, getProperyAssignmentByName as X, oxlintConfigTemplate as Xn, documentModelGenTypesTemplate as Xt, getObjectProperty as Y, oxfmtConfigTemplate as Yn, documentModelGenUtilsTemplate as Yt, getStringArrayPropertyElements as Z, editorsIndexTemplate as Zn, documentModelSchemaIndexTemplate as Zt, scalarsValidation as _, documentModelDocumentSchemaFileTemplate as _n, appDriveContentsFileTemplate as _r, parseArgs as _t, getOrCreateManifestFile as a, getDocumentModelDirName as an, connectEntrypointTemplate as ar, getOrCreateSourceFile as at, getCommandsHelpInfo as b, documentModelGenActionsFileTemplate as bn, customSubgraphSchemaTemplate as bt, operationHasEmptyInput as c, getEditorVariableNames as cn, agentsTemplate as cr, getProcessorMetadata as ct, generateDocumentModelZodSchemas as d, getActionInputName as dn, driveExplorerNavigationBreadcrumbsFileTemplate as dr, formatSafe as dt, documentModelOperationsModuleOperationsFileTemplate as en, documentModelsIndexTemplate as er, loadDocumentModelInDir as et, generateTypesAndZodSchemasFromGraphql as f, getActionInputTypeNames as fn, folderTreeFileTemplate as fr, formatSourceFileWithPrettier as ft, scalars as g, documentModelDocumentTypeTemplate as gn, driveExplorerFileTemplate as gr, configSpec as gt, getMockOverrideFieldNames as h, documentModelGenIndexFileTemplate as hn, emptyStateFileTemplate as hr, documentModelDocumentTypeMetadata as ht, createOrUpdateManifest as i, getModuleExportType as in, dockerfileTemplate as ir, getOrCreateDirectory as it, writeGeneratedProjectRootFiles as j, ManifestTemplate as jn, analyticsProcessorTemplate as jt, writeGeneratedEditorsFiles as k, styleTemplate as kn, processorsFactoryTemplate as kt, operationHasInput as l, getLatestDocumentModelSpec as ln, appEditorFileTemplate as lr, getAppMetadata as lt, getInputFieldNames as m, getActionTypeName as mn, appFilesFileTemplate as mr, getDocumentTypeMetadata as mt, tsMorphGenerateSubgraph as n, documentModelOperationsModuleCreatorsFileTemplate as nn, switchboardEntrypointTemplate as nr, buildStringLiteral as nt, pruneManifestSection as o, getDocumentModelSpecByVersionNumber as on, cursorMcpTemplate as or, getPreviousVersionSourceFile as ot, getDateLikeFieldNames as p, getActionType as pn, appFoldersFileTemplate as pr, runOxfmt as pt, getBooleanPropertyValue as q, syncAndPublishWorkflowTemplate as qn, documentModelIndexTemplate as qt, tsMorphGenerateProcessor as r, documentModelOperationModuleActionsFileTemplate as rn, nginxConfTemplate as rr, ensureDirectoriesExist as rt, makeModulesIndexFile as s, getDocumentModelVariableNames as sn, claudeSettingsLocalTemplate as sr, getSubgraphMetadata as st, makeSubgraphsIndexFile as t, documentModelOperationsModuleErrorFileTemplate as tn, documentModelsTemplate as tr, buildObjectLiteral as tt, tsMorphGenerateDocumentModel as u, getLatestDocumentModelSpecVersionNumber as un, appConfigFileTemplate as ur, getEditorMetadata as ut, tsMorphGenerateDocumentEditor as v, documentModelGenCreatorsFileTemplate as vn, createDocumentFileTemplate as vr, parseConfig as vt, applyProjectCustomizations as w, docsFromCliHelpTemplate as wn, relationalDbProcessorTemplate as wt, makeCliDocsFromHelp as x, documentModelRootActionsFileTemplate as xn, subgraphLibFileTemplate as xt, getCommandHelpInfo as y, documentModelGenControllerFileTemplate as yn, customSubgraphResolversTemplate as yt, validateDocumentModelState as z, mcpTemplate as zn, documentModelOperationsModuleTestFileTemplate as zt };
9131
+ export { getStringArrayPropertyElements as $, editorsIndexTemplate as $n, documentModelSchemaIndexTemplate as $t, writeGeneratedDocumentModelsFiles as A, subgraphsIndexTemplate as An, processorsIndexTemplate as At, makeEditorsIndexFile as B, npmrcTemplate as Bn, upgradeManifestTemplate as Bt, makeCliDocsFromHelp as C, documentModelRootActionsFileTemplate as Cn, subgraphLibFileTemplate as Ct, writeAiConfigFiles as D, vitestConfigTemplate as Dn, relationalDbMigrationsTemplate as Dt, applyProjectCustomizations as E, docsFromCliHelpTemplate as En, relationalDbProcessorTemplate as Et, writeModuleFiles as F, packageJsonExportsTemplate as Fn, analyticsFactoryTemplate as Ft, buildTsMorphProject as G, indexTsTemplate as Gn, documentModelTestFileTemplate as Gt, updateVersionedImports as H, mainTsxTemplate as Hn, makeOperationImportNames as Ht, writeProjectRootFiles as I, packageJsonScriptsTemplate as In, parseFilterValues as It, getAllImportNames as J, gitIgnoreTemplate as Jn, documentModelModuleFileTemplate as Jt, getDefaultProjectOptions as K, legacyIndexHtmlTemplate as Kn, documentModelSrcUtilsTemplate as Kt, tsMorphGenerateApp as L, pnpmWorkspaceTemplate as Ln, renderProcessorFilter as Lt, writeGeneratedProcessorsFiles as M, readmeTemplate as Mn, factoryBuildersTemplate as Mt, writeGeneratedProjectRootFiles as N, ManifestTemplate as Nn, analyticsProcessorTemplate as Nt, writeAllGeneratedProjectFiles as O, tsConfigTemplate as On, relationalDbIndexTemplate as Ot, writeGeneratedSubgraphsFiles as P, buildPowerhouseConfigTemplate as Pn, analyticsIndexTemplate as Pt, getProperyAssignmentByName as Q, oxlintConfigTemplate as Qn, documentModelGenTypesTemplate as Qt, makeEditorModuleFile as R, exportsTemplate as Rn, documentModelUtilsTemplate as Rt, getCommandsHelpInfo as S, documentModelGenActionsFileTemplate as Sn, customSubgraphSchemaTemplate as St, buildBoilerplatePackageJson as T, documentEditorEditorFileTemplate as Tn, relationalDbSchemaTemplate as Tt, getInitialStates as U, licenseTemplate as Un, makeOperationsImports as Ut, validateDocumentModelState as V, mcpTemplate as Vn, documentModelOperationsModuleTestFileTemplate as Vt, DEFAULT_PROJECT_OPTIONS as W, reactorTsTemplate as Wn, makeTestCaseForOperation as Wt, getObjectLiteral as X, geminiSettingsTemplate as Xn, documentModelHooksFileTemplate as Xt, getBooleanPropertyValue as Y, syncAndPublishWorkflowTemplate as Yn, documentModelIndexTemplate as Yt, getObjectProperty as Z, oxfmtConfigTemplate as Zn, documentModelGenUtilsTemplate as Zt, getMockOverrideFieldNames as _, documentModelGenIndexFileTemplate as _n, emptyStateFileTemplate as _r, documentModelDocumentTypeMetadata as _t, getOrCreateManifestFile as a, documentModelOperationModuleActionsFileTemplate as an, nginxConfTemplate as ar, ensureDirectoriesExist as at, tsMorphGenerateDocumentEditor as b, documentModelGenCreatorsFileTemplate as bn, createDocumentFileTemplate as br, parseConfig as bt, operationHasEmptyInput as c, getDocumentModelSpecByVersionNumber as cn, cursorMcpTemplate as cr, getPreviousVersionSourceFile as ct, buildMigrationPlan as d, getLatestDocumentModelSpec as dn, appEditorFileTemplate as dr, getAppMetadata as dt, documentModelGenReducerFileTemplate as en, editorsTemplate as er, getStringPropertyValue as et, fillToTsLiteral as f, getLatestDocumentModelSpecVersionNumber as fn, appConfigFileTemplate as fr, getEditorMetadata as ft, getInputFieldNames as g, getActionTypeName as gn, appFilesFileTemplate as gr, getDocumentTypeMetadata as gt, getDateLikeFieldNames as h, getActionType as hn, appFoldersFileTemplate as hr, runOxfmt as ht, createOrUpdateManifest as i, documentModelOperationsModuleCreatorsFileTemplate as in, switchboardEntrypointTemplate as ir, buildStringLiteral as it, writeGeneratedEditorsFiles as j, styleTemplate as jn, processorsFactoryTemplate as jt, writeCIFiles as k, tsconfigPathsTemplate as kn, relationalDbFactoryTemplate as kt, operationHasInput as l, getDocumentModelVariableNames as ln, claudeSettingsLocalTemplate as lr, getSubgraphMetadata as lt, generateTypesAndZodSchemasFromGraphql as m, getActionInputTypeNames as mn, folderTreeFileTemplate as mr, formatSourceFileWithPrettier as mt, tsMorphGenerateSubgraph as n, documentModelOperationsModuleOperationsFileTemplate as nn, documentModelsIndexTemplate as nr, loadDocumentModelInDir as nt, pruneManifestSection as o, getModuleExportType as on, dockerfileTemplate as or, getOrCreateDirectory as ot, generateDocumentModelZodSchemas as p, getActionInputName as pn, driveExplorerNavigationBreadcrumbsFileTemplate as pr, formatSafe as pt, getAllImportModuleSpecifiers as q, indexHtmlTemplate as qn, documentModelSrcIndexFileTemplate as qt, tsMorphGenerateProcessor as r, documentModelOperationsModuleErrorFileTemplate as rn, documentModelsTemplate as rr, buildObjectLiteral as rt, makeModulesIndexFile as s, getDocumentModelDirName as sn, connectEntrypointTemplate as sr, getOrCreateSourceFile as st, makeSubgraphsIndexFile as t, documentModelPhFactoriesFileTemplate as tn, upgradeManifestsTemplate as tr, getVariableDeclarationByTypeName as tt, tsMorphGenerateDocumentModel as u, getEditorVariableNames as un, agentsTemplate as ur, getProcessorMetadata as ut, scalars as v, documentModelDocumentTypeTemplate as vn, driveExplorerFileTemplate as vr, configSpec as vt, writeCliDocsMarkdownFile as w, documentEditorModuleFileTemplate as wn, subgraphIndexFileTemplate as wt, getCommandHelpInfo as x, documentModelGenControllerFileTemplate as xn, customSubgraphResolversTemplate as xt, scalarsValidation as y, documentModelDocumentSchemaFileTemplate as yn, appDriveContentsFileTemplate as yr, parseArgs as yt, makeEditorsFile as z, packageJsonTemplate as zn, upgradeTransitionTemplate as zt };
8722
9132
 
8723
- //# sourceMappingURL=file-builders-DaV8C_6p.mjs.map
9133
+ //# sourceMappingURL=file-builders-B4QZXx5u.mjs.map