@lotics/cli 0.36.0 → 0.36.1
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/dev/wrapper_page.js +16 -0
- package/dist/src/cli.js +28 -1
- package/dist/starter_template.d.ts +10 -0
- package/dist/starter_template.js +21 -1
- package/dist/starter_template.test.js +18 -1
- package/package.json +2 -2
package/dist/dev/wrapper_page.js
CHANGED
|
@@ -145,6 +145,20 @@ export function buildWrapperPage(args) {
|
|
|
145
145
|
return completed.file;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
+
// openExternal — the wrapper page is the top frame (un-sandboxed), so it
|
|
149
|
+
// opens the link directly; NOT forwarded to the RPC endpoint (no server
|
|
150
|
+
// op). Re-validate the scheme; never trust the iframe's payload.
|
|
151
|
+
function handleOpenExternal(payload) {
|
|
152
|
+
var url = payload && payload.url;
|
|
153
|
+
if (typeof url !== "string") throw new Error("openExternal requires a url string");
|
|
154
|
+
var parsed = new URL(url);
|
|
155
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
156
|
+
throw new Error('openExternal: unsupported URL scheme "' + parsed.protocol + '"');
|
|
157
|
+
}
|
|
158
|
+
window.open(parsed.href, "_blank", "noopener,noreferrer");
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
|
|
148
162
|
window.addEventListener("message", async function (event) {
|
|
149
163
|
if (event.source !== iframe.contentWindow || event.origin !== VITE_ORIGIN) return;
|
|
150
164
|
const msg = event.data;
|
|
@@ -153,6 +167,8 @@ export function buildWrapperPage(args) {
|
|
|
153
167
|
try {
|
|
154
168
|
const data = msg.op === "upload"
|
|
155
169
|
? await handleUpload(msg.payload)
|
|
170
|
+
: msg.op === "openExternal"
|
|
171
|
+
? handleOpenExternal(msg.payload)
|
|
156
172
|
: await rpc(msg.op, msg.payload);
|
|
157
173
|
const ms = Math.round(performance.now() - startedAt);
|
|
158
174
|
console.debug("[lotics-dev] " + msg.op + " " + ms + "ms", data);
|
package/dist/src/cli.js
CHANGED
|
@@ -32257,6 +32257,7 @@ import { tmpdir } from "node:os";
|
|
|
32257
32257
|
// src/starter_template.ts
|
|
32258
32258
|
var STARTER_FALLBACK_UI_VERSION = "1.8.0";
|
|
32259
32259
|
var STARTER_FALLBACK_SDK_VERSION = "0.11.0";
|
|
32260
|
+
var STARTER_REACT_NATIVE_VERSION = "0.85.3";
|
|
32260
32261
|
function buildStarterTemplate(args) {
|
|
32261
32262
|
const uiVersion = args.ui_version ?? `^${STARTER_FALLBACK_UI_VERSION}`;
|
|
32262
32263
|
const sdkVersion = args.sdk_version ?? `^${STARTER_FALLBACK_SDK_VERSION}`;
|
|
@@ -32288,7 +32289,7 @@ function buildStarterTemplate(args) {
|
|
|
32288
32289
|
"lucide-react-native": "^0.562.0",
|
|
32289
32290
|
react: "^19.0.0",
|
|
32290
32291
|
"react-dom": "^19.0.0",
|
|
32291
|
-
"react-native":
|
|
32292
|
+
"react-native": STARTER_REACT_NATIVE_VERSION,
|
|
32292
32293
|
"react-native-svg": "^15.0.0",
|
|
32293
32294
|
"react-native-web": "^0.21.0"
|
|
32294
32295
|
},
|
|
@@ -32366,6 +32367,11 @@ import react from "@vitejs/plugin-react";
|
|
|
32366
32367
|
// is identical to RN-SVG when running under RN-Web.
|
|
32367
32368
|
export default defineConfig({
|
|
32368
32369
|
plugins: [react()],
|
|
32370
|
+
// RN libraries (react-native-web, @react-native-picker's UnimplementedView)
|
|
32371
|
+
// reference the \`__DEV__\` global that Metro injects but Vite does not \u2014
|
|
32372
|
+
// undefined \u21D2 the bundle throws at load and the iframe renders blank. Define
|
|
32373
|
+
// it (false = production RN behaviour) so dev and the deployed build both boot.
|
|
32374
|
+
define: { __DEV__: "false" },
|
|
32369
32375
|
resolve: {
|
|
32370
32376
|
alias: [
|
|
32371
32377
|
{
|
|
@@ -32390,6 +32396,11 @@ export default defineConfig({
|
|
|
32390
32396
|
// Pre-bundling forces Vite to convert it to an ESM shim with a default
|
|
32391
32397
|
// export. Production build (rollup) handles it correctly without this.
|
|
32392
32398
|
include: ["recharts", "es-toolkit", "es-toolkit/compat"],
|
|
32399
|
+
// The dep optimizer pre-bundles deps with a SEPARATE esbuild pass that
|
|
32400
|
+
// top-level \`define\` doesn't always reach, so a pre-bundled RN dep can
|
|
32401
|
+
// still hit \`__DEV__ is not defined\` under \`lotics app dev\`. Define it
|
|
32402
|
+
// here too \u2014 belt-and-suspenders with the top-level \`define\` above.
|
|
32403
|
+
esbuildOptions: { define: { __DEV__: "false" } },
|
|
32393
32404
|
},
|
|
32394
32405
|
build: {
|
|
32395
32406
|
outDir: "dist",
|
|
@@ -32880,6 +32891,20 @@ function buildWrapperPage(args) {
|
|
|
32880
32891
|
return completed.file;
|
|
32881
32892
|
}
|
|
32882
32893
|
|
|
32894
|
+
// openExternal \u2014 the wrapper page is the top frame (un-sandboxed), so it
|
|
32895
|
+
// opens the link directly; NOT forwarded to the RPC endpoint (no server
|
|
32896
|
+
// op). Re-validate the scheme; never trust the iframe's payload.
|
|
32897
|
+
function handleOpenExternal(payload) {
|
|
32898
|
+
var url = payload && payload.url;
|
|
32899
|
+
if (typeof url !== "string") throw new Error("openExternal requires a url string");
|
|
32900
|
+
var parsed = new URL(url);
|
|
32901
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
32902
|
+
throw new Error('openExternal: unsupported URL scheme "' + parsed.protocol + '"');
|
|
32903
|
+
}
|
|
32904
|
+
window.open(parsed.href, "_blank", "noopener,noreferrer");
|
|
32905
|
+
return undefined;
|
|
32906
|
+
}
|
|
32907
|
+
|
|
32883
32908
|
window.addEventListener("message", async function (event) {
|
|
32884
32909
|
if (event.source !== iframe.contentWindow || event.origin !== VITE_ORIGIN) return;
|
|
32885
32910
|
const msg = event.data;
|
|
@@ -32888,6 +32913,8 @@ function buildWrapperPage(args) {
|
|
|
32888
32913
|
try {
|
|
32889
32914
|
const data = msg.op === "upload"
|
|
32890
32915
|
? await handleUpload(msg.payload)
|
|
32916
|
+
: msg.op === "openExternal"
|
|
32917
|
+
? handleOpenExternal(msg.payload)
|
|
32891
32918
|
: await rpc(msg.op, msg.payload);
|
|
32892
32919
|
const ms = Math.round(performance.now() - startedAt);
|
|
32893
32920
|
console.debug("[lotics-dev] " + msg.op + " " + ms + "ms", data);
|
|
@@ -41,6 +41,16 @@ export interface StarterFile {
|
|
|
41
41
|
*/
|
|
42
42
|
export declare const STARTER_FALLBACK_UI_VERSION = "1.8.0";
|
|
43
43
|
export declare const STARTER_FALLBACK_SDK_VERSION = "0.11.0";
|
|
44
|
+
/**
|
|
45
|
+
* react-native pin for scaffolded apps. Matches the monorepo frontend's pin so
|
|
46
|
+
* an app deep-typechecks `@lotics/ui`'s `.tsx` source against the SAME RN types
|
|
47
|
+
* the package is developed and CI'd against. A mismatch surfaces RN-version-
|
|
48
|
+
* sensitive type errors (e.g. `StyleSheet.absoluteFill`, which `frontend/` CI
|
|
49
|
+
* never sees because `packages/ui` is only typechecked through `frontend/`).
|
|
50
|
+
* RN is aliased to react-native-web at runtime, so this pin is effectively
|
|
51
|
+
* types-only.
|
|
52
|
+
*/
|
|
53
|
+
export declare const STARTER_REACT_NATIVE_VERSION = "0.85.3";
|
|
44
54
|
export declare function buildStarterTemplate(args: {
|
|
45
55
|
app_name: string;
|
|
46
56
|
app_id: string;
|
package/dist/starter_template.js
CHANGED
|
@@ -37,6 +37,16 @@
|
|
|
37
37
|
*/
|
|
38
38
|
export const STARTER_FALLBACK_UI_VERSION = "1.8.0";
|
|
39
39
|
export const STARTER_FALLBACK_SDK_VERSION = "0.11.0";
|
|
40
|
+
/**
|
|
41
|
+
* react-native pin for scaffolded apps. Matches the monorepo frontend's pin so
|
|
42
|
+
* an app deep-typechecks `@lotics/ui`'s `.tsx` source against the SAME RN types
|
|
43
|
+
* the package is developed and CI'd against. A mismatch surfaces RN-version-
|
|
44
|
+
* sensitive type errors (e.g. `StyleSheet.absoluteFill`, which `frontend/` CI
|
|
45
|
+
* never sees because `packages/ui` is only typechecked through `frontend/`).
|
|
46
|
+
* RN is aliased to react-native-web at runtime, so this pin is effectively
|
|
47
|
+
* types-only.
|
|
48
|
+
*/
|
|
49
|
+
export const STARTER_REACT_NATIVE_VERSION = "0.85.3";
|
|
40
50
|
export function buildStarterTemplate(args) {
|
|
41
51
|
const uiVersion = args.ui_version ?? `^${STARTER_FALLBACK_UI_VERSION}`;
|
|
42
52
|
const sdkVersion = args.sdk_version ?? `^${STARTER_FALLBACK_SDK_VERSION}`;
|
|
@@ -72,7 +82,7 @@ export function buildStarterTemplate(args) {
|
|
|
72
82
|
"lucide-react-native": "^0.562.0",
|
|
73
83
|
react: "^19.0.0",
|
|
74
84
|
"react-dom": "^19.0.0",
|
|
75
|
-
"react-native":
|
|
85
|
+
"react-native": STARTER_REACT_NATIVE_VERSION,
|
|
76
86
|
"react-native-svg": "^15.0.0",
|
|
77
87
|
"react-native-web": "^0.21.0",
|
|
78
88
|
},
|
|
@@ -143,6 +153,11 @@ import react from "@vitejs/plugin-react";
|
|
|
143
153
|
// is identical to RN-SVG when running under RN-Web.
|
|
144
154
|
export default defineConfig({
|
|
145
155
|
plugins: [react()],
|
|
156
|
+
// RN libraries (react-native-web, @react-native-picker's UnimplementedView)
|
|
157
|
+
// reference the \`__DEV__\` global that Metro injects but Vite does not —
|
|
158
|
+
// undefined ⇒ the bundle throws at load and the iframe renders blank. Define
|
|
159
|
+
// it (false = production RN behaviour) so dev and the deployed build both boot.
|
|
160
|
+
define: { __DEV__: "false" },
|
|
146
161
|
resolve: {
|
|
147
162
|
alias: [
|
|
148
163
|
{
|
|
@@ -167,6 +182,11 @@ export default defineConfig({
|
|
|
167
182
|
// Pre-bundling forces Vite to convert it to an ESM shim with a default
|
|
168
183
|
// export. Production build (rollup) handles it correctly without this.
|
|
169
184
|
include: ["recharts", "es-toolkit", "es-toolkit/compat"],
|
|
185
|
+
// The dep optimizer pre-bundles deps with a SEPARATE esbuild pass that
|
|
186
|
+
// top-level \`define\` doesn't always reach, so a pre-bundled RN dep can
|
|
187
|
+
// still hit \`__DEV__ is not defined\` under \`lotics app dev\`. Define it
|
|
188
|
+
// here too — belt-and-suspenders with the top-level \`define\` above.
|
|
189
|
+
esbuildOptions: { define: { __DEV__: "false" } },
|
|
170
190
|
},
|
|
171
191
|
build: {
|
|
172
192
|
outDir: "dist",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { buildStarterTemplate, STARTER_FALLBACK_SDK_VERSION, STARTER_FALLBACK_UI_VERSION, } from "./starter_template.js";
|
|
2
|
+
import { buildStarterTemplate, STARTER_FALLBACK_SDK_VERSION, STARTER_FALLBACK_UI_VERSION, STARTER_REACT_NATIVE_VERSION, } from "./starter_template.js";
|
|
3
3
|
function fileNamed(files, path) {
|
|
4
4
|
const f = files.find((f) => f.path === path);
|
|
5
5
|
if (!f)
|
|
@@ -17,6 +17,23 @@ describe("buildStarterTemplate", () => {
|
|
|
17
17
|
expect(config).toContain('"es-toolkit"');
|
|
18
18
|
expect(config).toContain('"es-toolkit/compat"');
|
|
19
19
|
});
|
|
20
|
+
test("vite.config.ts defines the RN __DEV__ global (else the bundle throws at load → blank iframe)", () => {
|
|
21
|
+
// `__DEV__` is a Metro-injected global that RN-ecosystem deps reference at
|
|
22
|
+
// module-eval time (e.g. @react-native-picker's UnimplementedView, pulled in
|
|
23
|
+
// via @lotics/ui's DatePicker). Vite doesn't define it; undefined ⇒ a runtime
|
|
24
|
+
// ReferenceError that no typecheck/lint/build catches. Pin it so it can't
|
|
25
|
+
// silently regress and re-blank every app that imports such a dep.
|
|
26
|
+
const config = fileNamed(buildStarterTemplate(baseArgs), "vite.config.ts");
|
|
27
|
+
// Top-level define (covers the prod build + most dev modules)...
|
|
28
|
+
expect(config).toMatch(/define:\s*\{\s*__DEV__:\s*"false"/);
|
|
29
|
+
// ...and the dep-optimizer's separate esbuild pass (covers pre-bundled
|
|
30
|
+
// deps under `lotics app dev`).
|
|
31
|
+
expect(config).toMatch(/esbuildOptions:\s*\{\s*define:\s*\{\s*__DEV__:\s*"false"/);
|
|
32
|
+
});
|
|
33
|
+
test("package.json pins react-native to the monorepo version (so apps typecheck @lotics/ui against the same RN types)", () => {
|
|
34
|
+
const pkg = JSON.parse(fileNamed(buildStarterTemplate(baseArgs), "package.json"));
|
|
35
|
+
expect(pkg.dependencies["react-native"]).toBe(STARTER_REACT_NATIVE_VERSION);
|
|
36
|
+
});
|
|
20
37
|
test("package.json uses caller-supplied versions for @lotics/ui and @lotics/app-sdk", () => {
|
|
21
38
|
const pkg = JSON.parse(fileNamed(buildStarterTemplate({ ...baseArgs, ui_version: "^9.9.9", sdk_version: "^2.2.2" }), "package.json"));
|
|
22
39
|
expect(pkg.dependencies["@lotics/ui"]).toBe("^9.9.9");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/cli",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"description": "Lotics SDK and CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@lotics/xlsx": "*",
|
|
25
25
|
"@types/node": "^22.15.21",
|
|
26
26
|
"esbuild": "^0.25.0",
|
|
27
|
-
"vitest": "^4.
|
|
27
|
+
"vitest": "^4.1.7"
|
|
28
28
|
},
|
|
29
29
|
"keywords": [
|
|
30
30
|
"lotics",
|