@lumerahq/cli 0.19.9-dev.2 → 0.19.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.
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-75I4RXB6.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-75I4RXB6.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-75I4RXB6.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-75I4RXB6.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-75I4RXB6.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-75I4RXB6.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-75I4RXB6.js").then((m) => m.diff(args.slice(1)));
|
|
241
241
|
break;
|
|
242
242
|
// Development
|
|
243
243
|
case "dev":
|
|
@@ -121,6 +121,7 @@ var collectionSchemaRule = {
|
|
|
121
121
|
};
|
|
122
122
|
|
|
123
123
|
// src/lib/hooks-parse.ts
|
|
124
|
+
import { Parser } from "acorn";
|
|
124
125
|
var VALID_HOOK_TRIGGERS = [
|
|
125
126
|
"before_create",
|
|
126
127
|
"after_create",
|
|
@@ -137,217 +138,280 @@ var KNOWN_HOOK_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
137
138
|
"enabled",
|
|
138
139
|
"metadata"
|
|
139
140
|
]);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (
|
|
154
|
-
|
|
155
|
-
if (ch === inString && prev !== "\\") inString = null;
|
|
156
|
-
prev = ch;
|
|
157
|
-
i++;
|
|
158
|
-
continue;
|
|
141
|
+
function isLiteralString(n) {
|
|
142
|
+
return !!n && n.type === "Literal" && typeof n.value === "string";
|
|
143
|
+
}
|
|
144
|
+
function getPropertyKey(prop) {
|
|
145
|
+
const key = prop.key;
|
|
146
|
+
if (!key) return void 0;
|
|
147
|
+
if (key.type === "Identifier") return key.name;
|
|
148
|
+
if (key.type === "Literal" && typeof key.value === "string") return key.value;
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
function objectExpressionToLiteral(node) {
|
|
152
|
+
const result = {};
|
|
153
|
+
for (const prop of node.properties) {
|
|
154
|
+
if (prop.type !== "Property") {
|
|
155
|
+
throw new Error("spread or shorthand properties are not supported");
|
|
159
156
|
}
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
-
out += ch;
|
|
163
|
-
prev = ch;
|
|
164
|
-
i++;
|
|
165
|
-
continue;
|
|
157
|
+
if (prop.computed) {
|
|
158
|
+
throw new Error("computed keys are not supported");
|
|
166
159
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
160
|
+
const key = getPropertyKey(prop);
|
|
161
|
+
if (key === void 0) throw new Error("non-string property key");
|
|
162
|
+
result[key] = literalNodeToValue(prop.value);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function literalNodeToValue(node) {
|
|
167
|
+
switch (node.type) {
|
|
168
|
+
case "Literal":
|
|
169
|
+
return node.value;
|
|
170
|
+
case "ObjectExpression":
|
|
171
|
+
return objectExpressionToLiteral(node);
|
|
172
|
+
case "ArrayExpression":
|
|
173
|
+
return node.elements.map(
|
|
174
|
+
(el) => el === null ? null : literalNodeToValue(el)
|
|
175
|
+
);
|
|
176
|
+
case "UnaryExpression": {
|
|
177
|
+
const arg = node.argument;
|
|
178
|
+
if (node.operator === "-" && arg.type === "Literal" && typeof arg.value === "number") {
|
|
179
|
+
return -arg.value;
|
|
180
|
+
}
|
|
181
|
+
throw new Error(`unsupported unary operator '${String(node.operator)}'`);
|
|
170
182
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
183
|
+
case "TemplateLiteral": {
|
|
184
|
+
const expressions = node.expressions;
|
|
185
|
+
const quasis = node.quasis;
|
|
186
|
+
if (expressions.length === 0 && quasis.length === 1) {
|
|
187
|
+
return quasis[0].value.cooked;
|
|
188
|
+
}
|
|
189
|
+
throw new Error("template literals with interpolation are not supported");
|
|
176
190
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
i++;
|
|
191
|
+
default:
|
|
192
|
+
throw new Error(`expected a literal value, got ${node.type}`);
|
|
180
193
|
}
|
|
181
|
-
return out;
|
|
182
194
|
}
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
function parseHookFile(content) {
|
|
196
|
+
const finding = {
|
|
197
|
+
configFound: false,
|
|
198
|
+
configKeys: [],
|
|
199
|
+
configIssues: [],
|
|
200
|
+
defaultHandlerFound: false
|
|
201
|
+
};
|
|
202
|
+
let ast;
|
|
203
|
+
try {
|
|
204
|
+
ast = Parser.parse(content, {
|
|
205
|
+
ecmaVersion: "latest",
|
|
206
|
+
sourceType: "module",
|
|
207
|
+
locations: true
|
|
208
|
+
});
|
|
209
|
+
} catch (err) {
|
|
210
|
+
const e = err;
|
|
211
|
+
finding.syntaxError = {
|
|
212
|
+
message: e.message ?? String(err),
|
|
213
|
+
line: e.loc?.line,
|
|
214
|
+
column: e.loc?.column
|
|
215
|
+
};
|
|
216
|
+
return finding;
|
|
217
|
+
}
|
|
218
|
+
let configNode;
|
|
219
|
+
let handlerNode;
|
|
220
|
+
for (const node of ast.body) {
|
|
221
|
+
if (node.type === "ExportNamedDeclaration") {
|
|
222
|
+
const decl = node.declaration;
|
|
223
|
+
if (decl && decl.type === "VariableDeclaration") {
|
|
224
|
+
for (const d of decl.declarations) {
|
|
225
|
+
if (d.id?.type === "Identifier" && d.id.name === "config" && d.init?.type === "ObjectExpression") {
|
|
226
|
+
configNode = d.init;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
231
|
+
const d = node.declaration;
|
|
232
|
+
if (d.type === "FunctionDeclaration" || d.type === "FunctionExpression" || d.type === "ArrowFunctionExpression") {
|
|
233
|
+
handlerNode = d;
|
|
234
|
+
}
|
|
195
235
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
236
|
+
}
|
|
237
|
+
if (configNode) {
|
|
238
|
+
finding.configFound = true;
|
|
239
|
+
const valueNodes = {};
|
|
240
|
+
for (const prop of configNode.properties) {
|
|
241
|
+
if (prop.type !== "Property") continue;
|
|
242
|
+
const key = getPropertyKey(prop);
|
|
243
|
+
if (key === void 0) continue;
|
|
244
|
+
finding.configKeys.push(key);
|
|
245
|
+
valueNodes[key] = prop.value;
|
|
200
246
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
247
|
+
for (const k of finding.configKeys) {
|
|
248
|
+
if (!KNOWN_HOOK_CONFIG_KEYS.has(k)) {
|
|
249
|
+
finding.configIssues.push({ kind: "unknown-key", key: k });
|
|
250
|
+
}
|
|
205
251
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
252
|
+
const readString = (field) => {
|
|
253
|
+
const n = valueNodes[field];
|
|
254
|
+
if (!n) return void 0;
|
|
255
|
+
if (isLiteralString(n)) return n.value;
|
|
256
|
+
finding.configIssues.push({ kind: "non-literal-field", field });
|
|
257
|
+
return void 0;
|
|
258
|
+
};
|
|
259
|
+
const external_id = readString("external_id");
|
|
260
|
+
const collection = readString("collection");
|
|
261
|
+
const trigger = readString("trigger");
|
|
262
|
+
const name = readString("name");
|
|
263
|
+
if (!collection && !("collection" in valueNodes)) {
|
|
264
|
+
finding.configIssues.push({ kind: "missing-required-field", field: "collection" });
|
|
265
|
+
}
|
|
266
|
+
if (!trigger && !("trigger" in valueNodes)) {
|
|
267
|
+
finding.configIssues.push({ kind: "missing-required-field", field: "trigger" });
|
|
268
|
+
}
|
|
269
|
+
if (trigger && !VALID_HOOK_TRIGGERS.includes(trigger)) {
|
|
270
|
+
finding.configIssues.push({ kind: "invalid-trigger", value: trigger });
|
|
271
|
+
}
|
|
272
|
+
let enabled;
|
|
273
|
+
if ("enabled" in valueNodes) {
|
|
274
|
+
const n = valueNodes.enabled;
|
|
275
|
+
if (n.type === "Literal" && typeof n.value === "boolean") {
|
|
276
|
+
enabled = n.value;
|
|
277
|
+
} else {
|
|
278
|
+
finding.configIssues.push({
|
|
279
|
+
kind: "invalid-enabled",
|
|
280
|
+
rawSource: content.slice(n.start, n.end)
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
let metadata;
|
|
285
|
+
if ("metadata" in valueNodes) {
|
|
286
|
+
const n = valueNodes.metadata;
|
|
287
|
+
if (n.type === "ObjectExpression") {
|
|
288
|
+
try {
|
|
289
|
+
metadata = objectExpressionToLiteral(n);
|
|
290
|
+
} catch (e) {
|
|
291
|
+
finding.configIssues.push({
|
|
292
|
+
kind: "metadata-unparseable",
|
|
293
|
+
reason: e.message
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
finding.configIssues.push({
|
|
298
|
+
kind: "metadata-unparseable",
|
|
299
|
+
reason: "metadata must be an inline object literal"
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (collection && trigger) {
|
|
304
|
+
finding.hook = {
|
|
305
|
+
external_id: external_id ?? "",
|
|
306
|
+
collection,
|
|
307
|
+
trigger,
|
|
308
|
+
enabled: enabled ?? true,
|
|
309
|
+
...name !== void 0 ? { name } : {},
|
|
310
|
+
...metadata !== void 0 ? { metadata } : {}
|
|
311
|
+
};
|
|
210
312
|
}
|
|
211
|
-
if (depth === 0) stripped += ch;
|
|
212
|
-
prev = ch;
|
|
213
313
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
314
|
+
if (handlerNode) {
|
|
315
|
+
finding.defaultHandlerFound = true;
|
|
316
|
+
const body = handlerNode.body;
|
|
317
|
+
if (body) {
|
|
318
|
+
if (body.type === "BlockStatement") {
|
|
319
|
+
finding.scriptBody = content.slice(body.start + 1, body.end - 1).trim();
|
|
320
|
+
} else {
|
|
321
|
+
finding.scriptBody = `return ${content.slice(body.start, body.end)};`;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
219
324
|
}
|
|
220
|
-
return
|
|
325
|
+
return finding;
|
|
221
326
|
}
|
|
222
327
|
function parseHookConfig(content) {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
const externalId = configMatch[1].match(/external_id\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
226
|
-
const collection = configMatch[1].match(/collection\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
227
|
-
const trigger = configMatch[1].match(/trigger\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
228
|
-
const enabled = configMatch[1].match(/enabled\s*:\s*(true|false)/)?.[1];
|
|
229
|
-
const name = configMatch[1].match(/name\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
230
|
-
if (!collection || !trigger) return null;
|
|
231
|
-
const hook = {
|
|
232
|
-
external_id: externalId || "",
|
|
233
|
-
collection,
|
|
234
|
-
trigger,
|
|
235
|
-
enabled: enabled !== "false"
|
|
236
|
-
};
|
|
237
|
-
if (name) hook.name = name;
|
|
238
|
-
const metadataMatch = configMatch[1].match(/metadata\s*:\s*(\{[^}]*\})/);
|
|
239
|
-
if (metadataMatch) {
|
|
240
|
-
try {
|
|
241
|
-
const metaStr = metadataMatch[1].replace(/'/g, '"').replace(/(\w+)\s*:/g, '"$1":').replace(/,\s*}/g, "}");
|
|
242
|
-
hook.metadata = JSON.parse(metaStr);
|
|
243
|
-
} catch {
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
return hook;
|
|
328
|
+
const finding = parseHookFile(content);
|
|
329
|
+
return finding.hook ?? null;
|
|
247
330
|
}
|
|
248
331
|
function extractHookScript(content) {
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
);
|
|
252
|
-
if (handlerMatch) {
|
|
253
|
-
return handlerMatch[1].trim();
|
|
254
|
-
}
|
|
255
|
-
const simpleMatch = content.match(
|
|
256
|
-
/export\s+default\s+async\s+function[^{]*\{([\s\S]*)\}[\s\n]*$/
|
|
257
|
-
);
|
|
258
|
-
if (simpleMatch) {
|
|
259
|
-
return simpleMatch[1].trim();
|
|
260
|
-
}
|
|
261
|
-
return content.replace(/export\s+const\s+config[\s\S]*?;/, "").trim();
|
|
262
|
-
}
|
|
263
|
-
function hasDefaultHandler(content) {
|
|
264
|
-
return /export\s+default\s+(?:async\s+)?function\b/.test(content);
|
|
332
|
+
const finding = parseHookFile(content);
|
|
333
|
+
return finding.scriptBody ?? "";
|
|
265
334
|
}
|
|
266
335
|
|
|
267
336
|
// src/lib/lint/rules/hook-verify.ts
|
|
268
|
-
function error2(target, message) {
|
|
337
|
+
function error2(target, message, line) {
|
|
269
338
|
return {
|
|
270
339
|
ruleId: "hook-verify",
|
|
271
340
|
target,
|
|
272
341
|
severity: "error",
|
|
273
|
-
message
|
|
342
|
+
message,
|
|
343
|
+
...line !== void 0 ? { line } : {}
|
|
274
344
|
};
|
|
275
345
|
}
|
|
346
|
+
function messageForIssue(issue) {
|
|
347
|
+
switch (issue.kind) {
|
|
348
|
+
case "missing-required-field":
|
|
349
|
+
return `Hook config is missing required field '${issue.field}'.`;
|
|
350
|
+
case "unknown-key":
|
|
351
|
+
return `Unknown config key '${issue.key}'. Known keys: ${[...KNOWN_HOOK_CONFIG_KEYS].join(", ")}.`;
|
|
352
|
+
case "invalid-trigger":
|
|
353
|
+
return `Invalid trigger '${issue.value}'. Must be one of: ${VALID_HOOK_TRIGGERS.join(", ")}.`;
|
|
354
|
+
case "invalid-enabled":
|
|
355
|
+
return `Invalid 'enabled' value \`${issue.rawSource}\`. Must be a literal \`true\` or \`false\`.`;
|
|
356
|
+
case "metadata-unparseable":
|
|
357
|
+
return `Could not parse 'metadata': ${issue.reason}. It must be an inline object literal with literal values (strings, numbers, booleans, null, arrays, or nested literal objects).`;
|
|
358
|
+
case "non-literal-field":
|
|
359
|
+
return `Field '${issue.field}' must be a string literal.`;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
276
362
|
var hookVerifyRule = {
|
|
277
363
|
id: "hook-verify",
|
|
278
364
|
description: "Validates hook file structure (config export, trigger, known keys, default handler) and verifies the script compiles via the backend.",
|
|
279
365
|
appliesTo: ["hook"],
|
|
280
366
|
async check(target, ctx) {
|
|
281
|
-
|
|
282
|
-
if (!config) {
|
|
367
|
+
if (target.filePath.endsWith(".ts")) {
|
|
283
368
|
return [
|
|
284
369
|
error2(
|
|
285
370
|
target,
|
|
286
|
-
"
|
|
371
|
+
"TypeScript hook files are not yet supported. Rename to `.js` and remove any TypeScript-specific syntax (type annotations, `as` casts, etc.)."
|
|
287
372
|
)
|
|
288
373
|
];
|
|
289
374
|
}
|
|
290
|
-
const
|
|
291
|
-
if (
|
|
292
|
-
|
|
375
|
+
const finding = parseHookFile(target.source);
|
|
376
|
+
if (finding.syntaxError) {
|
|
377
|
+
return [
|
|
293
378
|
error2(
|
|
294
379
|
target,
|
|
295
|
-
|
|
380
|
+
`Could not parse hook file: ${finding.syntaxError.message}`,
|
|
381
|
+
finding.syntaxError.line
|
|
296
382
|
)
|
|
297
|
-
|
|
383
|
+
];
|
|
298
384
|
}
|
|
299
|
-
if (!
|
|
385
|
+
if (!finding.configFound) {
|
|
386
|
+
return [
|
|
387
|
+
error2(
|
|
388
|
+
target,
|
|
389
|
+
"Missing `export const config = {...}`. Hook files must export a config object with at least `collection` and `trigger`."
|
|
390
|
+
)
|
|
391
|
+
];
|
|
392
|
+
}
|
|
393
|
+
const errors = [];
|
|
394
|
+
if (finding.hook !== void 0 && !finding.hook.external_id && !ctx.appName) {
|
|
300
395
|
errors.push(
|
|
301
396
|
error2(
|
|
302
397
|
target,
|
|
303
|
-
"
|
|
398
|
+
"Hook config is missing `external_id` and no app name is configured to derive one from the file name."
|
|
304
399
|
)
|
|
305
400
|
);
|
|
306
401
|
}
|
|
307
|
-
if (!
|
|
402
|
+
if (!finding.defaultHandlerFound) {
|
|
308
403
|
errors.push(
|
|
309
404
|
error2(
|
|
310
405
|
target,
|
|
311
|
-
|
|
406
|
+
"Missing default exported handler. Hook files must `export default function(ctx) { ... }` (async or arrow allowed)."
|
|
312
407
|
)
|
|
313
408
|
);
|
|
314
409
|
}
|
|
315
|
-
const
|
|
316
|
-
|
|
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
|
-
}
|
|
410
|
+
for (const issue of finding.configIssues) {
|
|
411
|
+
errors.push(error2(target, messageForIssue(issue)));
|
|
348
412
|
}
|
|
349
413
|
if (errors.length > 0) return errors;
|
|
350
|
-
let script =
|
|
414
|
+
let script = finding.scriptBody ?? "";
|
|
351
415
|
if (ctx.appName) {
|
|
352
416
|
script = script.replaceAll("{{app}}", ctx.appName);
|
|
353
417
|
}
|
|
@@ -530,21 +594,34 @@ function safePrintLint(warnings, projectRoot) {
|
|
|
530
594
|
if (process.env.LUMERA_DEBUG) console.error("[lint] print failed:", err);
|
|
531
595
|
}
|
|
532
596
|
}
|
|
597
|
+
async function safeLintPass(label, build) {
|
|
598
|
+
try {
|
|
599
|
+
const issues = await build();
|
|
600
|
+
const errors = issues.filter((issue) => issue.severity === "error");
|
|
601
|
+
return { issues, errors };
|
|
602
|
+
} catch (err) {
|
|
603
|
+
if (process.env.LUMERA_DEBUG) console.error(`[lint] ${label} pass failed:`, err);
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
533
607
|
async function lintCollectionFiles(projectRoot, platformDir, filterName) {
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
608
|
+
const result = await safeLintPass(
|
|
609
|
+
"collection",
|
|
610
|
+
async () => runLint({ projectRoot, targets: buildCollectionTargets(platformDir, filterName) })
|
|
611
|
+
);
|
|
612
|
+
if (!result || result.errors.length === 0) return;
|
|
613
|
+
safePrintLint(result.issues, projectRoot);
|
|
614
|
+
throw new Error(`Found ${result.errors.length} collection lint error(s)`);
|
|
539
615
|
}
|
|
540
616
|
async function lintHookFiles(api, projectRoot, platformDir, appName, filterName) {
|
|
541
|
-
const
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
617
|
+
const result = await safeLintPass("hook", async () => {
|
|
618
|
+
const targets = buildHookTargets(platformDir, filterName);
|
|
619
|
+
if (targets.length === 0) return [];
|
|
620
|
+
return runLint({ projectRoot, targets, api, appName });
|
|
621
|
+
});
|
|
622
|
+
if (!result || result.errors.length === 0) return;
|
|
623
|
+
safePrintLint(result.issues, projectRoot);
|
|
624
|
+
throw new Error(`Found ${result.errors.length} hook lint error(s)`);
|
|
548
625
|
}
|
|
549
626
|
var PACKAGE_MANAGERS = ["bun", "pnpm", "yarn", "npm"];
|
|
550
627
|
var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager"]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumerahq/cli",
|
|
3
|
-
"version": "0.19.9
|
|
3
|
+
"version": "0.19.9",
|
|
4
4
|
"description": "CLI for building and deploying Lumera apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"templates"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"acorn": "^8.16.0",
|
|
17
18
|
"archiver": "^7.0.1",
|
|
18
19
|
"dotenv": "^16.4.7",
|
|
19
20
|
"open": "^10.1.0",
|