@lumerahq/cli 0.18.2 → 0.18.3
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-XTRDJLIA.js → chunk-2I2VXPJK.js} +20 -38
- package/dist/{chunk-ILO2IR2G.js → chunk-G7427W43.js} +10 -3
- package/dist/chunk-YIQRLXEN.js +120 -0
- package/dist/deps-K54NOIZY.js +12 -0
- package/dist/{dev-RNV6CJQI.js → dev-62JXNDN3.js} +2 -2
- package/dist/index.js +16 -11
- package/dist/{init-YUZQ54HZ.js → init-ZDOPG3KN.js} +5 -5
- package/dist/{register-MLXJNMNR.js → register-COESODY2.js} +1 -1
- package/dist/{resources-6SJR45CY.js → resources-IJ2VFUG5.js} +64 -27
- package/dist/{run-2VKKOCHR.js → run-6ULEFGHJ.js} +8 -5
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// src/lib/deploy.ts
|
|
2
2
|
import { execSync, spawn } from "child_process";
|
|
3
|
+
import { createConnection } from "net";
|
|
3
4
|
import { existsSync, readFileSync } from "fs";
|
|
4
5
|
import { resolve, dirname } from "path";
|
|
5
6
|
import archiver from "archiver";
|
|
@@ -106,35 +107,22 @@ async function deploy(options) {
|
|
|
106
107
|
Deployed! ${result.url}`));
|
|
107
108
|
return { url: result.url, version };
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
appData.name = appTitle;
|
|
125
|
-
}
|
|
126
|
-
const endpoint = existing ? `${apiBase}/pb/collections/lm_custom_apps/records/${existing.id}` : `${apiBase}/pb/collections/lm_custom_apps/records`;
|
|
127
|
-
const res = await fetch(endpoint, {
|
|
128
|
-
method: existing ? "PATCH" : "POST",
|
|
129
|
-
headers: {
|
|
130
|
-
Authorization: `Bearer ${token}`,
|
|
131
|
-
"Content-Type": "application/json"
|
|
132
|
-
},
|
|
133
|
-
body: JSON.stringify(appData)
|
|
110
|
+
function isPortInUse(port, host = "127.0.0.1") {
|
|
111
|
+
return new Promise((resolve2) => {
|
|
112
|
+
const socket = createConnection({ port, host });
|
|
113
|
+
socket.once("connect", () => {
|
|
114
|
+
socket.destroy();
|
|
115
|
+
resolve2(true);
|
|
116
|
+
});
|
|
117
|
+
socket.once("error", () => {
|
|
118
|
+
socket.destroy();
|
|
119
|
+
resolve2(false);
|
|
120
|
+
});
|
|
121
|
+
socket.setTimeout(1e3, () => {
|
|
122
|
+
socket.destroy();
|
|
123
|
+
resolve2(false);
|
|
124
|
+
});
|
|
134
125
|
});
|
|
135
|
-
if (!res.ok) {
|
|
136
|
-
throw new Error(`Failed to register app: ${await res.text()}`);
|
|
137
|
-
}
|
|
138
126
|
}
|
|
139
127
|
function detectRunner(projectRoot) {
|
|
140
128
|
if (existsSync(resolve(projectRoot, "bun.lockb")) || existsSync(resolve(projectRoot, "bun.lock"))) {
|
|
@@ -161,6 +149,10 @@ async function dev(options) {
|
|
|
161
149
|
apiUrl
|
|
162
150
|
} = options;
|
|
163
151
|
const projectRoot = process.cwd();
|
|
152
|
+
if (await isPortInUse(port)) {
|
|
153
|
+
console.log(pc.yellow(` Dev server already running on port ${port}, skipping start.`));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
164
156
|
console.log();
|
|
165
157
|
console.log(pc.cyan(pc.bold(` ${appTitle} - Dev Server`)));
|
|
166
158
|
console.log();
|
|
@@ -169,16 +161,6 @@ async function dev(options) {
|
|
|
169
161
|
if (host) console.log(pc.dim(` Host: ${host}`));
|
|
170
162
|
console.log(pc.dim(` URL: ${appUrl}`));
|
|
171
163
|
console.log();
|
|
172
|
-
console.log(pc.dim(" Registering app with Lumera..."));
|
|
173
|
-
try {
|
|
174
|
-
await registerDevApp(apiUrl, token, appName, appTitle, appUrl);
|
|
175
|
-
console.log(pc.green(" \u2713 App registered"));
|
|
176
|
-
} catch (err) {
|
|
177
|
-
console.log(pc.yellow(" \u26A0 Failed to register app (continuing anyway)"));
|
|
178
|
-
if (err instanceof Error) {
|
|
179
|
-
console.log(pc.dim(` ${err.message}`));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
164
|
console.log();
|
|
183
165
|
console.log(pc.green(" Starting dev server..."));
|
|
184
166
|
console.log();
|
|
@@ -24,8 +24,10 @@ var CLI_USER_AGENT = `lumera-cli/${pkg.version}`;
|
|
|
24
24
|
var ApiClient = class {
|
|
25
25
|
baseUrl;
|
|
26
26
|
token;
|
|
27
|
-
|
|
27
|
+
projectExternalId;
|
|
28
|
+
constructor(token, baseUrl, projectExternalId) {
|
|
28
29
|
this.token = token || getToken();
|
|
30
|
+
this.projectExternalId = projectExternalId;
|
|
29
31
|
let base = baseUrl || process.env.LUMERA_BASE_URL || "https://app.lumerahq.com";
|
|
30
32
|
base = base.replace(/\/$/, "");
|
|
31
33
|
if (base.endsWith("/api")) {
|
|
@@ -39,6 +41,7 @@ var ApiClient = class {
|
|
|
39
41
|
"Content-Type": "application/json",
|
|
40
42
|
Authorization: `Bearer ${this.token}`,
|
|
41
43
|
"User-Agent": CLI_USER_AGENT,
|
|
44
|
+
...this.projectExternalId ? { "X-Lumera-Project": this.projectExternalId } : {},
|
|
42
45
|
...options.headers
|
|
43
46
|
};
|
|
44
47
|
const response = await fetch(url, {
|
|
@@ -251,9 +254,13 @@ var ApiClient = class {
|
|
|
251
254
|
updated: rec.updated
|
|
252
255
|
};
|
|
253
256
|
}
|
|
257
|
+
// Project manifest — list public collections for a project
|
|
258
|
+
async getProjectManifest(externalId) {
|
|
259
|
+
return this.request(`/api/pb/projects/${encodeURIComponent(externalId)}/manifest`);
|
|
260
|
+
}
|
|
254
261
|
};
|
|
255
|
-
function createApiClient(token, baseUrl) {
|
|
256
|
-
return new ApiClient(token, baseUrl);
|
|
262
|
+
function createApiClient(token, baseUrl, projectExternalId) {
|
|
263
|
+
return new ApiClient(token, baseUrl, projectExternalId);
|
|
257
264
|
}
|
|
258
265
|
|
|
259
266
|
export {
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadEnv
|
|
3
|
+
} from "./chunk-2CR762KB.js";
|
|
4
|
+
import {
|
|
5
|
+
createApiClient
|
|
6
|
+
} from "./chunk-G7427W43.js";
|
|
7
|
+
import {
|
|
8
|
+
findProjectRoot,
|
|
9
|
+
getAppName
|
|
10
|
+
} from "./chunk-ZH3NVYEQ.js";
|
|
11
|
+
|
|
12
|
+
// src/commands/deps.ts
|
|
13
|
+
import pc from "picocolors";
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
var DEPS_FILE = "platform/project_deps.json";
|
|
17
|
+
function loadDeps(projectRoot) {
|
|
18
|
+
const depsPath = join(projectRoot, DEPS_FILE);
|
|
19
|
+
if (!existsSync(depsPath)) return null;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(readFileSync(depsPath, "utf-8"));
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function syncDeps(projectRoot) {
|
|
27
|
+
const root = projectRoot ?? findProjectRoot();
|
|
28
|
+
loadEnv(root);
|
|
29
|
+
const deps2 = loadDeps(root);
|
|
30
|
+
if (!deps2 || !deps2.dependencies || Object.keys(deps2.dependencies).length === 0) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
const appName = getAppName(root);
|
|
34
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
35
|
+
let allOk = true;
|
|
36
|
+
for (const [depProject, config] of Object.entries(deps2.dependencies)) {
|
|
37
|
+
try {
|
|
38
|
+
const manifest = await api.getProjectManifest(depProject);
|
|
39
|
+
const remoteNames = new Set(manifest.collections.map((c) => c.name));
|
|
40
|
+
for (const col of config.collections) {
|
|
41
|
+
if (remoteNames.has(col)) {
|
|
42
|
+
console.log(pc.green(" \u2713"), `${depProject}/${col}`);
|
|
43
|
+
} else {
|
|
44
|
+
console.log(pc.red(" \u2717"), `${depProject}/${col} \u2014 not found in project manifest`);
|
|
45
|
+
allOk = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {
|
|
49
|
+
console.log(pc.red(" \u2717"), `${depProject}: failed to fetch manifest \u2014 ${e}`);
|
|
50
|
+
allOk = false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return allOk;
|
|
54
|
+
}
|
|
55
|
+
async function deps(args) {
|
|
56
|
+
const sub = args[0];
|
|
57
|
+
const projectRoot = findProjectRoot();
|
|
58
|
+
loadEnv(projectRoot);
|
|
59
|
+
if (sub === "sync") {
|
|
60
|
+
console.log();
|
|
61
|
+
console.log(pc.cyan(pc.bold(" Deps Sync")));
|
|
62
|
+
console.log(pc.dim(" Verifying cross-project dependencies..."));
|
|
63
|
+
console.log();
|
|
64
|
+
const ok = await syncDeps(projectRoot);
|
|
65
|
+
if (!ok) {
|
|
66
|
+
console.log();
|
|
67
|
+
console.log(pc.red(" Some dependencies could not be resolved."));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
console.log();
|
|
71
|
+
console.log(pc.green(" All dependencies verified."));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (sub === "list") {
|
|
75
|
+
const depsData = loadDeps(projectRoot);
|
|
76
|
+
if (!depsData || Object.keys(depsData.dependencies).length === 0) {
|
|
77
|
+
console.log(pc.dim(" No dependencies declared in platform/project_deps.json"));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
console.log();
|
|
81
|
+
console.log(pc.cyan(pc.bold(" Project Dependencies")));
|
|
82
|
+
console.log();
|
|
83
|
+
for (const [depProject, config] of Object.entries(depsData.dependencies)) {
|
|
84
|
+
console.log(` ${pc.bold(depProject)}`);
|
|
85
|
+
for (const col of config.collections) {
|
|
86
|
+
console.log(` \u2022 ${col}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
console.log();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (sub === "init") {
|
|
93
|
+
const depsPath = join(projectRoot, DEPS_FILE);
|
|
94
|
+
if (existsSync(depsPath)) {
|
|
95
|
+
console.log(pc.yellow(" platform/project_deps.json already exists."));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const platformDir = join(projectRoot, "platform");
|
|
99
|
+
mkdirSync(platformDir, { recursive: true });
|
|
100
|
+
const initial = { dependencies: {} };
|
|
101
|
+
writeFileSync(depsPath, JSON.stringify(initial, null, 2) + "\n");
|
|
102
|
+
console.log(pc.green(" \u2713"), "Created platform/project_deps.json");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
console.log(`
|
|
106
|
+
${pc.bold("lumera deps")} \u2014 manage cross-project dependencies
|
|
107
|
+
|
|
108
|
+
${pc.bold("Commands:")}
|
|
109
|
+
sync Fetch manifests and verify declared dependencies exist
|
|
110
|
+
list Show declared dependencies
|
|
111
|
+
init Create an empty platform/project_deps.json
|
|
112
|
+
|
|
113
|
+
${pc.bold("Dependency file:")} platform/project_deps.json
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export {
|
|
118
|
+
syncDeps,
|
|
119
|
+
deps
|
|
120
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dev
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2I2VXPJK.js";
|
|
4
4
|
import {
|
|
5
5
|
loadEnv
|
|
6
6
|
} from "./chunk-2CR762KB.js";
|
|
7
7
|
import {
|
|
8
8
|
createApiClient
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-G7427W43.js";
|
|
10
10
|
import {
|
|
11
11
|
findProjectRoot,
|
|
12
12
|
getApiUrl,
|
package/dist/index.js
CHANGED
|
@@ -91,6 +91,7 @@ var COMMANDS = [
|
|
|
91
91
|
"status",
|
|
92
92
|
"migrate",
|
|
93
93
|
"skills",
|
|
94
|
+
"deps",
|
|
94
95
|
"login",
|
|
95
96
|
"logout",
|
|
96
97
|
"whoami"
|
|
@@ -215,39 +216,39 @@ async function main() {
|
|
|
215
216
|
switch (command) {
|
|
216
217
|
// Resource commands
|
|
217
218
|
case "plan":
|
|
218
|
-
await import("./resources-
|
|
219
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.plan(args.slice(1)));
|
|
219
220
|
break;
|
|
220
221
|
case "apply":
|
|
221
|
-
await import("./resources-
|
|
222
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.apply(args.slice(1)));
|
|
222
223
|
break;
|
|
223
224
|
case "pull":
|
|
224
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.pull(args.slice(1)));
|
|
225
226
|
break;
|
|
226
227
|
case "destroy":
|
|
227
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.destroy(args.slice(1)));
|
|
228
229
|
break;
|
|
229
230
|
case "list":
|
|
230
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.list(args.slice(1)));
|
|
231
232
|
break;
|
|
232
233
|
case "show":
|
|
233
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.show(args.slice(1)));
|
|
234
235
|
break;
|
|
235
236
|
case "diff":
|
|
236
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-IJ2VFUG5.js").then((m) => m.diff(args.slice(1)));
|
|
237
238
|
break;
|
|
238
239
|
// Development
|
|
239
240
|
case "dev":
|
|
240
|
-
await import("./dev-
|
|
241
|
+
await import("./dev-62JXNDN3.js").then((m) => m.dev(args.slice(1)));
|
|
241
242
|
break;
|
|
242
243
|
case "run":
|
|
243
|
-
await import("./run-
|
|
244
|
+
await import("./run-6ULEFGHJ.js").then((m) => m.run(args.slice(1)));
|
|
244
245
|
break;
|
|
245
246
|
// Project
|
|
246
247
|
case "init":
|
|
247
|
-
await import("./init-
|
|
248
|
+
await import("./init-ZDOPG3KN.js").then((m) => m.init(args.slice(1)));
|
|
248
249
|
break;
|
|
249
250
|
case "register":
|
|
250
|
-
await import("./register-
|
|
251
|
+
await import("./register-COESODY2.js").then((m) => m.register(args.slice(1)));
|
|
251
252
|
break;
|
|
252
253
|
case "templates":
|
|
253
254
|
await import("./templates-ESFQ4QO4.js").then((m) => m.templates(subcommand, args.slice(2)));
|
|
@@ -262,6 +263,10 @@ async function main() {
|
|
|
262
263
|
case "skills":
|
|
263
264
|
await import("./skills-VY42VAXX.js").then((m) => m.skills(subcommand, args.slice(2)));
|
|
264
265
|
break;
|
|
266
|
+
// Dependencies
|
|
267
|
+
case "deps":
|
|
268
|
+
await import("./deps-K54NOIZY.js").then((m) => m.deps(args.slice(1)));
|
|
269
|
+
break;
|
|
265
270
|
// Auth
|
|
266
271
|
case "login":
|
|
267
272
|
await import("./auth-KFXSNCJB.js").then((m) => m.login(args.slice(1)));
|
|
@@ -7,16 +7,16 @@ import {
|
|
|
7
7
|
} from "./chunk-BHYDYR75.js";
|
|
8
8
|
import {
|
|
9
9
|
createApiClient
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import {
|
|
12
|
-
listAllTemplates,
|
|
13
|
-
resolveTemplate
|
|
14
|
-
} from "./chunk-CHRKCAIZ.js";
|
|
10
|
+
} from "./chunk-G7427W43.js";
|
|
15
11
|
import {
|
|
16
12
|
getToken,
|
|
17
13
|
init_auth,
|
|
18
14
|
setProjectId
|
|
19
15
|
} from "./chunk-ZH3NVYEQ.js";
|
|
16
|
+
import {
|
|
17
|
+
listAllTemplates,
|
|
18
|
+
resolveTemplate
|
|
19
|
+
} from "./chunk-CHRKCAIZ.js";
|
|
20
20
|
import "./chunk-PNKVD2UK.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/init.ts
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
syncDeps
|
|
3
|
+
} from "./chunk-YIQRLXEN.js";
|
|
1
4
|
import {
|
|
2
5
|
deploy
|
|
3
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2I2VXPJK.js";
|
|
4
7
|
import {
|
|
5
8
|
loadEnv
|
|
6
9
|
} from "./chunk-2CR762KB.js";
|
|
7
10
|
import {
|
|
8
11
|
createApiClient
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-G7427W43.js";
|
|
10
13
|
import {
|
|
11
14
|
findProjectRoot,
|
|
12
15
|
getApiUrl,
|
|
@@ -35,6 +38,18 @@ function detectPackageManager() {
|
|
|
35
38
|
}
|
|
36
39
|
return "npm";
|
|
37
40
|
}
|
|
41
|
+
var NAMESPACE_SEPARATOR = "__";
|
|
42
|
+
function sanitizeSlugForCollectionName(slug) {
|
|
43
|
+
return slug.replace(/-/g, "_");
|
|
44
|
+
}
|
|
45
|
+
function stripNamespacePrefix(name, appName) {
|
|
46
|
+
if (!appName) return name;
|
|
47
|
+
const prefix = sanitizeSlugForCollectionName(appName) + NAMESPACE_SEPARATOR;
|
|
48
|
+
if (name.startsWith(prefix)) {
|
|
49
|
+
return name.slice(prefix.length);
|
|
50
|
+
}
|
|
51
|
+
return name;
|
|
52
|
+
}
|
|
38
53
|
function computeLineDiff(oldText, newText) {
|
|
39
54
|
const oldLines = (oldText || "").trimEnd().split("\n");
|
|
40
55
|
const newLines = (newText || "").trimEnd().split("\n");
|
|
@@ -950,7 +965,7 @@ async function applyCollections(api, localCollections) {
|
|
|
950
965
|
}
|
|
951
966
|
return errors;
|
|
952
967
|
}
|
|
953
|
-
async function applyAutomations(api, localAutomations) {
|
|
968
|
+
async function applyAutomations(api, localAutomations, projectId) {
|
|
954
969
|
let errors = 0;
|
|
955
970
|
const remoteAutomations = await api.listAutomations();
|
|
956
971
|
const remoteByExternalId = new Map(remoteAutomations.filter((a) => a.external_id).map((a) => [a.external_id, a]));
|
|
@@ -962,6 +977,9 @@ async function applyAutomations(api, localAutomations) {
|
|
|
962
977
|
description: automation.description,
|
|
963
978
|
code
|
|
964
979
|
};
|
|
980
|
+
if (projectId) {
|
|
981
|
+
payload.project_id = projectId;
|
|
982
|
+
}
|
|
965
983
|
if (automation.inputs?.schema) {
|
|
966
984
|
payload.input_schema = automation.inputs.schema;
|
|
967
985
|
}
|
|
@@ -1059,7 +1077,7 @@ async function setSchedule(api, automationId, schedule, localPresets) {
|
|
|
1059
1077
|
console.log(pc.yellow(` \u26A0 Failed to set schedule: ${e}`));
|
|
1060
1078
|
}
|
|
1061
1079
|
}
|
|
1062
|
-
async function applyHooks(api, localHooks, collections) {
|
|
1080
|
+
async function applyHooks(api, localHooks, collections, projectId) {
|
|
1063
1081
|
let errors = 0;
|
|
1064
1082
|
const remoteHooks = await api.listHooks();
|
|
1065
1083
|
const remoteByExternalId = new Map(remoteHooks.filter((h) => h.external_id).map((h) => [h.external_id, h]));
|
|
@@ -1080,6 +1098,9 @@ async function applyHooks(api, localHooks, collections) {
|
|
|
1080
1098
|
enabled: hook.enabled !== false,
|
|
1081
1099
|
metadata: hook.metadata
|
|
1082
1100
|
};
|
|
1101
|
+
if (projectId) {
|
|
1102
|
+
payload.project_id = projectId;
|
|
1103
|
+
}
|
|
1083
1104
|
try {
|
|
1084
1105
|
if (remote) {
|
|
1085
1106
|
await api.updateHook(remote.id, payload);
|
|
@@ -1115,18 +1136,23 @@ async function applyApp(args) {
|
|
|
1115
1136
|
const distDir = resolve(projectRoot, "dist");
|
|
1116
1137
|
await deploy({ token, appName, appTitle, distDir, apiUrl });
|
|
1117
1138
|
}
|
|
1118
|
-
async function pullCollections(api, platformDir, filterName) {
|
|
1139
|
+
async function pullCollections(api, platformDir, filterName, appName) {
|
|
1119
1140
|
const collectionsDir = join(platformDir, "collections");
|
|
1120
1141
|
mkdirSync(collectionsDir, { recursive: true });
|
|
1121
1142
|
const collections = await api.listCollections();
|
|
1122
1143
|
for (const collection of collections) {
|
|
1123
1144
|
if (collection.system || collection.managed) continue;
|
|
1124
|
-
if (
|
|
1145
|
+
if (appName && collection.name.includes(NAMESPACE_SEPARATOR)) {
|
|
1146
|
+
const prefix = collection.name.split(NAMESPACE_SEPARATOR)[0];
|
|
1147
|
+
if (prefix !== sanitizeSlugForCollectionName(appName)) continue;
|
|
1148
|
+
}
|
|
1149
|
+
const localName = stripNamespacePrefix(collection.name, appName);
|
|
1150
|
+
if (filterName && localName !== filterName && collection.name !== filterName && collection.id !== filterName) {
|
|
1125
1151
|
continue;
|
|
1126
1152
|
}
|
|
1127
1153
|
const localFormat = {
|
|
1128
1154
|
id: collection.id,
|
|
1129
|
-
name:
|
|
1155
|
+
name: localName,
|
|
1130
1156
|
fields: collection.schema.map((field) => {
|
|
1131
1157
|
const localField = {
|
|
1132
1158
|
name: field.name,
|
|
@@ -1148,18 +1174,20 @@ async function pullCollections(api, platformDir, filterName) {
|
|
|
1148
1174
|
return null;
|
|
1149
1175
|
}).filter((idx) => idx !== null)
|
|
1150
1176
|
};
|
|
1151
|
-
const fileName = toSafeFilename(
|
|
1177
|
+
const fileName = toSafeFilename(localName);
|
|
1152
1178
|
const filePath = join(collectionsDir, `${fileName}.json`);
|
|
1153
1179
|
writeFileSync(filePath, JSON.stringify(localFormat, null, 2) + "\n");
|
|
1154
|
-
console.log(pc.green(" \u2713"), `${
|
|
1180
|
+
console.log(pc.green(" \u2713"), `${localName} \u2192 collections/${fileName}.json`);
|
|
1155
1181
|
}
|
|
1156
1182
|
}
|
|
1157
|
-
async function pullAutomations(api, platformDir, filterName) {
|
|
1183
|
+
async function pullAutomations(api, platformDir, filterName, projectId) {
|
|
1158
1184
|
const automationsDir = join(platformDir, "automations");
|
|
1159
1185
|
mkdirSync(automationsDir, { recursive: true });
|
|
1160
1186
|
const automations = await api.listAutomations({ include_code: true });
|
|
1161
1187
|
for (const automation of automations) {
|
|
1162
1188
|
if (!automation.external_id || automation.managed) continue;
|
|
1189
|
+
if (projectId && automation.project_id && automation.project_id !== projectId) continue;
|
|
1190
|
+
if (!projectId && automation.project_id) continue;
|
|
1163
1191
|
if (filterName && automation.external_id !== filterName && automation.name !== filterName) {
|
|
1164
1192
|
continue;
|
|
1165
1193
|
}
|
|
@@ -1202,19 +1230,21 @@ async function pullAutomations(api, platformDir, filterName) {
|
|
|
1202
1230
|
console.log(pc.green(" \u2713"), `${automation.name} \u2192 automations/${dirName}/`);
|
|
1203
1231
|
}
|
|
1204
1232
|
}
|
|
1205
|
-
async function pullHooks(api, platformDir, filterName) {
|
|
1233
|
+
async function pullHooks(api, platformDir, filterName, appName, projectId) {
|
|
1206
1234
|
const hooksDir = join(platformDir, "hooks");
|
|
1207
1235
|
mkdirSync(hooksDir, { recursive: true });
|
|
1208
1236
|
const hooks = await api.listHooks();
|
|
1209
1237
|
for (const hook of hooks) {
|
|
1210
1238
|
if (!hook.external_id) continue;
|
|
1239
|
+
if (projectId && hook.project_id && hook.project_id !== projectId) continue;
|
|
1240
|
+
if (!projectId && hook.project_id) continue;
|
|
1211
1241
|
if (filterName && hook.external_id !== filterName) {
|
|
1212
1242
|
continue;
|
|
1213
1243
|
}
|
|
1214
1244
|
const fileName = `${hook.external_id.replace(/[^a-zA-Z0-9_-]/g, "_")}.js`;
|
|
1215
1245
|
const content = `export const config = {
|
|
1216
1246
|
external_id: '${hook.external_id}',
|
|
1217
|
-
collection: '${hook.collection_name}',
|
|
1247
|
+
collection: '${stripNamespacePrefix(hook.collection_name, appName)}',
|
|
1218
1248
|
trigger: '${hook.event}',
|
|
1219
1249
|
enabled: ${hook.enabled},
|
|
1220
1250
|
};
|
|
@@ -1433,7 +1463,7 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
|
|
|
1433
1463
|
if (!filterType || filterType === "collections") {
|
|
1434
1464
|
const localCollections = loadLocalCollections(platformDir);
|
|
1435
1465
|
const remoteCollections = await api.listCollections();
|
|
1436
|
-
const remoteByName = new Map(remoteCollections.filter((c) => !c.system && !c.managed).map((c) => [c.name, c]));
|
|
1466
|
+
const remoteByName = new Map(remoteCollections.filter((c) => !c.system && !c.managed).map((c) => [stripNamespacePrefix(c.name, appName), c]));
|
|
1437
1467
|
const localNames = new Set(localCollections.map((c) => c.name));
|
|
1438
1468
|
for (const local of localCollections) {
|
|
1439
1469
|
const remote = remoteByName.get(local.name);
|
|
@@ -1456,8 +1486,13 @@ async function listResources(api, platformDir, filterType, appName, projectId) {
|
|
|
1456
1486
|
}
|
|
1457
1487
|
for (const remote of remoteCollections) {
|
|
1458
1488
|
if (remote.system || remote.managed) continue;
|
|
1459
|
-
if (
|
|
1460
|
-
|
|
1489
|
+
if (appName && remote.name.includes(NAMESPACE_SEPARATOR)) {
|
|
1490
|
+
const prefix = remote.name.split(NAMESPACE_SEPARATOR)[0];
|
|
1491
|
+
if (prefix !== sanitizeSlugForCollectionName(appName)) continue;
|
|
1492
|
+
}
|
|
1493
|
+
const stripped = stripNamespacePrefix(remote.name, appName);
|
|
1494
|
+
if (!localNames.has(stripped)) {
|
|
1495
|
+
results.push({ name: stripped, type: "collections", status: "remote-only" });
|
|
1461
1496
|
}
|
|
1462
1497
|
}
|
|
1463
1498
|
}
|
|
@@ -1981,8 +2016,8 @@ async function plan(args) {
|
|
|
1981
2016
|
const projectRoot = findProjectRoot();
|
|
1982
2017
|
loadEnv(projectRoot);
|
|
1983
2018
|
const platformDir = getPlatformDir();
|
|
1984
|
-
const api = createApiClient();
|
|
1985
2019
|
const appName = getAppName(projectRoot);
|
|
2020
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
1986
2021
|
const projectId = getProjectId(projectRoot);
|
|
1987
2022
|
const positionalArgs = args.filter((a) => !a.startsWith("-"));
|
|
1988
2023
|
const { type, name } = parseResource(positionalArgs[0]);
|
|
@@ -1990,6 +2025,7 @@ async function plan(args) {
|
|
|
1990
2025
|
console.log(pc.cyan(pc.bold(" Plan")));
|
|
1991
2026
|
console.log(pc.dim(" Comparing local files to remote state..."));
|
|
1992
2027
|
console.log();
|
|
2028
|
+
await syncDeps(projectRoot);
|
|
1993
2029
|
const allChanges = [];
|
|
1994
2030
|
let collections;
|
|
1995
2031
|
try {
|
|
@@ -2079,8 +2115,8 @@ async function apply(args) {
|
|
|
2079
2115
|
const projectRoot = findProjectRoot();
|
|
2080
2116
|
loadEnv(projectRoot);
|
|
2081
2117
|
const platformDir = getPlatformDir();
|
|
2082
|
-
const api = createApiClient();
|
|
2083
2118
|
const appName = getAppName(projectRoot);
|
|
2119
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2084
2120
|
const projectId = getProjectId(projectRoot);
|
|
2085
2121
|
const positionalArgs = args.filter((a) => !a.startsWith("-"));
|
|
2086
2122
|
const { type, name } = parseResource(positionalArgs[0]);
|
|
@@ -2096,6 +2132,7 @@ async function apply(args) {
|
|
|
2096
2132
|
console.log();
|
|
2097
2133
|
return;
|
|
2098
2134
|
}
|
|
2135
|
+
await syncDeps(projectRoot);
|
|
2099
2136
|
let collections;
|
|
2100
2137
|
try {
|
|
2101
2138
|
const remoteCollections = await api.listCollections();
|
|
@@ -2192,12 +2229,12 @@ async function apply(args) {
|
|
|
2192
2229
|
}
|
|
2193
2230
|
if (localAutomations.length > 0) {
|
|
2194
2231
|
console.log(pc.bold(" Automations:"));
|
|
2195
|
-
totalErrors += await applyAutomations(api, localAutomations);
|
|
2232
|
+
totalErrors += await applyAutomations(api, localAutomations, projectId);
|
|
2196
2233
|
console.log();
|
|
2197
2234
|
}
|
|
2198
2235
|
if (localHooks.length > 0) {
|
|
2199
2236
|
console.log(pc.bold(" Hooks:"));
|
|
2200
|
-
totalErrors += await applyHooks(api, localHooks, collections);
|
|
2237
|
+
totalErrors += await applyHooks(api, localHooks, collections, projectId);
|
|
2201
2238
|
console.log();
|
|
2202
2239
|
}
|
|
2203
2240
|
if (localAgents.length > 0) {
|
|
@@ -2234,8 +2271,8 @@ async function pull(args) {
|
|
|
2234
2271
|
const projectRoot = findProjectRoot();
|
|
2235
2272
|
loadEnv(projectRoot);
|
|
2236
2273
|
const platformDir = getPlatformDir();
|
|
2237
|
-
const api = createApiClient();
|
|
2238
2274
|
const appName = getAppName(projectRoot);
|
|
2275
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2239
2276
|
const projectId = getProjectId(projectRoot);
|
|
2240
2277
|
const { type, name } = parseResource(filteredArgs[0]);
|
|
2241
2278
|
if (!force) {
|
|
@@ -2293,17 +2330,17 @@ async function pull(args) {
|
|
|
2293
2330
|
console.log();
|
|
2294
2331
|
if (!type || type === "collections") {
|
|
2295
2332
|
console.log(pc.bold(" Collections:"));
|
|
2296
|
-
await pullCollections(api, platformDir, name || void 0);
|
|
2333
|
+
await pullCollections(api, platformDir, name || void 0, appName);
|
|
2297
2334
|
console.log();
|
|
2298
2335
|
}
|
|
2299
2336
|
if (!type || type === "automations") {
|
|
2300
2337
|
console.log(pc.bold(" Automations:"));
|
|
2301
|
-
await pullAutomations(api, platformDir, name || void 0);
|
|
2338
|
+
await pullAutomations(api, platformDir, name || void 0, projectId);
|
|
2302
2339
|
console.log();
|
|
2303
2340
|
}
|
|
2304
2341
|
if (!type || type === "hooks") {
|
|
2305
2342
|
console.log(pc.bold(" Hooks:"));
|
|
2306
|
-
await pullHooks(api, platformDir, name || void 0);
|
|
2343
|
+
await pullHooks(api, platformDir, name || void 0, appName, projectId);
|
|
2307
2344
|
console.log();
|
|
2308
2345
|
}
|
|
2309
2346
|
if (!type || type === "agents") {
|
|
@@ -2322,8 +2359,8 @@ async function destroy(args) {
|
|
|
2322
2359
|
const projectRoot = findProjectRoot();
|
|
2323
2360
|
loadEnv(projectRoot);
|
|
2324
2361
|
const platformDir = getPlatformDir();
|
|
2325
|
-
const api = createApiClient();
|
|
2326
2362
|
const appName = getAppName(projectRoot);
|
|
2363
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2327
2364
|
const projectId = getProjectId(projectRoot);
|
|
2328
2365
|
const { type, name } = parseResource(args[0]);
|
|
2329
2366
|
const skipConfirm = args.includes("--confirm");
|
|
@@ -2346,8 +2383,8 @@ async function list(args) {
|
|
|
2346
2383
|
const projectRoot = findProjectRoot();
|
|
2347
2384
|
loadEnv(projectRoot);
|
|
2348
2385
|
const platformDir = getPlatformDir();
|
|
2349
|
-
const api = createApiClient();
|
|
2350
2386
|
const appName = getAppName(projectRoot);
|
|
2387
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2351
2388
|
const projectId = getProjectId(projectRoot);
|
|
2352
2389
|
const showAll = args.includes("--all");
|
|
2353
2390
|
const positionalArgs = args.filter((a) => !a.startsWith("--"));
|
|
@@ -2427,8 +2464,8 @@ async function show(args) {
|
|
|
2427
2464
|
const projectRoot = findProjectRoot();
|
|
2428
2465
|
loadEnv(projectRoot);
|
|
2429
2466
|
const platformDir = getPlatformDir();
|
|
2430
|
-
const api = createApiClient();
|
|
2431
2467
|
const appName = getAppName(projectRoot);
|
|
2468
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2432
2469
|
const projectId = getProjectId(projectRoot);
|
|
2433
2470
|
const { type, name } = parseResource(args[0]);
|
|
2434
2471
|
if (!type) {
|
|
@@ -2487,8 +2524,8 @@ async function diff(args) {
|
|
|
2487
2524
|
const projectRoot = findProjectRoot();
|
|
2488
2525
|
loadEnv(projectRoot);
|
|
2489
2526
|
const platformDir = getPlatformDir();
|
|
2490
|
-
const api = createApiClient();
|
|
2491
2527
|
const appName = getAppName(projectRoot);
|
|
2528
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
2492
2529
|
const projectId = getProjectId(projectRoot);
|
|
2493
2530
|
const { type, name } = parseResource(args[0]);
|
|
2494
2531
|
if (!type || !name) {
|
|
@@ -3,10 +3,11 @@ import {
|
|
|
3
3
|
} from "./chunk-2CR762KB.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-G7427W43.js";
|
|
7
7
|
import {
|
|
8
8
|
findProjectRoot,
|
|
9
9
|
getApiUrl,
|
|
10
|
+
getAppName,
|
|
10
11
|
getToken,
|
|
11
12
|
init_auth
|
|
12
13
|
} from "./chunk-ZH3NVYEQ.js";
|
|
@@ -115,7 +116,8 @@ async function runScript(scriptPath, projectRoot) {
|
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
118
|
async function triggerAutomation(automationName, projectRoot, flags) {
|
|
118
|
-
const
|
|
119
|
+
const appName = getAppName(projectRoot);
|
|
120
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
119
121
|
const token = getToken(projectRoot);
|
|
120
122
|
let apiUrl = getApiUrl().replace(/\/+$/, "").replace(/\/api$/, "");
|
|
121
123
|
console.log();
|
|
@@ -235,13 +237,14 @@ async function runAutomationLocally(automationName, projectRoot, flags) {
|
|
|
235
237
|
process.on("SIGINT", () => uv.kill("SIGINT"));
|
|
236
238
|
process.on("SIGTERM", () => uv.kill("SIGTERM"));
|
|
237
239
|
}
|
|
238
|
-
async function invokeAgent(agentName, message, flags) {
|
|
240
|
+
async function invokeAgent(agentName, message, flags, projectRoot) {
|
|
239
241
|
if (!message) {
|
|
240
242
|
console.error(pc.red(" Message is required."));
|
|
241
243
|
console.error(pc.dim(' Usage: lumera run agents/<name> "Your message here"'));
|
|
242
244
|
process.exit(1);
|
|
243
245
|
}
|
|
244
|
-
const
|
|
246
|
+
const appName = projectRoot ? getAppName(projectRoot) : void 0;
|
|
247
|
+
const api = createApiClient(void 0, void 0, appName);
|
|
245
248
|
console.log();
|
|
246
249
|
console.log(pc.cyan(pc.bold(" Invoke Agent")));
|
|
247
250
|
console.log();
|
|
@@ -313,7 +316,7 @@ async function run(args) {
|
|
|
313
316
|
if (target.startsWith("agents/")) {
|
|
314
317
|
const agentName = target.replace("agents/", "");
|
|
315
318
|
const message = positionalArgs.join(" ") || void 0;
|
|
316
|
-
await invokeAgent(agentName, message, flags);
|
|
319
|
+
await invokeAgent(agentName, message, flags, projectRoot);
|
|
317
320
|
return;
|
|
318
321
|
}
|
|
319
322
|
await runScript(target, projectRoot);
|