@lunora/vite 1.0.0-alpha.2 → 1.0.0-alpha.200

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.
Files changed (33) hide show
  1. package/LICENSE.md +6 -0
  2. package/README.md +19 -2
  3. package/__assets__/package-og.svg +1 -1
  4. package/dist/index.d.mts +448 -262
  5. package/dist/index.d.ts +448 -262
  6. package/dist/index.mjs +3 -153
  7. package/dist/packem_shared/CLASS_A_WIRING-CEzeqjr2.mjs +33 -0
  8. package/dist/packem_shared/LUNORA_API_UPDATED_EVENT-CO2Rv2re.mjs +1 -0
  9. package/dist/packem_shared/STUDIO_PATH-UztnV2ca.mjs +1 -0
  10. package/dist/packem_shared/WORKER_STARTUP_HINT-COlRTY32.mjs +5 -0
  11. package/dist/packem_shared/checkLunoraProxy-C9M8c5eS.mjs +1 -0
  12. package/dist/packem_shared/codegen-plugin-dg384k5b.mjs +3 -0
  13. package/dist/packem_shared/codegenPlugin-Ce_SRTEe.mjs +1 -0
  14. package/dist/packem_shared/containerLogsPlugin-CWkqSCL3.mjs +1 -0
  15. package/dist/packem_shared/devStatePlugin-CcFV-eBl.mjs +1 -0
  16. package/dist/packem_shared/devVariablesPlugin-DY_bJXsX.mjs +1 -0
  17. package/dist/packem_shared/log-DE48L4Oz.mjs +1 -0
  18. package/dist/packem_shared/logStreamPlugin-DtOu5VX8.mjs +3 -0
  19. package/dist/packem_shared/lunoraSolutionFinder--J0x2mAM.mjs +1 -0
  20. package/dist/packem_shared/planViteRemoteBindings-E3GdC6pY.mjs +1 -0
  21. package/dist/packem_shared/server-close-Qoh4i6Ay.mjs +1 -0
  22. package/dist/packem_shared/wranglerValidatorPlugin-BdKLAEoq.mjs +3 -0
  23. package/package.json +9 -10
  24. package/dist/packem_shared/augmentWorkerStartupError-DhsXUW8k.mjs +0 -81
  25. package/dist/packem_shared/buildStudioUrl-5ppCdBHa.mjs +0 -210
  26. package/dist/packem_shared/codegenPlugin-BAyt6iWS.mjs +0 -210
  27. package/dist/packem_shared/createCommandProbe-Coo6bgVz.mjs +0 -36
  28. package/dist/packem_shared/devVariablesPlugin-BRWbWHhq.mjs +0 -20
  29. package/dist/packem_shared/frameworkComposePlugin-Cja0SF6x.mjs +0 -96
  30. package/dist/packem_shared/logStreamPlugin-CqvZ17kd.mjs +0 -61
  31. package/dist/packem_shared/planViteRemoteBindings-QN5ncUS1.mjs +0 -50
  32. package/dist/packem_shared/reconcileWranglerCrons-PxGwfCp_.mjs +0 -29
  33. package/dist/packem_shared/wranglerValidatorPlugin-Cf0nLP7-.mjs +0 -63
