@percepta/create 4.1.7 → 4.1.9

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 (63) hide show
  1. package/dist/{git-ops-BD7JNnal.js → git-ops-BNpQnEc1.js} +1 -1
  2. package/dist/{git-ops-BD7JNnal.js.map → git-ops-BNpQnEc1.js.map} +1 -1
  3. package/dist/{github-D3YOEl91.js → github-BOp8VQCY.js} +1 -1
  4. package/dist/{github-D3YOEl91.js.map → github-BOp8VQCY.js.map} +1 -1
  5. package/dist/index.js +185 -28
  6. package/dist/index.js.map +1 -1
  7. package/dist/{init-BD3EyyLO.js → init-CsuO_mu2.js} +2 -4
  8. package/dist/{init-BD3EyyLO.js.map → init-CsuO_mu2.js.map} +1 -1
  9. package/dist/{register-app-DZg-Pmtd.js → register-app-B9vKTkoI.js} +89 -37
  10. package/dist/register-app-B9vKTkoI.js.map +1 -0
  11. package/dist/{register-os-blueprint-Cgq1rXzQ.js → register-os-blueprint-Gdyn0pN1.js} +3 -4
  12. package/dist/{register-os-blueprint-Cgq1rXzQ.js.map → register-os-blueprint-Gdyn0pN1.js.map} +1 -1
  13. package/dist/{status-K6raTwwu.js → status-BrK9v1yb.js} +3 -3
  14. package/dist/{status-K6raTwwu.js.map → status-BrK9v1yb.js.map} +1 -1
  15. package/dist/{sync-Bi958-2W.js → sync-DC5DhIBT.js} +3 -3
  16. package/dist/{sync-Bi958-2W.js.map → sync-DC5DhIBT.js.map} +1 -1
  17. package/dist/{upstream-CAraZeSS.js → upstream-PNL6DGtl.js} +3 -3
  18. package/dist/{upstream-CAraZeSS.js.map → upstream-PNL6DGtl.js.map} +1 -1
  19. package/package.json +3 -3
  20. package/template-versions.json +2 -2
  21. package/templates/infra/os.blueprint.yaml.template +13 -0
  22. package/templates/monorepo/auth/README.md +2 -2
  23. package/templates/monorepo/auth/package.json +1 -1
  24. package/templates/monorepo/auth/src/drizzle/migrations/meta/0000_snapshot.json +547 -0
  25. package/templates/monorepo/package.json.template +6 -6
  26. package/templates/monorepo/pnpm-workspace.yaml +9 -1
  27. package/templates/webapp/AGENTS.md +39 -17
  28. package/templates/webapp/README.md +58 -59
  29. package/templates/webapp/agent-skills/access-control.md +13 -12
  30. package/templates/webapp/agent-skills/database.md +12 -5
  31. package/templates/webapp/agent-skills/inngest.md +10 -8
  32. package/templates/webapp/agent-skills/langfuse.md +7 -5
  33. package/templates/webapp/agent-skills/oneshot.md +15 -13
  34. package/templates/webapp/next.config.ts +1 -1
  35. package/templates/webapp/package.json.template +6 -6
  36. package/templates/webapp/playwright.config.ts +1 -2
  37. package/templates/webapp/scripts/seed.ts +3 -3
  38. package/templates/webapp/src/app/(app)/page.tsx +5 -3
  39. package/templates/webapp/src/app/(auth)/layout.tsx +2 -2
  40. package/templates/webapp/src/app/(settings)/settings/page.tsx +21 -22
  41. package/templates/webapp/src/components/FaroProvider.tsx +1 -2
  42. package/templates/webapp/src/components/Header.tsx +2 -8
  43. package/templates/webapp/src/components/form/FormItem.tsx +1 -1
  44. package/templates/webapp/src/drizzle/db.ts +3 -1
  45. package/templates/webapp/src/drizzle/schema/index.ts +1 -1
  46. package/templates/webapp/src/drizzle/schema/utils/jsonbFromZod.ts +1 -1
  47. package/templates/webapp/src/instrumentation.ts +3 -6
  48. package/templates/webapp/src/lib/auth/index.ts +2 -2
  49. package/templates/webapp/src/lib/auth-client.ts +3 -2
  50. package/templates/webapp/src/lib/trpc.ts +1 -1
  51. package/templates/webapp/src/server/trpc.ts +1 -1
  52. package/templates/webapp/src/services/DatabaseService.ts +1 -1
  53. package/templates/webapp/src/services/access/AppAccessControl.ts +1 -3
  54. package/templates/webapp/src/services/inngest/AppWorkflowService.ts +1 -1
  55. package/templates/webapp/src/startup-checks.ts +1 -1
  56. package/templates/webapp/src/styles/globals.css +13 -2
  57. package/dist/manifest-By1SgOjC.js +0 -59
  58. package/dist/manifest-By1SgOjC.js.map +0 -1
  59. package/dist/register-app-DZg-Pmtd.js.map +0 -1
  60. package/dist/template-versions-CEIP9vhl.js +0 -35
  61. package/dist/template-versions-CEIP9vhl.js.map +0 -1
  62. package/dist/validate-dssldJAj.js +0 -14
  63. package/dist/validate-dssldJAj.js.map +0 -1
@@ -1,7 +1,5 @@
1
- import { i as toTitleCase, n as toKebabCase, r as toSnakeCase } from "./template-versions-CEIP9vhl.js";
2
- import { t as validateProjectName } from "./validate-dssldJAj.js";
3
- import { i as detectMonorepo, t as readWorkspaceManifest } from "./index.js";
4
- import { a as createOrUpdateInfraPullRequestFiles, n as INFRA_REPOSITORY, o as resolveGitHubToken, r as createInfraGitHubApi, t as INFRA_BASE_BRANCH } from "./github-D3YOEl91.js";
1
+ import { a as validateProjectName, d as detectMonorepo, f as toKebabCase, m as toTitleCase, p as toSnakeCase, t as readWorkspaceManifest } from "./index.js";
2
+ import { a as createOrUpdateInfraPullRequestFiles, n as INFRA_REPOSITORY, o as resolveGitHubToken, r as createInfraGitHubApi, t as INFRA_BASE_BRANCH } from "./github-BOp8VQCY.js";
5
3
  import path from "node:path";
6
4
  import chalk from "chalk";
7
5
  import fs from "fs-extra";
@@ -143,6 +141,8 @@ function updateBlueprint(blueprintContent, appName, options) {
143
141
  changed = addAppInput(document, inputs, renderBetterAuthSecretInput(appName)) || changed;
144
142
  changed = addAppInput(document, inputs, renderLangfusePublicKeyInput()) || changed;
145
143
  changed = addAppInput(document, inputs, renderLangfuseSecretKeyInput()) || changed;
144
+ changed = addAppInput(document, inputs, renderInngestEventKeyInput()) || changed;
145
+ changed = addAppInput(document, inputs, renderInngestSigningKeyInput()) || changed;
146
146
  }
147
147
  if (options.appDatabase) changed = addAppDatabase(document, inputs, appName) || changed;
148
148
  if (options.appInstallation) {
@@ -192,8 +192,7 @@ function addAppDatabase(document, inputs, appName) {
192
192
  if (!isMap(defaultValue)) throw new Error("OS blueprint app_databases default must be a map.");
193
193
  if (defaultValue.has(appName)) return false;
194
194
  defaultValue.flow = false;
195
- const appDatabaseValue = document.createNode({});
196
- if (isMap(appDatabaseValue)) appDatabaseValue.flow = true;
195
+ const appDatabaseValue = document.createNode({ schema_name: toSnakeCase(appName) });
197
196
  defaultValue.set(appName, appDatabaseValue);
198
197
  return true;
199
198
  }
@@ -252,8 +251,28 @@ function renderLangfuseSecretKeyInput() {
252
251
  condition: `{{ ne (input "${langfusePublicKeyInputName()}") "" }}`
253
252
  };
254
253
  }
