@lotics/cli 0.89.1 → 0.90.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/src/cli.js +151 -118
- package/package.json +1 -1
package/dist/src/cli.js
CHANGED
|
@@ -30643,7 +30643,7 @@ import { tmpdir } from "node:os";
|
|
|
30643
30643
|
|
|
30644
30644
|
// src/starter_template.ts
|
|
30645
30645
|
var STARTER_FALLBACK_UI_VERSION = "6.1.0";
|
|
30646
|
-
var STARTER_FALLBACK_SDK_VERSION = "0.
|
|
30646
|
+
var STARTER_FALLBACK_SDK_VERSION = "0.52.0";
|
|
30647
30647
|
var STARTER_REACT_NATIVE_VERSION = "0.85.3";
|
|
30648
30648
|
var VITEST_SETUP_FILENAME = "vitest.setup.ts";
|
|
30649
30649
|
var VITEST_SETUP_CONTENT = `import { vi } from "vitest";
|
|
@@ -30793,8 +30793,32 @@ function buildStarterTemplate(args) {
|
|
|
30793
30793
|
path: "vite.config.ts",
|
|
30794
30794
|
content: `/// <reference types="vitest" />
|
|
30795
30795
|
import { defineConfig } from "vite";
|
|
30796
|
+
import type { Plugin } from "vite";
|
|
30796
30797
|
import react from "@vitejs/plugin-react";
|
|
30797
30798
|
|
|
30799
|
+
// @lotics/ui/icon.tsx deep-imports \`lucide-react-native/dist/esm/icons/<name>\`.
|
|
30800
|
+
// lucide-react-native's \`exports\` map lists only "." and "./icons", so a strict
|
|
30801
|
+
// resolver (the sandbox's vite dev optimizer) blocks the deep path with
|
|
30802
|
+
// \`Missing "./dist/esm/icons/<name>" specifier\`. lucide-react ships the same
|
|
30803
|
+
// per-icon files with NO exports map, so redirect there. A \`resolveId\` PLUGIN
|
|
30804
|
+
// (not \`resolve.alias\`) is required: the dep-optimizer SCAN runs plugin
|
|
30805
|
+
// resolveId hooks but does NOT apply regex \`resolve.alias\`, so the alias alone
|
|
30806
|
+
// fixes the production build but leaves the dev preview broken.
|
|
30807
|
+
function lucideIconsWebAlias(): Plugin {
|
|
30808
|
+
return {
|
|
30809
|
+
name: "lucide-icons-web-alias",
|
|
30810
|
+
enforce: "pre",
|
|
30811
|
+
async resolveId(source, importer, options) {
|
|
30812
|
+
const m = /^lucide-react-native\\/dist\\/esm\\/icons\\/(.+)$/.exec(source);
|
|
30813
|
+
if (!m) return null;
|
|
30814
|
+
return this.resolve(\`lucide-react/dist/esm/icons/\${m[1]}\`, importer, {
|
|
30815
|
+
...options,
|
|
30816
|
+
skipSelf: true,
|
|
30817
|
+
});
|
|
30818
|
+
},
|
|
30819
|
+
};
|
|
30820
|
+
}
|
|
30821
|
+
|
|
30798
30822
|
// Vite default base (/) emits absolute asset URLs in index.html. Lotics's
|
|
30799
30823
|
// render endpoint rewrites those to /v1/apps/{id}/asset/... so the bundle
|
|
30800
30824
|
// loads via the platform's asset proxy. Don't change \`base\` unless you
|
|
@@ -30804,14 +30828,8 @@ import react from "@vitejs/plugin-react";
|
|
|
30804
30828
|
// (View, Text, Pressable, StyleSheet, etc.) render in a pure-web environment.
|
|
30805
30829
|
// .web.tsx is prioritized in resolve.extensions so per-target variants
|
|
30806
30830
|
// (avatar.web.tsx, wave_avatar.web.tsx) win over the native .tsx file.
|
|
30807
|
-
//
|
|
30808
|
-
// @lotics/ui/icon.tsx imports from \`lucide-react-native/dist/esm/icons/<name>\`
|
|
30809
|
-
// \u2014 deep paths that lucide-react-native's package \`exports\` map blocks under
|
|
30810
|
-
// Vite's strict resolution. lucide-react has the same per-icon files with no
|
|
30811
|
-
// exports map, so we alias the deep path to use it. Web rendering of <svg>
|
|
30812
|
-
// is identical to RN-SVG when running under RN-Web.
|
|
30813
30831
|
export default defineConfig({
|
|
30814
|
-
plugins: [react()],
|
|
30832
|
+
plugins: [lucideIconsWebAlias(), react()],
|
|
30815
30833
|
// RN libraries reference globals Metro injects but Vite does not \u2014 undefined
|
|
30816
30834
|
// \u21D2 the bundle throws. \`__DEV__\` (react-native-web, @react-native-picker's
|
|
30817
30835
|
// UnimplementedView): throws at load, blank iframe. \`global\` (rn-web
|
|
@@ -30822,13 +30840,7 @@ export default defineConfig({
|
|
|
30822
30840
|
// is safe. Define both so dev and the deployed build behave identically.
|
|
30823
30841
|
define: { __DEV__: "false", global: "globalThis" },
|
|
30824
30842
|
resolve: {
|
|
30825
|
-
alias: [
|
|
30826
|
-
{
|
|
30827
|
-
find: /^lucide-react-native\\/dist\\/esm\\/icons\\/(.+)$/,
|
|
30828
|
-
replacement: "lucide-react/dist/esm/icons/$1",
|
|
30829
|
-
},
|
|
30830
|
-
{ find: "react-native", replacement: "react-native-web" },
|
|
30831
|
-
],
|
|
30843
|
+
alias: [{ find: "react-native", replacement: "react-native-web" }],
|
|
30832
30844
|
// \`.web.js\` resolves the web build of RN packages that ship \`X.js\` (native)
|
|
30833
30845
|
// beside \`X.web.js\` (web) \u2014 e.g. @react-native-picker/picker, whose compiled
|
|
30834
30846
|
// \`Picker.web.js\` renders a real <select>. Without it the extensionless
|
|
@@ -30907,6 +30919,12 @@ export default defineConfig({
|
|
|
30907
30919
|
// iframe loads modules from api.lotics.ai which already permits null
|
|
30908
30920
|
// origin via CORS.
|
|
30909
30921
|
cors: { origin: "*" },
|
|
30922
|
+
// Chat-authoring previews reach this dev server through the sandbox proxy
|
|
30923
|
+
// at \`5173-<id>-<token>.lotics-sandbox.app\`. Vite \u22655.4.12 rejects HMR
|
|
30924
|
+
// WebSocket upgrades whose Origin doesn't match a trusted host (its
|
|
30925
|
+
// cross-site WS hijack fix) \u2014 without this entry the proxied preview page
|
|
30926
|
+
// loads over HTTP but HMR never connects, so edits stop live-updating.
|
|
30927
|
+
allowedHosts: [".lotics-sandbox.app"],
|
|
30910
30928
|
// @lotics/ui/fonts.css references the API's /iframe/fonts/*.woff2 files
|
|
30911
30929
|
// by root-relative URL. A deployed app is served from the API origin so
|
|
30912
30930
|
// they resolve directly; under \`lotics app dev\` the app runs on
|
|
@@ -31050,6 +31068,7 @@ mount(
|
|
|
31050
31068
|
import { View } from "react-native";
|
|
31051
31069
|
import { useNavigate, useParams } from "react-router-dom";
|
|
31052
31070
|
import { AppRouter } from "@lotics/app-sdk/router";
|
|
31071
|
+
import { useAiContext } from "@lotics/app-sdk";
|
|
31053
31072
|
import { Card } from "@lotics/ui/card";
|
|
31054
31073
|
import { Text } from "@lotics/ui/text";
|
|
31055
31074
|
import { Button } from "@lotics/ui/button";
|
|
@@ -31114,6 +31133,16 @@ function ItemDetailScreen() {
|
|
|
31114
31133
|
const { id } = useParams();
|
|
31115
31134
|
const navigate = useNavigate();
|
|
31116
31135
|
const item = ITEMS.find((i) => i.id === id);
|
|
31136
|
+
// Tell the member's ambient chat agent what this screen is showing, so a
|
|
31137
|
+
// question like "summarise this" has context. This is PUSH-ONLY: a snapshot of
|
|
31138
|
+
// what the app rendered to the member, never a channel for chat to pull app
|
|
31139
|
+
// data \u2014 the text lands in the prompt as labeled data (not instructions) and
|
|
31140
|
+
// any record refs would act only within the member's own IAM. Pass null to
|
|
31141
|
+
// clear the slot (here: nothing to describe when the item isn't found).
|
|
31142
|
+
useAiContext(
|
|
31143
|
+
"item_detail",
|
|
31144
|
+
item ? { description: \`Viewing item "\${item.name}".\`, data: { id: item.id } } : null,
|
|
31145
|
+
);
|
|
31117
31146
|
return (
|
|
31118
31147
|
<Screen>
|
|
31119
31148
|
{/* An in-app Back control; navigate(-1) walks the history (the browser Back
|
|
@@ -31203,9 +31232,9 @@ each alias lives in \`package.json#lotics.workflows.<alias>\`.
|
|
|
31203
31232
|
path: "src/lucide-react-native.d.ts",
|
|
31204
31233
|
content: `// Type shim for lucide-react-native's deep-icon imports
|
|
31205
31234
|
// (\`lucide-react-native/dist/esm/icons/<name>\`). The package ships JS-only
|
|
31206
|
-
// files without per-file .d.ts. The
|
|
31207
|
-
// these to lucide-react at
|
|
31208
|
-
// TypeScript compile-time gap.
|
|
31235
|
+
// files without per-file .d.ts. The lucideIconsWebAlias() plugin in
|
|
31236
|
+
// vite.config.ts redirects these to lucide-react at resolve time; this
|
|
31237
|
+
// declaration covers the TypeScript compile-time gap.
|
|
31209
31238
|
declare module "lucide-react-native/dist/esm/icons/*" {
|
|
31210
31239
|
import type { ComponentType } from "react";
|
|
31211
31240
|
const Icon: ComponentType<{
|
|
@@ -32266,48 +32295,10 @@ function openBrowser(url) {
|
|
|
32266
32295
|
child.unref();
|
|
32267
32296
|
}
|
|
32268
32297
|
|
|
32269
|
-
// src/
|
|
32270
|
-
var
|
|
32271
|
-
|
|
32272
|
-
|
|
32273
|
-
// This file gives \`useWorkflow("alias")\` a typed input parameter at call
|
|
32274
|
-
// sites by augmenting the @lotics/app-sdk \`AppWorkflows\` interface.
|
|
32275
|
-
|
|
32276
|
-
import "@lotics/app-sdk";
|
|
32277
|
-
`;
|
|
32278
|
-
function generateAppWorkflowsDts(workflows) {
|
|
32279
|
-
const entries = Object.entries(workflows ?? {});
|
|
32280
|
-
if (entries.length === 0) {
|
|
32281
|
-
return `${HEADER}
|
|
32282
|
-
// No workflows declared in package.json#lotics.workflows.
|
|
32283
|
-
// Add an entry to enable typed useWorkflow<"alias"> at call sites.
|
|
32284
|
-
declare module "@lotics/app-sdk" {
|
|
32285
|
-
interface AppWorkflows {}
|
|
32286
|
-
}
|
|
32287
|
-
`;
|
|
32288
|
-
}
|
|
32289
|
-
entries.sort(([a], [b]) => a.localeCompare(b));
|
|
32290
|
-
const inputLines = [];
|
|
32291
|
-
const resultLines = [];
|
|
32292
|
-
for (const [alias, declaration] of entries) {
|
|
32293
|
-
const valueType = declaration.inputs ? inputsToType(declaration.inputs, { nullableOptional: true }) : "Record<string, unknown>";
|
|
32294
|
-
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
32295
|
-
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
32296
|
-
if (declaration.outputs) {
|
|
32297
|
-
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
32298
|
-
}
|
|
32299
|
-
}
|
|
32300
|
-
const resultsBlock = resultLines.length > 0 ? `
|
|
32301
|
-
interface AppWorkflowResults {
|
|
32302
|
-
${resultLines.join("\n")}
|
|
32303
|
-
}` : "";
|
|
32304
|
-
return `${HEADER}
|
|
32305
|
-
declare module "@lotics/app-sdk" {
|
|
32306
|
-
interface AppWorkflows {
|
|
32307
|
-
${inputLines.join("\n")}
|
|
32308
|
-
}${resultsBlock}
|
|
32309
|
-
}
|
|
32310
|
-
`;
|
|
32298
|
+
// ../shared/src/app_dts.ts
|
|
32299
|
+
var IDENTIFIER_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
32300
|
+
function isValidIdentifier(name) {
|
|
32301
|
+
return IDENTIFIER_REGEX.test(name);
|
|
32311
32302
|
}
|
|
32312
32303
|
function inputsToType(inputs, opts) {
|
|
32313
32304
|
const nullableOptional = opts?.nullableOptional === true;
|
|
@@ -32421,28 +32412,56 @@ function outputDeclToTsType(decl) {
|
|
|
32421
32412
|
return "unknown";
|
|
32422
32413
|
}
|
|
32423
32414
|
}
|
|
32424
|
-
var
|
|
32425
|
-
|
|
32426
|
-
|
|
32427
|
-
|
|
32415
|
+
var QUERIES_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
32416
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.queries.
|
|
32417
|
+
//
|
|
32418
|
+
// This file gives \`useQuery("alias", params)\` typed params at call sites by
|
|
32419
|
+
// augmenting the @lotics/app-sdk \`AppQueries\` interface.
|
|
32428
32420
|
|
|
32429
|
-
|
|
32430
|
-
|
|
32431
|
-
|
|
32421
|
+
import "@lotics/app-sdk";
|
|
32422
|
+
`;
|
|
32423
|
+
function generateAppQueriesDts(queries) {
|
|
32424
|
+
const entries = Object.entries(queries ?? {});
|
|
32425
|
+
if (entries.length === 0) {
|
|
32426
|
+
return `${QUERIES_HEADER}
|
|
32427
|
+
// No queries declared in package.json#lotics.queries.
|
|
32428
|
+
// Add an entry to enable typed useQuery("alias", params) at call sites.
|
|
32429
|
+
declare module "@lotics/app-sdk" {
|
|
32430
|
+
interface AppQueries {}
|
|
32431
|
+
}
|
|
32432
|
+
`;
|
|
32433
|
+
}
|
|
32434
|
+
entries.sort(([a], [b]) => a.localeCompare(b));
|
|
32435
|
+
const lines = [];
|
|
32436
|
+
for (const [alias, declaration] of entries) {
|
|
32437
|
+
const valueType = inputsToType(declaration.params ?? {});
|
|
32438
|
+
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
32439
|
+
lines.push(` ${aliasKey}: ${valueType};`);
|
|
32440
|
+
}
|
|
32441
|
+
return `${QUERIES_HEADER}
|
|
32442
|
+
declare module "@lotics/app-sdk" {
|
|
32443
|
+
interface AppQueries {
|
|
32444
|
+
${lines.join("\n")}
|
|
32445
|
+
}
|
|
32446
|
+
}
|
|
32447
|
+
`;
|
|
32448
|
+
}
|
|
32449
|
+
var WORKFLOWS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
32450
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.workflows.
|
|
32432
32451
|
//
|
|
32433
|
-
// This file gives \`
|
|
32434
|
-
// augmenting the @lotics/app-sdk \`
|
|
32452
|
+
// This file gives \`useWorkflow("alias")\` a typed input parameter at call
|
|
32453
|
+
// sites by augmenting the @lotics/app-sdk \`AppWorkflows\` interface.
|
|
32435
32454
|
|
|
32436
32455
|
import "@lotics/app-sdk";
|
|
32437
32456
|
`;
|
|
32438
|
-
function
|
|
32439
|
-
const entries = Object.entries(
|
|
32457
|
+
function generateAppWorkflowsDts(workflows) {
|
|
32458
|
+
const entries = Object.entries(workflows ?? {});
|
|
32440
32459
|
if (entries.length === 0) {
|
|
32441
|
-
return `${
|
|
32442
|
-
// No
|
|
32443
|
-
// Add an entry to enable typed
|
|
32460
|
+
return `${WORKFLOWS_HEADER}
|
|
32461
|
+
// No workflows declared in package.json#lotics.workflows.
|
|
32462
|
+
// Add an entry to enable typed useWorkflow<"alias"> at call sites.
|
|
32444
32463
|
declare module "@lotics/app-sdk" {
|
|
32445
|
-
interface
|
|
32464
|
+
interface AppWorkflows {}
|
|
32446
32465
|
}
|
|
32447
32466
|
`;
|
|
32448
32467
|
}
|
|
@@ -32450,7 +32469,7 @@ declare module "@lotics/app-sdk" {
|
|
|
32450
32469
|
const inputLines = [];
|
|
32451
32470
|
const resultLines = [];
|
|
32452
32471
|
for (const [alias, declaration] of entries) {
|
|
32453
|
-
const valueType = declaration.inputs ? inputsToType(declaration.inputs) : "Record<string, unknown>";
|
|
32472
|
+
const valueType = declaration.inputs ? inputsToType(declaration.inputs, { nullableOptional: true }) : "Record<string, unknown>";
|
|
32454
32473
|
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
32455
32474
|
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
32456
32475
|
if (declaration.outputs) {
|
|
@@ -32458,53 +32477,78 @@ declare module "@lotics/app-sdk" {
|
|
|
32458
32477
|
}
|
|
32459
32478
|
}
|
|
32460
32479
|
const resultsBlock = resultLines.length > 0 ? `
|
|
32461
|
-
interface
|
|
32480
|
+
interface AppWorkflowResults {
|
|
32462
32481
|
${resultLines.join("\n")}
|
|
32463
32482
|
}` : "";
|
|
32464
|
-
return `${
|
|
32483
|
+
return `${WORKFLOWS_HEADER}
|
|
32465
32484
|
declare module "@lotics/app-sdk" {
|
|
32466
|
-
interface
|
|
32485
|
+
interface AppWorkflows {
|
|
32467
32486
|
${inputLines.join("\n")}
|
|
32468
32487
|
}${resultsBlock}
|
|
32469
32488
|
}
|
|
32470
32489
|
`;
|
|
32471
32490
|
}
|
|
32472
|
-
|
|
32473
|
-
//
|
|
32474
|
-
var HEADER3 = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
32475
|
-
// DO NOT EDIT \u2014 regenerated from package.json#lotics.queries.
|
|
32491
|
+
var AGENTS_HEADER = `// Auto-generated by 'lotics app pull/dev/deploy'.
|
|
32492
|
+
// DO NOT EDIT \u2014 regenerated from package.json#lotics.agents.
|
|
32476
32493
|
//
|
|
32477
|
-
// This file gives \`
|
|
32478
|
-
// augmenting the @lotics/app-sdk \`
|
|
32494
|
+
// This file gives \`useAgentRun("alias")\` typed input + output at call sites by
|
|
32495
|
+
// augmenting the @lotics/app-sdk \`AppAgents\` / \`AppAgentResults\` interfaces.
|
|
32479
32496
|
|
|
32480
32497
|
import "@lotics/app-sdk";
|
|
32481
32498
|
`;
|
|
32482
|
-
function
|
|
32483
|
-
const entries = Object.entries(
|
|
32499
|
+
function generateAppAgentsDts(agents) {
|
|
32500
|
+
const entries = Object.entries(agents ?? {});
|
|
32484
32501
|
if (entries.length === 0) {
|
|
32485
|
-
return `${
|
|
32486
|
-
// No
|
|
32487
|
-
// Add an entry to enable typed
|
|
32502
|
+
return `${AGENTS_HEADER}
|
|
32503
|
+
// No agents declared in package.json#lotics.agents.
|
|
32504
|
+
// Add an entry to enable typed useAgentRun<"alias"> at call sites.
|
|
32488
32505
|
declare module "@lotics/app-sdk" {
|
|
32489
|
-
interface
|
|
32506
|
+
interface AppAgents {}
|
|
32490
32507
|
}
|
|
32491
32508
|
`;
|
|
32492
32509
|
}
|
|
32493
32510
|
entries.sort(([a], [b]) => a.localeCompare(b));
|
|
32494
|
-
const
|
|
32511
|
+
const inputLines = [];
|
|
32512
|
+
const resultLines = [];
|
|
32495
32513
|
for (const [alias, declaration] of entries) {
|
|
32496
|
-
const valueType = inputsToType(declaration.
|
|
32514
|
+
const valueType = declaration.inputs ? inputsToType(declaration.inputs) : "Record<string, unknown>";
|
|
32497
32515
|
const aliasKey = isValidIdentifier(alias) ? alias : JSON.stringify(alias);
|
|
32498
|
-
|
|
32516
|
+
inputLines.push(` ${aliasKey}: ${valueType};`);
|
|
32517
|
+
if (declaration.outputs) {
|
|
32518
|
+
resultLines.push(` ${aliasKey}: ${objectFieldsToType(declaration.outputs)};`);
|
|
32519
|
+
}
|
|
32499
32520
|
}
|
|
32500
|
-
|
|
32521
|
+
const resultsBlock = resultLines.length > 0 ? `
|
|
32522
|
+
interface AppAgentResults {
|
|
32523
|
+
${resultLines.join("\n")}
|
|
32524
|
+
}` : "";
|
|
32525
|
+
return `${AGENTS_HEADER}
|
|
32501
32526
|
declare module "@lotics/app-sdk" {
|
|
32502
|
-
interface
|
|
32503
|
-
${
|
|
32504
|
-
}
|
|
32527
|
+
interface AppAgents {
|
|
32528
|
+
${inputLines.join("\n")}
|
|
32529
|
+
}${resultsBlock}
|
|
32505
32530
|
}
|
|
32506
32531
|
`;
|
|
32507
32532
|
}
|
|
32533
|
+
var CAPABILITY_GATED_CALLS = {
|
|
32534
|
+
comments: ["useComments", "createComment", "updateComment", "deleteComment"]
|
|
32535
|
+
};
|
|
32536
|
+
function undeclaredCapabilities(sourceText, declared) {
|
|
32537
|
+
const used = [];
|
|
32538
|
+
for (const [capability, calls] of Object.entries(CAPABILITY_GATED_CALLS)) {
|
|
32539
|
+
const isCalled = calls.some((call) => new RegExp(`\\b${call}\\b`).test(sourceText));
|
|
32540
|
+
if (isCalled && declared?.[capability] !== true) used.push(capability);
|
|
32541
|
+
}
|
|
32542
|
+
return used;
|
|
32543
|
+
}
|
|
32544
|
+
function unboundAliases(declared, bound) {
|
|
32545
|
+
const boundWorkflows = new Set(bound.workflows ?? []);
|
|
32546
|
+
const boundAgents = new Set(bound.agents ?? []);
|
|
32547
|
+
return {
|
|
32548
|
+
workflows: [...declared.workflows ?? []].filter((a) => !boundWorkflows.has(a)),
|
|
32549
|
+
agents: [...declared.agents ?? []].filter((a) => !boundAgents.has(a))
|
|
32550
|
+
};
|
|
32551
|
+
}
|
|
32508
32552
|
|
|
32509
32553
|
// ../shared/src/app_query_ast.ts
|
|
32510
32554
|
function collectQueryTableIds(node) {
|
|
@@ -32545,7 +32589,7 @@ function walk(node, visit) {
|
|
|
32545
32589
|
}
|
|
32546
32590
|
|
|
32547
32591
|
// src/generate_app_fields.ts
|
|
32548
|
-
var
|
|
32592
|
+
var HEADER = `// Auto-generated by 'lotics app codegen' (and app pull/dev/deploy).
|
|
32549
32593
|
// DO NOT EDIT \u2014 regenerated from the workspace schema.
|
|
32550
32594
|
//
|
|
32551
32595
|
// Runtime field + option ids addressed by stable display-name aliases:
|
|
@@ -32639,7 +32683,7 @@ ${tableBlocks.join("\n")}
|
|
|
32639
32683
|
}
|
|
32640
32684
|
function generateAppFields(tables) {
|
|
32641
32685
|
if (tables.length === 0) {
|
|
32642
|
-
return `${
|
|
32686
|
+
return `${HEADER}
|
|
32643
32687
|
export const F = {} as const;
|
|
32644
32688
|
|
|
32645
32689
|
export const OPT = {} as const;
|
|
@@ -32651,7 +32695,7 @@ export type AppOptions = typeof OPT;
|
|
|
32651
32695
|
`;
|
|
32652
32696
|
}
|
|
32653
32697
|
const aliased = aliasTables(tables);
|
|
32654
|
-
return `${
|
|
32698
|
+
return `${HEADER}
|
|
32655
32699
|
${emitFieldMap(aliased)}
|
|
32656
32700
|
|
|
32657
32701
|
${emitOptionMap(aliased)}
|
|
@@ -32664,7 +32708,7 @@ export type AppOptions = typeof OPT;
|
|
|
32664
32708
|
}
|
|
32665
32709
|
|
|
32666
32710
|
// src/generate_package_fields.ts
|
|
32667
|
-
var
|
|
32711
|
+
var HEADER2 = `// Auto-generated by 'lotics app codegen' (linked/published app; also app pull/dev/deploy).
|
|
32668
32712
|
// DO NOT EDIT \u2014 regenerated from the installation's live binding.
|
|
32669
32713
|
//
|
|
32670
32714
|
// A package installation resolves F/OPT/ROLE at MODULE LOAD from its binding
|
|
@@ -32764,7 +32808,7 @@ ${lines.join("\n")}
|
|
|
32764
32808
|
}
|
|
32765
32809
|
function generatePackageAppFields(binding) {
|
|
32766
32810
|
const { entities, roles } = parseBinding(binding);
|
|
32767
|
-
return `${
|
|
32811
|
+
return `${HEADER2}
|
|
32768
32812
|
${emitFieldMap2(entities)}
|
|
32769
32813
|
|
|
32770
32814
|
${emitOptionMap2(entities)}
|
|
@@ -33361,17 +33405,6 @@ Ready. Next steps:`);
|
|
|
33361
33405
|
console.error(` # edit src/App.tsx`);
|
|
33362
33406
|
console.error(` lotics app deploy`);
|
|
33363
33407
|
}
|
|
33364
|
-
var CAPABILITY_GATED_CALLS = {
|
|
33365
|
-
comments: ["useComments", "createComment", "updateComment", "deleteComment"]
|
|
33366
|
-
};
|
|
33367
|
-
function undeclaredCapabilities(sourceText, declared) {
|
|
33368
|
-
const used = [];
|
|
33369
|
-
for (const [capability, calls] of Object.entries(CAPABILITY_GATED_CALLS)) {
|
|
33370
|
-
const isCalled = calls.some((call) => new RegExp(`\\b${call}\\b`).test(sourceText));
|
|
33371
|
-
if (isCalled && declared?.[capability] !== true) used.push(capability);
|
|
33372
|
-
}
|
|
33373
|
-
return used;
|
|
33374
|
-
}
|
|
33375
33408
|
function readAppSourceText(projectDir) {
|
|
33376
33409
|
const srcDir = path5.join(projectDir, "src");
|
|
33377
33410
|
if (!fs4.existsSync(srcDir)) return "";
|
|
@@ -33492,10 +33525,10 @@ function warnIfUnbranded(app) {
|
|
|
33492
33525
|
);
|
|
33493
33526
|
}
|
|
33494
33527
|
function warnIfUnboundAliases(app, declaredWorkflows, declaredAgents) {
|
|
33495
|
-
const
|
|
33496
|
-
|
|
33497
|
-
|
|
33498
|
-
|
|
33528
|
+
const { workflows: unboundWorkflows, agents: unboundAgents } = unboundAliases(
|
|
33529
|
+
{ workflows: Object.keys(declaredWorkflows), agents: Object.keys(declaredAgents) },
|
|
33530
|
+
{ workflows: Object.keys(app.workflows ?? {}), agents: Object.keys(app.agents ?? {}) }
|
|
33531
|
+
);
|
|
33499
33532
|
if (unboundWorkflows.length === 0 && unboundAgents.length === 0) return;
|
|
33500
33533
|
const lines = [
|
|
33501
33534
|
"\n\u26A0 The manifest declares aliases that are NOT bound on the server. Deploy ships code +",
|