package/dist/index.mjs CHANGED
@@ -1,153 +1,3 @@
1
- import { cloudflare } from '@cloudflare/vite-plugin';
2
- import errorOverlayPlugin from '@visulima/vite-overlay';
3
- import { detectAgentRules, claimAgentRulesHint, AGENT_RULES_HINT, detectFramework } from '@lunora/config';
4
- export { detectFramework } from '@lunora/config';
5
- import codegenPlugin from './packem_shared/codegenPlugin-BAyt6iWS.mjs';
6
- import devVariablesPlugin from './packem_shared/devVariablesPlugin-BRWbWHhq.mjs';
7
- import { createCommandProbe, withDevWorkerEnv } from './packem_shared/createCommandProbe-Coo6bgVz.mjs';
8
- export { DEV_WORKER_ENV_VALUE, DEV_WORKER_ENV_VAR } from './packem_shared/createCommandProbe-Coo6bgVz.mjs';
9
- import { frameworkComposePlugin } from './packem_shared/frameworkComposePlugin-Cja0SF6x.mjs';
10
- export { CLASS_A_WIRING, LUNORA_WORKER_VIRTUAL_ID, buildWorkerEntrySource, isAutoComposable } from './packem_shared/frameworkComposePlugin-Cja0SF6x.mjs';
11
- import logStreamPlugin from './packem_shared/logStreamPlugin-CqvZ17kd.mjs';
12
- import { planViteRemoteBindings, remoteBindingsCleanupPlugin, withRemoteBindings } from './packem_shared/planViteRemoteBindings-QN5ncUS1.mjs';
13
- import { studioPlugin } from './packem_shared/buildStudioUrl-5ppCdBHa.mjs';
14
- export { STUDIO_PATH, buildStudioUrl } from './packem_shared/buildStudioUrl-5ppCdBHa.mjs';
15
- import { withWorkerStartupHint } from './packem_shared/augmentWorkerStartupError-DhsXUW8k.mjs';
16
- export { WORKER_STARTUP_HINT, augmentWorkerStartupError, isWorkerEntryEvalError } from './packem_shared/augmentWorkerStartupError-DhsXUW8k.mjs';
17
- import { wranglerValidatorPlugin } from './packem_shared/wranglerValidatorPlugin-Cf0nLP7-.mjs';
18
- export { reconcileWranglerCrons } from './packem_shared/reconcileWranglerCrons-PxGwfCp_.mjs';
19
-
20
- const agentRulesHintPlugin = (options) => {
21
- return {
22
- apply: "serve",
23
- configureServer(server) {
24
- return () => {
25
- if (detectAgentRules(options.projectRoot).installed || !claimAgentRulesHint()) {
26
- return;
27
- }
28
- server.config.logger.warn(`
29
- [lunora] ${AGENT_RULES_HINT}
30
- `);
31
- };
32
- },
33
- name: "lunora:agent-rules-hint"
34
- };
35
- };
36
-
37
- const createPluginContext = () => {
38
- return {};
39
- };
40
- const FRAMEWORK_LABELS = {
41
- astro: "Astro",
42
- none: "standalone (SPA / SSR-less)",
43
- nuxt: "Nuxt",
44
- "react-router": "React Router",
45
- "solid-start": "SolidStart",
46
- sveltekit: "SvelteKit",
47
- "tanstack-start": "TanStack Start",
48
- "tanstack-start-solid": "TanStack Start (Solid)"
49
- };
50
- const formatFrameworkDetection = (detection) => {
51
- const label = FRAMEWORK_LABELS[detection.framework];
52
- if (detection.framework === "none") {
53
- return "[lunora] no meta-framework detected — running standalone (class C).";
54
- }
55
- if (detection.class === "B") {
56
- return `[lunora] detected ${label} (class B) — hook-injection composition is handled by the framework adapter (not yet wired here).`;
57
- }
58
- return `[lunora] detected ${label} (class ${detection.class}) — composing the Lunora worker into one Cloudflare Worker.`;
59
- };
60
- const frameworkDetectPlugin = (options, context) => {
61
- let logged = false;
62
- const detect = () => {
63
- context.framework ??= detectFramework(options.projectRoot);
64
- };
65
- return {
66
- config() {
67
- detect();
68
- },
69
- configResolved() {
70
- detect();
71
- },
72
- configureServer() {
73
- detect();
74
- if (!logged && context.framework !== void 0) {
75
- logged = true;
76
- console.info(formatFrameworkDetection(context.framework));
77
- }
78
- },
79
- name: "lunora:framework-detect"
80
- };
81
- };
82
-
83
- const resolveOptions = (options) => {
84
- const input = options ?? {};
85
- const schemaDirectory = input.schemaDir ?? "lunora";
86
- let cloudflareOption;
87
- if (input.cloudflare === false) {
88
- cloudflareOption = false;
89
- } else if (input.cloudflare === true || input.cloudflare === void 0) {
90
- cloudflareOption = {};
91
- } else {
92
- cloudflareOption = input.cloudflare;
93
- }
94
- let overlayOption;
95
- if (input.overlay === false) {
96
- overlayOption = false;
97
- } else if (input.overlay === true || input.overlay === void 0) {
98
- overlayOption = {};
99
- } else {
100
- overlayOption = input.overlay;
101
- }
102
- return {
103
- apiSpec: input.apiSpec ?? "openapi",
104
- cloudflare: cloudflareOption,
105
- studio: input.studio ?? true,
106
- generatedDir: input.generatedDir ?? `${schemaDirectory}/_generated`,
107
- overlay: overlayOption,
108
- projectRoot: input.projectRoot ?? process.cwd(),
109
- schemaDir: schemaDirectory,
110
- validateWrangler: input.validateWrangler ?? true
111
- };
112
- };
113
- const lunora = (options) => {
114
- const resolved = resolveOptions(options);
115
- const context = createPluginContext();
116
- const { isServe, plugin: commandProbe } = createCommandProbe();
117
- const plugins = [
118
- commandProbe,
119
- frameworkDetectPlugin(resolved, context),
120
- // Reads the detected framework off `context` and, for a class-A
121
- // framework (and only when the CF integration is on), resolves the
122
- // `virtual:lunora/worker` entry to a `composeWorker`-based worker that
123
- // routes `/_lunora/*` to Lunora and falls through to the framework SSR
124
- // handler — so the template never hand-wires `createWorker({ httpRouter })`.
125
- // A strict no-op for class-C and the `cloudflare: false` BYO path.
126
- frameworkComposePlugin(resolved, context),
127
- devVariablesPlugin(resolved),
128
- codegenPlugin(resolved),
129
- logStreamPlugin(),
130
- agentRulesHintPlugin(resolved)
131
- ];
132
- if (resolved.studio) {
133
- plugins.push(studioPlugin());
134
- }
135
- if (resolved.validateWrangler) {
136
- plugins.push(wranglerValidatorPlugin(resolved));
137
- }
138
- if (resolved.overlay !== false) {
139
- plugins.push(errorOverlayPlugin(resolved.overlay));
140
- }
141
- if (resolved.cloudflare !== false) {
142
- const remotePlan = planViteRemoteBindings({ projectRoot: resolved.projectRoot });
143
- if (remotePlan.enabled && remotePlan.configPath !== void 0) {
144
- plugins.push(remoteBindingsCleanupPlugin(remotePlan.cleanup));
145
- }
146
- const cloudflareOptions = withRemoteBindings(withDevWorkerEnv(resolved.cloudflare, isServe), isServe, remotePlan);
147
- plugins.push(...withWorkerStartupHint(cloudflare(cloudflareOptions)));
148
- }
149
- return plugins;
150
- };
151
- const VERSION = "0.0.0";
152
-
153
- export { VERSION, codegenPlugin, createCommandProbe, devVariablesPlugin, frameworkComposePlugin, logStreamPlugin, lunora, planViteRemoteBindings, remoteBindingsCleanupPlugin, studioPlugin, withDevWorkerEnv, withRemoteBindings, withWorkerStartupHint, wranglerValidatorPlugin };
1
+ import{createRequire as i}from"node:module";import{cloudflare as l}from"@cloudflare/vite-plugin";import{detectAgentRules as s,claimAgentRulesHint as u,AGENT_RULES_HINT as c,detectFramework as f,resolveTargetOrThrow as d,isRunnableTarget as m,runnableTargetIds as p}from"@lunora/config";import{detectFramework as ar}from"@lunora/config";import g from"@visulima/vite-overlay";import{l as a}from"./packem_shared/log-DE48L4Oz.mjs";import{r as S,c as v}from"./packem_shared/codegen-plugin-dg384k5b.mjs";import w from"./packem_shared/containerLogsPlugin-CWkqSCL3.mjs";import R from"./packem_shared/devStatePlugin-CcFV-eBl.mjs";import h from"./packem_shared/devVariablesPlugin-DY_bJXsX.mjs";import{frameworkComposePlugin as k}from"./packem_shared/CLASS_A_WIRING-CEzeqjr2.mjs";import{CLASS_A_WIRING as lr,GENERATED_CLASS_MODULES as sr,LUNORA_WORKER_VIRTUAL_ID as ur,buildWorkerEntrySource as cr,isAutoComposable as fr}from"./packem_shared/CLASS_A_WIRING-CEzeqjr2.mjs";import P from"./packem_shared/logStreamPlugin-DtOu5VX8.mjs";import{proxyCheckPlugin as A}from"./packem_shared/checkLunoraProxy-C9M8c5eS.mjs";import{checkLunoraProxy as mr}from"./packem_shared/checkLunoraProxy-C9M8c5eS.mjs";import{remoteBindingsPlugin as E}from"./packem_shared/planViteRemoteBindings-E3GdC6pY.mjs";import{planViteRemoteBindings as gr,withRemoteBindings as Sr}from"./packem_shared/planViteRemoteBindings-E3GdC6pY.mjs";import{lunoraSolutionFinders as T}from"./packem_shared/lunoraSolutionFinder--J0x2mAM.mjs";import{lunoraSolutionFinder as wr}from"./packem_shared/lunoraSolutionFinder--J0x2mAM.mjs";import{studioPlugin as _}from"./packem_shared/STUDIO_PATH-UztnV2ca.mjs";import{STUDIO_PATH as hr,buildStudioUrl as kr}from"./packem_shared/STUDIO_PATH-UztnV2ca.mjs";import{withWorkerStartupHint as x}from"./packem_shared/WORKER_STARTUP_HINT-COlRTY32.mjs";import{WORKER_STARTUP_HINT as Ar,augmentWorkerStartupError as Er,isWorkerEntryEvalError as Tr}from"./packem_shared/WORKER_STARTUP_HINT-COlRTY32.mjs";import{wranglerValidatorPlugin as O}from"./packem_shared/wranglerValidatorPlugin-BdKLAEoq.mjs";import{default as xr}from"./packem_shared/LUNORA_API_UPDATED_EVENT-CO2Rv2re.mjs";import{reconcileWranglerCrons as br}from"@lunora/config/cloudflare";const b=o=>({apply:"serve",configureServer(r){return()=>{s(o.projectRoot).installed||!u()||r.config.logger.warn(`
2
+ ${a(c)}
3
+ `)}},name:"lunora:agent-rules-hint"}),y=o=>({async config(r,t){t.isPreview!==!0&&await S(o,{info:e=>{console.info(e)},warn:e=>{console.warn(e)}})},enforce:"pre",name:"lunora:bindings-provision"}),L=()=>({}),W={astro:"Astro",none:"standalone (SPA / SSR-less)",nuxt:"Nuxt","react-router":"React Router","solid-start":"SolidStart",sveltekit:"SvelteKit","tanstack-start":"TanStack Start","tanstack-start-solid":"TanStack Start (Solid)",vinext:"Next.js on Vite (vinext)"},D=o=>{const r=W[o.framework];return o.framework==="none"?a("no meta-framework detected — running standalone."):o.class==="B"?a(`detected ${r} — composition is handled by the framework adapter.`):a(`detected ${r} — composing the Lunora worker into one Cloudflare Worker.`)},C=(o,r)=>{let t=!1;const e=()=>{r.framework??=f(o.projectRoot)};return{config(){e()},configResolved(){e()},configureServer(){e(),!t&&r.framework!==void 0&&(t=!0,console.info(D(r.framework)))},name:"lunora:framework-detect"}},N=o=>{if(o===!1)return!1;const r=o===!0||o===void 0?{}:o;return{...r,forwardedConsoleMethods:r.forwardedConsoleMethods??["error","warn"],solutionFinders:[...T,...r.solutionFinders??[]]}},U=(o,r)=>{const t=d(o,r);if(!m(t)){const e=p();throw new Error(`target "${t}" has no command-line toolchain, so the Lunora Vite plugin cannot build or serve it — it can only generate for it (\`lunora codegen --target ${t}\`). Buildable targets: ${e.join(", ")}`)}return t},I=o=>{const r=o??{},t=r.schemaDir??"lunora";let e;r.cloudflare===!1?e=!1:r.cloudflare===!0||r.cloudflare===void 0?e={}:e=r.cloudflare;const n=r.projectRoot??process.cwd();return{allowUnauthenticatedShardAccess:r.allowUnauthenticatedShardAccess??!1,apiSpec:r.apiSpec??"openapi",cloudflare:e,studio:r.studio??!0,generatedDir:`${t}/_generated`,overlay:N(r.overlay),projectRoot:n,schemaDir:t,shard:r.shard??{},target:U(n,r.target),validateWrangler:r.validateWrangler??!0}},er=o=>{const r=I(o),t=L(),e=[C(r,t),k(r,t),h(r),y(r),v(r),P(),R(r),b(r),A()];r.studio&&e.push(_(r)),r.validateWrangler&&e.push(O(r)),r.overlay!==!1&&e.push(g(r.overlay)),e.push(w(r));const n=r.cloudflare===!1?void 0:{...r.cloudflare};return e.push(E(n,{projectRoot:r.projectRoot})),n!==void 0&&e.push(...x(l(n))),e},or=i(import.meta.url)("../package.json").version;export{lr as CLASS_A_WIRING,sr as GENERATED_CLASS_MODULES,xr as LUNORA_API_UPDATED_EVENT,ur as LUNORA_WORKER_VIRTUAL_ID,hr as STUDIO_PATH,or as VERSION,Ar as WORKER_STARTUP_HINT,Er as augmentWorkerStartupError,kr as buildStudioUrl,cr as buildWorkerEntrySource,mr as checkLunoraProxy,v as codegenPlugin,w as containerLogsPlugin,ar as detectFramework,R as devStatePlugin,h as devVariablesPlugin,k as frameworkComposePlugin,fr as isAutoComposable,Tr as isWorkerEntryEvalError,P as logStreamPlugin,er as lunora,wr as lunoraSolutionFinder,T as lunoraSolutionFinders,gr as planViteRemoteBindings,A as proxyCheckPlugin,br as reconcileWranglerCrons,E as remoteBindingsPlugin,N as resolveOverlayOption,_ as studioPlugin,Sr as withRemoteBindings,x as withWorkerStartupHint,O as wranglerValidatorPlugin};
@@ -0,0 +1,33 @@
1
+ import{existsSync as w}from"node:fs";import{resolve as A,join as k}from"node:path";import{projectUsesUmbrella as S}from"@lunora/config";import{LunoraError as O}from"@lunora/errors";const u="virtual:lunora/worker",E="\0",m=`${E}${u}`,L=`// @lunora/vite — the composed worker entry is worker-only and unavailable in the client environment.
2
+ export default {};
3
+ `,_=/\/$/,p={"react-router":{handler:'{ fetch: (request) => createRequestHandler(() => import("virtual:react-router/server-build"), import.meta.env.MODE)(request) }',imports:'import { createRequestHandler } from "react-router";'},"solid-start":{handler:"ssrModule.default",imports:'import * as ssrModule from "@solidjs/start/server-handler";'},"tanstack-start":{handler:"ssrModule.default",imports:'import * as ssrModule from "@tanstack/react-start/server-entry";'},"tanstack-start-solid":{handler:"ssrModule.default",imports:'import * as ssrModule from "@tanstack/solid-start/server-entry";'},vinext:{handler:"ssrModule.default",imports:'import * as ssrModule from "vinext/server/fetch-handler";'}},d=r=>{const e=r.framework;return e?.class==="A"&&p[e.framework]!==void 0},$=["agents","containers","workflows"],N=(r,e,s=[],a=!1,t=!1,i={})=>{const o=p[r];if(o===void 0)throw new O("INTERNAL",`[lunora] no class-A worker wiring for framework "${r}"`);const n=e.replaceAll("\\","/"),f=a?"lunorash/runtime":"@lunora/runtime",h=s.map(l=>`
4
+ export * from "${n}/${l}";
5
+ `).join(""),c=JSON.stringify(Object.fromEntries(Object.entries(i).toSorted(([l],[v])=>l.localeCompare(v)))),R=c==="{}"?"":c;return`// Generated by @lunora/vite — class-A worker composition (PLAN4 M2).
6
+ // Do not edit: emitted from the detected framework (${r}). Point your
7
+ // wrangler \`main\` here (or re-export it) instead of hand-wiring createWorker.
8
+ import { composeWorker } from "${f}";
9
+ ${o.imports}
10
+ import { LUNORA_FUNCTIONS } from "${n}/functions";
11
+ import { openApiSpec } from "${n}/openapi";
12
+ import { createShardDO } from "${n}/shard";
13
+
14
+ export const ShardDO = createShardDO(${R});
15
+ ${h}
16
+
17
+ let worker;
18
+
19
+ export default {
20
+ async fetch(request, env, context) {
21
+ worker ??= composeWorker({${t?`
22
+ allowUnauthenticatedShardAccess: true,`:""}
23
+ functions: LUNORA_FUNCTIONS,
24
+ httpRouter: ${o.handler},
25
+ openApiSpec,
26
+ routes: {},
27
+ shardDO: env.SHARD,
28
+ });
29
+
30
+ return worker.fetch(request, env, context);
31
+ },
32
+ };
33
+ `},g=(r,e)=>{const s=A(r.projectRoot,r.generatedDir.replace(_,"")),a=S(r.projectRoot);return{load(t){if(t===m&&d(e)&&e.framework!==void 0){if(this.environment.name==="client")return L;const i=$.filter(o=>w(k(s,`${o}.ts`)));return N(e.framework.framework,s,i,a,r.allowUnauthenticatedShardAccess,r.shard)}},name:"lunora:framework-compose",resolveId(t){if(t===u&&d(e))return m}}};export{p as CLASS_A_WIRING,$ as GENERATED_CLASS_MODULES,u as LUNORA_WORKER_VIRTUAL_ID,m as RESOLVED_LUNORA_WORKER_ID,N as buildWorkerEntrySource,g as frameworkComposePlugin,d as isAutoComposable};
@@ -0,0 +1 @@
1
+ const a="lunora:api-updated";export{a as default};
@@ -0,0 +1 @@
1
+ import{detectAgentRules as A}from"@lunora/config";import{transportRejectionReason as H,serveJsonHandler as p,handleSeedRequest as I,handleSchemaEditRequest as _,handlePolicyScaffoldRequest as D,isStandaloneModulePath as N,renderStudioHtml as P,resolveAdminToken as v,sendStudioDocument as C,SEED_ENDPOINT as E,SCHEMA_EDIT_ENDPOINT as $,POLICY_SCAFFOLD_ENDPOINT as x,studioAssetsStamp as O,loadStudioAssets as R,applyStudioAssetCache as U,readStandaloneAsset as B,assetContentType as k}from"@lunora/config/studio-host";const f="/__lunora",j=`${f}/studio.js`,m=`${f}/styles.css`,W=/^\//,g=/\/$/,w={[x]:D,[$]:_,[E]:I},y=(t,e,s)=>{t.statusCode=200,t.setHeader("Content-Type",s),t.end(e)},F=t=>{const e=f.replace(W,"");if(t.resolvedLocal!==void 0&&t.resolvedLocal!=="")return`${t.resolvedLocal.endsWith("/")?t.resolvedLocal.slice(0,-1):t.resolvedLocal}/${e}`;const s=t.base===void 0||t.base==="/"?"":t.base.replace(g,"");if(t.address===void 0||typeof t.address=="string")return`http://localhost:5173${s}/${e}`;const a=t.address.address==="::"||t.address.address==="0.0.0.0"?"localhost":t.address.address;return`http://${a.includes(":")?`[${a}]`:a}:${String(t.address.port)}${s}/${e}`},G=t=>{try{return new URL(t,"http://localhost").pathname.replace(g,"")}catch{return t}},J=(t,e,s)=>{let a,c,r;const{projectRoot:S}=s,T=t.config.base??"/",h=T==="/"?"":T.replace(g,""),L=(n,d,o)=>{const i=O();if((a===void 0||i!==c)&&(a=R(t.config.logger),c=i),a===void 0){o.statusCode=501,o.setHeader("Content-Type","text/plain"),o.end("Lunora studio assets not found — install and build @lunora/studio.");return}const l=n===m,u=n.slice(n.lastIndexOf("/")+1);if(U(d,o,u,i))return;if(l){y(o,a.styles,"text/css; charset=utf-8");return}const b=B(u);if(b===void 0){o.statusCode=404,o.setHeader("Content-Type","text/plain"),o.end("Not found");return}y(o,b,k(u))};return(n,d,o)=>{const i=G(n.url??""),l=h!==""&&i.startsWith(h)?i.slice(h.length):i;if(l!==f&&!l.startsWith(`${f}/`)){o();return}if(e||H(n,t.config.logger)!==void 0){d.statusCode=403,d.setHeader("Content-Type","text/plain"),d.end("Lunora studio is only available on loopback hosts in dev.");return}const u=w[l];if(u!==void 0){p(n,d,u,S,{apiSpec:s.apiSpec,schemaDirectory:s.schemaDir});return}if(l===m||N(l)){L(l,n,d);return}r??=P({adminToken:v(S),basePath:f,dataEditable:!0,rulesInstalled:A(S).installed,runAsIdentity:!0,schemaEditable:!0,scriptSrc:j,styleHref:m}),C(d,r)}},q=t=>({apply:"serve",configureServer(e){const s=e.config.server?.host,a=s!==void 0&&s!==!1&&s!=="localhost"&&s!=="127.0.0.1"&&s!=="::1";return e.middlewares.use(J(e,a,t)),()=>{const c=()=>{const r=F({address:e.httpServer?.address()??void 0,base:e.config.base,resolvedLocal:e.resolvedUrls?.local[0]});e.config.logger.info(` \x1B[32m➜\x1B[39m \x1B[1mLunora\x1B[22m: \x1B[36m${r}\x1B[39m`)};if(typeof e.printUrls=="function"){const r=e.printUrls.bind(e);e.printUrls=()=>{r(),c()}}else e.httpServer?.listening===!0?c():e.httpServer?.once("listening",c)}},name:"lunora:studio"});export{f as STUDIO_PATH,j as STUDIO_SCRIPT_PATH,m as STUDIO_STYLE_PATH,F as buildStudioUrl,q as studioPlugin};
@@ -0,0 +1,5 @@
1
+ const a=[""," ┌─ Lunora ──────────────────────────────────────────────────────────────"," │ Your Worker entry threw while loading, so the dev server couldn't read"," │ its exports. The TypeError above comes from inside the Cloudflare"," │ runtime and hides the file that actually failed. It is almost always:"," │"," │ • A circular import in lunora/. A query/mutation/action module ran at"," │ the top level before `v`/`query`/`mutation` finished initializing,"," │ so they were `undefined` (hence `reading 'string'`/`'id'`/…)."," │ → Import `v`/`query`/`mutation` only from `lunora/_generated/server`,"," │ and don't import one lunora/ function module from another at the"," │ top level."," │"," │ • Stale or missing generated files."," │ → Re-run `lunora codegen`, then restart the dev server."," │"," │ Tip: check the lunora/ files you edited most recently — the throw is at"," │ their module top level."," └───────────────────────────────────────────────────────────────────────"].join(`
2
+ `),u=/runner-worker[/\\]index\.js/u,l=/getWorkerEntryExportTypes/u,c=e=>{if(!(e instanceof Error))return!1;const t=`${e.stack??""}
3
+ ${e.message}`;return u.test(t)||l.test(t)},i=Symbol.for("lunora.workerStartupHintApplied"),d=e=>{if(!c(e))return e;const t=e;return t[i]||Object.isFrozen(t)||Object.isSealed(t)||(t[i]=!0,t.message=`${t.message}
4
+ ${a}`,typeof t.stack=="string"&&(t.stack=`${t.stack}
5
+ ${a}`)),e},s=e=>async(...t)=>{try{return await e(...t)}catch(r){throw d(r)}},f=e=>typeof e=="function"?s(e):e!==null&&typeof e=="object"&&"handler"in e&&typeof e.handler=="function"?{...e,handler:s(e.handler)}:e,m=["configureServer","buildStart"],h=e=>e.map(t=>{let r=t;for(const n of m){const o=t[n];o!==void 0&&(r={...r,[n]:f(o)})}return r});export{a as WORKER_STARTUP_HINT,d as augmentWorkerStartupError,c as isWorkerEntryEvalError,h as withWorkerStartupHint};
@@ -0,0 +1 @@
1
+ import{l as a}from"./log-DE48L4Oz.mjs";const c=["/_lunora"],u="/_lunora/ws",h=e=>{if(e.startsWith("^"))try{return new RegExp(e,"u").test(u)}catch{return!1}return c.some(r=>e.startsWith(r)||r.startsWith(e))},i=(e,r)=>{if(!e)return[];const t=[];for(const[s,o]of Object.entries(e)){if(!h(s))continue;if(typeof o=="string"){t.push(`${r}.proxy["${s}"] uses the string shorthand, which does not proxy WebSocket upgrades. Live queries and shapes will never connect (the app hangs on its loading state) while HTTP RPC appears to work. Use the object form: { target: "${o}", ws: true }.`);continue}if(typeof o!="object"||o===null)continue;const n=o;n.ws!==!0&&t.push(`${r}.proxy["${s}"] is missing \`ws: true\`, so WebSocket upgrades are not proxied. Live queries and shapes will never connect (the app hangs on its loading state) while HTTP RPC appears to work.`),n.changeOrigin===!0&&t.push(`${r}.proxy["${s}"] sets \`changeOrigin: true\`, so the worker sees a different origin than the browser sends. Loopback-to-loopback is trusted by default; for any other dev host add the dev-server origin to the worker's \`security.csrf.trustedOrigins\` or the cookie-bearing WebSocket upgrade is rejected with FORBIDDEN_ORIGIN.`)}return t},g=()=>({apply:"serve",configResolved(e){const r=[...i(e.server.proxy,"server"),...i(e.preview.proxy,"preview")];for(const t of r)e.logger.warn(a(t))},name:"lunora:proxy-check"});export{i as checkLunoraProxy,g as proxyCheckPlugin};
@@ -0,0 +1,3 @@
1
+ import{existsSync as j,readFileSync as X}from"node:fs";import{join as N,resolve as p,sep as k,basename as q}from"node:path";import{listLunoraSourceFiles as Q,findTsconfig as Y,runCodegen as Z,describeErrorLevelFindings as ee,createCodegenProject as ne,refreshCodegenProject as re,CodegenDiagnosticError as te}from"@lunora/codegen";import{LUNORA_CONFIG_FILE as V,inferLunoraBindings as oe,isCodegenDisabled as ie,CODEGEN_ENV as x,runPostCodegenHook as M}from"@lunora/config";import{findWranglerFile as ae,readWranglerJsonc as ce,reconcileWranglerBindings as se,reconcileWranglerCrons as le,describePreservedCrons as de,reconcileWranglerCompatibilityDate as fe,WRANGLER_FILES as ge,collectWranglerSecretVariables as ue}from"@lunora/config/cloudflare";import{isRunnableDevEnvironment as he}from"vite";import me from"./LUNORA_API_UPDATED_EVENT-CO2Rv2re.mjs";import{L as d,a as A}from"./log-DE48L4Oz.mjs";import{createHash as pe}from"node:crypto";import{r as we,a as ye}from"./server-close-Qoh4i6Ay.mjs";const F=(n,r)=>{try{const{parsed:t,text:e}=ce(n);return t===void 0?`raw:${e}`:JSON.stringify(r?r(t):t)}catch{return"unreadable"}},$e=n=>{const r={...n},{triggers:t}=r;if(t!==null&&typeof t=="object"){const e={...t};delete e.crons,Object.keys(e).length>0?r.triggers=e:delete r.triggers}return r},T=n=>{const r=ae(n),t=r===void 0?"absent":F(r,$e),e=N(n,V),o=j(e)?F(e):"absent";return`${t}\0${o}`},ve=async(n,r,t)=>{try{const e=await oe({projectRoot:n.projectRoot,schemaDir:n.schemaDir}),o=se(n.projectRoot,e);o.changed&&r.info?.(`${d} inferred bindings → ${o.added.join(", ")} (written to ${o.wranglerPath??"wrangler.jsonc"})`);for(const c of o.warnings)r.warn(`${d} ${c}`);o.exportGaps.length>0&&t?.(o.exportGaps)}catch(e){const o=e instanceof Error?e.message:String(e);r.warn(`${d} binding inference skipped: ${o}`)}},L=new Map,Se=(n,r,t)=>{try{const e=le(n,r);e.changed&&t.info?.(`${d} synced ${r.length.toFixed(0)} cron trigger(s) into ${e.wranglerPath??"wrangler.jsonc"}`);for(const l of e.warnings)t.warn(`${d} ${l}`);const o=e.preserved.join("\0"),c=de(e.preserved);c!==void 0&&(e.changed||L.get(n)!==o)&&t.info?.(`${d} ${c}`),L.set(n,o)}catch(e){const o=e instanceof Error?e.message:String(e);t.warn(`${d} cron trigger sync skipped: ${o}`)}try{const e=fe(n);e.changed&&t.info?.(`${d} bumped compatibility_date to ${e.date??"unknown"} (Workers Cache enabled) → ${e.wranglerPath??"wrangler.jsonc"}`)}catch(e){const o=e instanceof Error?e.message:String(e);t.warn(`${d} compatibility date sync skipped: ${o}`)}},be=100,H=300,G=2,Ee=n=>{let r,t,e=0;const o=()=>{r&&(clearTimeout(r),r=void 0)},c=(u,h)=>{t&&clearTimeout(t),t=setTimeout(()=>{if(t=void 0,n.fingerprint()!==u){if(e+=1,e>G){n.logger.warn(`${d} \`postcodegen\` keeps rewriting the schema sources — stopping after ${String(G)} reruns. Make the hook idempotent or move it off the schema directory.`);return}n.logger.info(`${d} schema changed while \`postcodegen\` was running — regenerating`),h()}},H)},l=u=>{n.regenerate(u,h=>{c(h,()=>{l(u)})})};return{cancelPending:o,dispose:()=>{o(),t&&(clearTimeout(t),t=void 0)},onSave:u=>{o(),e=0,r=setTimeout(()=>{r=void 0,l(u)},be)}}},I=n=>{if(!j(n))return"unreadable";const r=Q(n),t=N(n,"schema.ts");j(t)&&r.push(t);const e=pe("sha256");for(const o of r.toSorted((c,l)=>c.localeCompare(l)))try{e.update(o).update("\0").update(X(o))}catch{}return e.digest("hex")},B=/[/\\]tsconfig\..+\.json$/u,ke=n=>{const r=n.map(e=>` • ${e.kind} "${e.exportName}" — class ${e.className} is not exported by your worker entry.`),t=[...new Set(n.map(e=>e.module))].map(e=>` export * from "./lunora/_generated/${e}";`);return[`[lunora] ${String(n.length)} declared ${n.length===1?"binding is":"bindings are"} not exported by your worker entry — \`wrangler deploy\` will fail.`,...r,"","Add to your worker entry:",...t].join(`
2
+ `)},Re=n=>{const{advisoryNames:r,platformDiagnosticNames:t}=ee(n),e=[...new Set([...r,...t])].toSorted((c,l)=>c.localeCompare(l));if(e.length===0)return;const o=e.length===1?"advisory/platform diagnostic":"advisories/platform diagnostics";return`${d} ${String(e.length)} ERROR-level ${o} (${e.join(", ")}) — see the log above for detail.`},je=(n,r,t)=>{if(r.warn(`${d} schema.ts not found at ${n} — codegen skipped`),t!==void 0){const e=`schema.ts not found at ${n} — generated output is now stale`;t.onError(new Error(e),e)}},U=(n,r,t,e)=>{const o=N(n.projectRoot,n.schemaDir,"schema.ts");if(!j(o))return je(o,r,t),{};try{const c=Z({apiSpec:n.apiSpec,lunoraDirectory:n.schemaDir,project:e,projectRoot:n.projectRoot,target:n.target,wranglerVariables:ue(n.projectRoot)});Se(n.projectRoot,c.cronTriggers,r);for(const l of c.advisories){const u=A(l.level,l.name,l.detail,l.remediation);l.level==="ERROR"?r.error(u):r.warn(u)}for(const l of c.platformDiagnostics){const u=A(l.level==="error"?"ERROR":"WARN",l.name,l.message,l.remediation);l.level==="error"?r.error(u):r.warn(u)}return{blockingMessage:Re(c),outputDirectory:p(c.outputDirectory)}}catch(c){const l=c instanceof Error?c.message:String(c);return r.error(`${d} codegen failed: ${l}`),t?.onError(c,l),{failure:`${d} codegen failed: ${l}`}}},Ce=(n,r,t)=>{let e;for(const[o,c]of Object.entries(n.environments)){if(o==="client"){e=c;continue}he(c)||c.hot.send({path:"*",triggeredBy:r,type:"full-reload"})}if(e===void 0){n.hot.send({type:"full-reload"});return}if(t){e.hot.send({type:"full-reload"});return}e.hot.send({event:me,type:"custom"})},Fe=n=>{const r=p(n.projectRoot,n.schemaDir),t=ie(process.env[x]);let e=p(n.projectRoot,n.generatedDir),o=0,c=!1,l;const u=new Map;let h,C=!1,D=!1,E;return{config(i,w){E=w.command},async buildStart(){const i={error:g=>{console.error(g)},info:g=>{console.info(g)},warn:g=>{console.warn(g)}},w=E!=="build"&&t,{blockingMessage:y,failure:R,outputDirectory:$}=w?{}:U(n,i);if(E==="build"&&R!==void 0&&this.error(R),$!==void 0){e=$,c=!0;let g;try{g=await M({cwd:n.projectRoot,logger:i})}finally{c=!1}g.ran&&(o=Date.now()),E==="build"&&g.error!==void 0&&this.error(g.error)}E==="build"&&y!==void 0&&this.error(y),await ve(n,i,g=>{l?.hot.send({err:{loc:void 0,message:ke(g),stack:""},type:"error"})}),l!==void 0&&(h=T(n.projectRoot),C=!0)},configureServer(i){l=i,i.watcher.add(r),h=T(n.projectRoot),C=!1;const w={error:a=>{i.config.logger.error(a)},info:a=>{i.config.logger.info(a)},warn:a=>{i.config.logger.warn(a)}};let y=!1;const R={onError(a,s){y=!0;const f=a instanceof te?{column:a.column,file:a.file,line:a.line}:void 0,b=f===void 0?`[lunora] codegen failed: ${s}
3
+ (see terminal for full stack trace and file location)`:`[lunora] codegen failed: ${s}`;l?.hot.send({err:{loc:f,message:b,stack:a instanceof Error?a.stack??"":""},type:"error"})}},$=(a,s)=>a===s||a.startsWith(s+k);let g=!1,m;const J=()=>{for(const a of Object.values(i.environments)){const s=a.moduleGraph;for(const f of s.idToModuleMap.values())f.id&&$(f.id,e)&&s.invalidateModule(f)}},z=async(a,s)=>{try{if(g)return;m===void 0?m=ne(r):re(m,r);const{outputDirectory:f}=U(n,w,R,m);if(f===void 0){m=void 0;return}e=f;const b=I(r);c=!0;let P;try{P=await M({cwd:n.projectRoot,logger:w})}finally{c=!1}if(P.ran&&(o=Date.now(),s(b)),P.error!==void 0)return;J(),Ce(i,a,y),y=!1}catch(f){w.error(`${d} codegen watch: ${f instanceof Error?f.message:String(f)}`)}},_=Ee({fingerprint:()=>I(r),logger:w,regenerate:(a,s)=>{z(a,s)}}),v=a=>{const s=p(a);if(B.test(s)){m=void 0;return}if(s.endsWith(`${k}tsconfig.json`)&&s===Y(r)){m=void 0;return}if($(s,r)&&!$(s,e)&&s.endsWith(".ts")&&!(s.includes(`${k}__tests__${k}`)||s.endsWith(".test.ts")||s.endsWith(".spec.ts"))){if(c||Date.now()-o<H){_.cancelPending();return}_.onSave(s)}},O=a=>{const s=p(a);(s.endsWith(`${k}tsconfig.json`)||B.test(s))&&(m=void 0)};t?i.config.logger.info(`${d} codegen watch disabled (${x}) — _generated/ is written only by an explicit \`lunora codegen\``):(i.watcher.on("add",v),i.watcher.on("change",v),i.watcher.on("unlink",v),i.watcher.on("unlink",O));const W=new Set([...ge.map(a=>p(n.projectRoot,a)),p(n.projectRoot,V)]);for(const a of W)i.watcher.add(a);const S=a=>{if(!W.has(p(a))||D)return;const s=T(n.projectRoot);if(!C){h=s;return}if(h===void 0){h=s;return}s!==h&&(h=s,D=!0,i.config.logger.info(`${d} ${q(p(a))} changed — restarting dev server`),Promise.resolve(i.restart()).finally(()=>{D=!1}).catch(f=>{const b=f instanceof Error?f.message:String(f);i.config.logger.error(`${d} dev server restart failed: ${b} — keeping the running server; re-save your config to retry.`),i.hot.send({err:{loc:void 0,message:`[lunora] dev server restart failed: ${b}`,stack:""},type:"error"})}))};i.watcher.on("add",S),i.watcher.on("change",S),i.watcher.on("unlink",S);const K=()=>{g||(g=!0,m=void 0,_.dispose(),i.watcher.off("add",v),i.watcher.off("change",v),i.watcher.off("unlink",v),i.watcher.off("unlink",O),i.watcher.off("add",S),i.watcher.off("change",S),i.watcher.off("unlink",S))};return()=>{ye(i,u,K)}},buildEnd(){we(u,this.environment)},name:"lunora:codegen"}};export{Fe as c,ve as r};
@@ -0,0 +1 @@
1
+ import{c as i}from"./codegen-plugin-dg384k5b.mjs";import"./LUNORA_API_UPDATED_EVENT-CO2Rv2re.mjs";import"./log-DE48L4Oz.mjs";import"./server-close-Qoh4i6Ay.mjs";export{i as default};
@@ -0,0 +1 @@
1
+ import{discoverContainerInfo as l,streamContainerLogs as m}from"@lunora/config";import{l as i}from"./log-DE48L4Oz.mjs";const p=r=>{let n;const a=()=>{n?.close(),n=void 0};return{apply:"serve",buildEnd(){a()},configureServer(t){if(n||process.env.LUNORA_CONTAINER_LOGS==="0")return;const c=l(r.projectRoot,r.schemaDir).containers.map(e=>({className:e.className,exportName:e.exportName}));if(c.length===0)return;const{logger:o}=t.config;n=m({containers:c,onLine:e=>{const s=i(`container:${e.name} ${e.text}`);e.level==="error"?o.warn(s):o.info(s)},onUnavailable:e=>{o.warn(i(`container: Docker engine unreachable — container logs unavailable (${e})`))}}),t.httpServer?.once("close",a)},name:"lunora:container-logs"}};export{p as default};
@@ -0,0 +1 @@
1
+ import{DEV_HANDOFF_ENV as d,claimDevServerState as c,DEV_LOG_FILE_ENV as p,DEV_DAEMON_ENV as u,clearDevServerState as f}from"@lunora/config";import{l as v}from"./log-DE48L4Oz.mjs";import{r as g,a as S}from"./server-close-Qoh4i6Ay.mjs";const m=/\/$/,D=o=>{const r=o.resolvedUrls?.local[0];if(r!==void 0)return r.replace(m,"");const t=o.httpServer?.address();if(t!==null&&typeof t=="object")return`http://localhost:${String(t.port)}`},O=o=>{let r=!1;const t=new Map;return{apply:"serve",configureServer(e){const l=o.projectRoot,a=()=>{if(r)return;const n=D(e);if(n===void 0)return;const s=Number(process.env[d]),i=c(l,{background:process.env[u]==="1",logFile:process.env[p],mode:"vite",pid:process.pid,readyAt:new Date().toISOString(),startedAt:new Date().toISOString(),url:n},Number.isInteger(s)&&s>0?{supersedePid:s}:void 0);if(!i.ok){i.existing!==void 0&&e.config.logger.warn(v(`another dev server is already recorded at ${i.existing.url} (pid ${String(i.existing.pid)}) — leaving .lunora/dev.json untouched`));return}r=!0};return S(e,t,()=>{r&&(f(l,process.pid),r=!1)}),()=>{if(typeof e.printUrls=="function"){const n=e.printUrls.bind(e);e.printUrls=()=>{n(),a()}}e.httpServer?.once("listening",()=>{setTimeout(a,0)})}},buildEnd(){g(t,this.environment)},name:"lunora:dev-state"}};export{O as default};
@@ -0,0 +1 @@
1
+ import{readFileSync as l}from"node:fs";import{join as c}from"node:path";import{ensureDevVariables as f,createConfirm as v,fillDevSecrets as m,DEV_VARS_FILE as i,parseDevVariableEntries as u,writeDevVariablesFileAtomically as d,upsertDevVariableLine as p}from"@lunora/config";import{findWranglerFile as V,readWranglerJsonc as E}from"@lunora/config/cloudflare";import{l as R}from"./log-DE48L4Oz.mjs";const t="WORKER_ENV",a="development",_=e=>{const r=V(e);return r===void 0?{}:E(r).parsed?.vars??{}},w=(e,r)=>{const n=c(e,i);let o;try{o=l(n,"utf8")}catch{return}u(o).some(s=>s.key===t)||t in _(e)||(d(n,p(o,t,a)),r(`set ${t}=${a} in ${i} so the dev worker runs in development mode`))},h=e=>{let r=!1;return{apply:"serve",config(n,o){r=o.isPreview===!0},async configResolved(){if(r)return;const n=o=>{console.info(R(o))};await f({confirm:v("[lunora] "),cwd:e.projectRoot,info:n}),m({cwd:e.projectRoot,info:n}),w(e.projectRoot,n)},enforce:"pre",name:"lunora:dev-vars"}};export{h as default};
@@ -0,0 +1 @@
1
+ import{paintBadge as a,BADGES as o}from"@lunora/config";const i=a(o.lunora),$=n=>`${i} ${n}`,A={ERROR:o.error,INFO:o.info,WARN:o.warn},e=(n,r,s,t)=>`${a(A[n])} ${r}: ${s} — ${t}`;export{i as L,e as a,$ as l};
@@ -0,0 +1,3 @@
1
+ import{detectAiAgent as u,LUNORA_EVENT_SOURCE as a,formatLunoraEvent as f}from"@lunora/config";import{a as l,r as d}from"./server-close-Qoh4i6Ay.mjs";const p=`"source":"${a}"`,i={error:"\x1B[31m",info:"\x1B[36m",reset:"\x1B[0m",warn:"\x1B[33m"},w=(r,t,e)=>e?`${i[t]}[lunora]${i.reset} ${r}`:`[lunora] ${r}`,v=r=>typeof r=="string"?r:Buffer.isBuffer(r)?r.toString("utf8"):void 0,m=(r,t)=>r.split(`
2
+ `).map(e=>{const n=f(e);return n?w(n.text,n.level,t):e}).join(`
3
+ `),S=(r,t)=>(...e)=>{try{const n=v(e[0]);if(n?.includes(p))return r(m(n,t),...e.slice(1))}catch{}return r(...e)},c=r=>{const t=r.write.bind(r),e=S(t,r.isTTY===!0);return r.write=e,()=>{r.write===e&&(r.write=t)}},g=()=>{const r=process.env.LUNORA_LOG_JSON;return r==="1"||r==="true"?!0:r==="0"||r==="false"?!1:u()!==void 0};let o;const A=()=>{const r=new Map;return{apply:"serve",buildEnd(){d(r,this.environment)},configureServer(t){if(g())return;o?.();const e=c(process.stdout),n=c(process.stderr),s=()=>{e(),n(),o===s&&(o=void 0)};o=s,l(t,r,s)},name:"lunora:log-stream"}};export{A as default};
@@ -0,0 +1 @@
1
+ import{findLunoraSolution as r}from"@lunora/codegen";const s={handle:e=>{const n=typeof e.message=="string"?e.message:"",o=r(n);return Promise.resolve(o?{body:o.body,header:o.header}:void 0)},name:"lunora",priority:100},i=[s];export{s as lunoraSolutionFinder,i as lunoraSolutionFinders};
@@ -0,0 +1 @@
1
+ import{readProjectRemotePreference as d}from"@lunora/config";import{resolveRemoteEnabled as s,materializeRemoteWranglerConfig as g}from"@lunora/config/cloudflare";import{l as c}from"./log-DE48L4Oz.mjs";const l=()=>{},u=e=>{const t=e.readPreference??d;if(!s({configPreference:t(e.projectRoot),envValue:e.remoteEnv??process.env.LUNORA_REMOTE}))return{cleanup:l,enabled:!1};const o=(e.materialize??g)({enabled:!0,projectRoot:e.projectRoot});return{cleanup:o.cleanup,configPath:o.configPath,enabled:!0,reason:o.reason}},m=(e,t)=>!t.enabled||t.configPath===void 0||typeof e.configPath=="string"?e:{...e,configPath:t.configPath},v=(e,t)=>{let n={cleanup:l,enabled:!1},i;const o=()=>{n.cleanup()};return{buildEnd:o,closeBundle:o,config(P,f){if(f.command!=="serve")return;if(n.cleanup(),n=u(t),e===void 0){n.enabled&&n.configPath!==void 0&&console.info(c(`remote bindings are materialized at ${n.configPath} — this project adds @cloudflare/vite-plugin itself (\`cloudflare: false\`), so pass that path as its \`configPath\` to use them.`));return}const r=e;i!==void 0&&r.configPath===i&&delete r.configPath;const a=m(e,n);a.configPath!==void 0&&r.configPath===void 0?(r.configPath=a.configPath,i=a.configPath):n.enabled&&n.configPath===void 0&&n.reason!==void 0&&console.info(c(`remote bindings requested but not applied: ${n.reason}`))},enforce:"pre",name:"lunora:remote-bindings"}};export{u as planViteRemoteBindings,v as remoteBindingsPlugin,m as withRemoteBindings};
@@ -0,0 +1 @@
1
+ const o=(e,s,t)=>{e.httpServer?e.httpServer.once("close",t):s.set(e.environments.client,t)},r=(e,s)=>{const t=e.get(s);t!==void 0&&(e.delete(s),t())};export{o as a,r};
@@ -0,0 +1,3 @@
1
+ import{spawnSync as i}from"node:child_process";import{validateWranglerProject as s,readWranglerJsonc as c}from"@lunora/config/cloudflare";import{LunoraError as l}from"@lunora/errors";import{l as a}from"./log-DE48L4Oz.mjs";const g=r=>r.startsWith("./")||r.startsWith("../")||r.startsWith("/")||r.includes("Dockerfile"),f=()=>{try{return i("docker",["info"],{stdio:"ignore"}).status===0}catch{return!1}},u=(r,n=f)=>{const{parsed:e}=c(r);!(e?.containers??[]).some(t=>typeof t?.image=="string"&&g(t.image))||n()||console.warn(a("wrangler.jsonc declares containers built from a local Dockerfile, but no Docker-compatible engine is running. Start Docker (or Colima) before `vite dev`, or the container instances will fail to start."))},d=(r,n)=>{const e=["[lunora] wrangler configuration is missing bindings required by your schema.",` file: ${r}`,"",...n.map(o=>` - ${o}`),""," Update your wrangler.jsonc and restart the dev server."];return new Error(e.join(`
2
+ `))},b=r=>{let n=!1;return{config(e,o){n=o.isPreview===!0},configResolved(){if(n)return;const e=s({projectRoot:r.projectRoot,schemaDir:r.schemaDir});if(!e.wranglerPath)throw new l("INTERNAL",["[lunora] wrangler.jsonc not found.",` searched in: ${r.projectRoot}`," create a wrangler.jsonc declaring at least the SHARD durable object binding."].join(`
3
+ `));for(const o of e.report.warnings)console.warn(a(`wrangler validator: ${o}`));if(e.problems.length>0)throw d(e.wranglerPath,e.problems);u(e.wranglerPath)},enforce:"pre",name:"lunora:wrangler-validator"}};export{u as warnWhenDockerMissing,b as wranglerValidatorPlugin};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/vite",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.200",
4
4
  "description": "The Lunora Vite plugin: codegen, type sync, wrangler validation, and an error overlay over @cloudflare/vite-plugin",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -25,7 +25,7 @@
