@lumerahq/cli 0.19.14 → 0.19.16-dev.0
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-4WZMUFC7.js → chunk-TPQGGLSD.js} +1 -1
- package/dist/{chunk-VOIZWYZD.js → chunk-VM5YR3HF.js} +12 -3
- package/dist/{chunk-MDCAEFUH.js → chunk-WIX3DUD5.js} +7 -0
- package/dist/{deps-KVHWZARX.js → deps-ALKBN6UT.js} +2 -2
- package/dist/{dev-PONRO7VN.js → dev-33OLPWUK.js} +3 -3
- package/dist/index.js +12 -12
- package/dist/{init-KJOWD2KQ.js → init-EBNELAZA.js} +1 -1
- package/dist/{register-QBRKXWNX.js → register-EQ5KYVLV.js} +1 -1
- package/dist/{resources-UZ3TNZ4K.js → resources-EZQGSI5L.js} +72 -12
- package/dist/{run-R6MO23U7.js → run-BQPH6BIK.js} +1 -1
- package/package.json +1 -1
|
@@ -9,6 +9,12 @@ import { existsSync, readFileSync } from "fs";
|
|
|
9
9
|
import { resolve, dirname } from "path";
|
|
10
10
|
import archiver from "archiver";
|
|
11
11
|
import pc from "picocolors";
|
|
12
|
+
var USER_CONTEXT_ENV = "LUMERA_USER_ID";
|
|
13
|
+
var USER_CONTEXT_HEADER = "X-Lumera-User-Id";
|
|
14
|
+
function userContextHeaders() {
|
|
15
|
+
const userID = process.env[USER_CONTEXT_ENV]?.trim();
|
|
16
|
+
return userID ? { [USER_CONTEXT_HEADER]: userID } : {};
|
|
17
|
+
}
|
|
12
18
|
function formatTimestampVersion(date = /* @__PURE__ */ new Date()) {
|
|
13
19
|
const pad = (value) => String(value).padStart(2, "0");
|
|
14
20
|
return [
|
|
@@ -56,7 +62,8 @@ async function ensureAppRecord(apiBase, token, appName, appTitle) {
|
|
|
56
62
|
{
|
|
57
63
|
headers: {
|
|
58
64
|
Authorization: `Bearer ${token}`,
|
|
59
|
-
"X-Lumera-Client": "lumera-cli"
|
|
65
|
+
"X-Lumera-Client": "lumera-cli",
|
|
66
|
+
...userContextHeaders()
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
);
|
|
@@ -75,7 +82,8 @@ async function ensureAppRecord(apiBase, token, appName, appTitle) {
|
|
|
75
82
|
headers: {
|
|
76
83
|
Authorization: `Bearer ${token}`,
|
|
77
84
|
"Content-Type": "application/json",
|
|
78
|
-
"X-Lumera-Client": "lumera-cli"
|
|
85
|
+
"X-Lumera-Client": "lumera-cli",
|
|
86
|
+
...userContextHeaders()
|
|
79
87
|
},
|
|
80
88
|
body: JSON.stringify(appData)
|
|
81
89
|
});
|
|
@@ -108,7 +116,8 @@ async function deploy(options) {
|
|
|
108
116
|
method: "POST",
|
|
109
117
|
headers: {
|
|
110
118
|
Authorization: `Bearer ${token}`,
|
|
111
|
-
"X-Lumera-Client": "lumera-cli"
|
|
119
|
+
"X-Lumera-Client": "lumera-cli",
|
|
120
|
+
...userContextHeaders()
|
|
112
121
|
},
|
|
113
122
|
body: formData
|
|
114
123
|
});
|
|
@@ -25,6 +25,12 @@ while (__pkgDir !== "/") {
|
|
|
25
25
|
}
|
|
26
26
|
var pkg = JSON.parse(readFileSync(resolve(__pkgDir, "package.json"), "utf-8"));
|
|
27
27
|
var CLI_USER_AGENT = `lumera-cli/${pkg.version}`;
|
|
28
|
+
var USER_CONTEXT_ENV = "LUMERA_USER_ID";
|
|
29
|
+
var USER_CONTEXT_HEADER = "X-Lumera-User-Id";
|
|
30
|
+
function userContextHeaders() {
|
|
31
|
+
const userID = process.env[USER_CONTEXT_ENV]?.trim();
|
|
32
|
+
return userID ? { [USER_CONTEXT_HEADER]: userID } : {};
|
|
33
|
+
}
|
|
28
34
|
var ApiError = class extends Error {
|
|
29
35
|
status;
|
|
30
36
|
body;
|
|
@@ -67,6 +73,7 @@ var ApiClient = class {
|
|
|
67
73
|
"User-Agent": CLI_USER_AGENT,
|
|
68
74
|
"X-Lumera-Client": "lumera-cli",
|
|
69
75
|
...this.projectExternalId ? { "X-Lumera-Project": this.projectExternalId } : {},
|
|
76
|
+
...userContextHeaders(),
|
|
70
77
|
...options.headers
|
|
71
78
|
};
|
|
72
79
|
const method = (options.method || "GET").toUpperCase();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deps,
|
|
3
3
|
syncDeps
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TPQGGLSD.js";
|
|
5
5
|
import "./chunk-2CR762KB.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-WIX3DUD5.js";
|
|
7
7
|
import "./chunk-ZH3NVYEQ.js";
|
|
8
8
|
import "./chunk-FJFIWC7G.js";
|
|
9
9
|
import "./chunk-PNKVD2UK.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
dev
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VM5YR3HF.js";
|
|
4
4
|
import {
|
|
5
5
|
syncDeps
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TPQGGLSD.js";
|
|
7
7
|
import {
|
|
8
8
|
loadEnv
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
10
10
|
import {
|
|
11
11
|
createApiClient
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-WIX3DUD5.js";
|
|
13
13
|
import {
|
|
14
14
|
findProjectRoot,
|
|
15
15
|
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-EZQGSI5L.js").then((m) => m.plan(args.slice(1)));
|
|
223
223
|
break;
|
|
224
224
|
case "apply":
|
|
225
|
-
await import("./resources-
|
|
225
|
+
await import("./resources-EZQGSI5L.js").then((m) => m.apply(args.slice(1)));
|
|
226
226
|
break;
|
|
227
227
|
case "pull":
|
|
228
|
-
await import("./resources-
|
|
228
|
+
await import("./resources-EZQGSI5L.js").then((m) => m.pull(args.slice(1)));
|
|
229
229
|
break;
|
|
230
230
|
case "destroy":
|
|
231
|
-
await import("./resources-
|
|
231
|
+
await import("./resources-EZQGSI5L.js").then((m) => m.destroy(args.slice(1)));
|
|
232
232
|
break;
|
|
233
233
|
case "list":
|
|
234
|
-
await import("./resources-
|
|
234
|
+
await import("./resources-EZQGSI5L.js").then((m) => m.list(args.slice(1)));
|
|
235
235
|
break;
|
|
236
236
|
case "show":
|
|
237
|
-
await import("./resources-
|
|
237
|
+
await import("./resources-EZQGSI5L.js").then((m) => m.show(args.slice(1)));
|
|
238
238
|
break;
|
|
239
239
|
case "diff":
|
|
240
|
-
await import("./resources-
|
|
240
|
+
await import("./resources-EZQGSI5L.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-33OLPWUK.js").then((m) => m.dev(args.slice(1)));
|
|
245
245
|
break;
|
|
246
246
|
case "run":
|
|
247
|
-
await import("./run-
|
|
247
|
+
await import("./run-BQPH6BIK.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-EBNELAZA.js").then((m) => m.init(args.slice(1)));
|
|
252
252
|
break;
|
|
253
253
|
case "register":
|
|
254
|
-
await import("./register-
|
|
254
|
+
await import("./register-EQ5KYVLV.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-ALKBN6UT.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-VM5YR3HF.js";
|
|
4
4
|
import {
|
|
5
5
|
syncDeps
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TPQGGLSD.js";
|
|
7
7
|
import {
|
|
8
8
|
loadEnv
|
|
9
9
|
} from "./chunk-2CR762KB.js";
|
|
10
10
|
import {
|
|
11
11
|
ApiError,
|
|
12
12
|
createApiClient
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WIX3DUD5.js";
|
|
14
14
|
import {
|
|
15
15
|
findProjectRoot,
|
|
16
16
|
getApiUrl,
|
|
@@ -34,12 +34,67 @@ import { join as join2, resolve } from "path";
|
|
|
34
34
|
|
|
35
35
|
// src/lib/lint/index.ts
|
|
36
36
|
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
37
|
-
import { basename, join } from "path";
|
|
37
|
+
import { basename, dirname, join } from "path";
|
|
38
38
|
|
|
39
|
-
// src/lib/lint/rules/
|
|
39
|
+
// src/lib/lint/rules/automation-config.ts
|
|
40
40
|
function isRecord(value) {
|
|
41
41
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
42
42
|
}
|
|
43
|
+
function warn(target, message) {
|
|
44
|
+
return {
|
|
45
|
+
ruleId: "automation-config",
|
|
46
|
+
target,
|
|
47
|
+
severity: "warning",
|
|
48
|
+
message
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
var automationConfigRule = {
|
|
52
|
+
id: "automation-config",
|
|
53
|
+
description: "Validates that automation config.json input schema uses the function-wrapped format the Run UI expects.",
|
|
54
|
+
appliesTo: ["automation"],
|
|
55
|
+
check(target) {
|
|
56
|
+
const schema = target.config;
|
|
57
|
+
const at = typeof target.configFilePath === "string" ? { ...target, filePath: target.configFilePath } : target;
|
|
58
|
+
if (schema === void 0 || schema === null) return [];
|
|
59
|
+
if (!isRecord(schema)) {
|
|
60
|
+
return [warn(at, 'config.json "inputs.schema" must be a JSON object.')];
|
|
61
|
+
}
|
|
62
|
+
const issues = [];
|
|
63
|
+
if (schema.type !== "function") {
|
|
64
|
+
issues.push(
|
|
65
|
+
warn(
|
|
66
|
+
at,
|
|
67
|
+
'config.json "inputs.schema" is missing `"type": "function"`. Without it the Run-Automation UI shows "requires no inputs". Wrap it as { "type": "function", "function": { "name": "main", "parameters": { \u2026 } } }.'
|
|
68
|
+
)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const fn = schema.function;
|
|
72
|
+
if (!isRecord(fn)) {
|
|
73
|
+
issues.push(warn(at, 'config.json "inputs.schema.function" object is missing.'));
|
|
74
|
+
return issues;
|
|
75
|
+
}
|
|
76
|
+
if (typeof fn.name !== "string" || fn.name.trim() === "") {
|
|
77
|
+
issues.push(warn(at, 'config.json "inputs.schema.function.name" should be the entry-point function name (usually "main").'));
|
|
78
|
+
}
|
|
79
|
+
const params = fn.parameters;
|
|
80
|
+
if (!isRecord(params)) {
|
|
81
|
+
issues.push(warn(at, 'config.json "inputs.schema.function.parameters" object is missing.'));
|
|
82
|
+
} else {
|
|
83
|
+
if (params.type !== "object") {
|
|
84
|
+
issues.push(warn(at, 'config.json "inputs.schema.function.parameters.type" should be "object".'));
|
|
85
|
+
}
|
|
86
|
+
if (!isRecord(params.properties)) {
|
|
87
|
+
issues.push(warn(at, 'config.json "inputs.schema.function.parameters.properties" object is missing.'));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return issues;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// src/lib/lint/rules/collection-schema.ts
|
|
95
|
+
function isRecord2(value) {
|
|
96
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
97
|
+
}
|
|
43
98
|
function error(target, message, snippet) {
|
|
44
99
|
return {
|
|
45
100
|
ruleId: "collection-schema",
|
|
@@ -61,7 +116,7 @@ var collectionSchemaRule = {
|
|
|
61
116
|
const message = err instanceof Error ? err.message : String(err);
|
|
62
117
|
return [error(target, `Invalid JSON: ${message}`)];
|
|
63
118
|
}
|
|
64
|
-
if (!
|
|
119
|
+
if (!isRecord2(parsed)) {
|
|
65
120
|
return [error(target, "Collection file must contain a JSON object.")];
|
|
66
121
|
}
|
|
67
122
|
const issues = [];
|
|
@@ -83,11 +138,12 @@ var collectionSchemaRule = {
|
|
|
83
138
|
}
|
|
84
139
|
}
|
|
85
140
|
if (!Array.isArray(fields)) {
|
|
86
|
-
|
|
141
|
+
const hint = Array.isArray(parsed.schema) ? ' Use "fields" (not "schema") for the field array \u2014 the JSON file format differs from the pb.ensure_collection() SDK shape. Use [] when the collection has no fields.' : " It must be an array (use [] when the collection has no fields).";
|
|
142
|
+
issues.push(error(target, `Missing required array field "fields".${hint}`));
|
|
87
143
|
} else {
|
|
88
144
|
for (let i = 0; i < fields.length; i++) {
|
|
89
145
|
const field = fields[i];
|
|
90
|
-
if (!
|
|
146
|
+
if (!isRecord2(field)) {
|
|
91
147
|
issues.push(error(target, `Field at index ${i} must be an object.`));
|
|
92
148
|
continue;
|
|
93
149
|
}
|
|
@@ -105,8 +161,9 @@ var collectionSchemaRule = {
|
|
|
105
161
|
} else {
|
|
106
162
|
for (let i = 0; i < indexes.length; i++) {
|
|
107
163
|
const index = indexes[i];
|
|
108
|
-
if (!
|
|
109
|
-
|
|
164
|
+
if (!isRecord2(index)) {
|
|
165
|
+
const hint = typeof index === "string" ? ' Indexes are objects like { "fields": ["title"], "unique": true }, not CREATE INDEX SQL strings.' : "";
|
|
166
|
+
issues.push(error(target, `Index at index ${i} must be an object.${hint}`));
|
|
110
167
|
continue;
|
|
111
168
|
}
|
|
112
169
|
if (!Array.isArray(index.fields) || !index.fields.every((field) => typeof field === "string" && field.trim() !== "")) {
|
|
@@ -498,7 +555,7 @@ var llmImportRule = {
|
|
|
498
555
|
};
|
|
499
556
|
|
|
500
557
|
// src/lib/lint/registry.ts
|
|
501
|
-
var ALL_RULES = [collectionSchemaRule, hookVerifyRule, llmImportRule];
|
|
558
|
+
var ALL_RULES = [automationConfigRule, collectionSchemaRule, hookVerifyRule, llmImportRule];
|
|
502
559
|
|
|
503
560
|
// src/lib/lint/format.ts
|
|
504
561
|
import { relative } from "path";
|
|
@@ -565,7 +622,10 @@ function buildAutomationTargets(localAutomations) {
|
|
|
565
622
|
kind: "automation",
|
|
566
623
|
name: a.automation.external_id,
|
|
567
624
|
filePath: a.filePath,
|
|
568
|
-
source: a.code
|
|
625
|
+
source: a.code,
|
|
626
|
+
config: a.automation.inputs?.schema,
|
|
627
|
+
// a.filePath is main.py; config.json is its sibling.
|
|
628
|
+
configFilePath: join(dirname(a.filePath), "config.json")
|
|
569
629
|
}));
|
|
570
630
|
}
|
|
571
631
|
function buildCollectionTargets(platformDir, _filterName) {
|