@lumerahq/cli 0.19.8 → 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/{chunk-SMZESQV2.js → chunk-EDRAYUWN.js} +7 -0
- package/dist/{chunk-2WDZ3QKS.js → chunk-WWEIOMW6.js} +1 -1
- package/dist/{deps-53AOYHH2.js → deps-WSZGH35V.js} +2 -2
- package/dist/{dev-RENAXSGD.js → dev-3SDNIPWA.js} +2 -2
- package/dist/index.js +12 -12
- package/dist/{init-J5BNFCSP.js → init-FW4RFXLL.js} +1 -1
- package/dist/{register-ZYUFXURK.js → register-HR2QQFWX.js} +1 -1
- package/dist/{resources-EPCEYCFY.js → resources-5ELZGJOH.js} +256 -55
- package/dist/{run-XWXUBWWH.js → run-YUL73K5O.js} +1 -1
- package/package.json +1 -1
|
@@ -195,6 +195,12 @@ var ApiClient = class {
|
|
|
195
195
|
body: JSON.stringify(def)
|
|
196
196
|
});
|
|
197
197
|
}
|
|
198
|
+
async compileHook(script) {
|
|
199
|
+
await this.request("/api/pb/hooks/compile", {
|
|
200
|
+
method: "POST",
|
|
201
|
+
body: JSON.stringify({ script })
|
|
202
|
+
});
|
|
203
|
+
}
|
|
198
204
|
async updateHook(id, def) {
|
|
199
205
|
return this.request(`/api/pb/hooks/${id}`, {
|
|
200
206
|
method: "PATCH",
|
|
@@ -355,6 +361,7 @@ function createApiClient(token, baseUrl, projectExternalId) {
|
|
|
355
361
|
}
|
|
356
362
|
|
|
357
363
|
export {
|
|
364
|
+
ApiError,
|
|
358
365
|
isApiErrorStatus,
|
|
359
366
|
createApiClient
|
|
360
367
|
};
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
deps,
|
|
3
3
|
projectResourceDepsEnabled,
|
|
4
4
|
syncDeps
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-WWEIOMW6.js";
|
|
6
6
|
import "./chunk-2CR762KB.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-EDRAYUWN.js";
|
|
8
8
|
import "./chunk-ZH3NVYEQ.js";
|
|
9
9
|
import "./chunk-FJFIWC7G.js";
|
|
10
10
|
import "./chunk-PNKVD2UK.js";
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WWEIOMW6.js";
|
|
8
8
|
import {
|
|
9
9
|
loadEnv
|
|
10
10
|
} from "./chunk-2CR762KB.js";
|
|
11
11
|
import {
|
|
12
12
|
createApiClient
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EDRAYUWN.js";
|
|
14
14
|
import {
|
|
15
15
|
findProjectRoot,
|
|
16
16
|
getApiUrl,
|
package/dist/index.js
CHANGED
|
@@ -219,39 +219,39 @@ 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":
|
|
244
|
-
await import("./dev-
|
|
244
|
+
await import("./dev-3SDNIPWA.js").then((m) => m.dev(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "run":
|
|
247
|
-
await import("./run-
|
|
247
|
+
await import("./run-YUL73K5O.js").then((m) => m.run(args.slice(1)));
|
|
248
248
|
break;
|
|
249
249
|
// Project
|
|
250
250
|
case "init":
|
|
251
|
-
await import("./init-
|
|
251
|
+
await import("./init-FW4RFXLL.js").then((m) => m.init(args.slice(1)));
|
|
252
252
|
break;
|
|
253
253
|
case "register":
|
|
254
|
-
await import("./register-
|
|
254
|
+
await import("./register-HR2QQFWX.js").then((m) => m.register(args.slice(1)));
|
|
255
255
|
break;
|
|
256
256
|
case "templates":
|
|
257
257
|
await import("./templates-LNUOTNLN.js").then((m) => m.templates(subcommand, args.slice(2)));
|
|
@@ -268,7 +268,7 @@ async function main() {
|
|
|
268
268
|
break;
|
|
269
269
|
// Dependencies
|
|
270
270
|
case "deps":
|
|
271
|
-
await import("./deps-
|
|
271
|
+
await import("./deps-WSZGH35V.js").then((m) => m.deps(args.slice(1)));
|
|
272
272
|
break;
|
|
273
273
|
// Auth
|
|
274
274
|
case "login":
|
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WWEIOMW6.js";
|
|
8
8
|
import {
|
|
9
9
|
loadEnv
|
|
10
10
|
} from "./chunk-2CR762KB.js";
|
|
11
11
|
import {
|
|
12
|
+
ApiError,
|
|
12
13
|
createApiClient
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-EDRAYUWN.js";
|
|
14
15
|
import {
|
|
15
16
|
findProjectRoot,
|
|
16
17
|
getApiUrl,
|
|
@@ -119,6 +120,212 @@ var collectionSchemaRule = {
|
|
|
119
120
|
}
|
|
120
121
|
};
|
|
121
122
|
|
|
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
|
+
}
|
|
184
|
+
function parseHookConfig(content) {
|
|
185
|
+
const configMatch = content.match(CONFIG_BLOCK_RE);
|
|
186
|
+
if (!configMatch) return null;
|
|
187
|
+
const externalId = configMatch[1].match(/external_id\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
188
|
+
const collection = configMatch[1].match(/collection\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
189
|
+
const trigger = configMatch[1].match(/trigger\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
190
|
+
const enabled = configMatch[1].match(/enabled\s*:\s*(true|false)/)?.[1];
|
|
191
|
+
const name = configMatch[1].match(/name\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
192
|
+
if (!collection || !trigger) return null;
|
|
193
|
+
const hook = {
|
|
194
|
+
external_id: externalId || "",
|
|
195
|
+
collection,
|
|
196
|
+
trigger,
|
|
197
|
+
enabled: enabled !== "false"
|
|
198
|
+
};
|
|
199
|
+
if (name) hook.name = name;
|
|
200
|
+
const metadataMatch = configMatch[1].match(/metadata\s*:\s*(\{[^}]*\})/);
|
|
201
|
+
if (metadataMatch) {
|
|
202
|
+
try {
|
|
203
|
+
const metaStr = metadataMatch[1].replace(/'/g, '"').replace(/(\w+)\s*:/g, '"$1":').replace(/,\s*}/g, "}");
|
|
204
|
+
hook.metadata = JSON.parse(metaStr);
|
|
205
|
+
} catch {
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return hook;
|
|
209
|
+
}
|
|
210
|
+
function extractHookScript(content) {
|
|
211
|
+
const handlerMatch = content.match(
|
|
212
|
+
/export\s+default\s+(?:async\s+)?function\s*(?:\w+)?\s*\([^)]*\)\s*\{([\s\S]*)\}[\s\n]*$/
|
|
213
|
+
);
|
|
214
|
+
if (handlerMatch) {
|
|
215
|
+
return handlerMatch[1].trim();
|
|
216
|
+
}
|
|
217
|
+
const simpleMatch = content.match(
|
|
218
|
+
/export\s+default\s+async\s+function[^{]*\{([\s\S]*)\}[\s\n]*$/
|
|
219
|
+
);
|
|
220
|
+
if (simpleMatch) {
|
|
221
|
+
return simpleMatch[1].trim();
|
|
222
|
+
}
|
|
223
|
+
return content.replace(/export\s+const\s+config[\s\S]*?;/, "").trim();
|
|
224
|
+
}
|
|
225
|
+
function hasDefaultHandler(content) {
|
|
226
|
+
return /export\s+default\s+(?:async\s+)?function\b/.test(content);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/lib/lint/rules/hook-verify.ts
|
|
230
|
+
function error2(target, message) {
|
|
231
|
+
return {
|
|
232
|
+
ruleId: "hook-verify",
|
|
233
|
+
target,
|
|
234
|
+
severity: "error",
|
|
235
|
+
message
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
var hookVerifyRule = {
|
|
239
|
+
id: "hook-verify",
|
|
240
|
+
description: "Validates hook file structure (config export, trigger, known keys, default handler) and verifies the script compiles via the backend.",
|
|
241
|
+
appliesTo: ["hook"],
|
|
242
|
+
async check(target, ctx) {
|
|
243
|
+
const config = parseHookConfig(target.source);
|
|
244
|
+
if (!config) {
|
|
245
|
+
return [
|
|
246
|
+
error2(
|
|
247
|
+
target,
|
|
248
|
+
"Missing or unparseable `export const config = {...}`. Hook files must export a config object with at least `collection` and `trigger`."
|
|
249
|
+
)
|
|
250
|
+
];
|
|
251
|
+
}
|
|
252
|
+
const errors = [];
|
|
253
|
+
if (!config.external_id && !ctx.appName) {
|
|
254
|
+
errors.push(
|
|
255
|
+
error2(
|
|
256
|
+
target,
|
|
257
|
+
"Hook config is missing `external_id` and no app name is configured to derive one from the file name."
|
|
258
|
+
)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
if (!hasDefaultHandler(target.source)) {
|
|
262
|
+
errors.push(
|
|
263
|
+
error2(
|
|
264
|
+
target,
|
|
265
|
+
"Missing default exported handler. Hook files must `export default function(ctx) { ... }` (async allowed)."
|
|
266
|
+
)
|
|
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
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (errors.length > 0) return errors;
|
|
312
|
+
let script = extractHookScript(target.source);
|
|
313
|
+
if (ctx.appName) {
|
|
314
|
+
script = script.replaceAll("{{app}}", ctx.appName);
|
|
315
|
+
}
|
|
316
|
+
if (!ctx.api) {
|
|
317
|
+
return [];
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
await ctx.api.compileHook(script);
|
|
321
|
+
} catch (err) {
|
|
322
|
+
const detail = err instanceof ApiError ? err.body.trim() : err instanceof Error ? err.message : String(err);
|
|
323
|
+
return [error2(target, `Hook failed to compile on the backend: ${detail}`)];
|
|
324
|
+
}
|
|
325
|
+
return [];
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
122
329
|
// src/lib/lint/rules/llm-import.ts
|
|
123
330
|
var FROM_LUMERA_IMPORT_LLM = /^\s*from\s+lumera\s+import\s+\(?\s*(?:[\w\s,]*?\b)?llm\b/;
|
|
124
331
|
var LUMERA_LLM_SUBMODULE = /^\s*(?:from\s+lumera\.llm\b|import\s+lumera\.llm\b)/;
|
|
@@ -162,7 +369,7 @@ var llmImportRule = {
|
|
|
162
369
|
};
|
|
163
370
|
|
|
164
371
|
// src/lib/lint/registry.ts
|
|
165
|
-
var ALL_RULES = [collectionSchemaRule, llmImportRule];
|
|
372
|
+
var ALL_RULES = [collectionSchemaRule, hookVerifyRule, llmImportRule];
|
|
166
373
|
|
|
167
374
|
// src/lib/lint/format.ts
|
|
168
375
|
import { relative } from "path";
|
|
@@ -207,13 +414,14 @@ function serializeLintWarnings(warnings, projectRoot) {
|
|
|
207
414
|
}
|
|
208
415
|
|
|
209
416
|
// src/lib/lint/index.ts
|
|
210
|
-
function runLint(ctx) {
|
|
417
|
+
async function runLint(ctx) {
|
|
211
418
|
const out = [];
|
|
212
419
|
for (const rule of ALL_RULES) {
|
|
213
420
|
for (const t of ctx.targets) {
|
|
214
421
|
if (!rule.appliesTo.includes(t.kind)) continue;
|
|
215
422
|
try {
|
|
216
|
-
|
|
423
|
+
const result = await rule.check(t, ctx);
|
|
424
|
+
out.push(...result);
|
|
217
425
|
} catch (err) {
|
|
218
426
|
if (process.env.LUMERA_DEBUG) {
|
|
219
427
|
console.error(`[lint] rule "${rule.id}" threw on ${t.filePath}:`, err);
|
|
@@ -247,12 +455,31 @@ function buildCollectionTargets(platformDir, _filterName) {
|
|
|
247
455
|
}
|
|
248
456
|
return targets;
|
|
249
457
|
}
|
|
458
|
+
function buildHookTargets(platformDir, filterName) {
|
|
459
|
+
const hooksDir = join(platformDir, "hooks");
|
|
460
|
+
if (!existsSync(hooksDir)) return [];
|
|
461
|
+
const targets = [];
|
|
462
|
+
for (const entry of readdirSync(hooksDir, { withFileTypes: true })) {
|
|
463
|
+
if (!entry.isFile()) continue;
|
|
464
|
+
if (!entry.name.endsWith(".js") && !entry.name.endsWith(".ts")) continue;
|
|
465
|
+
const base = entry.name.replace(/\.(js|ts)$/, "");
|
|
466
|
+
if (filterName && base !== filterName) continue;
|
|
467
|
+
const filePath = join(hooksDir, entry.name);
|
|
468
|
+
targets.push({
|
|
469
|
+
kind: "hook",
|
|
470
|
+
name: base,
|
|
471
|
+
filePath,
|
|
472
|
+
source: readFileSync(filePath, "utf-8")
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
return targets;
|
|
476
|
+
}
|
|
250
477
|
|
|
251
478
|
// src/commands/resources.ts
|
|
252
479
|
init_auth();
|
|
253
|
-
function safeLint(projectRoot, localAutomations) {
|
|
480
|
+
async function safeLint(projectRoot, localAutomations) {
|
|
254
481
|
try {
|
|
255
|
-
return runLint({ projectRoot, targets: buildAutomationTargets(localAutomations) });
|
|
482
|
+
return await runLint({ projectRoot, targets: buildAutomationTargets(localAutomations) });
|
|
256
483
|
} catch (err) {
|
|
257
484
|
if (process.env.LUMERA_DEBUG) console.error("[lint] pass failed:", err);
|
|
258
485
|
return [];
|
|
@@ -265,13 +492,22 @@ function safePrintLint(warnings, projectRoot) {
|
|
|
265
492
|
if (process.env.LUMERA_DEBUG) console.error("[lint] print failed:", err);
|
|
266
493
|
}
|
|
267
494
|
}
|
|
268
|
-
function lintCollectionFiles(projectRoot, platformDir, filterName) {
|
|
269
|
-
const issues = runLint({ projectRoot, targets: buildCollectionTargets(platformDir, filterName) });
|
|
495
|
+
async function lintCollectionFiles(projectRoot, platformDir, filterName) {
|
|
496
|
+
const issues = await runLint({ projectRoot, targets: buildCollectionTargets(platformDir, filterName) });
|
|
270
497
|
const errors = issues.filter((issue) => issue.severity === "error");
|
|
271
498
|
if (errors.length === 0) return;
|
|
272
499
|
printLintWarnings(issues, projectRoot);
|
|
273
500
|
throw new Error(`Found ${errors.length} collection lint error(s)`);
|
|
274
501
|
}
|
|
502
|
+
async function lintHookFiles(api, projectRoot, platformDir, appName, filterName) {
|
|
503
|
+
const targets = buildHookTargets(platformDir, filterName);
|
|
504
|
+
if (targets.length === 0) return;
|
|
505
|
+
const issues = await runLint({ projectRoot, targets, api, appName });
|
|
506
|
+
const errors = issues.filter((issue) => issue.severity === "error");
|
|
507
|
+
if (errors.length === 0) return;
|
|
508
|
+
printLintWarnings(issues, projectRoot);
|
|
509
|
+
throw new Error(`Found ${errors.length} hook lint error(s)`);
|
|
510
|
+
}
|
|
275
511
|
var PACKAGE_MANAGERS = ["bun", "pnpm", "yarn", "npm"];
|
|
276
512
|
var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager"]);
|
|
277
513
|
function isPackageManager(value) {
|
|
@@ -970,47 +1206,6 @@ function loadLocalHooks(platformDir, filterName, appName) {
|
|
|
970
1206
|
}
|
|
971
1207
|
return hooks;
|
|
972
1208
|
}
|
|
973
|
-
function parseHookConfig(content) {
|
|
974
|
-
const configMatch = content.match(/export\s+const\s+config\s*[=:]\s*(\{[\s\S]*?\});?/);
|
|
975
|
-
if (!configMatch) return null;
|
|
976
|
-
const externalId = configMatch[1].match(/external_id\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
977
|
-
const collection = configMatch[1].match(/collection\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
978
|
-
const trigger = configMatch[1].match(/trigger\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
979
|
-
const enabled = configMatch[1].match(/enabled\s*:\s*(true|false)/)?.[1];
|
|
980
|
-
const name = configMatch[1].match(/name\s*:\s*['"]([^'"]+)['"]/)?.[1];
|
|
981
|
-
if (!collection || !trigger) return null;
|
|
982
|
-
const hook = {
|
|
983
|
-
external_id: externalId || "",
|
|
984
|
-
collection,
|
|
985
|
-
trigger,
|
|
986
|
-
enabled: enabled !== "false"
|
|
987
|
-
};
|
|
988
|
-
if (name) hook.name = name;
|
|
989
|
-
const metadataMatch = configMatch[1].match(/metadata\s*:\s*(\{[^}]*\})/);
|
|
990
|
-
if (metadataMatch) {
|
|
991
|
-
try {
|
|
992
|
-
const metaStr = metadataMatch[1].replace(/'/g, '"').replace(/(\w+)\s*:/g, '"$1":').replace(/,\s*}/g, "}");
|
|
993
|
-
hook.metadata = JSON.parse(metaStr);
|
|
994
|
-
} catch {
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
return hook;
|
|
998
|
-
}
|
|
999
|
-
function extractHookScript(content) {
|
|
1000
|
-
const handlerMatch = content.match(
|
|
1001
|
-
/export\s+default\s+(?:async\s+)?function\s*(?:\w+)?\s*\([^)]*\)\s*\{([\s\S]*)\}[\s\n]*$/
|
|
1002
|
-
);
|
|
1003
|
-
if (handlerMatch) {
|
|
1004
|
-
return handlerMatch[1].trim();
|
|
1005
|
-
}
|
|
1006
|
-
const simpleMatch = content.match(
|
|
1007
|
-
/export\s+default\s+async\s+function[^{]*\{([\s\S]*)\}[\s\n]*$/
|
|
1008
|
-
);
|
|
1009
|
-
if (simpleMatch) {
|
|
1010
|
-
return simpleMatch[1].trim();
|
|
1011
|
-
}
|
|
1012
|
-
return content.replace(/export\s+const\s+config[\s\S]*?;/, "").trim();
|
|
1013
|
-
}
|
|
1014
1209
|
function convertCollectionToApiFormat(local) {
|
|
1015
1210
|
const schema = local.fields.map((field) => {
|
|
1016
1211
|
const apiField = {
|
|
@@ -2686,7 +2881,10 @@ async function plan(args) {
|
|
|
2686
2881
|
console.log(pc2.dim(" Comparing local files to remote state..."));
|
|
2687
2882
|
console.log();
|
|
2688
2883
|
if (!type || type === "collections") {
|
|
2689
|
-
lintCollectionFiles(projectRoot, platformDir, name || void 0);
|
|
2884
|
+
await lintCollectionFiles(projectRoot, platformDir, name || void 0);
|
|
2885
|
+
}
|
|
2886
|
+
if (!type || type === "hooks") {
|
|
2887
|
+
await lintHookFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
2690
2888
|
}
|
|
2691
2889
|
await syncDeps(projectRoot, { ignorePermissionDenied: true });
|
|
2692
2890
|
const allChanges = [];
|
|
@@ -2733,7 +2931,7 @@ async function plan(args) {
|
|
|
2733
2931
|
allChanges.push(...changes);
|
|
2734
2932
|
}
|
|
2735
2933
|
}
|
|
2736
|
-
const lintWarnings = safeLint(projectRoot, localAutomations);
|
|
2934
|
+
const lintWarnings = await safeLint(projectRoot, localAutomations);
|
|
2737
2935
|
if (allChanges.length === 0) {
|
|
2738
2936
|
if (jsonOutput) {
|
|
2739
2937
|
console.log(JSON.stringify({ changes: [], warnings: [], lintWarnings: serializeLintWarnings(lintWarnings, projectRoot) }));
|
|
@@ -2828,7 +3026,10 @@ async function apply(args) {
|
|
|
2828
3026
|
return;
|
|
2829
3027
|
}
|
|
2830
3028
|
if (!type || type === "collections") {
|
|
2831
|
-
lintCollectionFiles(projectRoot, platformDir, name || void 0);
|
|
3029
|
+
await lintCollectionFiles(projectRoot, platformDir, name || void 0);
|
|
3030
|
+
}
|
|
3031
|
+
if (!type || type === "hooks") {
|
|
3032
|
+
await lintHookFiles(api, projectRoot, platformDir, appName, name || void 0);
|
|
2832
3033
|
}
|
|
2833
3034
|
await syncDeps(projectRoot, { ignorePermissionDenied: true });
|
|
2834
3035
|
let collections;
|
|
@@ -2870,7 +3071,7 @@ async function apply(args) {
|
|
|
2870
3071
|
console.log();
|
|
2871
3072
|
console.log(pc2.green(" \u2713 Nothing to apply \u2014 local and remote are in sync."));
|
|
2872
3073
|
console.log();
|
|
2873
|
-
safePrintLint(safeLint(projectRoot, localAutomations), projectRoot);
|
|
3074
|
+
safePrintLint(await safeLint(projectRoot, localAutomations), projectRoot);
|
|
2874
3075
|
return;
|
|
2875
3076
|
}
|
|
2876
3077
|
console.log();
|
|
@@ -2898,7 +3099,7 @@ async function apply(args) {
|
|
|
2898
3099
|
console.log(pc2.dim(" No infrastructure changes \u2014 deploying app only."));
|
|
2899
3100
|
console.log();
|
|
2900
3101
|
}
|
|
2901
|
-
safePrintLint(safeLint(projectRoot, localAutomations), projectRoot);
|
|
3102
|
+
safePrintLint(await safeLint(projectRoot, localAutomations), projectRoot);
|
|
2902
3103
|
if (!autoConfirm && allChanges.length > 0) {
|
|
2903
3104
|
const { confirm } = await prompts({
|
|
2904
3105
|
type: "confirm",
|