25
25
  "directory": "packages/vite"
26
26
  },
27
27
  "files": [
28
- "dist",
28
+ "./dist",
29
29
  "__assets__",
30
30
  "README.md",
31
31
  "LICENSE.md"
@@ -45,16 +45,15 @@
45
45
  "access": "public"
46
46
  },
47
47
  "dependencies": {
48
- "@cloudflare/vite-plugin": "1.42.0",
49
- "@lunora/codegen": "1.0.0-alpha.2",
50
- "@lunora/config": "1.0.0-alpha.2",
51
- "@visulima/vite-overlay": "2.0.0-alpha.35",
52
- "jsonc-parser": "^3.3.1",
53
- "ts-morph": "^28.0.0"
48
+ "@cloudflare/vite-plugin": "1.51.2",
49
+ "@lunora/codegen": "1.0.0-alpha.164",
50
+ "@lunora/config": "1.0.0-alpha.200",
51
+ "@lunora/errors": "1.0.0-alpha.34",
52
+ "@visulima/vite-overlay": "2.0.12"
54
53
  },
55
54
  "peerDependencies": {
56
- "@lunora/studio": "1.0.0-alpha.1",
57
- "vite": "^8.0.16"
55
+ "@lunora/studio": ">=1.0.0-alpha.50 <2.0.0-0",
56
+ "vite": "^6.1.0 || ^7.0.0 || ^8.0.0"
58
57
  },
