@lumerahq/cli 0.19.9-dev.0 → 0.19.9-dev.2
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/dist/index.js
CHANGED
|
@@ -219,25 +219,25 @@ async function main() {
|
|
|
219
219
|
switch (command) {
|
|
220
220
|
// Resource commands
|
|
221
221
|
case "plan":
|
|
222
|
-
await import("./resources-
|
|
222
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-ZFGJITDH.js").then((m) => m.diff(args.slice(1)));
|
|
241
241
|
break;
|
|
242
242
|
// Development
|
|
243
243
|
case "dev":
|
|
@@ -121,8 +121,106 @@ var collectionSchemaRule = {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
// src/lib/hooks-parse.ts
|
|
124
|
+
var VALID_HOOK_TRIGGERS = [
|
|
125
|
+
"before_create",
|
|
126
|
+
"after_create",
|
|
127
|
+
"before_update",
|
|
128
|
+
"after_update",
|
|
129
|
+
"before_delete",
|
|
130
|
+
"after_delete"
|
|
131
|
+
];
|
|
132
|
+
var KNOWN_HOOK_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
133
|
+
"external_id",
|
|
134
|
+
"collection",
|
|
135
|
+
"trigger",
|
|
136
|
+
"name",
|
|
137
|
+
"enabled",
|
|
138
|
+
"metadata"
|
|
139
|
+
]);
|
|
140
|
+
var CONFIG_BLOCK_RE = /export\s+const\s+config\s*[=:]\s*(\{[\s\S]*?\});?/;
|
|
141
|
+
function extractConfigBody(content) {
|
|
142
|
+
const m = content.match(CONFIG_BLOCK_RE);
|
|
143
|
+
return m ? m[1] : null;
|
|
144
|
+
}
|
|
145
|
+
function stripJsComments(source) {
|
|
146
|
+
let out = "";
|
|
147
|
+
let inString = null;
|
|
148
|
+
let prev = "";
|
|
149
|
+
let i = 0;
|
|
150
|
+
while (i < source.length) {
|
|
151
|
+
const ch = source[i];
|
|
152
|
+
const next = source[i + 1];
|
|
153
|
+
if (inString) {
|
|
154
|
+
out += ch;
|
|
155
|
+
if (ch === inString && prev !== "\\") inString = null;
|
|
156
|
+
prev = ch;
|
|
157
|
+
i++;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
161
|
+
inString = ch;
|
|
162
|
+
out += ch;
|
|
163
|
+
prev = ch;
|
|
164
|
+
i++;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (ch === "/" && next === "/") {
|
|
168
|
+
while (i < source.length && source[i] !== "\n") i++;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (ch === "/" && next === "*") {
|
|
172
|
+
i += 2;
|
|
173
|
+
while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) i++;
|
|
174
|
+
i += 2;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
out += ch;
|
|
178
|
+
prev = ch;
|
|
179
|
+
i++;
|
|
180
|
+
}
|
|
181
|
+
return out;
|
|
182
|
+
}
|
|
183
|
+
function extractTopLevelConfigKeys(configBody) {
|
|
184
|
+
if (!configBody.startsWith("{") || !configBody.endsWith("}")) return [];
|
|
185
|
+
const inner = stripJsComments(configBody.slice(1, -1));
|
|
186
|
+
let stripped = "";
|
|
187
|
+
let depth = 0;
|
|
188
|
+
let inString = null;
|
|
189
|
+
let prev = "";
|
|
190
|
+
for (const ch of inner) {
|
|
191
|
+
if (inString) {
|
|
192
|
+
if (ch === inString && prev !== "\\") inString = null;
|
|
193
|
+
prev = ch;
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
197
|
+
inString = ch;
|
|
198
|
+
prev = ch;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (ch === "{" || ch === "[") {
|
|
202
|
+
depth++;
|
|
203
|
+
prev = ch;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (ch === "}" || ch === "]") {
|
|
207
|
+
depth--;
|
|
208
|
+
prev = ch;
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
if (depth === 0) stripped += ch;
|
|
212
|
+
prev = ch;
|
|
213
|
+
}
|
|
214
|
+
const keys = [];
|
|
215
|
+
const keyRe = /(?:^|,)\s*(?:['"]([^'"]+)['"]|(\w+))\s*:/g;
|
|
216
|
+
let m;
|
|
217
|
+
while ((m = keyRe.exec(stripped)) !== null) {
|
|
218
|
+
keys.push(m[1] || m[2]);
|
|
219
|
+
}
|
|
220
|
+
return keys;
|
|
221
|
+
}
|
|
124
222
|
function parseHookConfig(content) {
|
|
125
|
-
const configMatch = content.match(
|
|
223
|
+
const configMatch = content.match(CONFIG_BLOCK_RE);
|
|
126
224
|
if (!configMatch) return null;
|
|
127
225
|
const externalId = configMatch[1].match(/external_id\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
128
226
|
const collection = configMatch[1].match(/collection\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
@@ -177,7 +275,7 @@ function error2(target, message) {
|
|
|
177
275
|
}
|
|
178
276
|
var hookVerifyRule = {
|
|
179
277
|
id: "hook-verify",
|
|
180
|
-
description: "Validates hook file structure (config export
|
|
278
|
+
description: "Validates hook file structure (config export, trigger, known keys, default handler) and verifies the script compiles via the backend.",
|
|
181
279
|
appliesTo: ["hook"],
|
|
182
280
|
async check(target, ctx) {
|
|
183
281
|
const config = parseHookConfig(target.source);
|
|
@@ -189,22 +287,66 @@ var hookVerifyRule = {
|
|
|
189
287
|
)
|
|
190
288
|
];
|
|
191
289
|
}
|
|
290
|
+
const errors = [];
|
|
192
291
|
if (!config.external_id && !ctx.appName) {
|
|
193
|
-
|
|
292
|
+
errors.push(
|
|
194
293
|
error2(
|
|
195
294
|
target,
|
|
196
295
|
"Hook config is missing `external_id` and no app name is configured to derive one from the file name."
|
|
197
296
|
)
|
|
198
|
-
|
|
297
|
+
);
|
|
199
298
|
}
|
|
200
299
|
if (!hasDefaultHandler(target.source)) {
|
|
201
|
-
|
|
300
|
+
errors.push(
|
|
202
301
|
error2(
|
|
203
302
|
target,
|
|
204
303
|
"Missing default exported handler. Hook files must `export default function(ctx) { ... }` (async allowed)."
|
|
205
304
|
)
|
|
206
|
-
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
if (!VALID_HOOK_TRIGGERS.includes(config.trigger)) {
|
|
308
|
+
errors.push(
|
|
309
|
+
error2(
|
|
310
|
+
target,
|
|
311
|
+
`Invalid trigger '${config.trigger}'. Must be one of: ${VALID_HOOK_TRIGGERS.join(", ")}.`
|
|
312
|
+
)
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
const configBody = extractConfigBody(target.source);
|
|
316
|
+
if (configBody) {
|
|
317
|
+
const keys = extractTopLevelConfigKeys(configBody);
|
|
318
|
+
for (const key of keys) {
|
|
319
|
+
if (!KNOWN_HOOK_CONFIG_KEYS.has(key)) {
|
|
320
|
+
errors.push(
|
|
321
|
+
error2(
|
|
322
|
+
target,
|
|
323
|
+
`Unknown config key '${key}'. Known keys: ${[...KNOWN_HOOK_CONFIG_KEYS].join(", ")}.`
|
|
324
|
+
)
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (keys.includes("enabled")) {
|
|
329
|
+
const m = configBody.match(/enabled\s*:\s*([^,}\n]+)/);
|
|
330
|
+
const raw = m ? m[1].trim().replace(/,\s*$/, "").trim() : "";
|
|
331
|
+
if (raw !== "true" && raw !== "false") {
|
|
332
|
+
errors.push(
|
|
333
|
+
error2(
|
|
334
|
+
target,
|
|
335
|
+
`Invalid 'enabled' value '${raw}'. Must be a literal \`true\` or \`false\`.`
|
|
336
|
+
)
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (keys.includes("metadata") && !config.metadata) {
|
|
341
|
+
errors.push(
|
|
342
|
+
error2(
|
|
343
|
+
target,
|
|
344
|
+
"Could not parse 'metadata'. It must be an inline object literal with simple key/value pairs (e.g. `{ threshold: 100 }`); nested objects and non-literal values are not supported."
|
|
345
|
+
)
|
|
346
|
+
);
|
|
347
|
+
}
|
|
207
348
|
}
|
|
349
|
+
if (errors.length > 0) return errors;
|
|
208
350
|
let script = extractHookScript(target.source);
|
|
209
351
|
if (ctx.appName) {
|
|
210
352
|
script = script.replaceAll("{{app}}", ctx.appName);
|