@usequark/quark-create-app 1.25.2 → 1.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usequark/quark-create-app",
3
- "version": "1.25.2",
3
+ "version": "1.25.3",
4
4
  "description": "CLI to scaffold new Quark projects with Next.js, Prisma, BullMQ, and Railway deployment",
5
5
  "keywords": [
6
6
  "quark",
@@ -2,6 +2,29 @@ import { execa } from "execa";
2
2
 
3
3
  const RAILWAY = "railway";
4
4
 
5
+ /**
6
+ * Every helper `railway/iac` exports that can appear in a generated body.
7
+ *
8
+ * The import list is derived from the helpers the body actually calls, rather
9
+ * than hardcoded. A helper that is called but not imported is a ReferenceError
10
+ * when the CLI evaluates the file, and that evaluation only happens later, in
11
+ * the user's `railway config apply` — so nothing in this repo ever surfaced it.
12
+ * Deriving the list makes the two impossible to drift apart.
13
+ */
14
+ const IAC_HELPERS = [
15
+ "bucket",
16
+ "database",
17
+ "defineRailway",
18
+ "group",
19
+ "image",
20
+ "postgres",
21
+ "preserve",
22
+ "project",
23
+ "redis",
24
+ "service",
25
+ "volume",
26
+ ];
27
+
5
28
  /**
6
29
  * Escapes a string for safe embedding in a TypeScript string literal.
7
30
  * Handles backslashes, quotes, newlines, and template literal interpolation.
@@ -65,9 +88,6 @@ export async function generateIacFile({
65
88
  const { default: fs } = await import("fs-extra");
66
89
  const { dirname } = await import("node:path");
67
90
 
68
- const imports = new Set();
69
- imports.add(`import { defineRailway, project, service } from "railway/iac";`);
70
-
71
91
  const resourceLines = [];
72
92
 
73
93
  for (const svc of services) {
@@ -116,17 +136,25 @@ export async function generateIacFile({
116
136
 
117
137
  const resources = services.map((s) => toIdentifier(s.name)).join(", ");
118
138
 
119
- const content = `${Array.from(imports).join("\n")}
120
-
121
- export default defineRailway(() => {
139
+ const body = `export default defineRailway(() => {
122
140
  ${resourceLines.join("\n\n")}
123
141
 
124
- \treturn project("${escapeTsString(projectName)}", {
125
- \t\tresources: [${resources}],
126
- \t});
142
+ return project("${escapeTsString(projectName)}", {
143
+ resources: [${resources}],
144
+ });
127
145
  });
128
146
  `;
129
147
 
148
+ // Derive the import list from the body so a helper can never be called
149
+ // without being in scope. See IAC_HELPERS.
150
+ const used = IAC_HELPERS.filter((helper) =>
151
+ new RegExp(`\\b${helper}\\s*\\(`).test(body),
152
+ ).sort();
153
+
154
+ const content = `import { ${used.join(", ")} } from "railway/iac";
155
+
156
+ ${body}`;
157
+
130
158
  await fs.ensureDir(dirname(iacPath));
131
159
  await fs.writeFile(iacPath, content, "utf8");
132
160
  }
@@ -1,4 +1,4 @@
1
- import { defineRailway, project, service } from "railway/iac";
1
+ import { defineRailway, preserve, project, service } from "railway/iac";
2
2
 
3
3
  export default defineRailway(() => {
4
4
  const web = service("web", {