@lumerahq/cli 0.19.9-dev.0 → 0.19.9-dev.1
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-5ELZGJOH.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-5ELZGJOH.js").then((m) => m.diff(args.slice(1)));
|
|
241
241
|
break;
|
|
242
242
|
// Development
|
|
243
243
|
case "dev":
|
|
@@ -121,8 +121,68 @@ 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 extractTopLevelConfigKeys(configBody) {
|
|
146
|
+
if (!configBody.startsWith("{") || !configBody.endsWith("}")) return [];
|
|
147
|
+
const inner = configBody.slice(1, -1);
|
|
148
|
+
let stripped = "";
|
|
149
|
+
let depth = 0;
|
|
150
|
+
let inString = null;
|
|
151
|
+
let prev = "";
|
|
152
|
+
for (const ch of inner) {
|
|
153
|
+
if (inString) {
|
|
154
|
+
if (ch === inString && prev !== "\\") inString = null;
|
|
155
|
+
prev = ch;
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (ch === '"' || ch === "'" || ch === "`") {
|
|
159
|
+
inString = ch;
|
|
160
|
+
prev = ch;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (ch === "{" || ch === "[") {
|
|
164
|
+
depth++;
|
|
165
|
+
prev = ch;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
if (ch === "}" || ch === "]") {
|
|
169
|
+
depth--;
|
|
170
|
+
prev = ch;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (depth === 0) stripped += ch;
|
|
174
|
+
prev = ch;
|
|
175
|
+
}
|
|
176
|
+
const keys = [];
|
|
177
|
+
const keyRe = /(?:^|,)\s*(?:['"]([^'"]+)['"]|(\w+))\s*:/g;
|
|
178
|
+
let m;
|
|
179
|
+
while ((m = keyRe.exec(stripped)) !== null) {
|
|
180
|
+
keys.push(m[1] || m[2]);
|
|
181
|
+
}
|
|
182
|
+
return keys;
|
|
183
|
+
}
|
|
124
184
|
function parseHookConfig(content) {
|
|
125
|
-
const configMatch = content.match(
|
|
185
|
+
const configMatch = content.match(CONFIG_BLOCK_RE);
|
|
126
186
|
if (!configMatch) return null;
|
|
127
187
|
const externalId = configMatch[1].match(/external_id\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
128
188
|
const collection = configMatch[1].match(/collection\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
@@ -177,7 +237,7 @@ function error2(target, message) {
|
|
|
177
237
|
}
|
|
178
238
|
var hookVerifyRule = {
|
|
179
239
|
id: "hook-verify",
|
|
180
|
-
description: "Validates hook file structure (config export
|
|
240
|
+
description: "Validates hook file structure (config export, trigger, known keys, default handler) and verifies the script compiles via the backend.",
|
|
181
241
|
appliesTo: ["hook"],
|
|
182
242
|
async check(target, ctx) {
|
|
183
243
|
const config = parseHookConfig(target.source);
|
|
@@ -189,22 +249,66 @@ var hookVerifyRule = {
|
|
|
189
249
|
)
|
|
190
250
|
];
|
|
191
251
|
}
|
|
252
|
+
const errors = [];
|
|
192
253
|
if (!config.external_id && !ctx.appName) {
|
|
193
|
-
|
|
254
|
+
errors.push(
|
|
194
255
|
error2(
|
|
195
256
|
target,
|
|
196
257
|
"Hook config is missing `external_id` and no app name is configured to derive one from the file name."
|
|
197
258
|
)
|
|
198
|
-
|
|
259
|
+
);
|
|
199
260
|
}
|
|
200
261
|
if (!hasDefaultHandler(target.source)) {
|
|
201
|
-
|
|
262
|
+
errors.push(
|
|
202
263
|
error2(
|
|
203
264
|
target,
|
|
204
265
|
"Missing default exported handler. Hook files must `export default function(ctx) { ... }` (async allowed)."
|
|
205
266
|
)
|
|
206
|
-
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (!VALID_HOOK_TRIGGERS.includes(config.trigger)) {
|
|
270
|
+
errors.push(
|
|
271
|
+
error2(
|
|
272
|
+
target,
|
|
273
|
+
`Invalid trigger '${config.trigger}'. Must be one of: ${VALID_HOOK_TRIGGERS.join(", ")}.`
|
|
274
|
+
)
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
const configBody = extractConfigBody(target.source);
|
|
278
|
+
if (configBody) {
|
|
279
|
+
const keys = extractTopLevelConfigKeys(configBody);
|
|
280
|
+
for (const key of keys) {
|
|
281
|
+
if (!KNOWN_HOOK_CONFIG_KEYS.has(key)) {
|
|
282
|
+
errors.push(
|
|
283
|
+
error2(
|
|
284
|
+
target,
|
|
285
|
+
`Unknown config key '${key}'. Known keys: ${[...KNOWN_HOOK_CONFIG_KEYS].join(", ")}.`
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (keys.includes("enabled")) {
|
|
291
|
+
const m = configBody.match(/enabled\s*:\s*([^,}\n]+)/);
|
|
292
|
+
const raw = m ? m[1].trim().replace(/,\s*$/, "").trim() : "";
|
|
293
|
+
if (raw !== "true" && raw !== "false") {
|
|
294
|
+
errors.push(
|
|
295
|
+
error2(
|
|
296
|
+
target,
|
|
297
|
+
`Invalid 'enabled' value '${raw}'. Must be a literal \`true\` or \`false\`.`
|
|
298
|
+
)
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (keys.includes("metadata") && !config.metadata) {
|
|
303
|
+
errors.push(
|
|
304
|
+
error2(
|
|
305
|
+
target,
|
|
306
|
+
"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."
|
|
307
|
+
)
|
|
308
|
+
);
|
|
309
|
+
}
|
|
207
310
|
}
|
|
311
|
+
if (errors.length > 0) return errors;
|
|
208
312
|
let script = extractHookScript(target.source);
|
|
209
313
|
if (ctx.appName) {
|
|
210
314
|
script = script.replaceAll("{{app}}", ctx.appName);
|