254
+ function renderInngestEventKeyInput() {
255
+ return {
256
+ name: inngestEventKeyInputName(),
257
+ type: "string",
258
+ isSecret: true,
259
+ group: "applications",
260
+ displayName: "Inngest Event Key",
261
+ description: "Shared Inngest event key for generated OS webapps."
262
+ };
263
+ }
264
+ function renderInngestSigningKeyInput() {
265
+ return {
266
+ name: inngestSigningKeyInputName(),
267
+ type: "string",
268
+ isSecret: true,
269
+ group: "applications",
270
+ displayName: "Inngest Signing Key",
271
+ description: "Shared Inngest signing key for generated OS webapps."
272
+ };
273
+ }
255
274
  function renderAppInstallationEnv(appName) {
256
- const appHost = `${appName}.{{ input "${ingressDomainInputName()}" }}`;
275
+ const appInternalEndpoint = `http://${appName}-web-server.{{ .ryvn.env.name }}.svc.cluster.local:3000/api/inngest`;
257
276
  return [
258
277
  {
259
278
  key: "DATABASE_URL",
@@ -271,13 +290,25 @@ function renderAppInstallationEnv(appName) {
271
290
  name: "auth_database_url"
272
291
  }
273
292
  },
293
+ {
294
+ key: "DATABASE_SCHEMA",
295
+ value: toSnakeCase(appName)
296
+ },
297
+ {
298
+ key: "INGRESS_DOMAIN",
299
+ valueFromInput: { name: ingressDomainInputName() }
300
+ },
274
301
  {
275
302
  key: "APP_BASE_URL",
276
- value: `https://${appHost}`
303
+ value: `https://${appName}.$(INGRESS_DOMAIN)`
304
+ },
305
+ {
306
+ key: "BETTER_AUTH_URL",
307
+ value: `https://${appName}.$(INGRESS_DOMAIN)`
277
308
  },
278
309
  {
279
310
  key: "DEPLOYMENT_ENVIRONMENT",
280
- value: "{{ EnvironmentName }}"
311
+ value: "{{ .ryvn.env.name }}"
281
312
  },
282
313
  {
283
314
  key: "BETTER_AUTH_SECRET",
@@ -286,11 +317,35 @@ function renderAppInstallationEnv(appName) {
286
317
  },
287
318
  {
288
319
  key: "INNGEST_BASE_URL",
289
- value: "{{ (blueprintInstallation \"mosaic\").outputs.inngest_base_url }}"
320
+ valueFromOutput: {
321
+ blueprintInstallation: "mosaic",
322
+ name: "inngest_base_url"
323
+ }
324
+ },
325
+ {
326
+ key: "INNGEST_EVENT_KEY",
327
+ isSecret: true,
328
+ valueFromInput: { name: inngestEventKeyInputName() }
329
+ },
330
+ {
331
+ key: "INNGEST_SIGNING_KEY",
332
+ isSecret: true,
333
+ valueFromInput: { name: inngestSigningKeyInputName() }
334
+ },
335
+ {
336
+ key: "INNGEST_APP_URL",
337
+ value: appInternalEndpoint
338
+ },
339
+ {
340
+ key: "INNGEST_SERVE_HOST",
341
+ value: appInternalEndpoint
290
342
  },
291
343
  {
292
344
  key: "LANGFUSE_BASE_URL",
293
- value: "{{ (blueprintInstallation \"mosaic\").outputs.langfuse_base_url }}"
345
+ valueFromOutput: {
346
+ blueprintInstallation: "mosaic",
347
+ name: "langfuse_internal_url"
348
+ }
294
349
  },
295
350
  {
296
351
  key: "LANGFUSE_PUBLIC_KEY",
@@ -303,20 +358,32 @@ function renderAppInstallationEnv(appName) {
303
358
  },
304
359
  {
305
360
  key: "OTEL_EXPORTER_OTLP_ENDPOINT",
306
- value: "{{ (blueprintInstallation \"mosaic\").outputs.otel_exporter_otlp_endpoint }}"
361
+ valueFromOutput: {
362
+ blueprintInstallation: "mosaic",
363
+ name: "otel_exporter_otlp_endpoint"
364
+ }
307
365
  },
308
366
  {
309
367
  key: "SPICEDB_ENDPOINT",
310
- value: "{{ (blueprintInstallation \"mosaic\").outputs.spicedb_endpoint }}"
368
+ valueFromOutput: {
369
+ blueprintInstallation: "mosaic",
370
+ name: "spicedb_endpoint"
371
+ }
311
372
  },
312
373
  {
313
374
  key: "SPICEDB_PRESHARED_KEY",
314
375
  isSecret: true,
315
- value: "{{ (blueprintInstallation \"mosaic\").outputs.spicedb_preshared_key }}"
376
+ valueFromOutput: {
377
+ blueprintInstallation: "mosaic",
378
+ name: "spicedb_preshared_key"
379
+ }
316
380
  },
317
381
  {
318
382
  key: "SPICEDB_INSECURE",
319
- value: "{{ (blueprintInstallation \"mosaic\").outputs.spicedb_insecure }}"
383
+ valueFromOutput: {
384
+ blueprintInstallation: "mosaic",
385
+ name: "spicedb_insecure"
386
+ }
320
387
  }
321
388
  ];
322
389
  }
@@ -332,18 +399,6 @@ function renderAppInstallationConfig(appName) {
332
399
  "readinessEnabled: true",
333
400
  "startupEnabled: true",
334
401
  "",
335
- "env:",
336
- " - name: INNGEST_EVENT_KEY",
337
- " valueFrom:",
338
- " secretKeyRef:",
339
- ` name: '{{ (blueprintInstallation "mosaic").outputs.${mosaicInngestKeysSecretNameOutput()} }}'`,
340
- ` key: '{{ (blueprintInstallation "mosaic").outputs.${mosaicInngestEventKeySecretKeyOutput()} }}'`,
341
- " - name: INNGEST_SIGNING_KEY",
342
- " valueFrom:",
343
- " secretKeyRef:",
344
- ` name: '{{ (blueprintInstallation "mosaic").outputs.${mosaicInngestKeysSecretNameOutput()} }}'`,
345
- ` key: '{{ (blueprintInstallation "mosaic").outputs.${mosaicInngestSigningKeySecretKeyOutput()} }}'`,
346
- "",
347
402
  "resources:",
348
403
  " requests:",
349
404
  " cpu: \"100m\"",
@@ -389,21 +444,18 @@ function ingressDomainInputName() {
389
444
  function betterAuthSecretInputName(appName) {
390
445
  return `${toSnakeCase(appName)}_better_auth_secret`;
391
446
  }
392
- function mosaicInngestKeysSecretNameOutput() {
393
- return "inngest_keys_secret_name";
394
- }
395
- function mosaicInngestEventKeySecretKeyOutput() {
396
- return "inngest_event_key_secret_key";
397
- }
398
- function mosaicInngestSigningKeySecretKeyOutput() {
399
- return "inngest_signing_key_secret_key";
400
- }
401
447
  function langfusePublicKeyInputName() {
402
448
  return "langfuse_public_key";
403
449
  }
404
450
  function langfuseSecretKeyInputName() {
405
451
  return "langfuse_secret_key";
406
452
  }
453
+ function inngestEventKeyInputName() {
454
+ return "inngest_event_key";
455
+ }
456
+ function inngestSigningKeyInputName() {
457
+ return "inngest_signing_key";
458
+ }
407
459
  function normalizeAppName(appNameInput) {
408
460
  const appName = toKebabCase(appNameInput);
409
461
  const validation = validateProjectName(appName);
@@ -413,4 +465,4 @@ function normalizeAppName(appNameInput) {
413
465
  //#endregion
414
466
  export { registerAppCommand };
415
467
 
416
- //# sourceMappingURL=register-app-DZg-Pmtd.js.map
468
+ //# sourceMappingURL=register-app-B9vKTkoI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-app-B9vKTkoI.js","names":[],"sources":["../src/commands/infra/register-app.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { isMap, isSeq, parseDocument } from \"yaml\";\nimport {\n toKebabCase,\n toSnakeCase,\n toTitleCase,\n} from \"../../utils/case-converters.js\";\nimport { detectMonorepo } from \"../../utils/detect-monorepo.js\";\nimport { validateProjectName } from \"../../utils/validate.js\";\nimport { readWorkspaceManifest } from \"../../utils/workspace-manifest.js\";\nimport {\n createInfraGitHubApi,\n createOrUpdateInfraPullRequestFiles,\n INFRA_BASE_BRANCH,\n INFRA_REPOSITORY,\n type InfraGitHubApi,\n type InfraPullRequestFile,\n resolveGitHubToken,\n} from \"./github.js\";\n\nconst OS_POSTGRESQL_TERRAFORM_ALIAS = \"os-postgresql-terraform\";\nconst OS_POSTGRESQL_TERRAFORM_SERVICES = new Set([\n \"os-postgresql-terraform-aws\",\n \"os-postgresql-terraform-azure\",\n]);\nconst OS_BLUEPRINT_INPUT_GROUPS = [\n {\n name: \"general\",\n displayName: \"General\",\n description: \"Shared OS infrastructure settings.\",\n },\n {\n name: \"applications\",\n displayName: \"Applications\",\n description: \"Generated OS webapp settings.\",\n },\n {\n name: \"aws_postgresql\",\n displayName: \"AWS PostgreSQL\",\n description: \"AWS Aurora PostgreSQL settings.\",\n condition: '{{ eq EnvironmentProviderType \"aws\" }}',\n },\n {\n name: \"azure_postgresql\",\n displayName: \"Azure PostgreSQL\",\n description: \"Azure PostgreSQL Flexible Server settings.\",\n condition: '{{ eq EnvironmentProviderType \"azure\" }}',\n },\n];\n\nexport interface RegisterAppResult {\n appName: string;\n blueprintName: string;\n blueprintPath: string;\n branchName: string;\n customerSlug: string;\n pullRequestUrl: string | null;\n repository: typeof INFRA_REPOSITORY;\n status: \"already_registered\" | \"created_pr\" | \"updated_pr\";\n servicePath: string;\n targetPath: string;\n}\n\nexport async function registerApp(\n appNameInput: string,\n args: {\n cwd?: string;\n github?: InfraGitHubApi;\n } = {},\n): Promise<RegisterAppResult> {\n const appName = normalizeAppName(appNameInput);\n const cwd = args.cwd ?? process.cwd();\n const monorepoContext = await detectMonorepo(cwd);\n if (!monorepoContext.found || !monorepoContext.rootDir) {\n throw new Error(\n \"Run this command from a Mosaic customer monorepo with a .mosaic-workspace.json file.\",\n );\n }\n\n const workspaceManifest = await readWorkspaceManifest(\n monorepoContext.rootDir,\n );\n const customerSlug = workspaceManifest?.customerSlug;\n if (!customerSlug) {\n throw new Error(\n \".mosaic-workspace.json is missing customerSlug. Recreate the monorepo with a current @percepta/create.\",\n );\n }\n\n const github = args.github ?? createInfraGitHubApi(resolveGitHubToken());\n const blueprintName = `${customerSlug}-os`;\n const branchName = `blueberry/register-${customerSlug}-${appName}`;\n const blueprintPath = [\n \"ryvn\",\n \"definitions\",\n customerSlug,\n \"blueprints\",\n `${blueprintName}.blueprint.yaml`,\n ].join(\"/\");\n const servicePath = [\n \"ryvn\",\n \"definitions\",\n customerSlug,\n \"services\",\n `${appName}.service.yaml`,\n ].join(\"/\");\n\n const mainBlueprintFile = await github.getFile(\n blueprintPath,\n INFRA_BASE_BRANCH,\n );\n if (!mainBlueprintFile) {\n throw new Error(\n `${blueprintPath} does not exist in ${INFRA_REPOSITORY}. Run \\`pnpm mosaic infra register-os-blueprint\\` and merge that infra PR first.`,\n );\n }\n\n const mainServiceFile = await github.getFile(servicePath, INFRA_BASE_BRANCH);\n const serviceContent =\n mainServiceFile == null\n ? await readLocalServiceDefinition(monorepoContext.rootDir, appName)\n : null;\n const blueprintContent = registerAppInBlueprint(\n mainBlueprintFile.content,\n appName,\n );\n\n const files: InfraPullRequestFile[] = [];\n if (blueprintContent !== mainBlueprintFile.content) {\n files.push({\n baseFileSha: mainBlueprintFile.sha,\n content: blueprintContent,\n message: `Register ${appName} in ${blueprintName}`,\n path: blueprintPath,\n });\n }\n if (serviceContent != null) {\n files.push({\n content: serviceContent,\n message: `Register ${appName} service`,\n path: servicePath,\n });\n }\n\n if (files.length === 0) {\n return {\n appName,\n blueprintName,\n blueprintPath,\n branchName,\n customerSlug,\n pullRequestUrl: null,\n repository: INFRA_REPOSITORY,\n status: \"already_registered\",\n servicePath,\n targetPath: blueprintPath,\n };\n }\n\n const pullRequest = await createOrUpdateInfraPullRequestFiles({\n branchName,\n github,\n files,\n title: `Register ${appName} app`,\n body: [\n `Registers the ${appName} service and deployment in ${blueprintName}.`,\n \"\",\n \"Generated by `mosaic infra register-app`.\",\n ].join(\"\\n\"),\n });\n\n return {\n appName,\n blueprintName,\n blueprintPath,\n branchName,\n customerSlug,\n pullRequestUrl: pullRequest.pullRequestUrl,\n repository: INFRA_REPOSITORY,\n status: pullRequest.status,\n servicePath,\n targetPath: blueprintPath,\n };\n}\n\nexport async function registerAppCommand(appName: string): Promise<void> {\n try {\n const result = await registerApp(appName);\n\n if (result.status === \"already_registered\") {\n console.log(\n chalk.green(\"✔\"),\n `${result.appName} is already registered in ${result.repository} at`,\n chalk.cyan(result.targetPath),\n );\n return;\n }\n\n const verb =\n result.status === \"created_pr\" ? \"Created\" : \"Updated existing\";\n console.log(\n chalk.green(\"✔\"),\n `${verb} infra PR for ${result.appName}:`,\n chalk.cyan(result.pullRequestUrl),\n );\n } catch (error) {\n console.error(chalk.red(\"Error:\"), (error as Error).message);\n process.exit(1);\n }\n}\n\nexport function addAppDatabaseToBlueprint(\n blueprintContent: string,\n appName: string,\n): string {\n return updateBlueprint(blueprintContent, appName, {\n appDatabase: true,\n appInstallation: false,\n appInputs: false,\n });\n}\n\nexport function registerAppInBlueprint(\n blueprintContent: string,\n appName: string,\n): string {\n return updateBlueprint(blueprintContent, appName, {\n appDatabase: true,\n appInstallation: true,\n appInputs: true,\n });\n}\n\nfunction updateBlueprint(\n blueprintContent: string,\n appName: string,\n options: {\n appDatabase: boolean;\n appInstallation: boolean;\n appInputs: boolean;\n },\n): string {\n const document = parseDocument(blueprintContent);\n if (document.errors.length > 0) {\n throw new Error(\n `Invalid OS blueprint YAML: ${document.errors.map((error) => error.message).join(\"; \")}`,\n );\n }\n\n const spec = document.get(\"spec\", true);\n if (!isMap(spec)) {\n throw new Error(\"OS blueprint must include a spec map.\");\n }\n\n let changed = false;\n const inputs = spec.get(\"inputs\", true);\n if (!isSeq(inputs)) {\n throw new Error(\"OS blueprint spec.inputs must be a sequence.\");\n }\n\n changed = ensureInputGroups(document, spec) || changed;\n\n if (options.appInputs) {\n changed =\n addAppInput(document, inputs, renderIngressDomainInput()) || changed;\n changed =\n addAppInput(document, inputs, renderBetterAuthSecretInput(appName)) ||\n changed;\n changed =\n addAppInput(document, inputs, renderLangfusePublicKeyInput()) || changed;\n changed =\n addAppInput(document, inputs, renderLangfuseSecretKeyInput()) || changed;\n changed =\n addAppInput(document, inputs, renderInngestEventKeyInput()) || changed;\n changed =\n addAppInput(document, inputs, renderInngestSigningKeyInput()) || changed;\n }\n\n if (options.appDatabase) {\n changed = addAppDatabase(document, inputs, appName) || changed;\n }\n\n if (options.appInstallation) {\n const installations = spec.get(\"installations\", true);\n if (!isSeq(installations)) {\n throw new Error(\"OS blueprint spec.installations must be a sequence.\");\n }\n changed = ensureOsPostgresqlInstallationAlias(installations) || changed;\n changed = addAppInstallation(document, installations, appName) || changed;\n }\n\n return changed ? document.toString() : blueprintContent;\n}\n\nfunction ensureInputGroups(\n document: ReturnType<typeof parseDocument>,\n spec: {\n get(key: string, keepScalar?: true): unknown;\n set(key: string, value: unknown): void;\n },\n): boolean {\n let changed = false;\n const inputGroups = spec.get(\"inputGroups\", true);\n\n if (inputGroups == null) {\n spec.set(\"inputGroups\", document.createNode(OS_BLUEPRINT_INPUT_GROUPS));\n return true;\n }\n\n if (!isSeq(inputGroups)) {\n throw new Error(\"OS blueprint spec.inputGroups must be a sequence.\");\n }\n\n for (const group of OS_BLUEPRINT_INPUT_GROUPS) {\n const exists = inputGroups.items.some(\n (item) => isMap(item) && item.get(\"name\") === group.name,\n );\n if (exists) continue;\n\n inputGroups.add(document.createNode(group));\n changed = true;\n }\n\n return changed;\n}\n\nfunction ensureOsPostgresqlInstallationAlias(installations: {\n items: unknown[];\n}): boolean {\n let changed = false;\n\n for (const installation of installations.items) {\n if (!isMap(installation)) continue;\n\n const service = installation.get(\"service\");\n if (\n typeof service !== \"string\" ||\n !OS_POSTGRESQL_TERRAFORM_SERVICES.has(service)\n ) {\n continue;\n }\n\n if (installation.get(\"name\") === OS_POSTGRESQL_TERRAFORM_ALIAS) continue;\n\n installation.set(\"name\", OS_POSTGRESQL_TERRAFORM_ALIAS);\n changed = true;\n }\n\n return changed;\n}\n\nfunction addAppInput(\n document: ReturnType<typeof parseDocument>,\n inputs: { add(value: unknown): void; items: unknown[] },\n input: Record<string, unknown> & { name: string },\n): boolean {\n if (\n inputs.items.some((item) => isMap(item) && item.get(\"name\") === input.name)\n ) {\n return false;\n }\n\n inputs.add(document.createNode(input));\n return true;\n}\n\nfunction addAppDatabase(\n document: ReturnType<typeof parseDocument>,\n inputs: { items: unknown[] },\n appName: string,\n): boolean {\n const appDatabasesInput = inputs.items.find(\n (item) => isMap(item) && item.get(\"name\") === \"app_databases\",\n );\n if (!isMap(appDatabasesInput)) {\n throw new Error(\"OS blueprint must include an app_databases input.\");\n }\n\n const defaultValue = appDatabasesInput.get(\"default\", true);\n if (!isMap(defaultValue)) {\n throw new Error(\"OS blueprint app_databases default must be a map.\");\n }\n\n if (defaultValue.has(appName)) return false;\n\n defaultValue.flow = false;\n const appDatabaseValue = document.createNode({\n schema_name: toSnakeCase(appName),\n });\n defaultValue.set(appName, appDatabaseValue);\n return true;\n}\n\nfunction addAppInstallation(\n document: ReturnType<typeof parseDocument>,\n installations: { add(value: unknown): void; items: unknown[] },\n appName: string,\n): boolean {\n if (\n installations.items.some(\n (item) => isMap(item) && item.get(\"service\") === appName,\n )\n ) {\n return false;\n }\n\n installations.add(\n document.createNode({\n service: appName,\n env: renderAppInstallationEnv(appName),\n config: renderAppInstallationConfig(appName),\n }),\n );\n return true;\n}\n\nfunction renderIngressDomainInput(): Record<string, unknown> & {\n name: string;\n} {\n return {\n name: ingressDomainInputName(),\n type: \"string\",\n group: \"applications\",\n displayName: \"Ingress Domain\",\n description: \"Shared ingress domain for generated OS webapps.\",\n default: '{{ default \"example.local\" .ryvn.env.state.public_domain.name }}',\n };\n}\n\nfunction renderBetterAuthSecretInput(\n appName: string,\n): Record<string, unknown> & { name: string } {\n return {\n name: betterAuthSecretInputName(appName),\n type: \"string\",\n isSecret: true,\n group: \"applications\",\n displayName: `${toTitleCase(appName)} Better Auth Secret`,\n description: `Generated Better Auth signing secret for ${appName}.`,\n hidden: true,\n generated: {\n type: \"random-bytes\",\n length: 32,\n },\n };\n}\n\nfunction renderLangfusePublicKeyInput(): Record<string, unknown> & {\n name: string;\n} {\n return {\n name: langfusePublicKeyInputName(),\n type: \"string\",\n group: \"applications\",\n displayName: \"Langfuse Public Key\",\n description:\n \"Shared Langfuse public key for generated OS webapps. Leave empty to disable Langfuse export.\",\n default: \"\",\n };\n}\n\nfunction renderLangfuseSecretKeyInput(): Record<string, unknown> & {\n name: string;\n} {\n return {\n name: langfuseSecretKeyInputName(),\n type: \"string\",\n isSecret: true,\n group: \"applications\",\n displayName: \"Langfuse Secret Key\",\n description:\n \"Shared Langfuse secret key for generated OS webapps. Leave unset to disable Langfuse export.\",\n condition: `{{ ne (input \"${langfusePublicKeyInputName()}\") \"\" }}`,\n };\n}\n\nfunction renderInngestEventKeyInput(): Record<string, unknown> & {\n name: string;\n} {\n return {\n name: inngestEventKeyInputName(),\n type: \"string\",\n isSecret: true,\n group: \"applications\",\n displayName: \"Inngest Event Key\",\n description: \"Shared Inngest event key for generated OS webapps.\",\n };\n}\n\nfunction renderInngestSigningKeyInput(): Record<string, unknown> & {\n name: string;\n} {\n return {\n name: inngestSigningKeyInputName(),\n type: \"string\",\n isSecret: true,\n group: \"applications\",\n displayName: \"Inngest Signing Key\",\n description: \"Shared Inngest signing key for generated OS webapps.\",\n };\n}\n\nfunction renderAppInstallationEnv(\n appName: string,\n): Array<Record<string, unknown>> {\n const appInternalEndpoint = `http://${appName}-web-server.{{ .ryvn.env.name }}.svc.cluster.local:3000/api/inngest`;\n\n return [\n {\n key: \"DATABASE_URL\",\n isSecret: true,\n valueFromOutput: {\n serviceInstallation: \"os-postgresql-terraform\",\n name: `app_database_urls.${appName}`,\n },\n },\n {\n key: \"AUTH_DATABASE_URL\",\n isSecret: true,\n valueFromOutput: {\n serviceInstallation: \"os-postgresql-terraform\",\n name: \"auth_database_url\",\n },\n },\n {\n key: \"DATABASE_SCHEMA\",\n value: toSnakeCase(appName),\n },\n {\n key: \"INGRESS_DOMAIN\",\n valueFromInput: {\n name: ingressDomainInputName(),\n },\n },\n {\n key: \"APP_BASE_URL\",\n value: `https://${appName}.$(INGRESS_DOMAIN)`,\n },\n {\n key: \"BETTER_AUTH_URL\",\n value: `https://${appName}.$(INGRESS_DOMAIN)`,\n },\n {\n key: \"DEPLOYMENT_ENVIRONMENT\",\n value: \"{{ .ryvn.env.name }}\",\n },\n {\n key: \"BETTER_AUTH_SECRET\",\n isSecret: true,\n valueFromInput: {\n name: betterAuthSecretInputName(appName),\n },\n },\n {\n key: \"INNGEST_BASE_URL\",\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"inngest_base_url\",\n },\n },\n {\n key: \"INNGEST_EVENT_KEY\",\n isSecret: true,\n valueFromInput: {\n name: inngestEventKeyInputName(),\n },\n },\n {\n key: \"INNGEST_SIGNING_KEY\",\n isSecret: true,\n valueFromInput: {\n name: inngestSigningKeyInputName(),\n },\n },\n {\n key: \"INNGEST_APP_URL\",\n value: appInternalEndpoint,\n },\n {\n key: \"INNGEST_SERVE_HOST\",\n value: appInternalEndpoint,\n },\n {\n key: \"LANGFUSE_BASE_URL\",\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"langfuse_internal_url\",\n },\n },\n {\n key: \"LANGFUSE_PUBLIC_KEY\",\n valueFromInput: {\n name: langfusePublicKeyInputName(),\n },\n },\n {\n key: \"LANGFUSE_SECRET_KEY\",\n isSecret: true,\n valueFromInput: {\n name: langfuseSecretKeyInputName(),\n },\n },\n {\n key: \"OTEL_EXPORTER_OTLP_ENDPOINT\",\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"otel_exporter_otlp_endpoint\",\n },\n },\n {\n key: \"SPICEDB_ENDPOINT\",\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"spicedb_endpoint\",\n },\n },\n {\n key: \"SPICEDB_PRESHARED_KEY\",\n isSecret: true,\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"spicedb_preshared_key\",\n },\n },\n {\n key: \"SPICEDB_INSECURE\",\n valueFromOutput: {\n blueprintInstallation: \"mosaic\",\n name: \"spicedb_insecure\",\n },\n },\n ];\n}\n\nfunction renderAppInstallationConfig(appName: string): string {\n const appHost = `${appName}.{{ input \"${ingressDomainInputName()}\" }}`;\n\n return [\n \"replicaCount: 1\",\n \"\",\n \"service:\",\n \" port: 3000\",\n \"\",\n \"livenessEnabled: true\",\n \"readinessEnabled: true\",\n \"startupEnabled: true\",\n \"\",\n \"resources:\",\n \" requests:\",\n ' cpu: \"100m\"',\n \" memory: 256Mi\",\n \" limits:\",\n ' cpu: \"500m\"',\n \" memory: 512Mi\",\n \"\",\n \"ingress:\",\n \" enabled: true\",\n \" className: external-nginx\",\n \" annotations:\",\n \" cert-manager.io/cluster-issuer: external-issuer\",\n ' nginx.ingress.kubernetes.io/ssl-redirect: \"true\"',\n \" hosts:\",\n ` - host: '${appHost}'`,\n \" paths:\",\n \" - path: /\",\n \" pathType: Prefix\",\n \" tls:\",\n ` - secretName: ${appName}-tls`,\n \" hosts:\",\n ` - '${appHost}'`,\n \"\",\n ].join(\"\\n\");\n}\n\nasync function readLocalServiceDefinition(\n monorepoRoot: string,\n appName: string,\n): Promise<string> {\n const serviceDefinitionPath = path.join(\n monorepoRoot,\n \"packages\",\n appName,\n \"deploy\",\n \"ryvn\",\n `${appName}.service.yaml`,\n );\n if (!(await fs.pathExists(serviceDefinitionPath))) {\n throw new Error(\n `${serviceDefinitionPath} does not exist. Add the app's Ryvn service definition before registering it in infra.`,\n );\n }\n\n const content = await fs.readFile(serviceDefinitionPath, \"utf-8\");\n validateLocalServiceDefinition(content, appName, serviceDefinitionPath);\n return content.endsWith(\"\\n\") ? content : `${content}\\n`;\n}\n\nfunction validateLocalServiceDefinition(\n content: string,\n appName: string,\n serviceDefinitionPath: string,\n): void {\n const document = parseDocument(content);\n if (document.errors.length > 0) {\n throw new Error(\n `Invalid Ryvn service YAML at ${serviceDefinitionPath}: ${document.errors.map((error) => error.message).join(\"; \")}`,\n );\n }\n\n const service = document.toJS() as {\n kind?: unknown;\n metadata?: { name?: unknown };\n };\n if (service.kind !== \"Service\" || service.metadata?.name !== appName) {\n throw new Error(\n `${serviceDefinitionPath} must define kind: Service with metadata.name: ${appName}.`,\n );\n }\n}\n\nfunction ingressDomainInputName(): string {\n return \"ingress_domain\";\n}\n\nfunction betterAuthSecretInputName(appName: string): string {\n return `${toSnakeCase(appName)}_better_auth_secret`;\n}\n\nfunction langfusePublicKeyInputName(): string {\n return \"langfuse_public_key\";\n}\n\nfunction langfuseSecretKeyInputName(): string {\n return \"langfuse_secret_key\";\n}\n\nfunction inngestEventKeyInputName(): string {\n return \"inngest_event_key\";\n}\n\nfunction inngestSigningKeyInputName(): string {\n return \"inngest_signing_key\";\n}\n\nfunction normalizeAppName(appNameInput: string): string {\n const appName = toKebabCase(appNameInput);\n const validation = validateProjectName(appName);\n if (!validation.valid) {\n throw new Error(`Invalid app name: ${validation.error}`);\n }\n return appName;\n}\n"],"mappings":"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"}
@@ -1,6 +1,5 @@
1
- import { i as toTitleCase } from "./template-versions-CEIP9vhl.js";
2
- import { i as detectMonorepo, t as readWorkspaceManifest } from "./index.js";
3
- import { i as createOrUpdateInfraPullRequest, n as INFRA_REPOSITORY, o as resolveGitHubToken, r as createInfraGitHubApi, t as INFRA_BASE_BRANCH } from "./github-D3YOEl91.js";
1
+ import { d as detectMonorepo, m as toTitleCase, t as readWorkspaceManifest } from "./index.js";
2
+ import { i as createOrUpdateInfraPullRequest, n as INFRA_REPOSITORY, o as resolveGitHubToken, r as createInfraGitHubApi, t as INFRA_BASE_BRANCH } from "./github-BOp8VQCY.js";
4
3
  import path from "node:path";
5
4
  import chalk from "chalk";
6
5
  import fs from "fs-extra";
@@ -87,4 +86,4 @@ function getOsBlueprintTemplatePath() {
87
86
  //#endregion
88
87
  export { registerOsBlueprintCommand };
89
88
 
90
- //# sourceMappingURL=register-os-blueprint-Cgq1rXzQ.js.map
89
+ //# sourceMappingURL=register-os-blueprint-Gdyn0pN1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"register-os-blueprint-Cgq1rXzQ.js","names":[],"sources":["../src/commands/infra/register-os-blueprint.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { toTitleCase } from \"../../utils/case-converters.js\";\nimport { detectMonorepo } from \"../../utils/detect-monorepo.js\";\nimport { readWorkspaceManifest } from \"../../utils/workspace-manifest.js\";\nimport {\n createOrUpdateInfraPullRequest,\n createInfraGitHubApi,\n INFRA_BASE_BRANCH,\n INFRA_REPOSITORY,\n type InfraGitHubApi,\n resolveGitHubToken,\n} from \"./github.js\";\n\nconst OS_BLUEPRINT_TEMPLATE = \"os.blueprint.yaml.template\";\n\nexport interface RegisterOsBlueprintResult {\n blueprintName: string;\n branchName: string;\n customerSlug: string;\n pullRequestUrl: string | null;\n repository: typeof INFRA_REPOSITORY;\n status: \"already_registered\" | \"created_pr\" | \"updated_pr\";\n targetPath: string;\n}\n\nexport async function registerOsBlueprint(\n args: {\n cwd?: string;\n github?: InfraGitHubApi;\n } = {},\n): Promise<RegisterOsBlueprintResult> {\n const cwd = args.cwd ?? process.cwd();\n const monorepoContext = await detectMonorepo(cwd);\n if (!monorepoContext.found || !monorepoContext.rootDir) {\n throw new Error(\n \"Run this command from a Mosaic customer monorepo with a .mosaic-workspace.json file.\",\n );\n }\n\n const workspaceManifest = await readWorkspaceManifest(\n monorepoContext.rootDir,\n );\n const customerSlug = workspaceManifest?.customerSlug;\n if (!customerSlug) {\n throw new Error(\n \".mosaic-workspace.json is missing customerSlug. Recreate the monorepo with a current @percepta/create.\",\n );\n }\n\n const github = args.github ?? createInfraGitHubApi(resolveGitHubToken());\n const blueprintName = `${customerSlug}-os`;\n const branchName = `blueberry/register-${blueprintName}-blueprint`;\n const targetPath = [\n \"ryvn\",\n \"definitions\",\n customerSlug,\n \"blueprints\",\n `${blueprintName}.blueprint.yaml`,\n ].join(\"/\");\n const content = await renderOsBlueprint(customerSlug);\n\n const mainFile = await github.getFile(targetPath, INFRA_BASE_BRANCH);\n if (mainFile) {\n if (mainFile.content === content) {\n return {\n blueprintName,\n branchName,\n customerSlug,\n pullRequestUrl: null,\n repository: INFRA_REPOSITORY,\n status: \"already_registered\",\n targetPath,\n };\n }\n\n throw new Error(\n `${targetPath} already exists in ${INFRA_REPOSITORY}. Not overwriting an existing customer OS blueprint.`,\n );\n }\n\n const pullRequest = await createOrUpdateInfraPullRequest({\n branchName,\n content,\n github,\n message: `Register ${blueprintName} blueprint`,\n targetPath,\n title: `Register ${blueprintName} blueprint`,\n body: [\n `Registers the ${blueprintName} OS blueprint for ${customerSlug}.`,\n \"\",\n \"Generated by `mosaic infra register-os-blueprint`.\",\n ].join(\"\\n\"),\n });\n\n return {\n blueprintName,\n branchName,\n customerSlug,\n pullRequestUrl: pullRequest.pullRequestUrl,\n repository: INFRA_REPOSITORY,\n status: pullRequest.status,\n targetPath,\n };\n}\n\nexport async function registerOsBlueprintCommand(): Promise<void> {\n try {\n const result = await registerOsBlueprint();\n\n if (result.status === \"already_registered\") {\n console.log(\n chalk.green(\"✔\"),\n `${result.blueprintName} is already registered in ${result.repository} at`,\n chalk.cyan(result.targetPath),\n );\n return;\n }\n\n const verb =\n result.status === \"created_pr\" ? \"Created\" : \"Updated existing\";\n console.log(\n chalk.green(\"✔\"),\n `${verb} infra PR for ${result.blueprintName}:`,\n chalk.cyan(result.pullRequestUrl),\n );\n } catch (error) {\n console.error(chalk.red(\"Error:\"), (error as Error).message);\n process.exit(1);\n }\n}\n\nasync function renderOsBlueprint(customerSlug: string): Promise<string> {\n const template = await fs.readFile(getOsBlueprintTemplatePath(), \"utf-8\");\n const customerTitle = toTitleCase(customerSlug);\n\n return template\n .replaceAll(\"__CUSTOMER_SLUG__\", customerSlug)\n .replaceAll(\"__CUSTOMER_TITLE__\", customerTitle);\n}\n\nfunction getOsBlueprintTemplatePath(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../templates/infra\", OS_BLUEPRINT_TEMPLATE),\n path.resolve(currentDir, \"../../../templates/infra\", OS_BLUEPRINT_TEMPLATE),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate;\n }\n\n throw new Error(\n `OS blueprint template not found. Checked: ${candidates.join(\", \")}`,\n );\n}\n"],"mappings":";;;;;;;;AAgBA,MAAM,wBAAwB;AAY9B,eAAsB,oBACpB,OAGI,EAAE,EAC8B;CAEpC,MAAM,kBAAkB,MAAM,eADlB,KAAK,OAAO,QAAQ,KAAK,CACY;AACjD,KAAI,CAAC,gBAAgB,SAAS,CAAC,gBAAgB,QAC7C,OAAM,IAAI,MACR,uFACD;CAMH,MAAM,gBAAe,MAHW,sBAC9B,gBAAgB,QACjB,GACuC;AACxC,KAAI,CAAC,aACH,OAAM,IAAI,MACR,yGACD;CAGH,MAAM,SAAS,KAAK,UAAU,qBAAqB,oBAAoB,CAAC;CACxE,MAAM,gBAAgB,GAAG,aAAa;CACtC,MAAM,aAAa,sBAAsB,cAAc;CACvD,MAAM,aAAa;EACjB;EACA;EACA;EACA;EACA,GAAG,cAAc;EAClB,CAAC,KAAK,IAAI;CACX,MAAM,UAAU,MAAM,kBAAkB,aAAa;CAErD,MAAM,WAAW,MAAM,OAAO,QAAQ,YAAY,kBAAkB;AACpE,KAAI,UAAU;AACZ,MAAI,SAAS,YAAY,QACvB,QAAO;GACL;GACA;GACA;GACA,gBAAgB;GAChB,YAAY;GACZ,QAAQ;GACR;GACD;AAGH,QAAM,IAAI,MACR,GAAG,WAAW,qBAAqB,iBAAiB,sDACrD;;CAGH,MAAM,cAAc,MAAM,+BAA+B;EACvD;EACA;EACA;EACA,SAAS,YAAY,cAAc;EACnC;EACA,OAAO,YAAY,cAAc;EACjC,MAAM;GACJ,iBAAiB,cAAc,oBAAoB,aAAa;GAChE;GACA;GACD,CAAC,KAAK,KAAK;EACb,CAAC;AAEF,QAAO;EACL;EACA;EACA;EACA,gBAAgB,YAAY;EAC5B,YAAY;EACZ,QAAQ,YAAY;EACpB;EACD;;AAGH,eAAsB,6BAA4C;AAChE,KAAI;EACF,MAAM,SAAS,MAAM,qBAAqB;AAE1C,MAAI,OAAO,WAAW,sBAAsB;AAC1C,WAAQ,IACN,MAAM,MAAM,IAAI,EAChB,GAAG,OAAO,cAAc,4BAA4B,OAAO,WAAW,MACtE,MAAM,KAAK,OAAO,WAAW,CAC9B;AACD;;EAGF,MAAM,OACJ,OAAO,WAAW,eAAe,YAAY;AAC/C,UAAQ,IACN,MAAM,MAAM,IAAI,EAChB,GAAG,KAAK,gBAAgB,OAAO,cAAc,IAC7C,MAAM,KAAK,OAAO,eAAe,CAClC;UACM,OAAO;AACd,UAAQ,MAAM,MAAM,IAAI,SAAS,EAAG,MAAgB,QAAQ;AAC5D,UAAQ,KAAK,EAAE;;;AAInB,eAAe,kBAAkB,cAAuC;CACtE,MAAM,WAAW,MAAM,GAAG,SAAS,4BAA4B,EAAE,QAAQ;CACzE,MAAM,gBAAgB,YAAY,aAAa;AAE/C,QAAO,SACJ,WAAW,qBAAqB,aAAa,CAC7C,WAAW,sBAAsB,cAAc;;AAGpD,SAAS,6BAAqC;CAC5C,MAAM,aAAa,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;CAC/D,MAAM,aAAa,CACjB,KAAK,QAAQ,YAAY,sBAAsB,sBAAsB,EACrE,KAAK,QAAQ,YAAY,4BAA4B,sBAAsB,CAC5E;AAED,MAAK,MAAM,aAAa,WACtB,KAAI,GAAG,WAAW,UAAU,CAAE,QAAO;AAGvC,OAAM,IAAI,MACR,6CAA6C,WAAW,KAAK,KAAK,GACnE"}
1
+ {"version":3,"file":"register-os-blueprint-Gdyn0pN1.js","names":[],"sources":["../src/commands/infra/register-os-blueprint.ts"],"sourcesContent":["import path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { toTitleCase } from \"../../utils/case-converters.js\";\nimport { detectMonorepo } from \"../../utils/detect-monorepo.js\";\nimport { readWorkspaceManifest } from \"../../utils/workspace-manifest.js\";\nimport {\n createOrUpdateInfraPullRequest,\n createInfraGitHubApi,\n INFRA_BASE_BRANCH,\n INFRA_REPOSITORY,\n type InfraGitHubApi,\n resolveGitHubToken,\n} from \"./github.js\";\n\nconst OS_BLUEPRINT_TEMPLATE = \"os.blueprint.yaml.template\";\n\nexport interface RegisterOsBlueprintResult {\n blueprintName: string;\n branchName: string;\n customerSlug: string;\n pullRequestUrl: string | null;\n repository: typeof INFRA_REPOSITORY;\n status: \"already_registered\" | \"created_pr\" | \"updated_pr\";\n targetPath: string;\n}\n\nexport async function registerOsBlueprint(\n args: {\n cwd?: string;\n github?: InfraGitHubApi;\n } = {},\n): Promise<RegisterOsBlueprintResult> {\n const cwd = args.cwd ?? process.cwd();\n const monorepoContext = await detectMonorepo(cwd);\n if (!monorepoContext.found || !monorepoContext.rootDir) {\n throw new Error(\n \"Run this command from a Mosaic customer monorepo with a .mosaic-workspace.json file.\",\n );\n }\n\n const workspaceManifest = await readWorkspaceManifest(\n monorepoContext.rootDir,\n );\n const customerSlug = workspaceManifest?.customerSlug;\n if (!customerSlug) {\n throw new Error(\n \".mosaic-workspace.json is missing customerSlug. Recreate the monorepo with a current @percepta/create.\",\n );\n }\n\n const github = args.github ?? createInfraGitHubApi(resolveGitHubToken());\n const blueprintName = `${customerSlug}-os`;\n const branchName = `blueberry/register-${blueprintName}-blueprint`;\n const targetPath = [\n \"ryvn\",\n \"definitions\",\n customerSlug,\n \"blueprints\",\n `${blueprintName}.blueprint.yaml`,\n ].join(\"/\");\n const content = await renderOsBlueprint(customerSlug);\n\n const mainFile = await github.getFile(targetPath, INFRA_BASE_BRANCH);\n if (mainFile) {\n if (mainFile.content === content) {\n return {\n blueprintName,\n branchName,\n customerSlug,\n pullRequestUrl: null,\n repository: INFRA_REPOSITORY,\n status: \"already_registered\",\n targetPath,\n };\n }\n\n throw new Error(\n `${targetPath} already exists in ${INFRA_REPOSITORY}. Not overwriting an existing customer OS blueprint.`,\n );\n }\n\n const pullRequest = await createOrUpdateInfraPullRequest({\n branchName,\n content,\n github,\n message: `Register ${blueprintName} blueprint`,\n targetPath,\n title: `Register ${blueprintName} blueprint`,\n body: [\n `Registers the ${blueprintName} OS blueprint for ${customerSlug}.`,\n \"\",\n \"Generated by `mosaic infra register-os-blueprint`.\",\n ].join(\"\\n\"),\n });\n\n return {\n blueprintName,\n branchName,\n customerSlug,\n pullRequestUrl: pullRequest.pullRequestUrl,\n repository: INFRA_REPOSITORY,\n status: pullRequest.status,\n targetPath,\n };\n}\n\nexport async function registerOsBlueprintCommand(): Promise<void> {\n try {\n const result = await registerOsBlueprint();\n\n if (result.status === \"already_registered\") {\n console.log(\n chalk.green(\"✔\"),\n `${result.blueprintName} is already registered in ${result.repository} at`,\n chalk.cyan(result.targetPath),\n );\n return;\n }\n\n const verb =\n result.status === \"created_pr\" ? \"Created\" : \"Updated existing\";\n console.log(\n chalk.green(\"✔\"),\n `${verb} infra PR for ${result.blueprintName}:`,\n chalk.cyan(result.pullRequestUrl),\n );\n } catch (error) {\n console.error(chalk.red(\"Error:\"), (error as Error).message);\n process.exit(1);\n }\n}\n\nasync function renderOsBlueprint(customerSlug: string): Promise<string> {\n const template = await fs.readFile(getOsBlueprintTemplatePath(), \"utf-8\");\n const customerTitle = toTitleCase(customerSlug);\n\n return template\n .replaceAll(\"__CUSTOMER_SLUG__\", customerSlug)\n .replaceAll(\"__CUSTOMER_TITLE__\", customerTitle);\n}\n\nfunction getOsBlueprintTemplatePath(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const candidates = [\n path.resolve(currentDir, \"../templates/infra\", OS_BLUEPRINT_TEMPLATE),\n path.resolve(currentDir, \"../../../templates/infra\", OS_BLUEPRINT_TEMPLATE),\n ];\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) return candidate;\n }\n\n throw new Error(\n `OS blueprint template not found. Checked: ${candidates.join(\", \")}`,\n );\n}\n"],"mappings":";;;;;;;AAgBA,MAAM,wBAAwB;AAY9B,eAAsB,oBACpB,OAGI,CAAC,GAC+B;CAEpC,MAAM,kBAAkB,MAAM,eADlB,KAAK,OAAO,QAAQ,IAAI,CACY;CAChD,IAAI,CAAC,gBAAgB,SAAS,CAAC,gBAAgB,SAC7C,MAAM,IAAI,MACR,sFACF;CAMF,MAAM,gBAAe,MAHW,sBAC9B,gBAAgB,OAClB,IACwC;CACxC,IAAI,CAAC,cACH,MAAM,IAAI,MACR,wGACF;CAGF,MAAM,SAAS,KAAK,UAAU,qBAAqB,mBAAmB,CAAC;CACvE,MAAM,gBAAgB,GAAG,aAAa;CACtC,MAAM,aAAa,sBAAsB,cAAc;CACvD,MAAM,aAAa;EACjB;EACA;EACA;EACA;EACA,GAAG,cAAc;CACnB,EAAE,KAAK,GAAG;CACV,MAAM,UAAU,MAAM,kBAAkB,YAAY;CAEpD,MAAM,WAAW,MAAM,OAAO,QAAQ,YAAY,iBAAiB;CACnE,IAAI,UAAU;EACZ,IAAI,SAAS,YAAY,SACvB,OAAO;GACL;GACA;GACA;GACA,gBAAgB;GAChB,YAAY;GACZ,QAAQ;GACR;EACF;EAGF,MAAM,IAAI,MACR,GAAG,WAAW,qBAAqB,iBAAiB,qDACtD;CACF;CAEA,MAAM,cAAc,MAAM,+BAA+B;EACvD;EACA;EACA;EACA,SAAS,YAAY,cAAc;EACnC;EACA,OAAO,YAAY,cAAc;EACjC,MAAM;GACJ,iBAAiB,cAAc,oBAAoB,aAAa;GAChE;GACA;EACF,EAAE,KAAK,IAAI;CACb,CAAC;CAED,OAAO;EACL;EACA;EACA;EACA,gBAAgB,YAAY;EAC5B,YAAY;EACZ,QAAQ,YAAY;EACpB;CACF;AACF;AAEA,eAAsB,6BAA4C;CAChE,IAAI;EACF,MAAM,SAAS,MAAM,oBAAoB;EAEzC,IAAI,OAAO,WAAW,sBAAsB;GAC1C,QAAQ,IACN,MAAM,MAAM,GAAG,GACf,GAAG,OAAO,cAAc,4BAA4B,OAAO,WAAW,MACtE,MAAM,KAAK,OAAO,UAAU,CAC9B;GACA;EACF;EAEA,MAAM,OACJ,OAAO,WAAW,eAAe,YAAY;EAC/C,QAAQ,IACN,MAAM,MAAM,GAAG,GACf,GAAG,KAAK,gBAAgB,OAAO,cAAc,IAC7C,MAAM,KAAK,OAAO,cAAc,CAClC;CACF,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAI,QAAQ,GAAI,MAAgB,OAAO;EAC3D,QAAQ,KAAK,CAAC;CAChB;AACF;AAEA,eAAe,kBAAkB,cAAuC;CACtE,MAAM,WAAW,MAAM,GAAG,SAAS,2BAA2B,GAAG,OAAO;CACxE,MAAM,gBAAgB,YAAY,YAAY;CAE9C,OAAO,SACJ,WAAW,qBAAqB,YAAY,EAC5C,WAAW,sBAAsB,aAAa;AACnD;AAEA,SAAS,6BAAqC;CAC5C,MAAM,aAAa,KAAK,QAAQ,cAAc,OAAO,KAAK,GAAG,CAAC;CAC9D,MAAM,aAAa,CACjB,KAAK,QAAQ,YAAY,sBAAsB,qBAAqB,GACpE,KAAK,QAAQ,YAAY,4BAA4B,qBAAqB,CAC5E;CAEA,KAAK,MAAM,aAAa,YACtB,IAAI,GAAG,WAAW,SAAS,GAAG,OAAO;CAGvC,MAAM,IAAI,MACR,6CAA6C,WAAW,KAAK,IAAI,GACnE;AACF"}
@@ -1,5 +1,5 @@
1
- import { r as readManifest } from "./manifest-By1SgOjC.js";
2
- import { i as getTemplateVersionFromTag, n as getLatestTemplateTag } from "./git-ops-BD7JNnal.js";
1
+ import { c as readManifest } from "./index.js";
2
+ import { i as getTemplateVersionFromTag, n as getLatestTemplateTag } from "./git-ops-BNpQnEc1.js";
3
3
  import path from "node:path";
4
4
  import chalk from "chalk";
5
5
  //#region src/commands/status.ts
@@ -45,4 +45,4 @@ async function statusCommand(options) {
45
45
  //#endregion
46
46
  export { statusCommand };
47
47
 
48
- //# sourceMappingURL=status-K6raTwwu.js.map
48
+ //# sourceMappingURL=status-BrK9v1yb.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"status-K6raTwwu.js","names":[],"sources":["../src/commands/status.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n} from \"../utils/git-ops.js\";\nimport { readManifest } from \"../utils/manifest.js\";\n\nexport interface StatusOptions {\n mosaicTemplatePath?: string;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n\n console.log();\n console.log(chalk.bold(\"Mosaic Template Status\"));\n console.log();\n console.log(chalk.dim(\" Template type:\"), manifest.templateType);\n console.log(chalk.dim(\" Current version:\"), manifest.templateVersion);\n console.log(chalk.dim(\" Template commit:\"), manifest.templateCommit);\n console.log(chalk.dim(\" Created:\"), manifest.createdAt);\n if (manifest.lastSyncedAt) {\n console.log(chalk.dim(\" Last synced:\"), manifest.lastSyncedAt);\n }\n\n const rawPath =\n options.mosaicTemplatePath || process.env.MOSAIC_TEMPLATE_PATH;\n const mosaicTemplatePath = rawPath ? path.resolve(rawPath) : undefined;\n\n if (mosaicTemplatePath) {\n const latestTag = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (latestTag) {\n const latestVersion = getTemplateVersionFromTag(latestTag);\n console.log(chalk.dim(\" Latest version:\"), latestVersion);\n console.log();\n\n if (latestVersion !== manifest.templateVersion) {\n console.log(\n chalk.yellow(\n ` Update available: ${manifest.templateVersion} → ${latestVersion}`,\n ),\n );\n console.log(\n chalk.dim(\" Run:\"),\n `create sync --mosaic-template-path ${mosaicTemplatePath}`,\n );\n } else {\n console.log(chalk.green(\" Up to date\"));\n }\n } else {\n console.log();\n console.log(chalk.yellow(\" No template tags found in mosaic repo.\"));\n console.log(\n chalk.dim(\" Run:\"),\n `cd ${mosaicTemplatePath} && pnpm template:tag`,\n );\n }\n } else {\n console.log();\n console.log(\n chalk.dim(\n \" Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH to check for updates\",\n ),\n );\n }\n\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;AAYA,eAAsB,cAAc,SAAuC;CACzE,MAAM,MAAM,QAAQ,KAAK;AAEzB,KAAI;EACF,MAAM,WAAW,MAAM,aAAa,IAAI;AAExC,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,KAAK,yBAAyB,CAAC;AACjD,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,IAAI,mBAAmB,EAAE,SAAS,aAAa;AACjE,UAAQ,IAAI,MAAM,IAAI,qBAAqB,EAAE,SAAS,gBAAgB;AACtE,UAAQ,IAAI,MAAM,IAAI,qBAAqB,EAAE,SAAS,eAAe;AACrE,UAAQ,IAAI,MAAM,IAAI,aAAa,EAAE,SAAS,UAAU;AACxD,MAAI,SAAS,aACX,SAAQ,IAAI,MAAM,IAAI,iBAAiB,EAAE,SAAS,aAAa;EAGjE,MAAM,UACJ,QAAQ,sBAAsB,QAAQ,IAAI;EAC5C,MAAM,qBAAqB,UAAU,KAAK,QAAQ,QAAQ,GAAG,KAAA;AAE7D,MAAI,oBAAoB;GACtB,MAAM,YAAY,qBAChB,SAAS,cACT,mBACD;AACD,OAAI,WAAW;IACb,MAAM,gBAAgB,0BAA0B,UAAU;AAC1D,YAAQ,IAAI,MAAM,IAAI,oBAAoB,EAAE,cAAc;AAC1D,YAAQ,KAAK;AAEb,QAAI,kBAAkB,SAAS,iBAAiB;AAC9C,aAAQ,IACN,MAAM,OACJ,uBAAuB,SAAS,gBAAgB,KAAK,gBACtD,CACF;AACD,aAAQ,IACN,MAAM,IAAI,SAAS,EACnB,sCAAsC,qBACvC;UAED,SAAQ,IAAI,MAAM,MAAM,eAAe,CAAC;UAErC;AACL,YAAQ,KAAK;AACb,YAAQ,IAAI,MAAM,OAAO,2CAA2C,CAAC;AACrE,YAAQ,IACN,MAAM,IAAI,SAAS,EACnB,MAAM,mBAAmB,uBAC1B;;SAEE;AACL,WAAQ,KAAK;AACb,WAAQ,IACN,MAAM,IACJ,gFACD,CACF;;AAGH,UAAQ,KAAK;UACN,OAAO;AACd,UAAQ,MAAM,MAAM,IAAK,MAAgB,QAAQ,CAAC;AAClD,UAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"status-BrK9v1yb.js","names":[],"sources":["../src/commands/status.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n} from \"../utils/git-ops.js\";\nimport { readManifest } from \"../utils/manifest.js\";\n\nexport interface StatusOptions {\n mosaicTemplatePath?: string;\n}\n\nexport async function statusCommand(options: StatusOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n\n console.log();\n console.log(chalk.bold(\"Mosaic Template Status\"));\n console.log();\n console.log(chalk.dim(\" Template type:\"), manifest.templateType);\n console.log(chalk.dim(\" Current version:\"), manifest.templateVersion);\n console.log(chalk.dim(\" Template commit:\"), manifest.templateCommit);\n console.log(chalk.dim(\" Created:\"), manifest.createdAt);\n if (manifest.lastSyncedAt) {\n console.log(chalk.dim(\" Last synced:\"), manifest.lastSyncedAt);\n }\n\n const rawPath =\n options.mosaicTemplatePath || process.env.MOSAIC_TEMPLATE_PATH;\n const mosaicTemplatePath = rawPath ? path.resolve(rawPath) : undefined;\n\n if (mosaicTemplatePath) {\n const latestTag = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (latestTag) {\n const latestVersion = getTemplateVersionFromTag(latestTag);\n console.log(chalk.dim(\" Latest version:\"), latestVersion);\n console.log();\n\n if (latestVersion !== manifest.templateVersion) {\n console.log(\n chalk.yellow(\n ` Update available: ${manifest.templateVersion} → ${latestVersion}`,\n ),\n );\n console.log(\n chalk.dim(\" Run:\"),\n `create sync --mosaic-template-path ${mosaicTemplatePath}`,\n );\n } else {\n console.log(chalk.green(\" Up to date\"));\n }\n } else {\n console.log();\n console.log(chalk.yellow(\" No template tags found in mosaic repo.\"));\n console.log(\n chalk.dim(\" Run:\"),\n `cd ${mosaicTemplatePath} && pnpm template:tag`,\n );\n }\n } else {\n console.log();\n console.log(\n chalk.dim(\n \" Use --mosaic-template-path or set MOSAIC_TEMPLATE_PATH to check for updates\",\n ),\n );\n }\n\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;AAYA,eAAsB,cAAc,SAAuC;CACzE,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;EAChD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,kBAAkB,GAAG,SAAS,YAAY;EAChE,QAAQ,IAAI,MAAM,IAAI,oBAAoB,GAAG,SAAS,eAAe;EACrE,QAAQ,IAAI,MAAM,IAAI,oBAAoB,GAAG,SAAS,cAAc;EACpE,QAAQ,IAAI,MAAM,IAAI,YAAY,GAAG,SAAS,SAAS;EACvD,IAAI,SAAS,cACX,QAAQ,IAAI,MAAM,IAAI,gBAAgB,GAAG,SAAS,YAAY;EAGhE,MAAM,UACJ,QAAQ,sBAAsB,QAAQ,IAAI;EAC5C,MAAM,qBAAqB,UAAU,KAAK,QAAQ,OAAO,IAAI,KAAA;EAE7D,IAAI,oBAAoB;GACtB,MAAM,YAAY,qBAChB,SAAS,cACT,kBACF;GACA,IAAI,WAAW;IACb,MAAM,gBAAgB,0BAA0B,SAAS;IACzD,QAAQ,IAAI,MAAM,IAAI,mBAAmB,GAAG,aAAa;IACzD,QAAQ,IAAI;IAEZ,IAAI,kBAAkB,SAAS,iBAAiB;KAC9C,QAAQ,IACN,MAAM,OACJ,uBAAuB,SAAS,gBAAgB,KAAK,eACvD,CACF;KACA,QAAQ,IACN,MAAM,IAAI,QAAQ,GAClB,sCAAsC,oBACxC;IACF,OACE,QAAQ,IAAI,MAAM,MAAM,cAAc,CAAC;GAE3C,OAAO;IACL,QAAQ,IAAI;IACZ,QAAQ,IAAI,MAAM,OAAO,0CAA0C,CAAC;IACpE,QAAQ,IACN,MAAM,IAAI,QAAQ,GAClB,MAAM,mBAAmB,sBAC3B;GACF;EACF,OAAO;GACL,QAAQ,IAAI;GACZ,QAAQ,IACN,MAAM,IACJ,+EACF,CACF;EACF;EAEA,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
@@ -1,5 +1,5 @@
1
- import { i as resolveMosaicTemplatePath, r as readManifest } from "./manifest-By1SgOjC.js";
2
- import { i as getTemplateVersionFromTag, n as getLatestTemplateTag, r as getTemplateDiff } from "./git-ops-BD7JNnal.js";
1
+ import { c as readManifest, l as resolveMosaicTemplatePath } from "./index.js";
2
+ import { i as getTemplateVersionFromTag, n as getLatestTemplateTag, r as getTemplateDiff } from "./git-ops-BNpQnEc1.js";
3
3
  import path from "node:path";
4
4
  import chalk from "chalk";
5
5
  import fs from "fs-extra";
@@ -98,4 +98,4 @@ async function syncCommand(options) {
98
98
  //#endregion
99
99
  export { syncCommand };
100
100
 
101
- //# sourceMappingURL=sync-Bi958-2W.js.map
101
+ //# sourceMappingURL=sync-DC5DhIBT.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sync-Bi958-2W.js","names":[],"sources":["../src/commands/sync.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n getTemplateDiff,\n} from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface SyncOptions {\n mosaicTemplatePath?: string;\n to?: string;\n}\n\nfunction generateSyncContext(\n manifest: MosaicManifest,\n toVersion: string,\n diff: string,\n notes: string,\n): string {\n let content = `# Mosaic Sync Context\n\n## App Info\n- **Template:** ${manifest.templateType}\n- **Current version:** ${manifest.templateVersion}\n- **Target version:** ${toVersion}\n\n## Placeholder Mappings\n\nWhen applying template changes, replace these placeholder tokens with the actual values:\n\n| Placeholder | Value |\n|------------|-------|\n${Object.entries(manifest.placeholders)\n .map(([k, v]) => `| \\`${k}\\` | \\`${v}\\` |`)\n .join(\"\\n\")}\n\n## Template Changes (${manifest.templateVersion} → ${toVersion})\n\n\\`\\`\\`diff\n${diff}\n\\`\\`\\`\n`;\n\n if (notes.trim()) {\n content += `\n## Divergence Notes (from mosaic-template-notes.md)\n\n${notes}\n`;\n }\n\n content += `\n## Instructions\n\n1. Apply the template changes above to this app\n2. When you see placeholder tokens (e.g. \\`__APP_NAME__\\`), replace them with the actual values from the mapping table\n3. Check the divergence notes — preserve intentional divergences\n4. For files not modified locally: apply changes directly\n5. For files modified locally: merge intelligently, preserving local customizations\n6. After applying all changes, run: \\`pnpm install && pnpm build && pnpm lint\\`\n7. Update \\`.mosaic-template.json\\`: set \\`templateVersion\\` to \\`\"${toVersion}\"\\` and update \\`templateCommit\\`\n8. If you made decisions about merge conflicts, add notes to \\`mosaic-template-notes.md\\`\n9. Delete this file (\\`.mosaic-sync-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n const fromTag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n let toTag: string;\n if (options.to) {\n toTag = `template/${manifest.templateType}/${options.to}`;\n } else {\n const latest = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (!latest) {\n console.error(\n chalk.red(\n \"No template tags found. Run 'pnpm template:tag' in the mosaic repo first.\",\n ),\n );\n process.exit(1);\n }\n toTag = latest;\n }\n\n const toVersion = getTemplateVersionFromTag(toTag);\n\n if (toVersion === manifest.templateVersion) {\n console.log(chalk.green(\"Already up to date.\"));\n return;\n }\n\n const diff = getTemplateDiff(\n mosaicTemplatePath,\n manifest.source.templatePath,\n fromTag,\n toTag,\n );\n\n if (!diff.trim()) {\n console.log(chalk.green(\"No template file changes between versions.\"));\n return;\n }\n\n // Read mosaic-template-notes.md if it exists\n const notesPath = path.join(cwd, \"mosaic-template-notes.md\");\n let notes = \"\";\n if (await fs.pathExists(notesPath)) {\n notes = await fs.readFile(notesPath, \"utf-8\");\n }\n\n const context = generateSyncContext(manifest, toVersion, diff, notes);\n const contextPath = path.join(cwd, \".mosaic-sync-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Sync Context Generated\"));\n console.log();\n console.log(chalk.dim(\" From:\"), manifest.templateVersion);\n console.log(chalk.dim(\" To:\"), toVersion);\n console.log(chalk.dim(\" Context file:\"), \".mosaic-sync-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in this directory\");\n console.log(\n chalk.dim(\" 2.\"),\n 'Tell Claude: \"Read .mosaic-sync-context.md and apply the template changes\"',\n );\n console.log(\n chalk.dim(\" 3.\"),\n \"Review Claude's changes, then delete .mosaic-sync-context.md\",\n );\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAmBA,SAAS,oBACP,UACA,WACA,MACA,OACQ;CACR,IAAI,UAAU;;;kBAGE,SAAS,aAAa;yBACf,SAAS,gBAAgB;wBAC1B,UAAU;;;;;;;;EAQhC,OAAO,QAAQ,SAAS,aAAa,CACpC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,MAAM,CAC1C,KAAK,KAAK,CAAC;;uBAES,SAAS,gBAAgB,KAAK,UAAU;;;EAG7D,KAAK;;;AAIL,KAAI,MAAM,MAAM,CACd,YAAW;;;EAGb,MAAM;;AAIN,YAAW;;;;;;;;;qEASwD,UAAU;;;;AAK7E,QAAO;;AAGT,eAAsB,YAAY,SAAqC;CACrE,MAAM,MAAM,QAAQ,KAAK;AAEzB,KAAI;EACF,MAAM,WAAW,MAAM,aAAa,IAAI;EACxC,MAAM,qBAAqB,0BAA0B,QAAQ;EAE7D,MAAM,UAAU,YAAY,SAAS,aAAa,GAAG,SAAS;EAE9D,IAAI;AACJ,MAAI,QAAQ,GACV,SAAQ,YAAY,SAAS,aAAa,GAAG,QAAQ;OAChD;GACL,MAAM,SAAS,qBACb,SAAS,cACT,mBACD;AACD,OAAI,CAAC,QAAQ;AACX,YAAQ,MACN,MAAM,IACJ,4EACD,CACF;AACD,YAAQ,KAAK,EAAE;;AAEjB,WAAQ;;EAGV,MAAM,YAAY,0BAA0B,MAAM;AAElD,MAAI,cAAc,SAAS,iBAAiB;AAC1C,WAAQ,IAAI,MAAM,MAAM,sBAAsB,CAAC;AAC/C;;EAGF,MAAM,OAAO,gBACX,oBACA,SAAS,OAAO,cAChB,SACA,MACD;AAED,MAAI,CAAC,KAAK,MAAM,EAAE;AAChB,WAAQ,IAAI,MAAM,MAAM,6CAA6C,CAAC;AACtE;;EAIF,MAAM,YAAY,KAAK,KAAK,KAAK,2BAA2B;EAC5D,IAAI,QAAQ;AACZ,MAAI,MAAM,GAAG,WAAW,UAAU,CAChC,SAAQ,MAAM,GAAG,SAAS,WAAW,QAAQ;EAG/C,MAAM,UAAU,oBAAoB,UAAU,WAAW,MAAM,MAAM;EACrE,MAAM,cAAc,KAAK,KAAK,KAAK,0BAA0B;AAC7D,QAAM,GAAG,UAAU,aAAa,QAAQ;AAExC,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,KAAK,yBAAyB,CAAC;AACjD,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,IAAI,UAAU,EAAE,SAAS,gBAAgB;AAC3D,UAAQ,IAAI,MAAM,IAAI,QAAQ,EAAE,UAAU;AAC1C,UAAQ,IAAI,MAAM,IAAI,kBAAkB,EAAE,0BAA0B;AACpE,UAAQ,KAAK;AACb,UAAQ,IAAI,cAAc;AAC1B,UAAQ,IAAI,MAAM,IAAI,OAAO,EAAE,qCAAqC;AACpE,UAAQ,IACN,MAAM,IAAI,OAAO,EACjB,+EACD;AACD,UAAQ,IACN,MAAM,IAAI,OAAO,EACjB,+DACD;AACD,UAAQ,KAAK;UACN,OAAO;AACd,UAAQ,MAAM,MAAM,IAAK,MAAgB,QAAQ,CAAC;AAClD,UAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"sync-DC5DhIBT.js","names":[],"sources":["../src/commands/sync.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport {\n getLatestTemplateTag,\n getTemplateVersionFromTag,\n getTemplateDiff,\n} from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface SyncOptions {\n mosaicTemplatePath?: string;\n to?: string;\n}\n\nfunction generateSyncContext(\n manifest: MosaicManifest,\n toVersion: string,\n diff: string,\n notes: string,\n): string {\n let content = `# Mosaic Sync Context\n\n## App Info\n- **Template:** ${manifest.templateType}\n- **Current version:** ${manifest.templateVersion}\n- **Target version:** ${toVersion}\n\n## Placeholder Mappings\n\nWhen applying template changes, replace these placeholder tokens with the actual values:\n\n| Placeholder | Value |\n|------------|-------|\n${Object.entries(manifest.placeholders)\n .map(([k, v]) => `| \\`${k}\\` | \\`${v}\\` |`)\n .join(\"\\n\")}\n\n## Template Changes (${manifest.templateVersion} → ${toVersion})\n\n\\`\\`\\`diff\n${diff}\n\\`\\`\\`\n`;\n\n if (notes.trim()) {\n content += `\n## Divergence Notes (from mosaic-template-notes.md)\n\n${notes}\n`;\n }\n\n content += `\n## Instructions\n\n1. Apply the template changes above to this app\n2. When you see placeholder tokens (e.g. \\`__APP_NAME__\\`), replace them with the actual values from the mapping table\n3. Check the divergence notes — preserve intentional divergences\n4. For files not modified locally: apply changes directly\n5. For files modified locally: merge intelligently, preserving local customizations\n6. After applying all changes, run: \\`pnpm install && pnpm build && pnpm lint\\`\n7. Update \\`.mosaic-template.json\\`: set \\`templateVersion\\` to \\`\"${toVersion}\"\\` and update \\`templateCommit\\`\n8. If you made decisions about merge conflicts, add notes to \\`mosaic-template-notes.md\\`\n9. Delete this file (\\`.mosaic-sync-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function syncCommand(options: SyncOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n const fromTag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n let toTag: string;\n if (options.to) {\n toTag = `template/${manifest.templateType}/${options.to}`;\n } else {\n const latest = getLatestTemplateTag(\n manifest.templateType,\n mosaicTemplatePath,\n );\n if (!latest) {\n console.error(\n chalk.red(\n \"No template tags found. Run 'pnpm template:tag' in the mosaic repo first.\",\n ),\n );\n process.exit(1);\n }\n toTag = latest;\n }\n\n const toVersion = getTemplateVersionFromTag(toTag);\n\n if (toVersion === manifest.templateVersion) {\n console.log(chalk.green(\"Already up to date.\"));\n return;\n }\n\n const diff = getTemplateDiff(\n mosaicTemplatePath,\n manifest.source.templatePath,\n fromTag,\n toTag,\n );\n\n if (!diff.trim()) {\n console.log(chalk.green(\"No template file changes between versions.\"));\n return;\n }\n\n // Read mosaic-template-notes.md if it exists\n const notesPath = path.join(cwd, \"mosaic-template-notes.md\");\n let notes = \"\";\n if (await fs.pathExists(notesPath)) {\n notes = await fs.readFile(notesPath, \"utf-8\");\n }\n\n const context = generateSyncContext(manifest, toVersion, diff, notes);\n const contextPath = path.join(cwd, \".mosaic-sync-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Sync Context Generated\"));\n console.log();\n console.log(chalk.dim(\" From:\"), manifest.templateVersion);\n console.log(chalk.dim(\" To:\"), toVersion);\n console.log(chalk.dim(\" Context file:\"), \".mosaic-sync-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in this directory\");\n console.log(\n chalk.dim(\" 2.\"),\n 'Tell Claude: \"Read .mosaic-sync-context.md and apply the template changes\"',\n );\n console.log(\n chalk.dim(\" 3.\"),\n \"Review Claude's changes, then delete .mosaic-sync-context.md\",\n );\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAmBA,SAAS,oBACP,UACA,WACA,MACA,OACQ;CACR,IAAI,UAAU;;;kBAGE,SAAS,aAAa;yBACf,SAAS,gBAAgB;wBAC1B,UAAU;;;;;;;;EAQhC,OAAO,QAAQ,SAAS,YAAY,EACnC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,KAAK,EACzC,KAAK,IAAI,EAAE;;uBAES,SAAS,gBAAgB,KAAK,UAAU;;;EAG7D,KAAK;;;CAIL,IAAI,MAAM,KAAK,GACb,WAAW;;;EAGb,MAAM;;CAIN,WAAW;;;;;;;;;qEASwD,UAAU;;;;CAK7E,OAAO;AACT;AAEA,eAAsB,YAAY,SAAqC;CACrE,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EACvC,MAAM,qBAAqB,0BAA0B,OAAO;EAE5D,MAAM,UAAU,YAAY,SAAS,aAAa,GAAG,SAAS;EAE9D,IAAI;EACJ,IAAI,QAAQ,IACV,QAAQ,YAAY,SAAS,aAAa,GAAG,QAAQ;OAChD;GACL,MAAM,SAAS,qBACb,SAAS,cACT,kBACF;GACA,IAAI,CAAC,QAAQ;IACX,QAAQ,MACN,MAAM,IACJ,2EACF,CACF;IACA,QAAQ,KAAK,CAAC;GAChB;GACA,QAAQ;EACV;EAEA,MAAM,YAAY,0BAA0B,KAAK;EAEjD,IAAI,cAAc,SAAS,iBAAiB;GAC1C,QAAQ,IAAI,MAAM,MAAM,qBAAqB,CAAC;GAC9C;EACF;EAEA,MAAM,OAAO,gBACX,oBACA,SAAS,OAAO,cAChB,SACA,KACF;EAEA,IAAI,CAAC,KAAK,KAAK,GAAG;GAChB,QAAQ,IAAI,MAAM,MAAM,4CAA4C,CAAC;GACrE;EACF;EAGA,MAAM,YAAY,KAAK,KAAK,KAAK,0BAA0B;EAC3D,IAAI,QAAQ;EACZ,IAAI,MAAM,GAAG,WAAW,SAAS,GAC/B,QAAQ,MAAM,GAAG,SAAS,WAAW,OAAO;EAG9C,MAAM,UAAU,oBAAoB,UAAU,WAAW,MAAM,KAAK;EACpE,MAAM,cAAc,KAAK,KAAK,KAAK,yBAAyB;EAC5D,MAAM,GAAG,UAAU,aAAa,OAAO;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,wBAAwB,CAAC;EAChD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,SAAS,GAAG,SAAS,eAAe;EAC1D,QAAQ,IAAI,MAAM,IAAI,OAAO,GAAG,SAAS;EACzC,QAAQ,IAAI,MAAM,IAAI,iBAAiB,GAAG,yBAAyB;EACnE,QAAQ,IAAI;EACZ,QAAQ,IAAI,aAAa;EACzB,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,oCAAoC;EACnE,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,8EACF;EACA,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,8DACF;EACA,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
@@ -1,5 +1,5 @@
1
- import { i as resolveMosaicTemplatePath, r as readManifest } from "./manifest-By1SgOjC.js";
2
- import { t as getFileAtTag } from "./git-ops-BD7JNnal.js";
1
+ import { c as readManifest, l as resolveMosaicTemplatePath } from "./index.js";
2
+ import { t as getFileAtTag } from "./git-ops-BNpQnEc1.js";
3
3
  import path from "node:path";
4
4
  import chalk from "chalk";
5
5
  import fs from "fs-extra";
@@ -82,4 +82,4 @@ async function upstreamCommand(options) {
82
82
  //#endregion
83
83
  export { upstreamCommand };
84
84
 
85
- //# sourceMappingURL=upstream-CAraZeSS.js.map
85
+ //# sourceMappingURL=upstream-PNL6DGtl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upstream-CAraZeSS.js","names":[],"sources":["../src/commands/upstream.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { getFileAtTag } from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface UpstreamOptions {\n mosaicTemplatePath?: string;\n files?: string[];\n}\n\nasync function generateUpstreamContext(\n manifest: MosaicManifest,\n mosaicTemplatePath: string,\n tag: string,\n appDir: string,\n files: string[],\n): Promise<string> {\n let content = `# Mosaic Upstream Context\n\n## App Info\n- **App name:** ${manifest.placeholders.__APP_NAME__ || \"unknown\"}\n- **Template:** ${manifest.templateType}\n- **Template version:** ${manifest.templateVersion}\n\n## Placeholder Mappings\n\nWhen generalizing app code back to template, replace these values with placeholder tokens:\n\n| Value | Placeholder |\n|-------|------------|\n${Object.entries(manifest.placeholders)\n .sort((a, b) => b[1].length - a[1].length) // longest first to avoid partial matches\n .map(([k, v]) => `| \\`${v}\\` | \\`${k}\\` |`)\n .join(\"\\n\")}\n\n## Files to Review\n\n`;\n\n for (const file of files) {\n const appFilePath = path.resolve(appDir, file);\n const templateRelPath = `${manifest.source.templatePath}/${file}`;\n\n const appContent = (await fs.pathExists(appFilePath))\n ? await fs.readFile(appFilePath, \"utf-8\")\n : null;\n const templateContent = getFileAtTag(\n mosaicTemplatePath,\n tag,\n templateRelPath,\n );\n\n content += `### ${file}\\n\\n`;\n\n if (!templateContent && appContent) {\n content += `**New file** (not in template at ${manifest.templateVersion})\\n\\n`;\n content += `\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n } else if (templateContent && !appContent) {\n content += `**Deleted** (exists in template but not in app)\\n\\n`;\n } else if (appContent && templateContent) {\n content += `**App version:**\\n\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n content += `**Template version (at ${manifest.templateVersion}):**\\n\\`\\`\\`\\n${templateContent}\\n\\`\\`\\`\\n\\n`;\n } else {\n content += `**Not found** (file does not exist in app or template)\\n\\n`;\n }\n }\n\n content += `## Instructions\n\n1. Review each file above\n2. Determine which changes are generalizable (useful for all apps) vs app-specific\n3. For generalizable changes: apply them to the template at \\`${manifest.source.templatePath}/\\`\n4. When applying, replace app-specific values with placeholders using the mapping table above (replace longest values first)\n5. After applying, bump the version in \\`packages/blueberry/template-versions.json\\`\n6. Run \\`pnpm template:tag\\` to create the new version tag\n7. Delete this file (\\`.mosaic-upstream-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function upstreamCommand(options: UpstreamOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n if (!options.files || options.files.length === 0) {\n console.error(\n chalk.red(\"Specify files with --files <file1> <file2> ...\"),\n );\n console.log(\n chalk.dim(\n \" Example: create upstream --files src/config/getEnvConfig.ts\",\n ),\n );\n process.exit(1);\n }\n\n const tag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n const context = await generateUpstreamContext(\n manifest,\n mosaicTemplatePath,\n tag,\n cwd,\n options.files,\n );\n const contextPath = path.join(cwd, \".mosaic-upstream-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Upstream Context Generated\"));\n console.log();\n console.log(chalk.dim(\" Files:\"), options.files.join(\", \"));\n console.log(chalk.dim(\" Context file:\"), \".mosaic-upstream-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in the mosaic repo\");\n console.log(\n chalk.dim(\" 2.\"),\n `Tell Claude: \"Read ${path.resolve(cwd, \".mosaic-upstream-context.md\")} and apply generalizable changes to the template\"`,\n );\n console.log(chalk.dim(\" 3.\"), \"Review Claude's changes to the template\");\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAeA,eAAe,wBACb,UACA,oBACA,KACA,QACA,OACiB;CACjB,IAAI,UAAU;;;kBAGE,SAAS,aAAa,gBAAgB,UAAU;kBAChD,SAAS,aAAa;0BACd,SAAS,gBAAgB;;;;;;;;EAQjD,OAAO,QAAQ,SAAS,aAAa,CACpC,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,OAAO,CACzC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,MAAM,CAC1C,KAAK,KAAK,CAAC;;;;;AAMZ,MAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cAAc,KAAK,QAAQ,QAAQ,KAAK;EAC9C,MAAM,kBAAkB,GAAG,SAAS,OAAO,aAAa,GAAG;EAE3D,MAAM,aAAc,MAAM,GAAG,WAAW,YAAY,GAChD,MAAM,GAAG,SAAS,aAAa,QAAQ,GACvC;EACJ,MAAM,kBAAkB,aACtB,oBACA,KACA,gBACD;AAED,aAAW,OAAO,KAAK;AAEvB,MAAI,CAAC,mBAAmB,YAAY;AAClC,cAAW,oCAAoC,SAAS,gBAAgB;AACxE,cAAW,WAAW,WAAW;aACxB,mBAAmB,CAAC,WAC7B,YAAW;WACF,cAAc,iBAAiB;AACxC,cAAW,6BAA6B,WAAW;AACnD,cAAW,0BAA0B,SAAS,gBAAgB,gBAAgB,gBAAgB;QAE9F,YAAW;;AAIf,YAAW;;;;gEAImD,SAAS,OAAO,aAAa;;;;;;AAO3F,QAAO;;AAGT,eAAsB,gBAAgB,SAAyC;CAC7E,MAAM,MAAM,QAAQ,KAAK;AAEzB,KAAI;EACF,MAAM,WAAW,MAAM,aAAa,IAAI;EACxC,MAAM,qBAAqB,0BAA0B,QAAQ;AAE7D,MAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,WAAW,GAAG;AAChD,WAAQ,MACN,MAAM,IAAI,iDAAiD,CAC5D;AACD,WAAQ,IACN,MAAM,IACJ,gEACD,CACF;AACD,WAAQ,KAAK,EAAE;;EAKjB,MAAM,UAAU,MAAM,wBACpB,UACA,oBACA,YALsB,SAAS,aAAa,GAAG,SAAS,mBAMxD,KACA,QAAQ,MACT;EACD,MAAM,cAAc,KAAK,KAAK,KAAK,8BAA8B;AACjE,QAAM,GAAG,UAAU,aAAa,QAAQ;AAExC,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,KAAK,6BAA6B,CAAC;AACrD,UAAQ,KAAK;AACb,UAAQ,IAAI,MAAM,IAAI,WAAW,EAAE,QAAQ,MAAM,KAAK,KAAK,CAAC;AAC5D,UAAQ,IAAI,MAAM,IAAI,kBAAkB,EAAE,8BAA8B;AACxE,UAAQ,KAAK;AACb,UAAQ,IAAI,cAAc;AAC1B,UAAQ,IAAI,MAAM,IAAI,OAAO,EAAE,sCAAsC;AACrE,UAAQ,IACN,MAAM,IAAI,OAAO,EACjB,sBAAsB,KAAK,QAAQ,KAAK,8BAA8B,CAAC,mDACxE;AACD,UAAQ,IAAI,MAAM,IAAI,OAAO,EAAE,0CAA0C;AACzE,UAAQ,KAAK;UACN,OAAO;AACd,UAAQ,MAAM,MAAM,IAAK,MAAgB,QAAQ,CAAC;AAClD,UAAQ,KAAK,EAAE"}
1
+ {"version":3,"file":"upstream-PNL6DGtl.js","names":[],"sources":["../src/commands/upstream.ts"],"sourcesContent":["import path from \"node:path\";\nimport chalk from \"chalk\";\nimport fs from \"fs-extra\";\nimport { getFileAtTag } from \"../utils/git-ops.js\";\nimport {\n readManifest,\n resolveMosaicTemplatePath,\n type MosaicManifest,\n} from \"../utils/manifest.js\";\n\nexport interface UpstreamOptions {\n mosaicTemplatePath?: string;\n files?: string[];\n}\n\nasync function generateUpstreamContext(\n manifest: MosaicManifest,\n mosaicTemplatePath: string,\n tag: string,\n appDir: string,\n files: string[],\n): Promise<string> {\n let content = `# Mosaic Upstream Context\n\n## App Info\n- **App name:** ${manifest.placeholders.__APP_NAME__ || \"unknown\"}\n- **Template:** ${manifest.templateType}\n- **Template version:** ${manifest.templateVersion}\n\n## Placeholder Mappings\n\nWhen generalizing app code back to template, replace these values with placeholder tokens:\n\n| Value | Placeholder |\n|-------|------------|\n${Object.entries(manifest.placeholders)\n .sort((a, b) => b[1].length - a[1].length) // longest first to avoid partial matches\n .map(([k, v]) => `| \\`${v}\\` | \\`${k}\\` |`)\n .join(\"\\n\")}\n\n## Files to Review\n\n`;\n\n for (const file of files) {\n const appFilePath = path.resolve(appDir, file);\n const templateRelPath = `${manifest.source.templatePath}/${file}`;\n\n const appContent = (await fs.pathExists(appFilePath))\n ? await fs.readFile(appFilePath, \"utf-8\")\n : null;\n const templateContent = getFileAtTag(\n mosaicTemplatePath,\n tag,\n templateRelPath,\n );\n\n content += `### ${file}\\n\\n`;\n\n if (!templateContent && appContent) {\n content += `**New file** (not in template at ${manifest.templateVersion})\\n\\n`;\n content += `\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n } else if (templateContent && !appContent) {\n content += `**Deleted** (exists in template but not in app)\\n\\n`;\n } else if (appContent && templateContent) {\n content += `**App version:**\\n\\`\\`\\`\\n${appContent}\\n\\`\\`\\`\\n\\n`;\n content += `**Template version (at ${manifest.templateVersion}):**\\n\\`\\`\\`\\n${templateContent}\\n\\`\\`\\`\\n\\n`;\n } else {\n content += `**Not found** (file does not exist in app or template)\\n\\n`;\n }\n }\n\n content += `## Instructions\n\n1. Review each file above\n2. Determine which changes are generalizable (useful for all apps) vs app-specific\n3. For generalizable changes: apply them to the template at \\`${manifest.source.templatePath}/\\`\n4. When applying, replace app-specific values with placeholders using the mapping table above (replace longest values first)\n5. After applying, bump the version in \\`packages/blueberry/template-versions.json\\`\n6. Run \\`pnpm template:tag\\` to create the new version tag\n7. Delete this file (\\`.mosaic-upstream-context.md\\`) when done\n`;\n\n return content;\n}\n\nexport async function upstreamCommand(options: UpstreamOptions): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const manifest = await readManifest(cwd);\n const mosaicTemplatePath = resolveMosaicTemplatePath(options);\n\n if (!options.files || options.files.length === 0) {\n console.error(\n chalk.red(\"Specify files with --files <file1> <file2> ...\"),\n );\n console.log(\n chalk.dim(\n \" Example: create upstream --files src/config/getEnvConfig.ts\",\n ),\n );\n process.exit(1);\n }\n\n const tag = `template/${manifest.templateType}/${manifest.templateVersion}`;\n\n const context = await generateUpstreamContext(\n manifest,\n mosaicTemplatePath,\n tag,\n cwd,\n options.files,\n );\n const contextPath = path.join(cwd, \".mosaic-upstream-context.md\");\n await fs.writeFile(contextPath, context);\n\n console.log();\n console.log(chalk.bold(\"Upstream Context Generated\"));\n console.log();\n console.log(chalk.dim(\" Files:\"), options.files.join(\", \"));\n console.log(chalk.dim(\" Context file:\"), \".mosaic-upstream-context.md\");\n console.log();\n console.log(\"Next steps:\");\n console.log(chalk.dim(\" 1.\"), \"Open Claude Code in the mosaic repo\");\n console.log(\n chalk.dim(\" 2.\"),\n `Tell Claude: \"Read ${path.resolve(cwd, \".mosaic-upstream-context.md\")} and apply generalizable changes to the template\"`,\n );\n console.log(chalk.dim(\" 3.\"), \"Review Claude's changes to the template\");\n console.log();\n } catch (error) {\n console.error(chalk.red((error as Error).message));\n process.exit(1);\n }\n}\n"],"mappings":";;;;;;AAeA,eAAe,wBACb,UACA,oBACA,KACA,QACA,OACiB;CACjB,IAAI,UAAU;;;kBAGE,SAAS,aAAa,gBAAgB,UAAU;kBAChD,SAAS,aAAa;0BACd,SAAS,gBAAgB;;;;;;;;EAQjD,OAAO,QAAQ,SAAS,YAAY,EACnC,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,MAAM,EACxC,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,SAAS,EAAE,KAAK,EACzC,KAAK,IAAI,EAAE;;;;;CAMZ,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cAAc,KAAK,QAAQ,QAAQ,IAAI;EAC7C,MAAM,kBAAkB,GAAG,SAAS,OAAO,aAAa,GAAG;EAE3D,MAAM,aAAc,MAAM,GAAG,WAAW,WAAW,IAC/C,MAAM,GAAG,SAAS,aAAa,OAAO,IACtC;EACJ,MAAM,kBAAkB,aACtB,oBACA,KACA,eACF;EAEA,WAAW,OAAO,KAAK;EAEvB,IAAI,CAAC,mBAAmB,YAAY;GAClC,WAAW,oCAAoC,SAAS,gBAAgB;GACxE,WAAW,WAAW,WAAW;EACnC,OAAO,IAAI,mBAAmB,CAAC,YAC7B,WAAW;OACN,IAAI,cAAc,iBAAiB;GACxC,WAAW,6BAA6B,WAAW;GACnD,WAAW,0BAA0B,SAAS,gBAAgB,gBAAgB,gBAAgB;EAChG,OACE,WAAW;CAEf;CAEA,WAAW;;;;gEAImD,SAAS,OAAO,aAAa;;;;;;CAO3F,OAAO;AACT;AAEA,eAAsB,gBAAgB,SAAyC;CAC7E,MAAM,MAAM,QAAQ,IAAI;CAExB,IAAI;EACF,MAAM,WAAW,MAAM,aAAa,GAAG;EACvC,MAAM,qBAAqB,0BAA0B,OAAO;EAE5D,IAAI,CAAC,QAAQ,SAAS,QAAQ,MAAM,WAAW,GAAG;GAChD,QAAQ,MACN,MAAM,IAAI,gDAAgD,CAC5D;GACA,QAAQ,IACN,MAAM,IACJ,+DACF,CACF;GACA,QAAQ,KAAK,CAAC;EAChB;EAIA,MAAM,UAAU,MAAM,wBACpB,UACA,oBACA,YALsB,SAAS,aAAa,GAAG,SAAS,mBAMxD,KACA,QAAQ,KACV;EACA,MAAM,cAAc,KAAK,KAAK,KAAK,6BAA6B;EAChE,MAAM,GAAG,UAAU,aAAa,OAAO;EAEvC,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,KAAK,4BAA4B,CAAC;EACpD,QAAQ,IAAI;EACZ,QAAQ,IAAI,MAAM,IAAI,UAAU,GAAG,QAAQ,MAAM,KAAK,IAAI,CAAC;EAC3D,QAAQ,IAAI,MAAM,IAAI,iBAAiB,GAAG,6BAA6B;EACvE,QAAQ,IAAI;EACZ,QAAQ,IAAI,aAAa;EACzB,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,qCAAqC;EACpE,QAAQ,IACN,MAAM,IAAI,MAAM,GAChB,sBAAsB,KAAK,QAAQ,KAAK,6BAA6B,EAAE,kDACzE;EACA,QAAQ,IAAI,MAAM,IAAI,MAAM,GAAG,yCAAyC;EACxE,QAAQ,IAAI;CACd,SAAS,OAAO;EACd,QAAQ,MAAM,MAAM,IAAK,MAAgB,OAAO,CAAC;EACjD,QAAQ,KAAK,CAAC;CAChB;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percepta/create",
3
- "version": "4.1.7",
3
+ "version": "4.1.9",
4
4
  "description": "Scaffold a new Mosaic package",
5
5
  "keywords": [
6
6
  "cli",
@@ -34,11 +34,11 @@
34
34
  "yaml": "^2.7.0"
35
35
  },
36
36
  "devDependencies": {
37
+ "@percepta/build": "^1.2.1",
37
38
  "@types/fs-extra": "^11.0.4",
38
39
  "@types/node": "^24.1.0",
39
40
  "@types/validate-npm-package-name": "^4.0.2",
40
- "vitest": "^4.0.0",
41
- "@percepta/build": "1.1.0"
41
+ "vitest": "^4.0.0"
42
42
  },
43
43
  "engines": {
44
44
  "node": ">=18.0.0"
@@ -1,5 +1,5 @@
1
1
  {
2
- "monorepo": "1.0.5",
3
- "webapp": "1.3.3",
2
+ "monorepo": "1.0.6",
3
+ "webapp": "1.3.4",
4
4
  "library": "1.0.0"
5
5
  }
@@ -48,6 +48,18 @@ spec:
48
48
  displayName: "Langfuse Secret Key"
49
49
  description: "Shared Langfuse secret key for generated OS webapps. Leave unset to disable Langfuse export."
50
50
  condition: '{{ ne (input "langfuse_public_key") "" }}'
51
+ - name: inngest_event_key
52
+ type: string
53
+ isSecret: true
54
+ group: applications
55
+ displayName: "Inngest Event Key"
56
+ description: "Shared Inngest event key for generated OS webapps."
57
+ - name: inngest_signing_key
58
+ type: string
59
+ isSecret: true
60
+ group: applications
61
+ displayName: "Inngest Signing Key"
62
+ description: "Shared Inngest signing key for generated OS webapps."
51
63
  - name: auth_secret_name
52
64
  type: string
53
65
  group: general
@@ -131,6 +143,7 @@ spec:
131
143
 
132
144
  region: {{ .ryvn.env.state.cluster_region }}
133
145
  vpc_id: {{ .ryvn.env.state.vpc.id }}
146
+ sslmode: require
134
147
  subnet_ids:
135
148
  {{ .ryvn.env.state.vpc.private_subnet_ids | toYaml | nindent 2 }}
136
149
  {{ if ne (input "aws_postgresql_cluster_name") "" }}
@@ -5,8 +5,8 @@ This workspace wires the customer-global Better Auth database schema from
5
5
  session validation and user / group table references instead of creating
6
6
  app-local auth tables.
7
7
 
8
- Import auth as `@__CUSTOMER_SLUG__/auth`, the database handle as
9
- `@__CUSTOMER_SLUG__/auth/db`, and table definitions as `@__CUSTOMER_SLUG__/auth/schema`
8
+ Import auth as `@__REPO_NAME__/auth`, the database handle as
9
+ `@__REPO_NAME__/auth/db`, and table definitions as `@__REPO_NAME__/auth/schema`
10
10
  from app packages.
11
11
 
12
12
  The important identity invariant is:
@@ -1,5 +1,5 @@
1
1
  {
2
- "name": "@__CUSTOMER_SLUG__/auth",
2
+ "name": "@__REPO_NAME__/auth",
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
5
  "description": "Shared customer identity package.",