@lunora/cli 1.0.0-alpha.5 → 1.0.0-alpha.50
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/__assets__/package-og.svg +1 -1
- package/dist/bin.mjs +1 -1
- package/dist/index.d.mts +243 -114
- package/dist/index.d.ts +243 -114
- package/dist/index.mjs +7 -7
- package/dist/packem_chunks/handler.mjs +87 -6
- package/dist/packem_chunks/handler10.mjs +8 -14
- package/dist/packem_chunks/handler11.mjs +19 -189
- package/dist/packem_chunks/handler12.mjs +176 -115
- package/dist/packem_chunks/handler13.mjs +118 -52
- package/dist/packem_chunks/handler14.mjs +50 -43
- package/dist/packem_chunks/handler15.mjs +46 -67
- package/dist/packem_chunks/handler16.mjs +74 -37
- package/dist/packem_chunks/handler17.mjs +38 -100
- package/dist/packem_chunks/handler18.mjs +87 -152
- package/dist/packem_chunks/handler19.mjs +148 -67
- package/dist/packem_chunks/handler2.mjs +2 -2
- package/dist/packem_chunks/handler20.mjs +75 -75
- package/dist/packem_chunks/handler21.mjs +71 -288
- package/dist/packem_chunks/handler3.mjs +1 -1
- package/dist/packem_chunks/handler4.mjs +1 -1
- package/dist/packem_chunks/handler5.mjs +2 -2
- package/dist/packem_chunks/handler6.mjs +2 -2
- package/dist/packem_chunks/handler7.mjs +1 -1
- package/dist/packem_chunks/handler8.mjs +1 -1
- package/dist/packem_chunks/handler9.mjs +311 -12
- package/dist/packem_chunks/planDevCommand.mjs +47 -50
- package/dist/packem_chunks/runCodegenCommand.mjs +2 -2
- package/dist/packem_chunks/runDeployCommand.mjs +105 -15
- package/dist/packem_chunks/runInitCommand.mjs +1942 -88
- package/dist/packem_chunks/runMigrateGenerateCommand.mjs +5 -5
- package/dist/packem_chunks/runResetCommand.mjs +2 -2
- package/dist/packem_chunks/runRpcCommand.mjs +1 -1
- package/dist/packem_shared/{COMMANDS-DXaq12xm.mjs → COMMANDS-B0ftFD_3.mjs} +47 -21
- package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +31 -0
- package/dist/packem_shared/{command-BDXcJCCJ.mjs → command-D3lB_4Az.mjs} +6 -1
- package/dist/packem_shared/{commands-B9nASOYd.mjs → commands-B-gR09Z_.mjs} +61 -4
- package/dist/packem_shared/{createLogger-CHPNjFw2.mjs → createLogger-B40gPzQo.mjs} +9 -4
- package/dist/packem_shared/detect-package-manager-DYp7n3mJ.mjs +61 -0
- package/dist/packem_shared/{diffSnapshots-RR2ZE8Ya.mjs → diffSnapshots-BeDvvNiF.mjs} +1 -1
- package/dist/packem_shared/{insertSchemaExtension-BuzF6-t2.mjs → insertSchemaExtension-DAqbfr9Z.mjs} +15 -10
- package/dist/packem_shared/{output-format-7gyGR3h8.mjs → output-format-wUvAN6AL.mjs} +1 -1
- package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +9 -0
- package/dist/packem_shared/runAddCommand-bnY6-HKb.mjs +4 -0
- package/dist/packem_shared/{schemaIrToSnapshot-aBTo7TM5.mjs → schemaIrToSnapshot-DdsljJT-.mjs} +1 -1
- package/dist/packem_shared/storage-BIsph-Vk.mjs +84 -0
- package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +658 -0
- package/dist/packem_shared/wrangler-secrets-P2_ZUR-k.mjs +47 -0
- package/package.json +9 -10
- package/skills/lunora-setup-storage/SKILL.md +7 -3
- package/dist/packem_shared/features-ocSSpZtS.mjs +0 -24
- package/dist/packem_shared/runAddCommand-BF7XreDW.mjs +0 -4
- package/dist/packem_shared/tui-prompts-Bm15GPJA.mjs +0 -229
- /package/dist/packem_shared/{defaultSpawner-DxI3mebw.mjs → createRecordingSpawner-DxI3mebw.mjs} +0 -0
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.50",
|
|
4
4
|
"description": "The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-skills",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"lunora": "./dist/bin.mjs"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
|
-
"dist",
|
|
33
|
+
"./dist",
|
|
34
34
|
"__assets__",
|
|
35
35
|
"skills",
|
|
36
36
|
"README.md",
|
|
@@ -52,20 +52,19 @@
|
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@bomb.sh/tab": "0.0.17",
|
|
55
|
-
"@lunora/codegen": "1.0.0-alpha.
|
|
56
|
-
"@lunora/config": "1.0.0-alpha.
|
|
57
|
-
"@lunora/container": "1.0.0-alpha.
|
|
58
|
-
"@lunora/d1": "1.0.0-alpha.
|
|
59
|
-
"@lunora/seed": "1.0.0-alpha.
|
|
60
|
-
"@lunora/server": "1.0.0-alpha.1",
|
|
61
|
-
"@lunora/studio": "1.0.0-alpha.2",
|
|
62
|
-
"@lunora/values": "1.0.0-alpha.1",
|
|
55
|
+
"@lunora/codegen": "1.0.0-alpha.23",
|
|
56
|
+
"@lunora/config": "1.0.0-alpha.38",
|
|
57
|
+
"@lunora/container": "1.0.0-alpha.5",
|
|
58
|
+
"@lunora/d1": "1.0.0-alpha.16",
|
|
59
|
+
"@lunora/seed": "1.0.0-alpha.11",
|
|
63
60
|
"@visulima/cerebro": "3.0.0-alpha.32",
|
|
61
|
+
"@visulima/error": "6.0.0-alpha.34",
|
|
64
62
|
"@visulima/fs": "5.0.0-alpha.32",
|
|
65
63
|
"@visulima/pail": "4.0.0-alpha.22",
|
|
66
64
|
"@visulima/path": "3.0.0-alpha.13",
|
|
67
65
|
"@visulima/spinner": "1.0.0-alpha.4",
|
|
68
66
|
"@visulima/tui": "1.0.0-alpha.26",
|
|
67
|
+
"cfonts": "^3.3.1",
|
|
69
68
|
"giget": "3.3.0",
|
|
70
69
|
"jsonc-parser": "^3.3.1",
|
|
71
70
|
"magic-string": "^0.30.21",
|
|
@@ -41,7 +41,7 @@ This:
|
|
|
41
41
|
1. Adds `@lunora/storage` and `@lunora/server` to `package.json` (run
|
|
42
42
|
`pnpm install` afterwards).
|
|
43
43
|
2. Adds an R2 bucket binding to `wrangler.jsonc` (`r2_buckets`, binding
|
|
44
|
-
**`UPLOADS`**, `bucket_name: "
|
|
44
|
+
**`UPLOADS`**, `bucket_name: "replace-me-uploads"` — rename it to a real
|
|
45
45
|
bucket). It **merges** into any existing `r2_buckets`.
|
|
46
46
|
3. Scaffolds `STORAGE_SIGNING_SECRET` (a secret) and `STORAGE_PUBLIC_BASE_URL`
|
|
47
47
|
into `.dev.vars`.
|
|
@@ -137,8 +137,12 @@ persist that, and pass the bare key back in — the component re-scopes it.
|
|
|
137
137
|
|
|
138
138
|
1. **Skipping `verifySignedUrl` on the download route.** Without it, anyone can
|
|
139
139
|
read any key. Always verify before streaming.
|
|
140
|
-
2. **Placeholder bucket name.** `
|
|
141
|
-
|
|
140
|
+
2. **Placeholder bucket name.** `lunora init` and `lunora add storage` prompt for
|
|
141
|
+
the bucket name (or take `--bucket <name>`), but the low-level
|
|
142
|
+
`lunora registry add storage` writes the placeholder
|
|
143
|
+
`bucket_name: "replace-me-uploads"` — rename it to a real R2 bucket. (R2 names
|
|
144
|
+
are lowercase alphanumeric + hyphens, 3–63 chars; wrangler rejects anything
|
|
145
|
+
else on `dev`/`deploy`.)
|
|
142
146
|
3. **Short / shared signing secret.** Use ≥32 chars and a distinct secret per
|
|
143
147
|
bucket; reusing it lets one bucket's URLs sign for another.
|
|
144
148
|
4. **Proxying bytes through the Worker.** The design uploads/downloads directly
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
const AUTH_PROVIDER_OPTIONS = [
|
|
2
|
-
{ description: "Email + password on better-auth (default)", label: "Email & password", value: "auth" },
|
|
3
|
-
{ description: "Clerk-hosted auth", label: "Clerk", value: "auth-clerk" },
|
|
4
|
-
{ description: "Auth0 (OIDC)", label: "Auth0", value: "auth-auth0" }
|
|
5
|
-
];
|
|
6
|
-
const DEFAULT_AUTH_ITEM = "auth";
|
|
7
|
-
const promptAuthProvider = async (select) => await select("Which auth provider?", AUTH_PROVIDER_OPTIONS, { default: DEFAULT_AUTH_ITEM }) ?? DEFAULT_AUTH_ITEM;
|
|
8
|
-
const EMAIL_ITEM = "mail";
|
|
9
|
-
const normalizeFeature = (raw) => {
|
|
10
|
-
const value = raw.trim();
|
|
11
|
-
if (value === "") {
|
|
12
|
-
return void 0;
|
|
13
|
-
}
|
|
14
|
-
const lower = value.toLowerCase();
|
|
15
|
-
if (lower === "auth") {
|
|
16
|
-
return { kind: "auth" };
|
|
17
|
-
}
|
|
18
|
-
if (lower === "email" || lower === "mail") {
|
|
19
|
-
return { kind: "email" };
|
|
20
|
-
}
|
|
21
|
-
return { item: lower, kind: "item" };
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export { AUTH_PROVIDER_OPTIONS as A, DEFAULT_AUTH_ITEM as D, EMAIL_ITEM as E, normalizeFeature as n, promptAuthProvider as p };
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { isInteractive } from '@lunora/config';
|
|
3
|
-
import { render } from '@visulima/tui';
|
|
4
|
-
import { Box } from '@visulima/tui/components/box';
|
|
5
|
-
import { CommandPalette } from '@visulima/tui/components/command-palette';
|
|
6
|
-
import { ConfirmInput } from '@visulima/tui/components/confirm-input';
|
|
7
|
-
import { MultiSelect } from '@visulima/tui/components/multi-select';
|
|
8
|
-
import { SelectInput } from '@visulima/tui/components/select-input';
|
|
9
|
-
import { Spinner } from '@visulima/tui/components/spinner';
|
|
10
|
-
import { Text } from '@visulima/tui/components/text';
|
|
11
|
-
import { useApp } from '@visulima/tui/hooks/use-app';
|
|
12
|
-
import { useInput } from '@visulima/tui/hooks/use-input';
|
|
13
|
-
import { useEffect } from 'react';
|
|
14
|
-
|
|
15
|
-
const ACCENT = "#a855f7";
|
|
16
|
-
const SCROLL_LIMIT = 10;
|
|
17
|
-
const FILTER_THRESHOLD = 8;
|
|
18
|
-
const PromptFrame = ({ children }) => jsx(Box, { borderColor: ACCENT, borderStyle: "round", flexDirection: "column", paddingX: 1, children });
|
|
19
|
-
const runInkPrompt = async (build, fallback) => {
|
|
20
|
-
let result = fallback;
|
|
21
|
-
const instance = render(
|
|
22
|
-
build((value) => {
|
|
23
|
-
result = value;
|
|
24
|
-
}),
|
|
25
|
-
{ exitOnCtrlC: true }
|
|
26
|
-
);
|
|
27
|
-
try {
|
|
28
|
-
await instance.waitUntilExit();
|
|
29
|
-
} catch {
|
|
30
|
-
} finally {
|
|
31
|
-
instance.unmount();
|
|
32
|
-
}
|
|
33
|
-
return result;
|
|
34
|
-
};
|
|
35
|
-
const itemLabel = (option) => option.description === void 0 ? option.label : `${option.label} — ${option.description}`;
|
|
36
|
-
const useCommit = (finish) => {
|
|
37
|
-
const { exit } = useApp();
|
|
38
|
-
return (result) => {
|
|
39
|
-
finish(result);
|
|
40
|
-
exit();
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
const useEscapeToExit = () => {
|
|
44
|
-
const { exit } = useApp();
|
|
45
|
-
useInput((_input, key) => {
|
|
46
|
-
if (key.escape) {
|
|
47
|
-
exit();
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
const SelectView = ({ finish, initialIndex, message, options }) => {
|
|
52
|
-
const commit = useCommit(finish);
|
|
53
|
-
useEscapeToExit();
|
|
54
|
-
return jsxs(PromptFrame, { children: [
|
|
55
|
-
jsx(Text, { bold: true, children: message }),
|
|
56
|
-
jsx(
|
|
57
|
-
SelectInput,
|
|
58
|
-
{
|
|
59
|
-
accentColor: ACCENT,
|
|
60
|
-
initialIndex,
|
|
61
|
-
items: options.map((option) => {
|
|
62
|
-
return { key: option.value, label: itemLabel(option), value: option.value };
|
|
63
|
-
}),
|
|
64
|
-
limit: SCROLL_LIMIT,
|
|
65
|
-
onSelect: (item) => {
|
|
66
|
-
commit(item.value);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
] });
|
|
71
|
-
};
|
|
72
|
-
const PaletteView = ({ finish, message, options }) => {
|
|
73
|
-
const { exit } = useApp();
|
|
74
|
-
const commit = useCommit(finish);
|
|
75
|
-
return jsxs(Box, { flexDirection: "column", children: [
|
|
76
|
-
jsx(Text, { bold: true, children: message }),
|
|
77
|
-
jsx(
|
|
78
|
-
CommandPalette,
|
|
79
|
-
{
|
|
80
|
-
accentColor: ACCENT,
|
|
81
|
-
autoFocus: true,
|
|
82
|
-
commands: options.map((option) => {
|
|
83
|
-
return { description: option.description, id: option.value, label: option.label };
|
|
84
|
-
}),
|
|
85
|
-
limit: SCROLL_LIMIT,
|
|
86
|
-
onCancel: () => {
|
|
87
|
-
exit();
|
|
88
|
-
},
|
|
89
|
-
onSelect: (id) => {
|
|
90
|
-
commit(id);
|
|
91
|
-
},
|
|
92
|
-
placeholder: "Type to filter…"
|
|
93
|
-
}
|
|
94
|
-
)
|
|
95
|
-
] });
|
|
96
|
-
};
|
|
97
|
-
const tuiSelect = async (message, options, settings) => {
|
|
98
|
-
if (!isInteractive() || options.length === 0) {
|
|
99
|
-
return settings?.default;
|
|
100
|
-
}
|
|
101
|
-
if (options.length > FILTER_THRESHOLD) {
|
|
102
|
-
return runInkPrompt((finish) => jsx(PaletteView, { finish, message, options }), settings?.default);
|
|
103
|
-
}
|
|
104
|
-
const defaultIndex = settings?.default === void 0 ? -1 : options.findIndex((option) => option.value === settings.default);
|
|
105
|
-
return runInkPrompt(
|
|
106
|
-
(finish) => jsx(SelectView, { finish, initialIndex: defaultIndex >= 0 ? defaultIndex : void 0, message, options }),
|
|
107
|
-
settings?.default
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
const MultiSelectView = ({ defaults, finish, message, options }) => {
|
|
111
|
-
const commit = useCommit(finish);
|
|
112
|
-
useEscapeToExit();
|
|
113
|
-
return jsxs(PromptFrame, { children: [
|
|
114
|
-
jsx(Text, { bold: true, children: message }),
|
|
115
|
-
jsx(Text, { dimColor: true, children: "space toggles · enter confirms · esc cancels" }),
|
|
116
|
-
jsx(
|
|
117
|
-
MultiSelect,
|
|
118
|
-
{
|
|
119
|
-
accentColor: ACCENT,
|
|
120
|
-
defaultValue: [...defaults],
|
|
121
|
-
limit: SCROLL_LIMIT,
|
|
122
|
-
onSubmit: (values) => {
|
|
123
|
-
const chosen = new Set(values);
|
|
124
|
-
commit(options.filter((option) => chosen.has(option.value)).map((option) => option.value));
|
|
125
|
-
},
|
|
126
|
-
options: options.map((option) => {
|
|
127
|
-
return { key: option.value, label: itemLabel(option), value: option.value };
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
)
|
|
131
|
-
] });
|
|
132
|
-
};
|
|
133
|
-
const tuiMultiSelect = async (message, options, settings) => {
|
|
134
|
-
const defaults = settings?.defaults ?? [];
|
|
135
|
-
if (!isInteractive() || options.length === 0) {
|
|
136
|
-
return [...defaults];
|
|
137
|
-
}
|
|
138
|
-
return runInkPrompt((finish) => jsx(MultiSelectView, { defaults, finish, message, options }), [...defaults]);
|
|
139
|
-
};
|
|
140
|
-
const ConfirmView = ({ defaultYes, finish, message }) => {
|
|
141
|
-
const commit = useCommit(finish);
|
|
142
|
-
return jsx(PromptFrame, { children: jsxs(Box, { children: [
|
|
143
|
-
jsxs(Text, { bold: true, children: [
|
|
144
|
-
message,
|
|
145
|
-
" "
|
|
146
|
-
] }),
|
|
147
|
-
jsx(
|
|
148
|
-
ConfirmInput,
|
|
149
|
-
{
|
|
150
|
-
defaultChoice: defaultYes ? "confirm" : "cancel",
|
|
151
|
-
onCancel: () => {
|
|
152
|
-
commit(false);
|
|
153
|
-
},
|
|
154
|
-
onConfirm: () => {
|
|
155
|
-
commit(true);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
)
|
|
159
|
-
] }) });
|
|
160
|
-
};
|
|
161
|
-
const tuiConfirm = async (message, options) => {
|
|
162
|
-
const defaultYes = options?.defaultYes === true;
|
|
163
|
-
if (!isInteractive()) {
|
|
164
|
-
return defaultYes;
|
|
165
|
-
}
|
|
166
|
-
return runInkPrompt((finish) => jsx(ConfirmView, { defaultYes, finish, message }), false);
|
|
167
|
-
};
|
|
168
|
-
const createTuiConfirm = () => isInteractive() ? (message) => tuiConfirm(message, { defaultYes: true }) : () => Promise.resolve(false);
|
|
169
|
-
const SelfExit = ({ children }) => {
|
|
170
|
-
const { exit } = useApp();
|
|
171
|
-
useEffect(() => {
|
|
172
|
-
exit();
|
|
173
|
-
}, [exit]);
|
|
174
|
-
return children;
|
|
175
|
-
};
|
|
176
|
-
const printFrame = async (element) => {
|
|
177
|
-
const instance = render(jsx(SelfExit, { children: element }));
|
|
178
|
-
try {
|
|
179
|
-
await instance.waitUntilExit();
|
|
180
|
-
} catch {
|
|
181
|
-
} finally {
|
|
182
|
-
instance.unmount();
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
const tuiIntro = async (message) => {
|
|
186
|
-
if (!isInteractive()) {
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
await printFrame(
|
|
190
|
-
jsxs(Box, { borderColor: ACCENT, borderStyle: "round", paddingX: 1, children: [
|
|
191
|
-
jsxs(Text, { bold: true, color: ACCENT, children: [
|
|
192
|
-
"◆ Lunora",
|
|
193
|
-
" "
|
|
194
|
-
] }),
|
|
195
|
-
jsx(Text, { children: message })
|
|
196
|
-
] })
|
|
197
|
-
);
|
|
198
|
-
};
|
|
199
|
-
const tuiOutro = async (message) => {
|
|
200
|
-
if (!isInteractive()) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
await printFrame(
|
|
204
|
-
jsxs(Box, { paddingX: 1, children: [
|
|
205
|
-
jsx(Text, { color: "green", children: "✔ " }),
|
|
206
|
-
jsx(Text, { children: message })
|
|
207
|
-
] })
|
|
208
|
-
);
|
|
209
|
-
};
|
|
210
|
-
const SpinnerView = ({ label }) => jsxs(Box, { children: [
|
|
211
|
-
jsx(Text, { color: ACCENT, children: jsx(Spinner, { type: "dots" }) }),
|
|
212
|
-
jsxs(Text, { children: [
|
|
213
|
-
" ",
|
|
214
|
-
label
|
|
215
|
-
] })
|
|
216
|
-
] });
|
|
217
|
-
const withTuiSpinner = async (label, task) => {
|
|
218
|
-
if (!isInteractive()) {
|
|
219
|
-
return task();
|
|
220
|
-
}
|
|
221
|
-
const instance = render(jsx(SpinnerView, { label }));
|
|
222
|
-
try {
|
|
223
|
-
return await task();
|
|
224
|
-
} finally {
|
|
225
|
-
instance.unmount();
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
export { tuiConfirm as a, tuiIntro as b, createTuiConfirm as c, tuiOutro as d, tuiMultiSelect as e, tuiSelect as t, withTuiSpinner as w };
|
/package/dist/packem_shared/{defaultSpawner-DxI3mebw.mjs → createRecordingSpawner-DxI3mebw.mjs}
RENAMED
|
File without changes
|