@lunora/cli 1.0.0-alpha.90 → 1.0.0-alpha.92
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/bin.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/packem_chunks/handler15.mjs +85 -45
- package/dist/packem_chunks/handler16.mjs +37 -93
- package/dist/packem_chunks/handler17.mjs +99 -38
- package/dist/packem_chunks/handler18.mjs +151 -86
- package/dist/packem_chunks/handler19.mjs +73 -147
- package/dist/packem_chunks/handler20.mjs +74 -76
- package/dist/packem_chunks/handler21.mjs +182 -74
- package/dist/packem_shared/{COMMANDS-DZ0NnuqI.mjs → COMMANDS-CstRNuDU.mjs} +24 -9
- package/package.json +7 -5
|
@@ -1,96 +1,94 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
1
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import {
|
|
4
|
-
import { p as parseApiSpec } from '../packem_shared/api-spec-Bx0iKbxA.mjs';
|
|
5
|
-
import { a as renderCodegenHint } from '../packem_shared/codegen-error-DJG-ghs_.mjs';
|
|
3
|
+
import { parse } from 'jsonc-parser';
|
|
6
4
|
import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
|
|
7
|
-
import {
|
|
8
|
-
import { v as validateOutputFormat, i as isJsonFormat, p as printJson, l as loggerForFormat } from '../packem_shared/output-format-B4642rjE.mjs';
|
|
9
|
-
import { r as runSchemaDriftGate } from '../packem_shared/schema-drift-gate-BtBt0as0.mjs';
|
|
10
|
-
import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
|
|
11
|
-
import { validateWranglerProject } from '@lunora/config';
|
|
5
|
+
import { o as openUrl } from '../packem_shared/open-url-4PBLY9X0.mjs';
|
|
12
6
|
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
const DEFAULT_DEV_PORT = 8787;
|
|
8
|
+
const STUDIO_PATH = "/_lunora/studio";
|
|
9
|
+
const findWranglerFile = (projectRoot) => {
|
|
10
|
+
for (const candidate of ["wrangler.jsonc", "wrangler.json"]) {
|
|
11
|
+
const fullPath = join(projectRoot, candidate);
|
|
12
|
+
if (existsSync(fullPath)) {
|
|
13
|
+
return fullPath;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return void 0;
|
|
17
|
+
};
|
|
18
|
+
const readWrangler = (projectRoot) => {
|
|
19
|
+
const file = findWranglerFile(projectRoot);
|
|
20
|
+
if (!file) {
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const parsed = parse(readFileSync(file, "utf8"));
|
|
25
|
+
return parsed !== null && typeof parsed === "object" ? parsed : void 0;
|
|
26
|
+
} catch {
|
|
27
|
+
return void 0;
|
|
16
28
|
}
|
|
17
|
-
const exec = execArgsFor(detectPackageManager(cwd), "tsc", ["--noEmit", "-p", "tsconfig.json"]);
|
|
18
|
-
const result = await spawner({ args: exec.args, command: exec.command, cwd });
|
|
19
|
-
return result.code === 0 ? {} : { error: `type errors: tsc --noEmit exited ${String(result.code)}` };
|
|
20
29
|
};
|
|
21
|
-
const
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
return { code: 0, errors: [], warnings: [], wranglerPath };
|
|
30
|
+
const resolveDevPort = (wrangler) => {
|
|
31
|
+
if (!wrangler) {
|
|
32
|
+
return DEFAULT_DEV_PORT;
|
|
25
33
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
const { dev } = wrangler;
|
|
35
|
+
if (dev !== null && typeof dev === "object") {
|
|
36
|
+
const { port } = dev;
|
|
37
|
+
if (typeof port === "number" && Number.isFinite(port)) {
|
|
38
|
+
return port;
|
|
30
39
|
}
|
|
31
40
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
return DEFAULT_DEV_PORT;
|
|
42
|
+
};
|
|
43
|
+
const resolveRemoteUrl = (wrangler) => {
|
|
44
|
+
if (!wrangler) {
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const { routes } = wrangler;
|
|
48
|
+
if (Array.isArray(routes) && routes.length > 0) {
|
|
49
|
+
const first = routes[0];
|
|
50
|
+
if (typeof first === "string") {
|
|
51
|
+
return `https://${first.split("/")[0] ?? first}${STUDIO_PATH}`;
|
|
52
|
+
}
|
|
53
|
+
if (first !== null && typeof first === "object") {
|
|
54
|
+
const { pattern } = first;
|
|
55
|
+
if (typeof pattern === "string" && pattern.length > 0) {
|
|
56
|
+
return `https://${pattern.split("/")[0] ?? pattern}${STUDIO_PATH}`;
|
|
39
57
|
}
|
|
40
58
|
}
|
|
41
|
-
return { code: 1, errors, warnings, wranglerPath };
|
|
42
59
|
}
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
const { name } = wrangler;
|
|
61
|
+
if (typeof name === "string" && name.length > 0) {
|
|
62
|
+
return `https://${name}.workers.dev${STUDIO_PATH}`;
|
|
63
|
+
}
|
|
64
|
+
return void 0;
|
|
45
65
|
};
|
|
46
|
-
const
|
|
66
|
+
const runViewCommand = async (options) => {
|
|
47
67
|
const cwd = options.cwd ?? process.cwd();
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
68
|
+
const wrangler = readWrangler(cwd);
|
|
69
|
+
const { logger } = options;
|
|
70
|
+
let url;
|
|
71
|
+
if (options.remote) {
|
|
72
|
+
url = resolveRemoteUrl(wrangler);
|
|
73
|
+
if (!url) {
|
|
74
|
+
logger.error("view --remote: could not determine the remote URL from wrangler config (set `routes` or `name`).");
|
|
75
|
+
return { code: 1, url: void 0 };
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
url = `http://localhost:${String(resolveDevPort(wrangler))}${STUDIO_PATH}`;
|
|
53
79
|
}
|
|
54
|
-
|
|
55
|
-
const errors = [...validation.report.errors];
|
|
56
|
-
const warnings = [...validation.report.warnings];
|
|
80
|
+
logger.info(`opening ${url}`);
|
|
57
81
|
try {
|
|
58
|
-
|
|
59
|
-
const gate = runSchemaDriftGate({ allowDrift: options.allowSchemaDrift === true, codegen, logger, readOnly: true });
|
|
60
|
-
if (gate.blocked) {
|
|
61
|
-
errors.push(gate.reason);
|
|
62
|
-
}
|
|
82
|
+
await openUrl(url, { opener: options.opener });
|
|
63
83
|
} catch (error) {
|
|
64
84
|
const message = error instanceof Error ? error.message : String(error);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (options.typecheck !== false) {
|
|
68
|
-
const typecheck = await runTypecheckStep(cwd, options.spawner ?? defaultSpawner);
|
|
69
|
-
if (typecheck.error !== void 0) {
|
|
70
|
-
errors.push(typecheck.error);
|
|
71
|
-
}
|
|
72
|
-
if (typecheck.warning !== void 0) {
|
|
73
|
-
warnings.push(typecheck.warning);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const result = reportVerifyResult(logger, errors, warnings, validation.wranglerPath);
|
|
77
|
-
if (isJsonFormat(options.format)) {
|
|
78
|
-
printJson(result);
|
|
85
|
+
logger.error(`view: failed to open URL: ${message}`);
|
|
86
|
+
return { code: 1, url };
|
|
79
87
|
}
|
|
80
|
-
return
|
|
88
|
+
return { code: 0, url };
|
|
81
89
|
};
|
|
82
|
-
const execute = defineHandler(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
apiSpec: parseApiSpec(options.apiSpec),
|
|
86
|
-
cwd,
|
|
87
|
-
format: options.format,
|
|
88
|
-
logger,
|
|
89
|
-
// `--no-typecheck` is declared as a `no-*` option but cerebro exposes it
|
|
90
|
-
// under the negated `typecheck` key (false when passed, true when absent).
|
|
91
|
-
typecheck: options.typecheck === false ? false : void 0
|
|
92
|
-
});
|
|
93
|
-
return { code: result.code };
|
|
94
|
-
});
|
|
90
|
+
const execute = defineHandler(
|
|
91
|
+
({ cwd, logger, options }) => runViewCommand({ cwd, logger, remote: options.remote === true })
|
|
92
|
+
);
|
|
95
93
|
|
|
96
|
-
export { execute,
|
|
94
|
+
export { execute, runViewCommand };
|
|
@@ -1,94 +1,202 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { parse } from 'jsonc-parser';
|
|
1
|
+
import { readLinkedProject } from '@lunora/config';
|
|
4
2
|
import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs';
|
|
5
|
-
import {
|
|
3
|
+
import { e as execArgsFor, d as detectPackageManager } from '../packem_shared/detect-package-manager-v4hHpQd0.mjs';
|
|
4
|
+
import { defaultSpawner } from '../packem_shared/createRecordingSpawner-WuSn20kb.mjs';
|
|
5
|
+
import { createR2Sql } from '@lunora/bindings/r2sql';
|
|
6
|
+
import { createPipelineLogReader } from '@lunora/runtime';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const LOG_LEVELS = /* @__PURE__ */ new Set(["debug", "error", "fatal", "info", "log", "trace", "warn"]);
|
|
9
|
+
const EPOCH_MILLIS_RE = /^\d+$/;
|
|
10
|
+
const parseTimestamp = (value, flag) => {
|
|
11
|
+
if (value === void 0) {
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
const trimmed = value.trim();
|
|
15
|
+
if (EPOCH_MILLIS_RE.test(trimmed)) {
|
|
16
|
+
return Number(trimmed);
|
|
15
17
|
}
|
|
16
|
-
|
|
18
|
+
const parsed = Date.parse(trimmed);
|
|
19
|
+
if (Number.isNaN(parsed)) {
|
|
20
|
+
throw new TypeError(`logs: invalid ${flag} "${value}" — pass epoch-millis or an ISO 8601 date`);
|
|
21
|
+
}
|
|
22
|
+
return parsed;
|
|
17
23
|
};
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
if (!file) {
|
|
24
|
+
const parseLevel = (value, flag) => {
|
|
25
|
+
if (value === void 0) {
|
|
21
26
|
return void 0;
|
|
22
27
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return parsed !== null && typeof parsed === "object" ? parsed : void 0;
|
|
26
|
-
} catch {
|
|
27
|
-
return void 0;
|
|
28
|
+
if (!LOG_LEVELS.has(value)) {
|
|
29
|
+
throw new TypeError(`logs: invalid ${flag} "${value}" — expected one of trace, debug, log, info, warn, error, fatal`);
|
|
28
30
|
}
|
|
31
|
+
return value;
|
|
29
32
|
};
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (dev !== null && typeof dev === "object") {
|
|
36
|
-
const { port } = dev;
|
|
37
|
-
if (typeof port === "number" && Number.isFinite(port)) {
|
|
38
|
-
return port;
|
|
39
|
-
}
|
|
33
|
+
const buildQuery = (options) => {
|
|
34
|
+
const query = {};
|
|
35
|
+
const sinceTs = parseTimestamp(options.since, "--since");
|
|
36
|
+
if (sinceTs !== void 0) {
|
|
37
|
+
query.sinceTs = sinceTs;
|
|
40
38
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!wrangler) {
|
|
45
|
-
return void 0;
|
|
39
|
+
const untilTs = parseTimestamp(options.until, "--until");
|
|
40
|
+
if (untilTs !== void 0) {
|
|
41
|
+
query.untilTs = untilTs;
|
|
46
42
|
}
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
43
|
+
const level = parseLevel(options.level, "--level");
|
|
44
|
+
if (level !== void 0) {
|
|
45
|
+
query.level = level;
|
|
46
|
+
}
|
|
47
|
+
const minLevel = parseLevel(options.minLevel, "--min-level");
|
|
48
|
+
if (minLevel !== void 0) {
|
|
49
|
+
query.minLevel = minLevel;
|
|
50
|
+
}
|
|
51
|
+
if (options.functionPrefix !== void 0) {
|
|
52
|
+
query.functionPathPrefix = options.functionPrefix;
|
|
53
|
+
}
|
|
54
|
+
if (options.traceId !== void 0) {
|
|
55
|
+
query.traceId = options.traceId;
|
|
56
|
+
}
|
|
57
|
+
if (options.shardKey !== void 0) {
|
|
58
|
+
query.shardKey = options.shardKey;
|
|
59
|
+
}
|
|
60
|
+
if (options.userId !== void 0) {
|
|
61
|
+
query.userId = options.userId;
|
|
62
|
+
}
|
|
63
|
+
if (options.limit !== void 0) {
|
|
64
|
+
const limit = Number(options.limit);
|
|
65
|
+
if (!Number.isFinite(limit)) {
|
|
66
|
+
throw new TypeError(`logs: invalid --limit "${options.limit}" — expected a number`);
|
|
58
67
|
}
|
|
68
|
+
query.limit = limit;
|
|
59
69
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
70
|
+
if (options.cursor !== void 0) {
|
|
71
|
+
const cursorTs = Number(options.cursor);
|
|
72
|
+
if (!Number.isFinite(cursorTs)) {
|
|
73
|
+
throw new TypeError(`logs: invalid --cursor "${options.cursor}" — expected the epoch-millis ts from a prior page's nextCursor`);
|
|
74
|
+
}
|
|
75
|
+
query.cursor = { ts: cursorTs };
|
|
63
76
|
}
|
|
64
|
-
return
|
|
77
|
+
return query;
|
|
65
78
|
};
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
const formatRow = (row) => {
|
|
80
|
+
const time = new Date(row.ts).toISOString();
|
|
81
|
+
const level = row.level.toUpperCase().padEnd(5);
|
|
82
|
+
return `${time} ${level} ${row.functionPath} ${row.message}`;
|
|
83
|
+
};
|
|
84
|
+
const runDurableLogsCommand = async (options) => {
|
|
85
|
+
const environment = options.environment ?? process.env;
|
|
86
|
+
const accountId = environment.R2_SQL_ACCOUNT_ID;
|
|
87
|
+
const apiToken = environment.R2_SQL_TOKEN;
|
|
88
|
+
const bucket = environment.R2_SQL_BUCKET;
|
|
89
|
+
const missing = [];
|
|
90
|
+
if (accountId === void 0 || accountId.length === 0) {
|
|
91
|
+
missing.push("R2_SQL_ACCOUNT_ID");
|
|
92
|
+
}
|
|
93
|
+
if (apiToken === void 0 || apiToken.length === 0) {
|
|
94
|
+
missing.push("R2_SQL_TOKEN");
|
|
95
|
+
}
|
|
96
|
+
if (bucket === void 0 || bucket.length === 0) {
|
|
97
|
+
missing.push("R2_SQL_BUCKET");
|
|
98
|
+
}
|
|
99
|
+
if (options.table === void 0 || options.table.length === 0) {
|
|
100
|
+
missing.push("--table");
|
|
101
|
+
}
|
|
102
|
+
if (missing.length > 0) {
|
|
103
|
+
options.logger.error(
|
|
104
|
+
`logs --durable: R2 SQL not configured (missing ${missing.join(", ")}). The Pipeline must write to an R2 Data Catalog (Iceberg) table, and you must supply R2_SQL_ACCOUNT_ID / R2_SQL_TOKEN / R2_SQL_BUCKET plus --table — see the observability docs.`
|
|
105
|
+
);
|
|
106
|
+
return { code: 1, error: "not configured" };
|
|
79
107
|
}
|
|
80
|
-
|
|
108
|
+
let query;
|
|
81
109
|
try {
|
|
82
|
-
|
|
110
|
+
query = buildQuery(options);
|
|
83
111
|
} catch (error) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
112
|
+
options.logger.error(error instanceof Error ? error.message : String(error));
|
|
113
|
+
return { code: 1, error: "invalid option" };
|
|
114
|
+
}
|
|
115
|
+
const client = createR2Sql({ accountId, apiToken, bucket, fetch: options.fetch });
|
|
116
|
+
const reader = createPipelineLogReader(client, { namespace: options.namespace, table: options.table });
|
|
117
|
+
const page = await reader.query(query);
|
|
118
|
+
for (const row of page.rows) {
|
|
119
|
+
process.stdout.write(`${options.ndjson === true ? JSON.stringify(row) : formatRow(row)}
|
|
120
|
+
`);
|
|
121
|
+
}
|
|
122
|
+
if (page.rows.length === 0) {
|
|
123
|
+
options.logger.info("logs --durable: no matching log records");
|
|
124
|
+
} else if (page.nextCursor !== void 0) {
|
|
125
|
+
options.logger.info(`logs --durable: more rows available — pass --cursor ${String(page.nextCursor.ts)} for the next page`);
|
|
126
|
+
}
|
|
127
|
+
return { code: 0, rows: page.rows };
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const LOG_FORMATS = /* @__PURE__ */ new Set(["json", "pretty"]);
|
|
131
|
+
const runLogsCommand = async (options) => {
|
|
132
|
+
const cwd = options.cwd ?? process.cwd();
|
|
133
|
+
if (options.format !== void 0 && !LOG_FORMATS.has(options.format)) {
|
|
134
|
+
options.logger.error(`logs: unknown --format "${options.format}" — expected pretty | json`);
|
|
135
|
+
return { code: 1, descriptor: void 0, error: "invalid format" };
|
|
136
|
+
}
|
|
137
|
+
const args = ["tail"];
|
|
138
|
+
if (options.worker !== void 0) {
|
|
139
|
+
args.push(options.worker);
|
|
140
|
+
}
|
|
141
|
+
const env = options.env ?? readLinkedProject(cwd)?.env;
|
|
142
|
+
if (env !== void 0) {
|
|
143
|
+
args.push("--env", env);
|
|
144
|
+
}
|
|
145
|
+
if (options.format !== void 0) {
|
|
146
|
+
args.push("--format", options.format);
|
|
87
147
|
}
|
|
88
|
-
|
|
148
|
+
if (options.status !== void 0) {
|
|
149
|
+
args.push("--status", options.status);
|
|
150
|
+
}
|
|
151
|
+
if (options.search !== void 0) {
|
|
152
|
+
args.push("--search", options.search);
|
|
153
|
+
}
|
|
154
|
+
if (options.temporary) {
|
|
155
|
+
args.push("--temporary");
|
|
156
|
+
}
|
|
157
|
+
const exec = execArgsFor(detectPackageManager(cwd), "wrangler", args);
|
|
158
|
+
const descriptor = {
|
|
159
|
+
args: exec.args,
|
|
160
|
+
command: exec.command,
|
|
161
|
+
cwd
|
|
162
|
+
};
|
|
163
|
+
options.logger.info(`tailing logs via ${descriptor.command} ${descriptor.args.join(" ")}`);
|
|
164
|
+
const spawner = options.spawner ?? defaultSpawner;
|
|
165
|
+
const result = await spawner(descriptor);
|
|
166
|
+
return {
|
|
167
|
+
code: result.code,
|
|
168
|
+
descriptor
|
|
169
|
+
};
|
|
89
170
|
};
|
|
90
|
-
const execute = defineHandler(
|
|
91
|
-
|
|
92
|
-
|
|
171
|
+
const execute = defineHandler(({ argument, cwd, logger, options }) => {
|
|
172
|
+
if (options.durable === true) {
|
|
173
|
+
return runDurableLogsCommand({
|
|
174
|
+
cursor: options.cursor,
|
|
175
|
+
functionPrefix: options.functionPrefix,
|
|
176
|
+
level: options.level,
|
|
177
|
+
limit: options.limit,
|
|
178
|
+
logger,
|
|
179
|
+
minLevel: options.minLevel,
|
|
180
|
+
namespace: options.namespace,
|
|
181
|
+
ndjson: options.ndjson === true,
|
|
182
|
+
shardKey: options.shardKey,
|
|
183
|
+
since: options.since,
|
|
184
|
+
table: options.table,
|
|
185
|
+
traceId: options.traceId,
|
|
186
|
+
until: options.until,
|
|
187
|
+
userId: options.userId
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
return runLogsCommand({
|
|
191
|
+
cwd,
|
|
192
|
+
env: options.env,
|
|
193
|
+
format: options.format,
|
|
194
|
+
logger,
|
|
195
|
+
search: options.search,
|
|
196
|
+
status: options.status,
|
|
197
|
+
temporary: options.temporary === true,
|
|
198
|
+
worker: argument[0]
|
|
199
|
+
});
|
|
200
|
+
});
|
|
93
201
|
|
|
94
|
-
export { execute,
|
|
202
|
+
export { execute, runLogsCommand };
|
|
@@ -509,9 +509,9 @@ const linkCommand = {
|
|
|
509
509
|
|
|
510
510
|
const logsCommand = {
|
|
511
511
|
argument: { description: "Worker name (defaults to the name in wrangler config)", name: "worker", type: String },
|
|
512
|
-
description: "Stream live logs from a deployed
|
|
512
|
+
description: "Stream live logs from a deployed Worker, or read the durable log archive with --durable",
|
|
513
513
|
group: "Deploy",
|
|
514
|
-
loader: () => import('../packem_chunks/
|
|
514
|
+
loader: () => import('../packem_chunks/handler21.mjs').then((m) => {
|
|
515
515
|
return { default: m.execute };
|
|
516
516
|
}),
|
|
517
517
|
name: "logs",
|
|
@@ -524,7 +524,22 @@ const logsCommand = {
|
|
|
524
524
|
description: "Tail a temporary-account deployment when unauthenticated (wrangler tail --temporary). Errors if you're already authenticated.",
|
|
525
525
|
name: "temporary",
|
|
526
526
|
type: Boolean
|
|
527
|
-
}
|
|
527
|
+
},
|
|
528
|
+
// --- durable-archive path (--durable) ---
|
|
529
|
+
{ description: "Read the durable log archive (pipelineLogSink → R2) via R2 SQL instead of tailing live", name: "durable", type: Boolean },
|
|
530
|
+
{ description: "durable: Iceberg table the Pipeline writes to (required with --durable)", name: "table", type: String },
|
|
531
|
+
{ description: "durable: Iceberg namespace (R2 Data Catalog database) the table lives in", name: "namespace", type: String },
|
|
532
|
+
{ description: "durable: lower time bound (epoch-millis or ISO 8601), inclusive", name: "since", type: String },
|
|
533
|
+
{ description: "durable: upper time bound (epoch-millis or ISO 8601), inclusive", name: "until", type: String },
|
|
534
|
+
{ description: "durable: exact severity filter (trace|debug|log|info|warn|error|fatal)", name: "level", type: String },
|
|
535
|
+
{ description: "durable: severity floor — this level and every more-severe one", name: "min-level", type: String },
|
|
536
|
+
{ description: "durable: keep function paths starting with this prefix (LIKE 'prefix%')", name: "function-prefix", type: String },
|
|
537
|
+
{ description: "durable: trace-id filter", name: "trace-id", type: String },
|
|
538
|
+
{ description: "durable: shard-key filter", name: "shard-key", type: String },
|
|
539
|
+
{ description: "durable: user-id filter", name: "user-id", type: String },
|
|
540
|
+
{ description: "durable: max rows (clamped to 1–10000; default 500)", name: "limit", type: String },
|
|
541
|
+
{ description: "durable: resume after a prior page — the ts from its nextCursor", name: "cursor", type: String },
|
|
542
|
+
{ description: "durable: emit one JSON object per line instead of a table", name: "ndjson", type: Boolean }
|
|
528
543
|
]
|
|
529
544
|
};
|
|
530
545
|
|
|
@@ -571,7 +586,7 @@ const prepareCommand = {
|
|
|
571
586
|
description: "Run codegen + binding reconcile + wrangler validation (no Vite) — for CI",
|
|
572
587
|
examples: [["lunora prepare", "Codegen + binding reconcile + validate (CI, before deploy)"]],
|
|
573
588
|
group: "Deploy",
|
|
574
|
-
loader: () => import('../packem_chunks/
|
|
589
|
+
loader: () => import('../packem_chunks/handler15.mjs').then((m) => {
|
|
575
590
|
return { default: m.execute };
|
|
576
591
|
}),
|
|
577
592
|
name: "prepare",
|
|
@@ -595,7 +610,7 @@ const registryCommand = {
|
|
|
595
610
|
["lunora registry build --check", "Verify the committed catalog is current"]
|
|
596
611
|
],
|
|
597
612
|
group: "Project",
|
|
598
|
-
loader: () => import('../packem_chunks/
|
|
613
|
+
loader: () => import('../packem_chunks/handler16.mjs').then((m) => {
|
|
599
614
|
return { default: m.execute };
|
|
600
615
|
}),
|
|
601
616
|
name: "registry",
|
|
@@ -645,7 +660,7 @@ const rulesCommand = {
|
|
|
645
660
|
["lunora rules check --strict", "Exit non-zero when rules are missing (CI gate)"]
|
|
646
661
|
],
|
|
647
662
|
group: "Project",
|
|
648
|
-
loader: () => import('../packem_chunks/
|
|
663
|
+
loader: () => import('../packem_chunks/handler17.mjs').then((m) => {
|
|
649
664
|
return { default: m.execute };
|
|
650
665
|
}),
|
|
651
666
|
name: "rules",
|
|
@@ -683,7 +698,7 @@ const seedCommand = {
|
|
|
683
698
|
["lunora seed --seed 7 --dry-run", "Print the NDJSON for seed 7 without inserting"]
|
|
684
699
|
],
|
|
685
700
|
group: "Data",
|
|
686
|
-
loader: () => import('../packem_chunks/
|
|
701
|
+
loader: () => import('../packem_chunks/handler18.mjs').then((m) => {
|
|
687
702
|
return { default: m.execute };
|
|
688
703
|
}),
|
|
689
704
|
name: "seed",
|
|
@@ -712,7 +727,7 @@ const verifyCommand = {
|
|
|
712
727
|
["lunora verify --no-typecheck", "Skip the TypeScript type-check"]
|
|
713
728
|
],
|
|
714
729
|
group: "Deploy",
|
|
715
|
-
loader: () => import('../packem_chunks/
|
|
730
|
+
loader: () => import('../packem_chunks/handler19.mjs').then((m) => {
|
|
716
731
|
return { default: m.execute };
|
|
717
732
|
}),
|
|
718
733
|
name: "verify",
|
|
@@ -731,7 +746,7 @@ const viewCommand = {
|
|
|
731
746
|
["lunora view --remote", "Open the deployed studio"]
|
|
732
747
|
],
|
|
733
748
|
group: "Project",
|
|
734
|
-
loader: () => import('../packem_chunks/
|
|
749
|
+
loader: () => import('../packem_chunks/handler20.mjs').then((m) => {
|
|
735
750
|
return { default: m.execute };
|
|
736
751
|
}),
|
|
737
752
|
name: "view",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.92",
|
|
4
4
|
"description": "The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skills",
|
|
@@ -52,12 +52,14 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@bomb.sh/tab": "0.0.19",
|
|
55
|
-
"@lunora/
|
|
56
|
-
"@lunora/
|
|
55
|
+
"@lunora/bindings": "1.0.0-alpha.9",
|
|
56
|
+
"@lunora/codegen": "1.0.0-alpha.48",
|
|
57
|
+
"@lunora/config": "1.0.0-alpha.73",
|
|
57
58
|
"@lunora/container": "1.0.0-alpha.13",
|
|
58
|
-
"@lunora/d1": "1.0.0-alpha.
|
|
59
|
+
"@lunora/d1": "1.0.0-alpha.35",
|
|
59
60
|
"@lunora/errors": "1.0.0-alpha.6",
|
|
60
|
-
"@lunora/
|
|
61
|
+
"@lunora/runtime": "1.0.0-alpha.31",
|
|
62
|
+
"@lunora/seed": "1.0.0-alpha.28",
|
|
61
63
|
"@visulima/cerebro": "3.0.0",
|
|
62
64
|
"@visulima/error": "6.0.0",
|
|
63
65
|
"@visulima/fs": "5.0.4",
|