@open-mercato/cli 0.6.4-develop.4382.1.6b4f656b77 → 0.6.4

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 (109) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/agentic/guides/core.customers.md +1 -1
  3. package/dist/agentic/shared/AGENTS.md.template +56 -33
  4. package/dist/agentic/shared/ai/skills/{auto-continue-pr → om-auto-continue-pr}/SKILL.md +19 -19
  5. package/dist/agentic/shared/ai/skills/{auto-create-pr → om-auto-continue-pr}/STANDALONE.md +1 -1
  6. package/dist/agentic/shared/ai/skills/{auto-continue-pr-loop → om-auto-continue-pr-loop}/SKILL.md +32 -32
  7. package/dist/agentic/shared/ai/skills/{auto-create-pr → om-auto-create-pr}/SKILL.md +24 -24
  8. package/dist/agentic/shared/ai/skills/{auto-fix-github → om-auto-create-pr}/STANDALONE.md +1 -1
  9. package/dist/agentic/shared/ai/skills/{auto-create-pr-loop → om-auto-create-pr-loop}/SKILL.md +40 -40
  10. package/dist/agentic/shared/ai/skills/{auto-fix-github → om-auto-fix-github}/SKILL.md +3 -3
  11. package/dist/agentic/shared/ai/skills/{auto-continue-pr → om-auto-fix-github}/STANDALONE.md +1 -1
  12. package/dist/agentic/shared/ai/skills/{auto-review-pr → om-auto-review-pr}/SKILL.md +5 -5
  13. package/dist/agentic/shared/ai/skills/{auto-review-pr → om-auto-review-pr}/STANDALONE.md +1 -1
  14. package/dist/agentic/shared/ai/skills/{auto-upgrade-0.4.10-to-0.5.0 → om-auto-upgrade-0.4.10-to-0.5.0}/SKILL.md +1 -1
  15. package/dist/agentic/shared/ai/skills/{backend-ui-design → om-backend-ui-design}/SKILL.md +2 -2
  16. package/dist/agentic/shared/ai/skills/{code-review → om-code-review}/SKILL.md +1 -1
  17. package/dist/agentic/shared/ai/skills/{code-review → om-code-review}/references/review-checklist.md +3 -0
  18. package/dist/agentic/shared/ai/skills/{data-model-design → om-data-model-design}/SKILL.md +4 -2
  19. package/dist/agentic/shared/ai/skills/{eject-and-customize → om-eject-and-customize}/SKILL.md +2 -2
  20. package/dist/agentic/shared/ai/skills/{implement-spec → om-implement-spec}/SKILL.md +6 -6
  21. package/dist/agentic/shared/ai/skills/{integration-builder → om-integration-builder}/SKILL.md +1 -1
  22. package/dist/agentic/shared/ai/skills/{integration-tests → om-integration-tests}/SKILL.md +1 -1
  23. package/dist/agentic/shared/ai/skills/{module-scaffold → om-module-scaffold}/SKILL.md +5 -3
  24. package/dist/agentic/shared/ai/skills/{module-scaffold → om-module-scaffold}/references/naming-conventions.md +7 -8
  25. package/dist/agentic/shared/ai/skills/om-prepare-issue/SKILL.md +202 -0
  26. package/dist/agentic/shared/ai/skills/{spec-writing → om-spec-writing}/SKILL.md +6 -6
  27. package/dist/agentic/shared/ai/skills/{spec-writing → om-spec-writing}/references/spec-checklist.md +3 -3
  28. package/dist/agentic/shared/ai/skills/{system-extension → om-system-extension}/SKILL.md +1 -1
  29. package/dist/agentic/shared/ai/skills/{trim-unused-modules → om-trim-unused-modules}/SKILL.md +1 -1
  30. package/dist/agentic/shared/ai/skills/{troubleshooter → om-troubleshooter}/SKILL.md +1 -1
  31. package/dist/bin.js +1 -0
  32. package/dist/bin.js.map +2 -2
  33. package/dist/lib/__integration__/TC-INT-008.spec.js +1 -1
  34. package/dist/lib/__integration__/TC-INT-008.spec.js.map +2 -2
  35. package/dist/lib/agentic-setup.js +52 -51
  36. package/dist/lib/agentic-setup.js.map +2 -2
  37. package/dist/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.meta.js +7 -0
  38. package/dist/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.meta.js.map +7 -0
  39. package/dist/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.spec.js +63 -0
  40. package/dist/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.spec.js.map +7 -0
  41. package/dist/lib/deploy/railway/env.js +98 -0
  42. package/dist/lib/deploy/railway/env.js.map +7 -0
  43. package/dist/lib/deploy/railway/graphql-client.js +99 -0
  44. package/dist/lib/deploy/railway/graphql-client.js.map +7 -0
  45. package/dist/lib/deploy/railway/index.js +1115 -0
  46. package/dist/lib/deploy/railway/index.js.map +7 -0
  47. package/dist/lib/deploy/railway/operations.js +249 -0
  48. package/dist/lib/deploy/railway/operations.js.map +7 -0
  49. package/dist/lib/deploy/railway/options.js +155 -0
  50. package/dist/lib/deploy/railway/options.js.map +7 -0
  51. package/dist/lib/deploy/railway/railway-cli.js +61 -0
  52. package/dist/lib/deploy/railway/railway-cli.js.map +7 -0
  53. package/dist/lib/deploy/railway/redaction.js +88 -0
  54. package/dist/lib/deploy/railway/redaction.js.map +7 -0
  55. package/dist/lib/deploy/railway/source.js +128 -0
  56. package/dist/lib/deploy/railway/source.js.map +7 -0
  57. package/dist/lib/deploy/railway/state.js +41 -0
  58. package/dist/lib/deploy/railway/state.js.map +7 -0
  59. package/dist/lib/deploy/railway/token.js +46 -0
  60. package/dist/lib/deploy/railway/token.js.map +7 -0
  61. package/dist/lib/deploy/railway/types.js +1 -0
  62. package/dist/lib/deploy/railway/types.js.map +7 -0
  63. package/dist/lib/generators/openapi.js +4 -0
  64. package/dist/lib/generators/openapi.js.map +2 -2
  65. package/dist/lib/testing/integration.js +57 -26
  66. package/dist/lib/testing/integration.js.map +2 -2
  67. package/dist/lib/testing/runtime-utils.js +16 -8
  68. package/dist/lib/testing/runtime-utils.js.map +2 -2
  69. package/dist/mercato.js +23 -8
  70. package/dist/mercato.js.map +2 -2
  71. package/package.json +11 -12
  72. package/src/bin.ts +1 -0
  73. package/src/lib/__integration__/TC-INT-008.spec.ts +1 -1
  74. package/src/lib/agentic-setup.ts +52 -51
  75. package/src/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.meta.ts +3 -0
  76. package/src/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.spec.ts +71 -0
  77. package/src/lib/deploy/railway/__tests__/dry-run.test.ts +61 -0
  78. package/src/lib/deploy/railway/__tests__/env.test.ts +55 -0
  79. package/src/lib/deploy/railway/__tests__/graphql-client.test.ts +80 -0
  80. package/src/lib/deploy/railway/__tests__/operations.test.ts +21 -0
  81. package/src/lib/deploy/railway/__tests__/options.test.ts +78 -0
  82. package/src/lib/deploy/railway/__tests__/redaction.test.ts +62 -0
  83. package/src/lib/deploy/railway/__tests__/source.test.ts +130 -0
  84. package/src/lib/deploy/railway/__tests__/state.test.ts +24 -0
  85. package/src/lib/deploy/railway/__tests__/token.test.ts +39 -0
  86. package/src/lib/deploy/railway/env.ts +112 -0
  87. package/src/lib/deploy/railway/graphql-client.ts +128 -0
  88. package/src/lib/deploy/railway/index.ts +1454 -0
  89. package/src/lib/deploy/railway/operations.ts +248 -0
  90. package/src/lib/deploy/railway/options.ts +167 -0
  91. package/src/lib/deploy/railway/railway-cli.ts +65 -0
  92. package/src/lib/deploy/railway/redaction.ts +91 -0
  93. package/src/lib/deploy/railway/source.ts +143 -0
  94. package/src/lib/deploy/railway/state.ts +45 -0
  95. package/src/lib/deploy/railway/token.ts +49 -0
  96. package/src/lib/deploy/railway/types.ts +87 -0
  97. package/src/lib/generators/openapi.ts +3 -0
  98. package/src/lib/testing/__tests__/integration.test.ts +79 -0
  99. package/src/lib/testing/__tests__/runtime-utils.test.ts +45 -1
  100. package/src/lib/testing/integration.ts +74 -28
  101. package/src/lib/testing/runtime-utils.ts +17 -8
  102. package/src/mercato.ts +33 -8
  103. /package/dist/agentic/shared/ai/skills/{backend-ui-design → om-backend-ui-design}/references/ui-components.md +0 -0
  104. /package/dist/agentic/shared/ai/skills/{data-model-design → om-data-model-design}/references/mikro-orm-cheatsheet.md +0 -0
  105. /package/dist/agentic/shared/ai/skills/{integration-builder → om-integration-builder}/references/adapter-contracts.md +0 -0
  106. /package/dist/agentic/shared/ai/skills/{module-scaffold → om-module-scaffold}/references/navigation-patterns.md +0 -0
  107. /package/dist/agentic/shared/ai/skills/{spec-writing → om-spec-writing}/references/spec-template.md +0 -0
  108. /package/dist/agentic/shared/ai/skills/{system-extension → om-system-extension}/references/extension-contracts.md +0 -0
  109. /package/dist/agentic/shared/ai/skills/{troubleshooter → om-troubleshooter}/references/diagnostic-commands.md +0 -0
