@lumerahq/cli 0.19.4 → 0.19.6
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-SU26C4GL.js → chunk-53NOF33P.js} +49 -9
- package/dist/{chunk-5T22627H.js → chunk-RUJRTLHA.js} +1 -1
- package/dist/{chunk-UH5X43VV.js → chunk-WY6UMJNI.js} +2 -0
- package/dist/{deps-GCOH3TXL.js → deps-73XZXRYP.js} +2 -2
- package/dist/{dev-JLSTLIMZ.js → dev-YYMFCXZ5.js} +3 -3
- package/dist/index.js +12 -12
- package/dist/{init-CBZAIERZ.js → init-7YWMMTBF.js} +1 -1
- package/dist/{register-N2LF3CCK.js → register-KJMSMMD6.js} +1 -1
- package/dist/{resources-RHF2MDF7.js → resources-P7WAHOHR.js} +159 -44
- package/dist/{run-XJLB4AFD.js → run-C23KZI4Z.js} +1 -1
- package/package.json +1 -1
- package/templates/default/AGENTS.md +3 -3
|
@@ -137,19 +137,59 @@ function isPortInUse(port, host = "127.0.0.1") {
|
|
|
137
137
|
});
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
return
|
|
140
|
+
function commandAvailable(command) {
|
|
141
|
+
try {
|
|
142
|
+
execSync(`${command} --version`, { stdio: "ignore" });
|
|
143
|
+
return true;
|
|
144
|
+
} catch {
|
|
145
|
+
return false;
|
|
146
146
|
}
|
|
147
|
+
}
|
|
148
|
+
function parsePackageManagerSpecifier(value) {
|
|
149
|
+
const raw = (value || "").trim();
|
|
150
|
+
if (!raw) return void 0;
|
|
151
|
+
const name = raw.split("@")[0];
|
|
152
|
+
return ["bun", "pnpm", "yarn", "npm"].includes(name) ? name : void 0;
|
|
153
|
+
}
|
|
154
|
+
function packageManagerFromPackageJson(projectRoot) {
|
|
147
155
|
try {
|
|
148
|
-
|
|
149
|
-
return
|
|
156
|
+
const pkg = JSON.parse(readFileSync(resolve(projectRoot, "package.json"), "utf-8"));
|
|
157
|
+
return parsePackageManagerSpecifier(pkg.packageManager);
|
|
150
158
|
} catch {
|
|
151
|
-
return
|
|
159
|
+
return void 0;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function runnerForPackageManager(pm) {
|
|
163
|
+
if (pm === "pnpm") return ["pnpm", "exec"];
|
|
164
|
+
if (pm === "bun") return ["bunx"];
|
|
165
|
+
if (pm === "yarn") return ["yarn"];
|
|
166
|
+
return ["npx"];
|
|
167
|
+
}
|
|
168
|
+
function detectRunner(projectRoot) {
|
|
169
|
+
const requested = parsePackageManagerSpecifier(process.env.LUMERA_PACKAGE_MANAGER);
|
|
170
|
+
if (requested && commandAvailable(runnerForPackageManager(requested)[0])) {
|
|
171
|
+
return runnerForPackageManager(requested);
|
|
172
|
+
}
|
|
173
|
+
const declared = packageManagerFromPackageJson(projectRoot);
|
|
174
|
+
if (declared && commandAvailable(runnerForPackageManager(declared)[0])) {
|
|
175
|
+
return runnerForPackageManager(declared);
|
|
176
|
+
}
|
|
177
|
+
const lockfileManagers = [
|
|
178
|
+
{ pm: "pnpm", file: "pnpm-lock.yaml" },
|
|
179
|
+
{ pm: "bun", file: "bun.lockb" },
|
|
180
|
+
{ pm: "bun", file: "bun.lock" },
|
|
181
|
+
{ pm: "yarn", file: "yarn.lock" },
|
|
182
|
+
{ pm: "npm", file: "package-lock.json" }
|
|
183
|
+
];
|
|
184
|
+
for (const { pm, file } of lockfileManagers) {
|
|
185
|
+
const runner = runnerForPackageManager(pm);
|
|
186
|
+
if (existsSync(resolve(projectRoot, file)) && commandAvailable(runner[0])) return runner;
|
|
187
|
+
}
|
|
188
|
+
for (const pm of ["pnpm", "bun", "yarn", "npm"]) {
|
|
189
|
+
const runner = runnerForPackageManager(pm);
|
|
190
|
+
if (commandAvailable(runner[0])) return runner;
|
|
152
191
|
}
|
|
192
|
+
return ["npx"];
|
|
153
193
|
}
|
|
154
194
|
function getParentOrigin(apiUrl) {
|
|
155
195
|
return apiUrl.replace(/\/api\/?$/, "").replace(/\/$/, "");
|
|
@@ -117,6 +117,7 @@ var ApiClient = class {
|
|
|
117
117
|
const qs = new URLSearchParams();
|
|
118
118
|
if (params?.external_id) qs.set("external_id", params.external_id);
|
|
119
119
|
if (params?.include_code) qs.set("include_code", "true");
|
|
120
|
+
if (params?.project_id) qs.set("project_id", params.project_id);
|
|
120
121
|
qs.set("limit", "100");
|
|
121
122
|
const all = [];
|
|
122
123
|
let offset = 0;
|
|
@@ -179,6 +180,7 @@ var ApiClient = class {
|
|
|
179
180
|
const query = new URLSearchParams();
|
|
180
181
|
if (params?.collection_id) query.set("collection_id", params.collection_id);
|
|
181
182
|
if (params?.external_id) query.set("external_id", params.external_id);
|
|
183
|
+
if (params?.project_id) query.set("project_id", params.project_id);
|
|
182
184
|
const queryString = query.toString();
|
|
183
185
|
const path = queryString ? `/api/pb/hooks?${queryString}` : "/api/pb/hooks";
|
|
184
186
|
const result = await this.request(path);
|
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
deps,
|
|
3
3
|
projectResourceDepsEnabled,
|
|
4
4
|
syncDeps
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RUJRTLHA.js";
|
|
6
6
|
import "./chunk-2CR762KB.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-WY6UMJNI.js";
|
|
8
8
|
import "./chunk-ZH3NVYEQ.js";
|
|
9
9
|
import "./chunk-FJFIWC7G.js";
|
|
10
10
|
import "./chunk-PNKVD2UK.js";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dev
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-53NOF33P.js";
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RUJRTLHA.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-WY6UMJNI.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-P7WAHOHR.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-P7WAHOHR.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-P7WAHOHR.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-P7WAHOHR.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-P7WAHOHR.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-P7WAHOHR.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-P7WAHOHR.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-YYMFCXZ5.js").then((m) => m.dev(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "run":
|
|
247
|
-
await import("./run-
|
|
247
|
+
await import("./run-C23KZI4Z.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-7YWMMTBF.js").then((m) => m.init(args.slice(1)));
|
|
252
252
|
break;
|
|
253
253
|
case "register":
|
|
254
|
-
await import("./register-
|
|
254
|
+
await import("./register-KJMSMMD6.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-73XZXRYP.js").then((m) => m.deps(args.slice(1)));
|
|
272
272
|
break;
|
|
273
273
|
// Auth
|
|
274
274
|
case "login":
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-53NOF33P.js";
|
|
4
4
|
import {
|
|
5
5
|
projectResourceDepsEnabled,
|
|
6
6
|
syncDeps
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RUJRTLHA.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-WY6UMJNI.js";
|
|
14
14
|
import {
|
|
15
15
|
findProjectRoot,
|
|
16
16
|
getApiUrl,
|
|
@@ -272,13 +272,82 @@ function lintCollectionFiles(projectRoot, platformDir, filterName) {
|
|
|
272
272
|
printLintWarnings(issues, projectRoot);
|
|
273
273
|
throw new Error(`Found ${errors.length} collection lint error(s)`);
|
|
274
274
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
275
|
+
var PACKAGE_MANAGERS = ["bun", "pnpm", "yarn", "npm"];
|
|
276
|
+
var PACKAGE_MANAGER_VALUE_FLAGS = /* @__PURE__ */ new Set(["--package-manager"]);
|
|
277
|
+
function isPackageManager(value) {
|
|
278
|
+
return PACKAGE_MANAGERS.includes(value);
|
|
279
|
+
}
|
|
280
|
+
function commandAvailable(command) {
|
|
281
|
+
try {
|
|
282
|
+
execFileSync(command, ["--version"], { stdio: "ignore" });
|
|
283
|
+
return true;
|
|
284
|
+
} catch {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function parsePackageManagerSpecifier(value) {
|
|
289
|
+
const raw = (value || "").trim();
|
|
290
|
+
if (!raw) return void 0;
|
|
291
|
+
const name = raw.split("@")[0];
|
|
292
|
+
return isPackageManager(name) ? name : void 0;
|
|
293
|
+
}
|
|
294
|
+
function packageManagerFromPackageJson(projectRoot) {
|
|
295
|
+
try {
|
|
296
|
+
const pkg = JSON.parse(readFileSync2(join2(projectRoot, "package.json"), "utf-8"));
|
|
297
|
+
return parsePackageManagerSpecifier(pkg.packageManager);
|
|
298
|
+
} catch {
|
|
299
|
+
return void 0;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function getFlagValue(args, name) {
|
|
303
|
+
const long = `--${name}`;
|
|
304
|
+
for (let i = 0; i < args.length; i++) {
|
|
305
|
+
const arg = args[i];
|
|
306
|
+
if (arg === long) {
|
|
307
|
+
const next = args[i + 1];
|
|
308
|
+
return next && !next.startsWith("-") ? next : void 0;
|
|
309
|
+
}
|
|
310
|
+
if (arg.startsWith(`${long}=`)) {
|
|
311
|
+
return arg.slice(long.length + 1);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return void 0;
|
|
315
|
+
}
|
|
316
|
+
function getPositionalArgs(args) {
|
|
317
|
+
const out = [];
|
|
318
|
+
for (let i = 0; i < args.length; i++) {
|
|
319
|
+
const arg = args[i];
|
|
320
|
+
if (PACKAGE_MANAGER_VALUE_FLAGS.has(arg)) {
|
|
321
|
+
i++;
|
|
322
|
+
continue;
|
|
281
323
|
}
|
|
324
|
+
if (arg.startsWith("-")) continue;
|
|
325
|
+
out.push(arg);
|
|
326
|
+
}
|
|
327
|
+
return out;
|
|
328
|
+
}
|
|
329
|
+
function detectPackageManager(projectRoot, override) {
|
|
330
|
+
const requested = parsePackageManagerSpecifier(override || process.env.LUMERA_PACKAGE_MANAGER);
|
|
331
|
+
if (requested) {
|
|
332
|
+
if (!commandAvailable(requested)) {
|
|
333
|
+
throw new Error(`Package manager '${requested}' was requested but is not available on PATH`);
|
|
334
|
+
}
|
|
335
|
+
return requested;
|
|
336
|
+
}
|
|
337
|
+
const declared = packageManagerFromPackageJson(projectRoot);
|
|
338
|
+
if (declared && commandAvailable(declared)) return declared;
|
|
339
|
+
const lockfileManagers = [
|
|
340
|
+
{ pm: "pnpm", file: "pnpm-lock.yaml" },
|
|
341
|
+
{ pm: "bun", file: "bun.lockb" },
|
|
342
|
+
{ pm: "bun", file: "bun.lock" },
|
|
343
|
+
{ pm: "yarn", file: "yarn.lock" },
|
|
344
|
+
{ pm: "npm", file: "package-lock.json" }
|
|
345
|
+
];
|
|
346
|
+
for (const { pm, file } of lockfileManagers) {
|
|
347
|
+
if (existsSync2(join2(projectRoot, file)) && commandAvailable(pm)) return pm;
|
|
348
|
+
}
|
|
349
|
+
for (const pm of ["pnpm", "bun", "yarn", "npm"]) {
|
|
350
|
+
if (commandAvailable(pm)) return pm;
|
|
282
351
|
}
|
|
283
352
|
return "npm";
|
|
284
353
|
}
|
|
@@ -294,6 +363,23 @@ function stripNamespacePrefix(name, appName) {
|
|
|
294
363
|
}
|
|
295
364
|
return name;
|
|
296
365
|
}
|
|
366
|
+
function buildCollectionIdMap(collections, appName) {
|
|
367
|
+
const result = /* @__PURE__ */ new Map();
|
|
368
|
+
const add = (key, id) => {
|
|
369
|
+
const trimmed = (key || "").trim();
|
|
370
|
+
if (trimmed) result.set(trimmed, id);
|
|
371
|
+
};
|
|
372
|
+
for (const collection of collections) {
|
|
373
|
+
add(collection.id, collection.id);
|
|
374
|
+
add(collection.name, collection.id);
|
|
375
|
+
const stripped = stripNamespacePrefix(collection.name, appName);
|
|
376
|
+
add(stripped, collection.id);
|
|
377
|
+
if (collection.name.includes(NAMESPACE_SEPARATOR)) {
|
|
378
|
+
add(collection.name.split(NAMESPACE_SEPARATOR).slice(1).join(NAMESPACE_SEPARATOR), collection.id);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return result;
|
|
382
|
+
}
|
|
297
383
|
function computeLineDiff(oldText, newText) {
|
|
298
384
|
const oldLines = (oldText || "").trimEnd().split("\n");
|
|
299
385
|
const newLines = (newText || "").trimEnd().split("\n");
|
|
@@ -558,6 +644,9 @@ ${pc2.dim("Resources:")}
|
|
|
558
644
|
${pc2.dim("Options:")}
|
|
559
645
|
--yes, -y Skip confirmation prompt (for CI/CD)
|
|
560
646
|
--skip-build Skip build step when applying app
|
|
647
|
+
--no-app Apply resources only; do not build/deploy the app
|
|
648
|
+
--resources-only Alias for --no-app
|
|
649
|
+
--package-manager Package manager for app builds (pnpm, bun, yarn, npm)
|
|
561
650
|
|
|
562
651
|
${pc2.dim("Examples:")}
|
|
563
652
|
lumera apply # Apply everything (shows plan, asks to confirm)
|
|
@@ -566,6 +655,8 @@ ${pc2.dim("Examples:")}
|
|
|
566
655
|
lumera apply agents -y # Apply agents without confirmation
|
|
567
656
|
lumera apply app # Deploy frontend
|
|
568
657
|
lumera apply app --skip-build # Deploy without rebuilding
|
|
658
|
+
lumera apply --no-app -y # Apply resources without app build/deploy
|
|
659
|
+
lumera apply app --package-manager pnpm
|
|
569
660
|
`);
|
|
570
661
|
}
|
|
571
662
|
function showPullHelp() {
|
|
@@ -974,6 +1065,16 @@ function mapFieldType(type) {
|
|
|
974
1065
|
};
|
|
975
1066
|
return typeMap[type] || type;
|
|
976
1067
|
}
|
|
1068
|
+
function normalizeConstraintValue(fieldType, value) {
|
|
1069
|
+
if (value === void 0 || value === null) return void 0;
|
|
1070
|
+
if (["text", "email", "url", "editor"].includes(fieldType) && value === 0) {
|
|
1071
|
+
return void 0;
|
|
1072
|
+
}
|
|
1073
|
+
if (fieldType === "date" && value === "") {
|
|
1074
|
+
return void 0;
|
|
1075
|
+
}
|
|
1076
|
+
return value;
|
|
1077
|
+
}
|
|
977
1078
|
function fieldsDiffer(local, remote) {
|
|
978
1079
|
if (mapFieldType(local.type) !== remote.type) return true;
|
|
979
1080
|
if ((local.required || false) !== (remote.required || false)) return true;
|
|
@@ -1002,11 +1103,11 @@ function fieldsDiffer(local, remote) {
|
|
|
1002
1103
|
const remoteDecimalPrecision = opts.decimalPrecision !== void 0 ? opts.decimalPrecision : 2;
|
|
1003
1104
|
if (localDecimalPrecision !== remoteDecimalPrecision) return true;
|
|
1004
1105
|
}
|
|
1005
|
-
const localMin = local.
|
|
1006
|
-
const remoteMin =
|
|
1106
|
+
const localMin = normalizeConstraintValue(local.type, local.min);
|
|
1107
|
+
const remoteMin = normalizeConstraintValue(local.type, opts.min);
|
|
1007
1108
|
if (localMin !== remoteMin) return true;
|
|
1008
|
-
const localMax = local.
|
|
1009
|
-
const remoteMax =
|
|
1109
|
+
const localMax = normalizeConstraintValue(local.type, local.max);
|
|
1110
|
+
const remoteMax = normalizeConstraintValue(local.type, opts.max);
|
|
1010
1111
|
if (localMax !== remoteMax) return true;
|
|
1011
1112
|
return false;
|
|
1012
1113
|
}
|
|
@@ -1100,9 +1201,12 @@ async function planCollections(api, localCollections) {
|
|
|
1100
1201
|
}
|
|
1101
1202
|
return changes;
|
|
1102
1203
|
}
|
|
1103
|
-
async function planAutomations(api, localAutomations) {
|
|
1204
|
+
async function planAutomations(api, localAutomations, projectId) {
|
|
1104
1205
|
const changes = [];
|
|
1105
|
-
const remoteAutomations = await api.listAutomations({
|
|
1206
|
+
const remoteAutomations = await api.listAutomations({
|
|
1207
|
+
include_code: true,
|
|
1208
|
+
...projectId ? { project_id: projectId } : {}
|
|
1209
|
+
});
|
|
1106
1210
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
1107
1211
|
const remotePresetCache = /* @__PURE__ */ new Map();
|
|
1108
1212
|
const getRemotePresets = (automationId) => {
|
|
@@ -1285,9 +1389,9 @@ async function pullMailboxes(api, platformDir, filterName) {
|
|
|
1285
1389
|
console.log(pc2.yellow(` \u26A0 mailbox '${filterName}' not found on remote`));
|
|
1286
1390
|
}
|
|
1287
1391
|
}
|
|
1288
|
-
async function planHooks(api, localHooks, collections) {
|
|
1392
|
+
async function planHooks(api, localHooks, collections, projectId) {
|
|
1289
1393
|
const changes = [];
|
|
1290
|
-
const remoteHooks = await api.listHooks();
|
|
1394
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
1291
1395
|
const remoteByExternalId = new Map(remoteHooks.filter((h) => h.external_id).map((h) => [h.external_id, h]));
|
|
1292
1396
|
for (const { hook, script, fileName } of localHooks) {
|
|
1293
1397
|
const remote = remoteByExternalId.get(hook.external_id);
|
|
@@ -1375,7 +1479,7 @@ async function applyCollections(api, localCollections) {
|
|
|
1375
1479
|
}
|
|
1376
1480
|
async function applyAutomations(api, localAutomations, projectId) {
|
|
1377
1481
|
let errors = 0;
|
|
1378
|
-
const remoteAutomations = await api.listAutomations();
|
|
1482
|
+
const remoteAutomations = await api.listAutomations(projectId ? { project_id: projectId } : void 0);
|
|
1379
1483
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
1380
1484
|
for (const { automation, code } of localAutomations) {
|
|
1381
1485
|
const remote = remoteByExternalId.get(automation.external_id);
|
|
@@ -1487,7 +1591,7 @@ async function setSchedule(api, automationId, schedule, localPresets) {
|
|
|
1487
1591
|
}
|
|
1488
1592
|
async function applyHooks(api, localHooks, collections, projectId) {
|
|
1489
1593
|
let errors = 0;
|
|
1490
|
-
const remoteHooks = await api.listHooks();
|
|
1594
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
1491
1595
|
const remoteByExternalId = new Map(remoteHooks.filter((h) => h.external_id).map((h) => [h.external_id, h]));
|
|
1492
1596
|
for (const { hook, script, fileName } of localHooks) {
|
|
1493
1597
|
const remote = remoteByExternalId.get(hook.external_id);
|
|
@@ -1535,7 +1639,7 @@ async function applyApp(args) {
|
|
|
1535
1639
|
if (!skipBuild) {
|
|
1536
1640
|
console.log(pc2.dim(" Building..."));
|
|
1537
1641
|
try {
|
|
1538
|
-
const pm = detectPackageManager();
|
|
1642
|
+
const pm = detectPackageManager(projectRoot, getFlagValue(args, "package-manager"));
|
|
1539
1643
|
execSync(`${pm} run build`, { cwd: projectRoot, stdio: "inherit" });
|
|
1540
1644
|
} catch {
|
|
1541
1645
|
throw new Error("Build failed");
|
|
@@ -1597,7 +1701,10 @@ async function pullCollections(api, platformDir, filterName, appName) {
|
|
|
1597
1701
|
async function pullAutomations(api, platformDir, filterName, projectId) {
|
|
1598
1702
|
const automationsDir = join2(platformDir, "automations");
|
|
1599
1703
|
mkdirSync(automationsDir, { recursive: true });
|
|
1600
|
-
const automations = await api.listAutomations({
|
|
1704
|
+
const automations = await api.listAutomations({
|
|
1705
|
+
include_code: true,
|
|
1706
|
+
...projectId ? { project_id: projectId } : {}
|
|
1707
|
+
});
|
|
1601
1708
|
for (const automation of automations) {
|
|
1602
1709
|
if (!automation.external_id || automation.managed) continue;
|
|
1603
1710
|
if (projectId && automation.project_id && automation.project_id !== projectId) continue;
|
|
@@ -1647,7 +1754,7 @@ async function pullAutomations(api, platformDir, filterName, projectId) {
|
|
|
1647
1754
|
async function pullHooks(api, platformDir, filterName, appName, projectId) {
|
|
1648
1755
|
const hooksDir = join2(platformDir, "hooks");
|
|
1649
1756
|
mkdirSync(hooksDir, { recursive: true });
|
|
1650
|
-
const hooks = await api.listHooks();
|
|
1757
|
+
const hooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
1651
1758
|
for (const hook of hooks) {
|
|
1652
1759
|
if (!hook.external_id) continue;
|
|
1653
1760
|
if (projectId && hook.project_id && hook.project_id !== projectId) continue;
|
|
@@ -1925,7 +2032,10 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
|
|
|
1925
2032
|
}
|
|
1926
2033
|
if (!filterType || filterType === "automations") {
|
|
1927
2034
|
const localAutomations = loadLocalAutomations(platformDir, void 0, appName);
|
|
1928
|
-
const remoteAutomations = await api.listAutomations({
|
|
2035
|
+
const remoteAutomations = await api.listAutomations({
|
|
2036
|
+
include_code: true,
|
|
2037
|
+
...projectId ? { project_id: projectId } : {}
|
|
2038
|
+
});
|
|
1929
2039
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id && !a.managed).map((a) => [a.external_id, a]));
|
|
1930
2040
|
const localIds = new Set(localAutomations.map((a) => a.automation.external_id));
|
|
1931
2041
|
for (const { automation, code } of localAutomations) {
|
|
@@ -1951,7 +2061,7 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
|
|
|
1951
2061
|
}
|
|
1952
2062
|
if (!filterType || filterType === "hooks") {
|
|
1953
2063
|
const localHooks = loadLocalHooks(platformDir, void 0, appName);
|
|
1954
|
-
const remoteHooks = await api.listHooks();
|
|
2064
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
1955
2065
|
const remoteByExternalId = new Map(remoteHooks.filter((h) => h.external_id).map((h) => [h.external_id, h]));
|
|
1956
2066
|
const localIds = new Set(localHooks.map((h) => h.hook.external_id));
|
|
1957
2067
|
for (const { hook, script } of localHooks) {
|
|
@@ -2111,7 +2221,7 @@ async function destroyResources(api, platformDir, resourceType, resourceName, sk
|
|
|
2111
2221
|
if (!resourceType || resourceType === "automations") {
|
|
2112
2222
|
try {
|
|
2113
2223
|
const localAutomations = loadLocalAutomations(platformDir, resourceName || void 0, appName);
|
|
2114
|
-
const remoteAutomations = await api.listAutomations();
|
|
2224
|
+
const remoteAutomations = await api.listAutomations(projectId ? { project_id: projectId } : void 0);
|
|
2115
2225
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
2116
2226
|
for (const { automation } of localAutomations) {
|
|
2117
2227
|
const remote = remoteByExternalId.get(automation.external_id);
|
|
@@ -2124,7 +2234,7 @@ async function destroyResources(api, platformDir, resourceType, resourceName, sk
|
|
|
2124
2234
|
}
|
|
2125
2235
|
if (!resourceType || resourceType === "hooks") {
|
|
2126
2236
|
const localHooks = loadLocalHooks(platformDir, resourceName || void 0, appName);
|
|
2127
|
-
const remoteHooks = await api.listHooks();
|
|
2237
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
2128
2238
|
const remoteByExternalId = new Map(remoteHooks.filter((h) => h.external_id).map((h) => [h.external_id, h]));
|
|
2129
2239
|
for (const { hook } of localHooks) {
|
|
2130
2240
|
const remote = remoteByExternalId.get(hook.external_id);
|
|
@@ -2365,7 +2475,7 @@ async function showResource(api, platformDir, resourceType, resourceName, appNam
|
|
|
2365
2475
|
console.log();
|
|
2366
2476
|
} else if (resourceType === "automations") {
|
|
2367
2477
|
const localAutomations = loadLocalAutomations(platformDir, resourceName, appName);
|
|
2368
|
-
const remoteAutomations = await api.listAutomations();
|
|
2478
|
+
const remoteAutomations = await api.listAutomations(projectId ? { project_id: projectId } : void 0);
|
|
2369
2479
|
const local = localAutomations[0];
|
|
2370
2480
|
const remote = remoteAutomations.find((a) => a.external_id === resourceName || a.name === resourceName);
|
|
2371
2481
|
if (!local && !remote) {
|
|
@@ -2388,7 +2498,7 @@ async function showResource(api, platformDir, resourceType, resourceName, appNam
|
|
|
2388
2498
|
console.log();
|
|
2389
2499
|
} else if (resourceType === "hooks") {
|
|
2390
2500
|
const localHooks = loadLocalHooks(platformDir, resourceName, appName);
|
|
2391
|
-
const remoteHooks = await api.listHooks();
|
|
2501
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
2392
2502
|
const local = localHooks[0];
|
|
2393
2503
|
const remote = remoteHooks.find((h) => h.external_id === resourceName);
|
|
2394
2504
|
if (!local && !remote) {
|
|
@@ -2526,7 +2636,7 @@ async function plan(args) {
|
|
|
2526
2636
|
let collections;
|
|
2527
2637
|
try {
|
|
2528
2638
|
const remoteCollections = await api.listCollections();
|
|
2529
|
-
collections =
|
|
2639
|
+
collections = buildCollectionIdMap(remoteCollections, appName);
|
|
2530
2640
|
} catch {
|
|
2531
2641
|
collections = /* @__PURE__ */ new Map();
|
|
2532
2642
|
}
|
|
@@ -2541,14 +2651,14 @@ async function plan(args) {
|
|
|
2541
2651
|
if (!type || type === "automations") {
|
|
2542
2652
|
localAutomations = loadLocalAutomations(platformDir, name || void 0, appName);
|
|
2543
2653
|
if (localAutomations.length > 0) {
|
|
2544
|
-
const changes = await planAutomations(api, localAutomations);
|
|
2654
|
+
const changes = await planAutomations(api, localAutomations, projectId);
|
|
2545
2655
|
allChanges.push(...changes);
|
|
2546
2656
|
}
|
|
2547
2657
|
}
|
|
2548
2658
|
if (!type || type === "hooks") {
|
|
2549
2659
|
const localHooks = loadLocalHooks(platformDir, name || void 0, appName);
|
|
2550
2660
|
if (localHooks.length > 0) {
|
|
2551
|
-
const changes = await planHooks(api, localHooks, collections);
|
|
2661
|
+
const changes = await planHooks(api, localHooks, collections, projectId);
|
|
2552
2662
|
allChanges.push(...changes);
|
|
2553
2663
|
}
|
|
2554
2664
|
}
|
|
@@ -2642,9 +2752,13 @@ async function apply(args) {
|
|
|
2642
2752
|
const appName = getAppName(projectRoot);
|
|
2643
2753
|
const api = createApiClient(void 0, void 0, appName);
|
|
2644
2754
|
const projectId = getProjectId(projectRoot);
|
|
2645
|
-
const positionalArgs = args
|
|
2755
|
+
const positionalArgs = getPositionalArgs(args);
|
|
2646
2756
|
const { type, name } = parseResource(positionalArgs[0]);
|
|
2647
2757
|
const autoConfirm = args.includes("--yes") || args.includes("-y") || !!process.env.CI;
|
|
2758
|
+
const skipApp = args.includes("--no-app") || args.includes("--resources-only");
|
|
2759
|
+
if (type === "app" && skipApp) {
|
|
2760
|
+
throw new Error("Cannot combine app resource with --no-app / --resources-only");
|
|
2761
|
+
}
|
|
2648
2762
|
if (type === "app") {
|
|
2649
2763
|
console.log();
|
|
2650
2764
|
console.log(pc2.cyan(pc2.bold(" Apply")));
|
|
@@ -2663,8 +2777,7 @@ async function apply(args) {
|
|
|
2663
2777
|
let collections;
|
|
2664
2778
|
try {
|
|
2665
2779
|
const remoteCollections = await api.listCollections();
|
|
2666
|
-
collections =
|
|
2667
|
-
for (const c of remoteCollections) collections.set(c.id, c.id);
|
|
2780
|
+
collections = buildCollectionIdMap(remoteCollections, appName);
|
|
2668
2781
|
} catch {
|
|
2669
2782
|
collections = /* @__PURE__ */ new Map();
|
|
2670
2783
|
}
|
|
@@ -2675,8 +2788,8 @@ async function apply(args) {
|
|
|
2675
2788
|
const localAgents = !type || type === "agents" ? loadLocalAgents(platformDir, name || void 0, appName) : [];
|
|
2676
2789
|
const localMailboxes = !type || type === "mailboxes" ? loadLocalMailboxes(platformDir, name || void 0) : [];
|
|
2677
2790
|
if (localCollections.length > 0) allChanges.push(...await planCollections(api, localCollections));
|
|
2678
|
-
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations));
|
|
2679
|
-
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections));
|
|
2791
|
+
if (localAutomations.length > 0) allChanges.push(...await planAutomations(api, localAutomations, projectId));
|
|
2792
|
+
if (localHooks.length > 0) allChanges.push(...await planHooks(api, localHooks, collections, projectId));
|
|
2680
2793
|
if (localAgents.length > 0) allChanges.push(...await planAgents(api, localAgents, projectId));
|
|
2681
2794
|
if (localMailboxes.length > 0) allChanges.push(...await planMailboxes(api, localMailboxes));
|
|
2682
2795
|
if (name) {
|
|
@@ -2688,7 +2801,7 @@ async function apply(args) {
|
|
|
2688
2801
|
}
|
|
2689
2802
|
}
|
|
2690
2803
|
let willDeployApp = false;
|
|
2691
|
-
if (!type) {
|
|
2804
|
+
if (!type && !skipApp) {
|
|
2692
2805
|
try {
|
|
2693
2806
|
if (existsSync2(join2(projectRoot, "dist")) || existsSync2(join2(projectRoot, "src"))) {
|
|
2694
2807
|
willDeployApp = true;
|
|
@@ -2754,8 +2867,7 @@ async function apply(args) {
|
|
|
2754
2867
|
}
|
|
2755
2868
|
try {
|
|
2756
2869
|
const remoteCollections = await api.listCollections();
|
|
2757
|
-
collections =
|
|
2758
|
-
for (const c of remoteCollections) collections.set(c.id, c.id);
|
|
2870
|
+
collections = buildCollectionIdMap(remoteCollections, appName);
|
|
2759
2871
|
} catch {
|
|
2760
2872
|
}
|
|
2761
2873
|
if (localAutomations.length > 0) {
|
|
@@ -2816,7 +2928,7 @@ async function pull(args) {
|
|
|
2816
2928
|
let collections;
|
|
2817
2929
|
try {
|
|
2818
2930
|
const remoteCollections = await api.listCollections();
|
|
2819
|
-
collections =
|
|
2931
|
+
collections = buildCollectionIdMap(remoteCollections, appName);
|
|
2820
2932
|
} catch {
|
|
2821
2933
|
collections = /* @__PURE__ */ new Map();
|
|
2822
2934
|
}
|
|
@@ -2832,7 +2944,7 @@ async function pull(args) {
|
|
|
2832
2944
|
if (!type || type === "automations") {
|
|
2833
2945
|
const localAutomations = loadLocalAutomations(platformDir, name || void 0, appName);
|
|
2834
2946
|
if (localAutomations.length > 0) {
|
|
2835
|
-
const changes = await planAutomations(api, localAutomations);
|
|
2947
|
+
const changes = await planAutomations(api, localAutomations, projectId);
|
|
2836
2948
|
for (const c of changes) {
|
|
2837
2949
|
if (c.type === "update") conflicts.push(`automations/${c.name}`);
|
|
2838
2950
|
}
|
|
@@ -2841,7 +2953,7 @@ async function pull(args) {
|
|
|
2841
2953
|
if (!type || type === "hooks") {
|
|
2842
2954
|
const localHooks = loadLocalHooks(platformDir, name || void 0, appName);
|
|
2843
2955
|
if (localHooks.length > 0) {
|
|
2844
|
-
const changes = await planHooks(api, localHooks, collections);
|
|
2956
|
+
const changes = await planHooks(api, localHooks, collections, projectId);
|
|
2845
2957
|
for (const c of changes) {
|
|
2846
2958
|
if (c.type === "update") conflicts.push(`hooks/${c.name}`);
|
|
2847
2959
|
}
|
|
@@ -3120,7 +3232,10 @@ async function diff(args) {
|
|
|
3120
3232
|
}
|
|
3121
3233
|
} else if (type === "automations") {
|
|
3122
3234
|
const localAutomations = loadLocalAutomations(platformDir, name, appName);
|
|
3123
|
-
const remoteAutomations = await api.listAutomations({
|
|
3235
|
+
const remoteAutomations = await api.listAutomations({
|
|
3236
|
+
include_code: true,
|
|
3237
|
+
...projectId ? { project_id: projectId } : {}
|
|
3238
|
+
});
|
|
3124
3239
|
const local = localAutomations[0];
|
|
3125
3240
|
const localExtId = local?.automation.external_id;
|
|
3126
3241
|
const remote = remoteAutomations.find(
|
|
@@ -3150,7 +3265,7 @@ async function diff(args) {
|
|
|
3150
3265
|
}
|
|
3151
3266
|
} else if (type === "hooks") {
|
|
3152
3267
|
const localHooks = loadLocalHooks(platformDir, name, appName);
|
|
3153
|
-
const remoteHooks = await api.listHooks();
|
|
3268
|
+
const remoteHooks = await api.listHooks(projectId ? { project_id: projectId } : void 0);
|
|
3154
3269
|
const local = localHooks[0];
|
|
3155
3270
|
const localExtId = local?.hook.external_id;
|
|
3156
3271
|
const remote = remoteHooks.find(
|
package/package.json
CHANGED
|
@@ -49,11 +49,11 @@ For detailed technical reference (data models, relationships, design decisions),
|
|
|
49
49
|
|
|
50
50
|
### Installing components
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
Install shadcn components with `pnpm dlx` (the sandbox's default JS package manager):
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
pnpm dlx shadcn@latest add button card dialog # Install specific components
|
|
56
|
+
pnpm dlx shadcn@latest add table input label select # Install more as needed
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Components install into `src/components/ui/` and are fully editable.
|