59
58
  "peerDependenciesMeta": {
60
59
  "@lunora/studio": {
@@ -1,81 +0,0 @@
1
- const WORKER_STARTUP_HINT = [
2
- "",
3
- " ┌─ Lunora ──────────────────────────────────────────────────────────────",
4
- " │ Your Worker entry threw while loading, so the dev server couldn't read",
5
- " │ its exports. The TypeError above comes from inside the Cloudflare",
6
- " │ runtime and hides the file that actually failed. It is almost always:",
7
- " │",
8
- " │ • A circular import in lunora/. A query/mutation/action module ran at",
9
- " │ the top level before `v`/`query`/`mutation` finished initializing,",
10
- " │ so they were `undefined` (hence `reading 'string'`/`'id'`/…).",
11
- " │ → Import `v`/`query`/`mutation` only from `lunora/_generated/server`,",
12
- " │ and don't import one lunora/ function module from another at the",
13
- " │ top level.",
14
- " │",
15
- " │ • Stale or missing generated files.",
16
- " │ → Re-run `lunora codegen`, then restart the dev server.",
17
- " │",
18
- " │ Tip: check the lunora/ files you edited most recently — the throw is at",
19
- " │ their module top level.",
20
- " └───────────────────────────────────────────────────────────────────────"
21
- ].join("\n");
22
- const RUNNER_WORKER_RE = /runner-worker[/\\]index\.js/u;
23
- const EXPORT_TYPES_PROBE_RE = /getWorkerEntryExportTypes/u;
24
- const isWorkerEntryEvalError = (error) => {
25
- if (!(error instanceof Error)) {
26
- return false;
27
- }
28
- const haystack = `${error.stack ?? ""}
29
- ${error.message}`;
30
- return RUNNER_WORKER_RE.test(haystack) || EXPORT_TYPES_PROBE_RE.test(haystack);
31
- };
32
- const HINTED = /* @__PURE__ */ Symbol.for("lunora.workerStartupHintApplied");
33
- const augmentWorkerStartupError = (error) => {
34
- if (!isWorkerEntryEvalError(error)) {
35
- return error;
36
- }
37
- const flagged = error;
38
- if (flagged[HINTED]) {
39
- return error;
40
- }
41
- if (Object.isFrozen(flagged) || Object.isSealed(flagged)) {
42
- return error;
43
- }
44
- flagged[HINTED] = true;
45
- flagged.message = `${flagged.message}
46
- ${WORKER_STARTUP_HINT}`;
47
- if (typeof flagged.stack === "string") {
48
- flagged.stack = `${flagged.stack}
49
- ${WORKER_STARTUP_HINT}`;
50
- }
51
- return error;
52
- };
53
- const wrapHookFunction = (function_) => async (...arguments_) => {
54
- try {
55
- return await function_(...arguments_);
56
- } catch (error) {
57
- throw augmentWorkerStartupError(error);
58
- }
59
- };
60
- const wrapHook = (hook) => {
61
- if (typeof hook === "function") {
62
- return wrapHookFunction(hook);
63
- }
64
- if (hook !== null && typeof hook === "object" && "handler" in hook && typeof hook["handler"] === "function") {
65
- return { ...hook, handler: wrapHookFunction(hook.handler) };
66
- }
67
- return hook;
68
- };
69
- const WRAPPED_HOOKS = ["configureServer", "buildStart"];
70
- const withWorkerStartupHint = (plugins) => plugins.map((plugin) => {
71
- let next = plugin;
72
- for (const hookName of WRAPPED_HOOKS) {
73
- const hook = plugin[hookName];
74
- if (hook !== void 0) {
75
- next = { ...next, [hookName]: wrapHook(hook) };
76
- }
77
- }
78
- return next;
79
- });
80
-
81
- export { WORKER_STARTUP_HINT, augmentWorkerStartupError, isWorkerEntryEvalError, withWorkerStartupHint };
@@ -1,210 +0,0 @@
1
- import { detectAgentRules } from '@lunora/config';
2
- import { handleSeedRequest, handleSchemaEditRequest, handlePolicyScaffoldRequest, SEED_ENDPOINT, SCHEMA_EDIT_ENDPOINT, POLICY_SCAFFOLD_ENDPOINT, serveJsonHandler, renderStudioHtml, resolveAdminToken, studioAssetsStamp, loadStudioAssets } from '@lunora/config/studio-host';
3
-
4
- const STUDIO_PATH = "/__lunora";
5
- const STUDIO_SCRIPT_PATH = `${STUDIO_PATH}/studio.js`;
6
- const STUDIO_STYLE_PATH = `${STUDIO_PATH}/styles.css`;
7
- const LEADING_SLASH = /^\//;
8
- const TRAILING_SLASH = /\/$/;
9
- const JSON_ENDPOINT_HANDLERS = {
10
- [POLICY_SCAFFOLD_ENDPOINT]: handlePolicyScaffoldRequest,
11
- [SCHEMA_EDIT_ENDPOINT]: handleSchemaEditRequest,
12
- [SEED_ENDPOINT]: handleSeedRequest
13
- };
14
- const STATE_CHANGING_ENDPOINTS = new Set(Object.keys(JSON_ENDPOINT_HANDLERS));
15
- const headerValue = (raw) => {
16
- const value = Array.isArray(raw) ? raw[0] : raw;
17
- return typeof value === "string" ? value.trim().toLowerCase() : void 0;
18
- };
19
- const isLoopbackAddress = (remoteAddress) => {
20
- if (remoteAddress === void 0 || remoteAddress === "") {
21
- return true;
22
- }
23
- const address = remoteAddress.toLowerCase();
24
- const v4 = address.startsWith("::ffff:") ? address.slice(7) : address;
25
- if (v4 === "::1") {
26
- return true;
27
- }
28
- return v4.startsWith("127.");
29
- };
30
- const hostnameOf = (host) => {
31
- if (host === void 0) {
32
- return void 0;
33
- }
34
- if (host.startsWith("[")) {
35
- const close = host.indexOf("]");
36
- return close === -1 ? host.slice(1) : host.slice(1, close);
37
- }
38
- const colon = host.indexOf(":");
39
- return colon === -1 ? host : host.slice(0, colon);
40
- };
41
- const LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "127.0.0.1", "::1", "localhost"]);
42
- const transportRejectionReason = (request) => {
43
- if (!isLoopbackAddress(request.socket?.remoteAddress ?? void 0)) {
44
- return "Lunora studio is only available on loopback connections in dev.";
45
- }
46
- const host = hostnameOf(headerValue(request.headers?.host));
47
- if (host !== void 0 && !LOOPBACK_HOSTS.has(host)) {
48
- return "Lunora studio rejects a non-localhost Host header in dev.";
49
- }
50
- return void 0;
51
- };
52
- const originRejectionReason = (headers) => {
53
- const secFetchSite = headerValue(headers["sec-fetch-site"]);
54
- if (secFetchSite !== void 0) {
55
- return secFetchSite === "same-origin" || secFetchSite === "same-site" || secFetchSite === "none" ? void 0 : "cross-origin request rejected";
56
- }
57
- const origin = headerValue(headers.origin);
58
- if (origin === void 0 || origin === "null") {
59
- return void 0;
60
- }
61
- let originHost;
62
- try {
63
- originHost = new URL(origin).host.toLowerCase();
64
- } catch {
65
- return "invalid origin header";
66
- }
67
- const host = headerValue(headers.host);
68
- return host === void 0 || originHost !== host ? "cross-origin request rejected" : void 0;
69
- };
70
- const csrfRejectionReason = (request) => {
71
- const headers = request.headers ?? {};
72
- const originReason = originRejectionReason(headers);
73
- if (originReason !== void 0) {
74
- return originReason;
75
- }
76
- const method = (request.method ?? "GET").toUpperCase();
77
- if (method !== "GET" && method !== "HEAD") {
78
- const contentType = headerValue(headers["content-type"]);
79
- if (!contentType?.startsWith("application/json")) {
80
- return "content-type must be application/json";
81
- }
82
- }
83
- return void 0;
84
- };
85
- const sendOk = (response, body, contentType) => {
86
- response.statusCode = 200;
87
- response.setHeader("Content-Type", contentType);
88
- response.end(body);
89
- };
90
- const buildStudioUrl = (input) => {
91
- const path = STUDIO_PATH.replace(LEADING_SLASH, "");
92
- if (input.resolvedLocal !== void 0 && input.resolvedLocal !== "") {
93
- const origin = input.resolvedLocal.endsWith("/") ? input.resolvedLocal.slice(0, -1) : input.resolvedLocal;
94
- return `${origin}/${path}`;
95
- }
96
- const base = input.base === void 0 || input.base === "/" ? "" : input.base.replace(TRAILING_SLASH, "");
97
- if (input.address === void 0 || typeof input.address === "string") {
98
- return `http://localhost:5173${base}/${path}`;
99
- }
100
- const host = input.address.address === "::" || input.address.address === "0.0.0.0" ? "localhost" : input.address.address;
101
- const bracketed = host.includes(":") ? `[${host}]` : host;
102
- return `http://${bracketed}:${String(input.address.port)}${base}/${path}`;
103
- };
104
- const pathnameOf = (url) => {
105
- try {
106
- return new URL(url, "http://localhost").pathname.replace(TRAILING_SLASH, "");
107
- } catch {
108
- return url;
109
- }
110
- };
111
- const createStudioHandler = (server, isNonLoopbackBind) => {
112
- let assets;
113
- let assetsStamp;
114
- let html;
115
- const projectRoot = server.config.root ?? process.cwd();
116
- const serveStaticAsset = (pathname, response) => {
117
- const stamp = studioAssetsStamp();
118
- if (assets === void 0 || stamp !== assetsStamp) {
119
- assets = loadStudioAssets(server.config.logger);
120
- assetsStamp = stamp;
121
- }
122
- if (assets === void 0) {
123
- response.statusCode = 501;
124
- response.setHeader("Content-Type", "text/plain");
125
- response.end("Lunora studio assets not found — install and build @lunora/studio.");
126
- return;
127
- }
128
- const isScript = pathname === STUDIO_SCRIPT_PATH;
129
- sendOk(response, isScript ? assets.script : assets.styles, isScript ? "text/javascript; charset=utf-8" : "text/css; charset=utf-8");
130
- };
131
- return (request, response, next) => {
132
- const pathname = pathnameOf(request.url ?? "");
133
- if (pathname !== STUDIO_PATH && !pathname.startsWith(`${STUDIO_PATH}/`)) {
134
- next();
135
- return;
136
- }
137
- if (isNonLoopbackBind || transportRejectionReason(request) !== void 0) {
138
- response.statusCode = 403;
139
- response.setHeader("Content-Type", "text/plain");
140
- response.end("Lunora studio is only available on loopback hosts in dev.");
141
- return;
142
- }
143
- if (STATE_CHANGING_ENDPOINTS.has(pathname)) {
144
- const csrf = csrfRejectionReason(request);
145
- if (csrf !== void 0) {
146
- response.statusCode = 403;
147
- response.setHeader("Content-Type", "application/json; charset=utf-8");
148
- response.end(JSON.stringify({ error: csrf, ok: false }));
149
- return;
150
- }
151
- }
152
- const jsonHandler = JSON_ENDPOINT_HANDLERS[pathname];
153
- if (jsonHandler !== void 0) {
154
- serveJsonHandler(request, response, jsonHandler, projectRoot);
155
- return;
156
- }
157
- if (pathname === STUDIO_SCRIPT_PATH || pathname === STUDIO_STYLE_PATH) {
158
- serveStaticAsset(pathname, response);
159
- return;
160
- }
161
- html ??= renderStudioHtml({
162
- adminToken: resolveAdminToken(projectRoot),
163
- basePath: STUDIO_PATH,
164
- // Loopback-only dev route (it 403s on a non-loopback bind), so the
165
- // developer owns the data — let them edit rows, run-as a user, and edit
166
- // the schema by default.
167
- dataEditable: true,
168
- rulesInstalled: detectAgentRules(projectRoot).installed,
169
- runAsIdentity: true,
170
- schemaEditable: true,
171
- scriptSrc: STUDIO_SCRIPT_PATH,
172
- styleHref: STUDIO_STYLE_PATH
173
- });
174
- sendOk(response, html, "text/html; charset=utf-8");
175
- };
176
- };
177
- const studioPlugin = () => {
178
- return {
179
- apply: "serve",
180
- configureServer(server) {
181
- const configuredHost = server.config.server?.host;
182
- const isNonLoopbackBind = configuredHost !== void 0 && configuredHost !== false && configuredHost !== "localhost" && configuredHost !== "127.0.0.1" && configuredHost !== "::1";
183
- server.middlewares.use(createStudioHandler(server, isNonLoopbackBind));
184
- return () => {
185
- const announce = () => {
186
- const url = buildStudioUrl({
187
- address: server.httpServer?.address() ?? void 0,
188
- base: server.config.base,
189
- resolvedLocal: server.resolvedUrls?.local[0]
190
- });
191
- server.config.logger.info(` \x1B[32m➜\x1B[39m \x1B[1mLunora\x1B[22m: \x1B[36m${url}\x1B[39m`);
192
- };
193
- if (typeof server.printUrls === "function") {
194
- const printUrls = server.printUrls.bind(server);
195
- server.printUrls = () => {
196
- printUrls();
197
- announce();
198
- };
199
- } else if (server.httpServer?.listening === true) {
200
- announce();
201
- } else {
202
- server.httpServer?.once("listening", announce);
203
- }
204
- };
205
- },
206
- name: "lunora:studio"
207
- };
208
- };
209
-
210
- export { STUDIO_PATH, STUDIO_SCRIPT_PATH, STUDIO_STYLE_PATH, buildStudioUrl, studioPlugin };