@@ -31,118 +31,119 @@ function generateShared(config) {
31
31
  copyFile(srcDir, "ai/lessons.md", join(targetDir, ".ai", "lessons.md"));
32
32
  writeTemplate(
33
33
  srcDir,
34
- "ai/skills/spec-writing/SKILL.md",
35
- join(targetDir, ".ai", "skills", "spec-writing", "SKILL.md"),
34
+ "ai/skills/om-spec-writing/SKILL.md",
35
+ join(targetDir, ".ai", "skills", "om-spec-writing", "SKILL.md"),
36
36
  config
37
37
  );
38
38
  copyFile(
39
39
  srcDir,
40
- "ai/skills/spec-writing/references/spec-template.md",
41
- join(targetDir, ".ai", "skills", "spec-writing", "references", "spec-template.md")
40
+ "ai/skills/om-spec-writing/references/spec-template.md",
41
+ join(targetDir, ".ai", "skills", "om-spec-writing", "references", "spec-template.md")
42
42
  );
43
43
  copyFile(
44
44
  srcDir,
45
- "ai/skills/spec-writing/references/spec-checklist.md",
46
- join(targetDir, ".ai", "skills", "spec-writing", "references", "spec-checklist.md")
45
+ "ai/skills/om-spec-writing/references/spec-checklist.md",
46
+ join(targetDir, ".ai", "skills", "om-spec-writing", "references", "spec-checklist.md")
47
47
  );
48
48
  copyFile(
49
49
  srcDir,
50
- "ai/skills/backend-ui-design/SKILL.md",
51
- join(targetDir, ".ai", "skills", "backend-ui-design", "SKILL.md")
50
+ "ai/skills/om-backend-ui-design/SKILL.md",
51
+ join(targetDir, ".ai", "skills", "om-backend-ui-design", "SKILL.md")
52
52
  );
53
53
  copyFile(
54
54
  srcDir,
55
- "ai/skills/backend-ui-design/references/ui-components.md",
56
- join(targetDir, ".ai", "skills", "backend-ui-design", "references", "ui-components.md")
55
+ "ai/skills/om-backend-ui-design/references/ui-components.md",
56
+ join(targetDir, ".ai", "skills", "om-backend-ui-design", "references", "ui-components.md")
57
57
  );
58
58
  copyFile(
59
59
  srcDir,
60
- "ai/skills/code-review/SKILL.md",
61
- join(targetDir, ".ai", "skills", "code-review", "SKILL.md")
60
+ "ai/skills/om-code-review/SKILL.md",
61
+ join(targetDir, ".ai", "skills", "om-code-review", "SKILL.md")
62
62
  );
63
63
  copyFile(
64
64
  srcDir,
65
- "ai/skills/code-review/references/review-checklist.md",
66
- join(targetDir, ".ai", "skills", "code-review", "references", "review-checklist.md")
65
+ "ai/skills/om-code-review/references/review-checklist.md",
66
+ join(targetDir, ".ai", "skills", "om-code-review", "references", "review-checklist.md")
67
67
  );
68
- copyFile(srcDir, "ai/skills/integration-builder/SKILL.md", join(targetDir, ".ai", "skills", "integration-builder", "SKILL.md"));
68
+ copyFile(srcDir, "ai/skills/om-integration-builder/SKILL.md", join(targetDir, ".ai", "skills", "om-integration-builder", "SKILL.md"));
69
69
  copyFile(
70
70
  srcDir,
71
- "ai/skills/integration-builder/references/adapter-contracts.md",
72
- join(targetDir, ".ai", "skills", "integration-builder", "references", "adapter-contracts.md")
71
+ "ai/skills/om-integration-builder/references/adapter-contracts.md",
72
+ join(targetDir, ".ai", "skills", "om-integration-builder", "references", "adapter-contracts.md")
73
73
  );
74
74
  copyFile(
75
75
  srcDir,
76
- "ai/skills/system-extension/SKILL.md",
77
- join(targetDir, ".ai", "skills", "system-extension", "SKILL.md")
76
+ "ai/skills/om-system-extension/SKILL.md",
77
+ join(targetDir, ".ai", "skills", "om-system-extension", "SKILL.md")
78
78
  );
79
79
  copyFile(
80
80
  srcDir,
81
- "ai/skills/system-extension/references/extension-contracts.md",
82
- join(targetDir, ".ai", "skills", "system-extension", "references", "extension-contracts.md")
81
+ "ai/skills/om-system-extension/references/extension-contracts.md",
82
+ join(targetDir, ".ai", "skills", "om-system-extension", "references", "extension-contracts.md")
83
83
  );
84
84
  copyFile(
85
85
  srcDir,
86
- "ai/skills/module-scaffold/SKILL.md",
87
- join(targetDir, ".ai", "skills", "module-scaffold", "SKILL.md")
86
+ "ai/skills/om-module-scaffold/SKILL.md",
87
+ join(targetDir, ".ai", "skills", "om-module-scaffold", "SKILL.md")
88
88
  );
89
89
  copyFile(
90
90
  srcDir,
91
- "ai/skills/module-scaffold/references/naming-conventions.md",
92
- join(targetDir, ".ai", "skills", "module-scaffold", "references", "naming-conventions.md")
91
+ "ai/skills/om-module-scaffold/references/naming-conventions.md",
92
+ join(targetDir, ".ai", "skills", "om-module-scaffold", "references", "naming-conventions.md")
93
93
  );
94
94
  copyFile(
95
95
  srcDir,
96
- "ai/skills/module-scaffold/references/navigation-patterns.md",
97
- join(targetDir, ".ai", "skills", "module-scaffold", "references", "navigation-patterns.md")
96
+ "ai/skills/om-module-scaffold/references/navigation-patterns.md",
97
+ join(targetDir, ".ai", "skills", "om-module-scaffold", "references", "navigation-patterns.md")
98
98
  );
99
99
  copyFile(
100
100
  srcDir,
101
- "ai/skills/troubleshooter/SKILL.md",
102
- join(targetDir, ".ai", "skills", "troubleshooter", "SKILL.md")
101
+ "ai/skills/om-troubleshooter/SKILL.md",
102
+ join(targetDir, ".ai", "skills", "om-troubleshooter", "SKILL.md")
103
103
  );
104
104
  copyFile(
105
105
  srcDir,
106
- "ai/skills/troubleshooter/references/diagnostic-commands.md",
107
- join(targetDir, ".ai", "skills", "troubleshooter", "references", "diagnostic-commands.md")
106
+ "ai/skills/om-troubleshooter/references/diagnostic-commands.md",
107
+ join(targetDir, ".ai", "skills", "om-troubleshooter", "references", "diagnostic-commands.md")
108
108
  );
109
109
  copyFile(
110
110
  srcDir,
111
- "ai/skills/eject-and-customize/SKILL.md",
112
- join(targetDir, ".ai", "skills", "eject-and-customize", "SKILL.md")
111
+ "ai/skills/om-eject-and-customize/SKILL.md",
112
+ join(targetDir, ".ai", "skills", "om-eject-and-customize", "SKILL.md")
113
113
  );
114
114
  copyFile(
115
115
  srcDir,
116
- "ai/skills/data-model-design/SKILL.md",
117
- join(targetDir, ".ai", "skills", "data-model-design", "SKILL.md")
116
+ "ai/skills/om-data-model-design/SKILL.md",
117
+ join(targetDir, ".ai", "skills", "om-data-model-design", "SKILL.md")
118
118
  );
119
119
  copyFile(
120
120
  srcDir,
121
- "ai/skills/data-model-design/references/mikro-orm-cheatsheet.md",
122
- join(targetDir, ".ai", "skills", "data-model-design", "references", "mikro-orm-cheatsheet.md")
121
+ "ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md",
122
+ join(targetDir, ".ai", "skills", "om-data-model-design", "references", "mikro-orm-cheatsheet.md")
123
123
  );
124
124
  copyFile(
125
125
  srcDir,
126
- "ai/skills/implement-spec/SKILL.md",
127
- join(targetDir, ".ai", "skills", "implement-spec", "SKILL.md")
126
+ "ai/skills/om-implement-spec/SKILL.md",
127
+ join(targetDir, ".ai", "skills", "om-implement-spec", "SKILL.md")
128
128
  );
129
129
  copyFile(
130
130
  srcDir,
131
- "ai/skills/integration-tests/SKILL.md",
132
- join(targetDir, ".ai", "skills", "integration-tests", "SKILL.md")
131
+ "ai/skills/om-integration-tests/SKILL.md",
132
+ join(targetDir, ".ai", "skills", "om-integration-tests", "SKILL.md")
133
133
  );
134
134
  copyFile(
135
135
  srcDir,
136
- "ai/skills/auto-upgrade-0.4.10-to-0.5.0/SKILL.md",
137
- join(targetDir, ".ai", "skills", "auto-upgrade-0.4.10-to-0.5.0", "SKILL.md")
136
+ "ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md",
137
+ join(targetDir, ".ai", "skills", "om-auto-upgrade-0.4.10-to-0.5.0", "SKILL.md")
138
138
  );
139
139
  for (const autoSkill of [
140
- "auto-create-pr",
141
- "auto-continue-pr",
142
- "auto-create-pr-loop",
143
- "auto-continue-pr-loop",
144
- "auto-review-pr",
145
- "auto-fix-github"
140
+ "om-auto-create-pr",
141
+ "om-auto-continue-pr",
142
+ "om-auto-create-pr-loop",
143
+ "om-auto-continue-pr-loop",
144
+ "om-auto-review-pr",
145
+ "om-auto-fix-github",
146
+ "om-prepare-issue"
146
147
  ]) {
147
148
  copyFile(
148
149
  srcDir,
@@ -159,8 +160,8 @@ function generateShared(config) {
159
160
  }
160
161
  copyFile(
161
162
  srcDir,
162
- "ai/skills/trim-unused-modules/SKILL.md",
163
- join(targetDir, ".ai", "skills", "trim-unused-modules", "SKILL.md")
163
+ "ai/skills/om-trim-unused-modules/SKILL.md",
164
+ join(targetDir, ".ai", "skills", "om-trim-unused-modules", "SKILL.md")
164
165
  );
165
166
  copyFile(srcDir, "ai/qa/tests/playwright.config.ts", join(targetDir, ".ai", "qa", "tests", "playwright.config.ts"));
166
167
  if (existsSync(GUIDES_DIR)) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/agentic-setup.ts"],
4
- "sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, symlinkSync, lstatSync, unlinkSync, readdirSync } from 'node:fs'\nimport { join, dirname, basename } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), __dirname is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst AGENTIC_DIR = join(__dirname, '..', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // AGENTS.md\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n\n // .ai/ structure\n writeTemplate(srcDir, 'ai/specs/README.md', join(targetDir, '.ai', 'specs', 'README.md'), config)\n copyFile(srcDir, 'ai/specs/SPEC-000-template.md', join(targetDir, '.ai', 'specs', 'SPEC-000-template.md'))\n copyFile(srcDir, 'ai/lessons.md', join(targetDir, '.ai', 'lessons.md'))\n\n // .ai/skills/\n writeTemplate(\n srcDir,\n 'ai/skills/spec-writing/SKILL.md',\n join(targetDir, '.ai', 'skills', 'spec-writing', 'SKILL.md'),\n config,\n )\n copyFile(\n srcDir,\n 'ai/skills/spec-writing/references/spec-template.md',\n join(targetDir, '.ai', 'skills', 'spec-writing', 'references', 'spec-template.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/spec-writing/references/spec-checklist.md',\n join(targetDir, '.ai', 'skills', 'spec-writing', 'references', 'spec-checklist.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/backend-ui-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'backend-ui-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/backend-ui-design/references/ui-components.md',\n join(targetDir, '.ai', 'skills', 'backend-ui-design', 'references', 'ui-components.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/code-review/SKILL.md',\n join(targetDir, '.ai', 'skills', 'code-review', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/code-review/references/review-checklist.md',\n join(targetDir, '.ai', 'skills', 'code-review', 'references', 'review-checklist.md'),\n )\n copyFile(srcDir, 'ai/skills/integration-builder/SKILL.md', join(targetDir, '.ai', 'skills', 'integration-builder', 'SKILL.md'))\n copyFile(\n srcDir,\n 'ai/skills/integration-builder/references/adapter-contracts.md',\n join(targetDir, '.ai', 'skills', 'integration-builder', 'references', 'adapter-contracts.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/system-extension/SKILL.md',\n join(targetDir, '.ai', 'skills', 'system-extension', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/system-extension/references/extension-contracts.md',\n join(targetDir, '.ai', 'skills', 'system-extension', 'references', 'extension-contracts.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/module-scaffold/SKILL.md',\n join(targetDir, '.ai', 'skills', 'module-scaffold', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/module-scaffold/references/naming-conventions.md',\n join(targetDir, '.ai', 'skills', 'module-scaffold', 'references', 'naming-conventions.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/module-scaffold/references/navigation-patterns.md',\n join(targetDir, '.ai', 'skills', 'module-scaffold', 'references', 'navigation-patterns.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/troubleshooter/SKILL.md',\n join(targetDir, '.ai', 'skills', 'troubleshooter', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/troubleshooter/references/diagnostic-commands.md',\n join(targetDir, '.ai', 'skills', 'troubleshooter', 'references', 'diagnostic-commands.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/eject-and-customize/SKILL.md',\n join(targetDir, '.ai', 'skills', 'eject-and-customize', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/data-model-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'data-model-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/data-model-design/references/mikro-orm-cheatsheet.md',\n join(targetDir, '.ai', 'skills', 'data-model-design', 'references', 'mikro-orm-cheatsheet.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/implement-spec/SKILL.md',\n join(targetDir, '.ai', 'skills', 'implement-spec', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/integration-tests/SKILL.md',\n join(targetDir, '.ai', 'skills', 'integration-tests', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/auto-upgrade-0.4.10-to-0.5.0/SKILL.md',\n join(targetDir, '.ai', 'skills', 'auto-upgrade-0.4.10-to-0.5.0', 'SKILL.md'),\n )\n\n for (const autoSkill of [\n 'auto-create-pr',\n 'auto-continue-pr',\n 'auto-create-pr-loop',\n 'auto-continue-pr-loop',\n 'auto-review-pr',\n 'auto-fix-github',\n ]) {\n copyFile(\n srcDir,\n `ai/skills/${autoSkill}/SKILL.md`,\n join(targetDir, '.ai', 'skills', autoSkill, 'SKILL.md'),\n )\n if (existsSync(join(srcDir, 'ai', 'skills', autoSkill, 'STANDALONE.md'))) {\n copyFile(\n srcDir,\n `ai/skills/${autoSkill}/STANDALONE.md`,\n join(targetDir, '.ai', 'skills', autoSkill, 'STANDALONE.md'),\n )\n }\n }\n\n copyFile(\n srcDir,\n 'ai/skills/trim-unused-modules/SKILL.md',\n join(targetDir, '.ai', 'skills', 'trim-unused-modules', 'SKILL.md'),\n )\n\n copyFile(srcDir, 'ai/qa/tests/playwright.config.ts', join(targetDir, '.ai', 'qa', 'tests', 'playwright.config.ts'))\n\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n }\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // Symlink .claude/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.claude', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // Symlink .codex/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.codex', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // Symlink .cursor/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.cursor', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction ensureSkillsLink(linkPath: string, target: string): void {\n ensureDir(linkPath)\n if (existsSync(linkPath) && !lstatSync(linkPath).isSymbolicLink()) {\n return\n }\n if (lstatSync(linkPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n unlinkSync(linkPath)\n }\n symlinkSync(target, linkPath)\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Agentic setup for the CLI `agentic:init` command.\n *\n * Source files live in packages/create-app/agentic/ and are copied\n * to packages/cli/dist/agentic/ during build (see build.mjs).\n * This module reads those files at runtime \u2014 no embedded string constants.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, symlinkSync, lstatSync, unlinkSync, readdirSync } from 'node:fs'\nimport { join, dirname, basename } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// In the built output (dist/lib/agentic-setup.js), __dirname is dist/lib/.\n// agentic/ is copied to dist/agentic/ by build.mjs.\nconst AGENTIC_DIR = join(__dirname, '..', 'agentic')\nconst GUIDES_DIR = join(AGENTIC_DIR, 'guides')\n\ntype AskFn = (question: string) => Promise<string>\n\ninterface AgenticSetupOptions {\n tool?: string\n force?: boolean\n}\n\ninterface AgenticConfig {\n projectName: string\n targetDir: string\n}\n\n// \u2500\u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction resolvePlaceholders(content: string, config: AgenticConfig): string {\n return content.replace(/\\{\\{PROJECT_NAME\\}\\}/g, config.projectName)\n}\n\nfunction ensureDir(filePath: string): void {\n const dir = dirname(filePath)\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true })\n}\n\nfunction writeTemplate(srcDir: string, srcRelative: string, destPath: string, config: AgenticConfig): void {\n const srcPath = join(srcDir, srcRelative)\n const content = readFileSync(srcPath, 'utf-8')\n ensureDir(destPath)\n writeFileSync(destPath, resolvePlaceholders(content, config))\n}\n\nfunction copyFile(srcDir: string, srcRelative: string, destPath: string): void {\n const srcPath = join(srcDir, srcRelative)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n}\n\n// \u2500\u2500\u2500 Generators \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction generateShared(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'shared')\n\n // AGENTS.md\n writeTemplate(srcDir, 'AGENTS.md.template', join(targetDir, 'AGENTS.md'), config)\n\n // .ai/ structure\n writeTemplate(srcDir, 'ai/specs/README.md', join(targetDir, '.ai', 'specs', 'README.md'), config)\n copyFile(srcDir, 'ai/specs/SPEC-000-template.md', join(targetDir, '.ai', 'specs', 'SPEC-000-template.md'))\n copyFile(srcDir, 'ai/lessons.md', join(targetDir, '.ai', 'lessons.md'))\n\n // .ai/skills/\n writeTemplate(\n srcDir,\n 'ai/skills/om-spec-writing/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-spec-writing', 'SKILL.md'),\n config,\n )\n copyFile(\n srcDir,\n 'ai/skills/om-spec-writing/references/spec-template.md',\n join(targetDir, '.ai', 'skills', 'om-spec-writing', 'references', 'spec-template.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-spec-writing/references/spec-checklist.md',\n join(targetDir, '.ai', 'skills', 'om-spec-writing', 'references', 'spec-checklist.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-backend-ui-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-backend-ui-design/references/ui-components.md',\n join(targetDir, '.ai', 'skills', 'om-backend-ui-design', 'references', 'ui-components.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-code-review/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-code-review', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-code-review/references/review-checklist.md',\n join(targetDir, '.ai', 'skills', 'om-code-review', 'references', 'review-checklist.md'),\n )\n copyFile(srcDir, 'ai/skills/om-integration-builder/SKILL.md', join(targetDir, '.ai', 'skills', 'om-integration-builder', 'SKILL.md'))\n copyFile(\n srcDir,\n 'ai/skills/om-integration-builder/references/adapter-contracts.md',\n join(targetDir, '.ai', 'skills', 'om-integration-builder', 'references', 'adapter-contracts.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-system-extension/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-system-extension', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-system-extension/references/extension-contracts.md',\n join(targetDir, '.ai', 'skills', 'om-system-extension', 'references', 'extension-contracts.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/references/naming-conventions.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'naming-conventions.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-module-scaffold/references/navigation-patterns.md',\n join(targetDir, '.ai', 'skills', 'om-module-scaffold', 'references', 'navigation-patterns.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-troubleshooter/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-troubleshooter/references/diagnostic-commands.md',\n join(targetDir, '.ai', 'skills', 'om-troubleshooter', 'references', 'diagnostic-commands.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-eject-and-customize/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-eject-and-customize', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-data-model-design/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-data-model-design', 'SKILL.md'),\n )\n copyFile(\n srcDir,\n 'ai/skills/om-data-model-design/references/mikro-orm-cheatsheet.md',\n join(targetDir, '.ai', 'skills', 'om-data-model-design', 'references', 'mikro-orm-cheatsheet.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-implement-spec/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-implement-spec', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-integration-tests/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-integration-tests', 'SKILL.md'),\n )\n\n copyFile(\n srcDir,\n 'ai/skills/om-auto-upgrade-0.4.10-to-0.5.0/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-auto-upgrade-0.4.10-to-0.5.0', 'SKILL.md'),\n )\n\n for (const autoSkill of [\n 'om-auto-create-pr',\n 'om-auto-continue-pr',\n 'om-auto-create-pr-loop',\n 'om-auto-continue-pr-loop',\n 'om-auto-review-pr',\n 'om-auto-fix-github',\n 'om-prepare-issue',\n ]) {\n copyFile(\n srcDir,\n `ai/skills/${autoSkill}/SKILL.md`,\n join(targetDir, '.ai', 'skills', autoSkill, 'SKILL.md'),\n )\n if (existsSync(join(srcDir, 'ai', 'skills', autoSkill, 'STANDALONE.md'))) {\n copyFile(\n srcDir,\n `ai/skills/${autoSkill}/STANDALONE.md`,\n join(targetDir, '.ai', 'skills', autoSkill, 'STANDALONE.md'),\n )\n }\n }\n\n copyFile(\n srcDir,\n 'ai/skills/om-trim-unused-modules/SKILL.md',\n join(targetDir, '.ai', 'skills', 'om-trim-unused-modules', 'SKILL.md'),\n )\n\n copyFile(srcDir, 'ai/qa/tests/playwright.config.ts', join(targetDir, '.ai', 'qa', 'tests', 'playwright.config.ts'))\n\n if (existsSync(GUIDES_DIR)) {\n const guidesDestDir = join(targetDir, '.ai', 'guides')\n for (const file of readdirSync(GUIDES_DIR)) {\n if (!file.endsWith('.md')) continue\n const srcPath = join(GUIDES_DIR, file)\n const destPath = join(guidesDestDir, file)\n ensureDir(destPath)\n copyFileSync(srcPath, destPath)\n }\n }\n}\n\nfunction generateClaudeCode(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'claude-code')\n\n writeTemplate(srcDir, 'CLAUDE.md.template', join(targetDir, 'CLAUDE.md'), config)\n copyFile(srcDir, 'settings.json', join(targetDir, '.claude', 'settings.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.ts', join(targetDir, '.claude', 'hooks', 'entity-migration-check.ts'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.mcp.json.example'))\n\n // Symlink .claude/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.claude', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction generateCodex(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'codex')\n\n const agentsPath = join(targetDir, 'AGENTS.md')\n if (existsSync(agentsPath)) {\n const enforcement = readFileSync(join(srcDir, 'enforcement-rules.md'), 'utf-8')\n let agents = readFileSync(agentsPath, 'utf-8')\n const MARKER_START = '<!-- CODEX_ENFORCEMENT_RULES_START -->'\n const MARKER_END = '<!-- CODEX_ENFORCEMENT_RULES_END -->'\n\n if (agents.includes(MARKER_START)) {\n const startIdx = agents.indexOf(MARKER_START)\n const endIdx = agents.indexOf(MARKER_END)\n if (endIdx !== -1) {\n agents = agents.slice(0, startIdx) + enforcement + agents.slice(endIdx + MARKER_END.length)\n }\n } else {\n const firstNewline = agents.indexOf('\\n')\n if (firstNewline !== -1) {\n agents = agents.slice(0, firstNewline + 1) + '\\n' + enforcement + '\\n' + agents.slice(firstNewline + 1)\n } else {\n agents = agents + '\\n\\n' + enforcement\n }\n }\n writeFileSync(agentsPath, agents)\n }\n\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.codex', 'mcp.json.example'))\n\n // Symlink .codex/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.codex', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction generateCursor(config: AgenticConfig): void {\n const { targetDir } = config\n const srcDir = join(AGENTIC_DIR, 'cursor')\n\n writeTemplate(srcDir, 'rules/open-mercato.mdc', join(targetDir, '.cursor', 'rules', 'open-mercato.mdc'), config)\n copyFile(srcDir, 'rules/entity-guard.mdc', join(targetDir, '.cursor', 'rules', 'entity-guard.mdc'))\n copyFile(srcDir, 'rules/generated-guard.mdc', join(targetDir, '.cursor', 'rules', 'generated-guard.mdc'))\n copyFile(srcDir, 'hooks.json', join(targetDir, '.cursor', 'hooks.json'))\n copyFile(srcDir, 'hooks/entity-migration-check.mjs', join(targetDir, '.cursor', 'hooks', 'entity-migration-check.mjs'))\n copyFile(srcDir, 'mcp.json.example', join(targetDir, '.cursor', 'mcp.json.example'))\n\n // Symlink .cursor/skills \u2192 ../.ai/skills\n ensureSkillsLink(join(targetDir, '.cursor', 'skills'), join('..', '.ai', 'skills'))\n}\n\nfunction ensureSkillsLink(linkPath: string, target: string): void {\n ensureDir(linkPath)\n if (existsSync(linkPath) && !lstatSync(linkPath).isSymbolicLink()) {\n return\n }\n if (lstatSync(linkPath, { throwIfNoEntry: false })?.isSymbolicLink()) {\n unlinkSync(linkPath)\n }\n symlinkSync(target, linkPath)\n}\n\n// \u2500\u2500\u2500 Wizard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst TOOLS = [\n { key: '1', label: 'Claude Code (Anthropic)', id: 'claude-code' },\n { key: '2', label: 'Codex (OpenAI)', id: 'codex' },\n { key: '3', label: 'Cursor (Anysphere)', id: 'cursor' },\n { key: '4', label: 'Multiple tools (select individually)', id: 'multiple' },\n { key: '5', label: 'Skip \u2014 set up manually later', id: 'skip' },\n] as const\n\nconst SELECTABLE = TOOLS.filter((t) => t.id !== 'multiple' && t.id !== 'skip')\n\nasync function promptSelection(ask: AskFn): Promise<string[]> {\n console.log('')\n console.log('\uD83E\uDD16 Agentic workflow setup')\n console.log('')\n console.log(' Which AI coding tool will you use with this project?')\n console.log('')\n for (const tool of TOOLS) {\n console.log(` ${tool.key}. ${tool.label}`)\n }\n console.log('')\n\n const answer = (await ask(' Enter number(s) separated by comma [1]: ')).trim() || '1'\n\n if (answer === '5') return ['skip']\n\n if (answer === '4') {\n const selected: string[] = []\n for (const tool of SELECTABLE) {\n const yn = await ask(` Include ${tool.label}? [y/N]: `)\n if (yn.toLowerCase() === 'y' || yn.toLowerCase() === 'yes') {\n selected.push(tool.id)\n }\n }\n return selected.length > 0 ? selected : ['skip']\n }\n\n const keys = answer.split(',').map((s) => s.trim())\n const ids: string[] = []\n for (const key of keys) {\n const tool = TOOLS.find((t) => t.key === key)\n if (tool && tool.id !== 'multiple' && tool.id !== 'skip') {\n ids.push(tool.id)\n }\n }\n return ids.length > 0 ? ids : ['skip']\n}\n\nexport async function runAgenticSetup(\n targetDir: string,\n ask: AskFn,\n options?: AgenticSetupOptions,\n): Promise<void> {\n let selectedIds: string[]\n\n if (options?.tool) {\n selectedIds = options.tool.split(',').map((t) => t.trim())\n } else {\n selectedIds = await promptSelection(ask)\n }\n\n if (selectedIds.includes('skip')) {\n console.log('')\n console.log(' Skipped agentic setup.')\n console.log('')\n return\n }\n\n const config: AgenticConfig = {\n projectName: basename(targetDir),\n targetDir,\n }\n\n generateShared(config)\n if (selectedIds.includes('claude-code')) generateClaudeCode(config)\n if (selectedIds.includes('codex')) generateCodex(config)\n if (selectedIds.includes('cursor')) generateCursor(config)\n\n console.log('')\n console.log(' Agentic setup complete:')\n if (selectedIds.includes('claude-code')) {\n console.log(' \u2713 Claude Code \u2014 CLAUDE.md, .claude/hooks/, .mcp.json.example')\n }\n if (selectedIds.includes('codex')) {\n console.log(' \u2713 Codex \u2014 AGENTS.md enforcement rules, .codex/mcp.json.example')\n }\n if (selectedIds.includes('cursor')) {\n console.log(' \u2713 Cursor \u2014 .cursor/rules/, .cursor/hooks/, .cursor/mcp.json.example')\n }\n console.log('')\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,7 @@
1
+ const integrationMeta = {
2
+ requiredEnvVars: ["RAILWAY_INTEGRATION_TOKEN", "RAILWAY_INTEGRATION_APP_ROOT"]
3
+ };
4
+ export {
5
+ integrationMeta
6
+ };
7
+ //# sourceMappingURL=TC-CLI-RAILWAY-001.meta.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.meta.ts"],
4
+ "sourcesContent": ["export const integrationMeta = {\n requiredEnvVars: ['RAILWAY_INTEGRATION_TOKEN', 'RAILWAY_INTEGRATION_APP_ROOT'],\n}\n"],
5
+ "mappings": "AAAO,MAAM,kBAAkB;AAAA,EAC7B,iBAAiB,CAAC,6BAA6B,8BAA8B;AAC/E;",
6
+ "names": []
7
+ }
@@ -0,0 +1,63 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { resolve } from "node:path";
4
+ import { expect, test } from "@playwright/test";
5
+ const token = process.env.RAILWAY_INTEGRATION_TOKEN;
6
+ const appRoot = process.env.RAILWAY_INTEGRATION_APP_ROOT;
7
+ const cliBin = resolve(process.cwd(), "packages/cli/dist/bin.js");
8
+ function runCli(args) {
9
+ if (!appRoot || !token) throw new Error("Railway integration environment is incomplete.");
10
+ return execFileSync(process.execPath, [cliBin, ...args], {
11
+ cwd: appRoot,
12
+ encoding: "utf8",
13
+ env: {
14
+ ...process.env,
15
+ RAILWAY_API_TOKEN: token,
16
+ CI: "true"
17
+ },
18
+ timeout: 15 * 60 * 1e3
19
+ });
20
+ }
21
+ test.describe("mercato deploy railway live integration", () => {
22
+ test.skip(!token || !appRoot, "RAILWAY_INTEGRATION_TOKEN and RAILWAY_INTEGRATION_APP_ROOT are required");
23
+ test("deploys, verifies health, resumes, and cleans up", async ({ request }) => {
24
+ expect(existsSync(cliBin)).toBe(true);
25
+ const projectName = `mercato-integration-${Date.now()}`;
26
+ try {
27
+ const output = runCli([
28
+ "deploy",
29
+ "railway",
30
+ "--project",
31
+ projectName,
32
+ "--source",
33
+ "local",
34
+ "--no-worker",
35
+ "--non-interactive"
36
+ ]);
37
+ const outputLines = output.trim().split(/\r?\n/);
38
+ const deployUrl = outputLines.find((line) => line.startsWith("DEPLOY_URL="))?.slice("DEPLOY_URL=".length);
39
+ expect(deployUrl).toBeTruthy();
40
+ expect(outputLines.at(-1)).toBe(`DEPLOY_URL=${deployUrl}`);
41
+ const health = await request.get(`${deployUrl}/api/healthz`);
42
+ expect(health.status()).toBe(200);
43
+ expect(await health.json()).toEqual({
44
+ status: "ok",
45
+ ts: expect.any(String)
46
+ });
47
+ const resumeOutput = runCli([
48
+ "deploy",
49
+ "railway",
50
+ "--source",
51
+ "local",
52
+ "--no-worker",
53
+ "--non-interactive"
54
+ ]);
55
+ expect(resumeOutput).toContain(`Project: https://railway.com/project/`);
56
+ } finally {
57
+ if (appRoot && existsSync(resolve(appRoot, ".mercato", "railway.json"))) {
58
+ runCli(["deploy", "railway", "--cleanup", "--non-interactive", "--yes"]);
59
+ }
60
+ }
61
+ });
62
+ });
63
+ //# sourceMappingURL=TC-CLI-RAILWAY-001.spec.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/lib/deploy/railway/__integration__/TC-CLI-RAILWAY-001.spec.ts"],
4
+ "sourcesContent": ["import { execFileSync } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { expect, test } from '@playwright/test'\n\nconst token = process.env.RAILWAY_INTEGRATION_TOKEN\nconst appRoot = process.env.RAILWAY_INTEGRATION_APP_ROOT\nconst cliBin = resolve(process.cwd(), 'packages/cli/dist/bin.js')\n\nfunction runCli(args: string[]): string {\n if (!appRoot || !token) throw new Error('Railway integration environment is incomplete.')\n return execFileSync(process.execPath, [cliBin, ...args], {\n cwd: appRoot,\n encoding: 'utf8',\n env: {\n ...process.env,\n RAILWAY_API_TOKEN: token,\n CI: 'true',\n },\n timeout: 15 * 60 * 1000,\n })\n}\n\ntest.describe('mercato deploy railway live integration', () => {\n test.skip(!token || !appRoot, 'RAILWAY_INTEGRATION_TOKEN and RAILWAY_INTEGRATION_APP_ROOT are required')\n\n test('deploys, verifies health, resumes, and cleans up', async ({ request }) => {\n expect(existsSync(cliBin)).toBe(true)\n const projectName = `mercato-integration-${Date.now()}`\n\n try {\n const output = runCli([\n 'deploy',\n 'railway',\n '--project',\n projectName,\n '--source',\n 'local',\n '--no-worker',\n '--non-interactive',\n ])\n const outputLines = output.trim().split(/\\r?\\n/)\n const deployUrl = outputLines\n .find((line) => line.startsWith('DEPLOY_URL='))\n ?.slice('DEPLOY_URL='.length)\n expect(deployUrl).toBeTruthy()\n expect(outputLines.at(-1)).toBe(`DEPLOY_URL=${deployUrl}`)\n\n const health = await request.get(`${deployUrl}/api/healthz`)\n expect(health.status()).toBe(200)\n expect(await health.json()).toEqual({\n status: 'ok',\n ts: expect.any(String),\n })\n\n const resumeOutput = runCli([\n 'deploy',\n 'railway',\n '--source',\n 'local',\n '--no-worker',\n '--non-interactive',\n ])\n expect(resumeOutput).toContain(`Project: https://railway.com/project/`)\n } finally {\n if (appRoot && existsSync(resolve(appRoot, '.mercato', 'railway.json'))) {\n runCli(['deploy', 'railway', '--cleanup', '--non-interactive', '--yes'])\n }\n }\n })\n})\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AACxB,SAAS,QAAQ,YAAY;AAE7B,MAAM,QAAQ,QAAQ,IAAI;AAC1B,MAAM,UAAU,QAAQ,IAAI;AAC5B,MAAM,SAAS,QAAQ,QAAQ,IAAI,GAAG,0BAA0B;AAEhE,SAAS,OAAO,MAAwB;AACtC,MAAI,CAAC,WAAW,CAAC,MAAO,OAAM,IAAI,MAAM,gDAAgD;AACxF,SAAO,aAAa,QAAQ,UAAU,CAAC,QAAQ,GAAG,IAAI,GAAG;AAAA,IACvD,KAAK;AAAA,IACL,UAAU;AAAA,IACV,KAAK;AAAA,MACH,GAAG,QAAQ;AAAA,MACX,mBAAmB;AAAA,MACnB,IAAI;AAAA,IACN;AAAA,IACA,SAAS,KAAK,KAAK;AAAA,EACrB,CAAC;AACH;AAEA,KAAK,SAAS,2CAA2C,MAAM;AAC7D,OAAK,KAAK,CAAC,SAAS,CAAC,SAAS,yEAAyE;AAEvG,OAAK,oDAAoD,OAAO,EAAE,QAAQ,MAAM;AAC9E,WAAO,WAAW,MAAM,CAAC,EAAE,KAAK,IAAI;AACpC,UAAM,cAAc,uBAAuB,KAAK,IAAI,CAAC;AAErD,QAAI;AACF,YAAM,SAAS,OAAO;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,cAAc,OAAO,KAAK,EAAE,MAAM,OAAO;AAC/C,YAAM,YAAY,YACf,KAAK,CAAC,SAAS,KAAK,WAAW,aAAa,CAAC,GAC5C,MAAM,cAAc,MAAM;AAC9B,aAAO,SAAS,EAAE,WAAW;AAC7B,aAAO,YAAY,GAAG,EAAE,CAAC,EAAE,KAAK,cAAc,SAAS,EAAE;AAEzD,YAAM,SAAS,MAAM,QAAQ,IAAI,GAAG,SAAS,cAAc;AAC3D,aAAO,OAAO,OAAO,CAAC,EAAE,KAAK,GAAG;AAChC,aAAO,MAAM,OAAO,KAAK,CAAC,EAAE,QAAQ;AAAA,QAClC,QAAQ;AAAA,QACR,IAAI,OAAO,IAAI,MAAM;AAAA,MACvB,CAAC;AAED,YAAM,eAAe,OAAO;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,YAAY,EAAE,UAAU,2CAA2C;AAAA,IAC5E,UAAE;AACA,UAAI,WAAW,WAAW,QAAQ,SAAS,YAAY,cAAc,CAAC,GAAG;AACvE,eAAO,CAAC,UAAU,WAAW,aAAa,qBAAqB,OAAO,CAAC;AAAA,MACzE;AAAA,IACF;AAAA,EACF,CAAC;AACH,CAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,98 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { spawnSync } from "node:child_process";
3
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { dirname, resolve } from "node:path";
5
+ import { assertSafeVariables, formatVariableValue } from "./redaction.js";
6
+ function resolveEnvFile(cwd, requested) {
7
+ const candidates = requested ? [requested] : [".env.production", ".env"];
8
+ for (const candidate of candidates) {
9
+ const path = resolve(cwd, candidate);
10
+ if (existsSync(path)) return path;
11
+ }
12
+ throw new Error(`Environment file not found. Checked: ${candidates.join(", ")}.`);
13
+ }
14
+ function parseEnvFile(contents) {
15
+ const result = {};
16
+ for (const rawLine of contents.split(/\r?\n/)) {
17
+ const line = rawLine.trim();
18
+ if (!line || line.startsWith("#")) continue;
19
+ const normalized = line.startsWith("export ") ? line.slice(7).trim() : line;
20
+ const separator = normalized.indexOf("=");
21
+ if (separator <= 0) continue;
22
+ const key = normalized.slice(0, separator).trim();
23
+ let value = normalized.slice(separator + 1).trim();
24
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
25
+ value = value.slice(1, -1);
26
+ }
27
+ result[key] = value.replace(/\\n/g, "\n");
28
+ }
29
+ return result;
30
+ }
31
+ function generateProtectedSecrets(existing) {
32
+ return {
33
+ AUTH_SECRET: existing.AUTH_SECRET || randomBytes(64).toString("hex"),
34
+ JWT_SECRET: existing.JWT_SECRET || randomBytes(64).toString("hex"),
35
+ TENANT_DATA_ENCRYPTION_FALLBACK_KEY: existing.TENANT_DATA_ENCRYPTION_FALLBACK_KEY || randomBytes(32).toString("base64url")
36
+ };
37
+ }
38
+ function computeRailwayVariables(input) {
39
+ const variables = {
40
+ ...input.env,
41
+ ...input.protectedSecrets,
42
+ DATABASE_URL: "${{Postgres.DATABASE_URL}}",
43
+ REDIS_URL: "${{Redis.REDIS_URL}}",
44
+ CACHE_STRATEGY: "redis",
45
+ NODE_ENV: "production",
46
+ NEXT_TELEMETRY_DISABLED: "1",
47
+ PORT: "3000",
48
+ OM_AI_PROVIDER: input.env.OM_AI_PROVIDER || "openai",
49
+ OM_AI_MODEL: input.env.OM_AI_MODEL || "gpt-5-mini",
50
+ QUEUE_STRATEGY: "async",
51
+ NEXT_PUBLIC_QUEUE_STRATEGY: "async",
52
+ AUTO_SPAWN_WORKERS: input.role === "app" && !input.workerEnabled ? "true" : "false",
53
+ OM_AUTO_SPAWN_WORKERS: input.role === "app" && !input.workerEnabled ? "true" : "false"
54
+ };
55
+ if (input.appUrl) {
56
+ variables.APP_URL = input.appUrl;
57
+ variables.NEXT_PUBLIC_APP_URL = input.appUrl;
58
+ }
59
+ delete variables.RAILWAY_API_TOKEN;
60
+ delete variables.RAILWAY_TOKEN;
61
+ assertSafeVariables(variables, {
62
+ railwayToken: input.railwayToken,
63
+ allowedKeys: input.allowedSecretKeys
64
+ });
65
+ return variables;
66
+ }
67
+ function formatVariablePlan(variables, railwayToken) {
68
+ return Object.keys(variables).sort().map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? "", railwayToken)}`);
69
+ }
70
+ function writeGeneratedSecrets(envFile, secrets) {
71
+ const ignoreCheck = spawnSync("git", ["check-ignore", "--quiet", envFile], {
72
+ cwd: dirname(envFile),
73
+ stdio: "ignore"
74
+ });
75
+ if (ignoreCheck.status !== 0) {
76
+ throw new Error(`Refusing --write-env because ${envFile} is not ignored by Git.`);
77
+ }
78
+ const existing = readFileSync(envFile, "utf8");
79
+ const missing = Object.entries(secrets).filter(([key]) => !new RegExp(`^${key}=`, "m").test(existing));
80
+ if (missing.length === 0) return;
81
+ const suffix = missing.map(([key, value]) => `${key}=${value}`).join("\n");
82
+ writeFileSync(envFile, `${existing.trimEnd()}
83
+
84
+ # DO NOT COMMIT: generated for Railway deployment
85
+ ${suffix}
86
+ `, {
87
+ mode: 384
88
+ });
89
+ }
90
+ export {
91
+ computeRailwayVariables,
92
+ formatVariablePlan,
93
+ generateProtectedSecrets,
94
+ parseEnvFile,
95
+ resolveEnvFile,
96
+ writeGeneratedSecrets
97
+ };
98
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lib/deploy/railway/env.ts"],
4
+ "sourcesContent": ["import { randomBytes } from 'node:crypto'\nimport { spawnSync } from 'node:child_process'\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { assertSafeVariables, formatVariableValue } from './redaction'\n\nexport type RailwayServiceRole = 'app' | 'worker'\n\nexport function resolveEnvFile(cwd: string, requested?: string): string {\n const candidates = requested ? [requested] : ['.env.production', '.env']\n for (const candidate of candidates) {\n const path = resolve(cwd, candidate)\n if (existsSync(path)) return path\n }\n throw new Error(`Environment file not found. Checked: ${candidates.join(', ')}.`)\n}\n\nexport function parseEnvFile(contents: string): Record<string, string> {\n const result: Record<string, string> = {}\n for (const rawLine of contents.split(/\\r?\\n/)) {\n const line = rawLine.trim()\n if (!line || line.startsWith('#')) continue\n const normalized = line.startsWith('export ') ? line.slice(7).trim() : line\n const separator = normalized.indexOf('=')\n if (separator <= 0) continue\n const key = normalized.slice(0, separator).trim()\n let value = normalized.slice(separator + 1).trim()\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1)\n }\n result[key] = value.replace(/\\\\n/g, '\\n')\n }\n return result\n}\n\nexport function generateProtectedSecrets(existing: Record<string, string>): Record<string, string> {\n return {\n AUTH_SECRET: existing.AUTH_SECRET || randomBytes(64).toString('hex'),\n JWT_SECRET: existing.JWT_SECRET || randomBytes(64).toString('hex'),\n TENANT_DATA_ENCRYPTION_FALLBACK_KEY:\n existing.TENANT_DATA_ENCRYPTION_FALLBACK_KEY || randomBytes(32).toString('base64url'),\n }\n}\n\nexport function computeRailwayVariables(input: {\n env: Record<string, string>\n role: RailwayServiceRole\n workerEnabled: boolean\n appUrl?: string\n protectedSecrets: Record<string, string>\n railwayToken?: string\n allowedSecretKeys?: string[]\n}): Record<string, string> {\n const variables: Record<string, string> = {\n ...input.env,\n ...input.protectedSecrets,\n DATABASE_URL: '${{Postgres.DATABASE_URL}}',\n REDIS_URL: '${{Redis.REDIS_URL}}',\n CACHE_STRATEGY: 'redis',\n NODE_ENV: 'production',\n NEXT_TELEMETRY_DISABLED: '1',\n PORT: '3000',\n OM_AI_PROVIDER: input.env.OM_AI_PROVIDER || 'openai',\n OM_AI_MODEL: input.env.OM_AI_MODEL || 'gpt-5-mini',\n QUEUE_STRATEGY: 'async',\n NEXT_PUBLIC_QUEUE_STRATEGY: 'async',\n AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n OM_AUTO_SPAWN_WORKERS: input.role === 'app' && !input.workerEnabled ? 'true' : 'false',\n }\n\n if (input.appUrl) {\n variables.APP_URL = input.appUrl\n variables.NEXT_PUBLIC_APP_URL = input.appUrl\n }\n\n delete variables.RAILWAY_API_TOKEN\n delete variables.RAILWAY_TOKEN\n assertSafeVariables(variables, {\n railwayToken: input.railwayToken,\n allowedKeys: input.allowedSecretKeys,\n })\n return variables\n}\n\nexport function formatVariablePlan(\n variables: Record<string, string>,\n railwayToken?: string,\n): string[] {\n return Object.keys(variables)\n .sort()\n .map((key) => `+ ADD ${key}=${formatVariableValue(key, variables[key] ?? '', railwayToken)}`)\n}\n\nexport function writeGeneratedSecrets(envFile: string, secrets: Record<string, string>): void {\n const ignoreCheck = spawnSync('git', ['check-ignore', '--quiet', envFile], {\n cwd: dirname(envFile),\n stdio: 'ignore',\n })\n if (ignoreCheck.status !== 0) {\n throw new Error(`Refusing --write-env because ${envFile} is not ignored by Git.`)\n }\n const existing = readFileSync(envFile, 'utf8')\n const missing = Object.entries(secrets).filter(([key]) => !new RegExp(`^${key}=`, 'm').test(existing))\n if (missing.length === 0) return\n const suffix = missing.map(([key, value]) => `${key}=${value}`).join('\\n')\n writeFileSync(envFile, `${existing.trimEnd()}\\n\\n# DO NOT COMMIT: generated for Railway deployment\\n${suffix}\\n`, {\n mode: 0o600,\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,99 @@
1
+ import {
2
+ collectSensitiveStructuredValues,
3
+ redactStructuredValue,
4
+ redactText
5
+ } from "./redaction.js";
6
+ class RailwayGraphqlError extends Error {
7
+ constructor(message, status, code) {
8
+ super(message);
9
+ this.status = status;
10
+ this.code = code;
11
+ this.name = "RailwayGraphqlError";
12
+ }
13
+ }
14
+ function shouldRetry(error) {
15
+ return error instanceof RailwayGraphqlError && (error.status !== void 0 && error.status >= 500 || error.code === "INTERNAL_ERROR");
16
+ }
17
+ function wait(milliseconds) {
18
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
19
+ }
20
+ function createRailwayGraphqlClient(input) {
21
+ const endpoint = input.endpoint ?? "https://backboard.railway.com/graphql/v2";
22
+ if (!endpoint.startsWith("https://")) {
23
+ throw new Error("Railway GraphQL endpoint must use HTTPS.");
24
+ }
25
+ const fetchImpl = input.fetchImpl ?? fetch;
26
+ const logger = input.logger ?? console;
27
+ async function execute(operation, variables) {
28
+ const requestSecrets = [input.token, ...collectSensitiveStructuredValues(variables)];
29
+ if (input.verbose) {
30
+ logger.log(
31
+ `[railway:gql] ${operation.name} ${JSON.stringify(redactStructuredValue(variables, requestSecrets))}`
32
+ );
33
+ }
34
+ const response = await fetchImpl(endpoint, {
35
+ method: "POST",
36
+ headers: {
37
+ Authorization: `Bearer ${input.token}`,
38
+ "Content-Type": "application/json"
39
+ },
40
+ body: JSON.stringify({
41
+ operationName: operation.name,
42
+ query: operation.query,
43
+ variables
44
+ }),
45
+ signal: AbortSignal.timeout(operation.mutation ? 3e4 : 1e4)
46
+ });
47
+ const bodyText = await response.text();
48
+ let body;
49
+ try {
50
+ body = JSON.parse(bodyText);
51
+ } catch {
52
+ throw new RailwayGraphqlError(
53
+ `Railway returned a non-JSON response (${response.status}).`,
54
+ response.status
55
+ );
56
+ }
57
+ const firstError = body.errors?.[0];
58
+ if (!response.ok || firstError) {
59
+ throw new RailwayGraphqlError(
60
+ redactText(
61
+ firstError?.message || `Railway request failed (${response.status}).`,
62
+ requestSecrets
63
+ ),
64
+ response.status,
65
+ firstError?.extensions?.code
66
+ );
67
+ }
68
+ if (body.data === void 0) {
69
+ throw new RailwayGraphqlError("Railway response did not include data.", response.status);
70
+ }
71
+ if (input.verbose) {
72
+ logger.log(
73
+ `[railway:gql] ${operation.name} response ${JSON.stringify(redactStructuredValue(body.data, requestSecrets))}`
74
+ );
75
+ }
76
+ return body.data;
77
+ }
78
+ return {
79
+ async request(operation, variables = {}) {
80
+ const attempts = operation.mutation ? 1 : 2;
81
+ let lastError;
82
+ for (let attempt = 0; attempt < attempts; attempt += 1) {
83
+ try {
84
+ return await execute(operation, variables);
85
+ } catch (error) {
86
+ lastError = error;
87
+ if (attempt + 1 >= attempts || !shouldRetry(error)) throw error;
88
+ await wait(250 * 2 ** attempt);
89
+ }
90
+ }
91
+ throw lastError;
92
+ }
93
+ };
94
+ }
95
+ export {
96
+ RailwayGraphqlError,
97
+ createRailwayGraphqlClient
98
+ };
99
+ //# sourceMappingURL=graphql-client.js.map