@lunora/nuxt 1.0.0-alpha.110 → 1.0.0-alpha.112

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/module.d.mts CHANGED
@@ -11,6 +11,50 @@ import { defineNuxtModule } from '@nuxt/kit';
11
11
  * otherwise-valid build") and the `@lunora/astro` precedent this mirrors.
12
12
  */
13
13
  declare const checkWorkerEntry: (rootDirectory: string, warn: (message: string) => void) => void;
14
+ /**
15
+ * One entry of Nuxt's resolved plugin list (`app.plugins` at `app:resolve`):
16
+ * an absolute `src` plus the `mode` Nuxt derived for it. Declared structurally
17
+ * for the same reason as {@link LunoraNuxtModule} — `@nuxt/schema`, which owns
18
+ * `NuxtPlugin`, is not a resolvable dependency here — and `NuxtPlugin[]`
19
+ * satisfies it.
20
+ */
21
+ interface ResolvedNuxtPlugin {
22
+ mode?: "all" | "client" | "server";
23
+ src: string;
24
+ }
25
+ /**
26
+ * Warn when the project's ONLY `LunoraClient` provider is a client-only plugin.
27
+ *
28
+ * `@lunora/vue`'s composables call `useLunora()` unconditionally — ahead of
29
+ * their own browser guard — and it throws when nothing is injected. A
30
+ * `plugins/lunora.client.ts` by definition never runs on the server, so the
31
+ * first server-rendered page touching Lunora answers 500 with
32
+ * `useLunora(): no LunoraClient provided`. The fix is dropping `.client` from
33
+ * the filename plus a universal way to read the origin, which the warning says.
34
+ *
35
+ * Takes Nuxt's own resolved plugin list (`app.plugins`, from the `app:resolve`
36
+ * hook) rather than scanning `plugins/` itself. That is the whole point: Nuxt
37
+ * loads plugins with a two-pattern, ONE-level glob — top-level entries plus a
38
+ * subdirectory's `index` file — over every layer's configured plugins dir, so
39
+ * a filesystem scan of its own has to mirror the glob, the extension list,
40
+ * `dir.plugins` and every layer — and gets the answer WRONG in both directions
41
+ * when it doesn't. A recursive scan counts `plugins/lib/make-client.ts` (an
42
+ * ordinary colocated helper Nuxt never loads) as a universal provider and goes
43
+ * silent on a genuinely broken app. Reading `mode` off the resolved entry also
44
+ * drops the `.client` filename rule, since that is what Nuxt derived it from.
45
+ *
46
+ * Detection of the provider itself is the same shape as
47
+ * {@link looksLikeShardDoExport}: a documented keyword test, not a TS parse,
48
+ * because the outcome is a build-time warning. Its imprecision is a
49
+ * `createLunora` mention inside a comment, whose only cost is a warning
50
+ * pointing at a file that is already about the client.
51
+ *
52
+ * Silence requires a provider Nuxt loads on the server — `mode` `"all"` or
53
+ * `"server"` — not merely a working app: an app that confines every Lunora
54
+ * usage to `<ClientOnly>` is correct with a client-only provider and still
55
+ * warns, which is why the message names that case as a reason to ignore it.
56
+ */
57
+ declare const checkClientOnlyProvider: (plugins: ReadonlyArray<ResolvedNuxtPlugin>, warn: (message: string) => void) => void;
14
58
  /** Options for the `@lunora/nuxt` module (configurable under the `lunora` key in `nuxt.config`). */
15
59
  interface ModuleOptions {
16
60
  /**
@@ -31,4 +75,4 @@ type LunoraNuxtModule = typeof defineNuxtModule<ModuleOptions> extends {
31
75
  (): unknown;
32
76
  } ? Result : never;
33
77
  declare const lunoraNuxtModule: LunoraNuxtModule;
34
- export { ModuleOptions, checkWorkerEntry, lunoraNuxtModule as default };
78
+ export { ModuleOptions, ResolvedNuxtPlugin, checkClientOnlyProvider, checkWorkerEntry, lunoraNuxtModule as default };
package/dist/module.d.ts CHANGED
@@ -11,6 +11,50 @@ import { defineNuxtModule } from '@nuxt/kit';
11
11
  * otherwise-valid build") and the `@lunora/astro` precedent this mirrors.
12
12
  */
13
13
  declare const checkWorkerEntry: (rootDirectory: string, warn: (message: string) => void) => void;
14
+ /**
15
+ * One entry of Nuxt's resolved plugin list (`app.plugins` at `app:resolve`):
16
+ * an absolute `src` plus the `mode` Nuxt derived for it. Declared structurally
17
+ * for the same reason as {@link LunoraNuxtModule} — `@nuxt/schema`, which owns
18
+ * `NuxtPlugin`, is not a resolvable dependency here — and `NuxtPlugin[]`
19
+ * satisfies it.
20
+ */
21
+ interface ResolvedNuxtPlugin {
22
+ mode?: "all" | "client" | "server";
23
+ src: string;
24
+ }
25
+ /**
26
+ * Warn when the project's ONLY `LunoraClient` provider is a client-only plugin.
27
+ *
28
+ * `@lunora/vue`'s composables call `useLunora()` unconditionally — ahead of
29
+ * their own browser guard — and it throws when nothing is injected. A
30
+ * `plugins/lunora.client.ts` by definition never runs on the server, so the
31
+ * first server-rendered page touching Lunora answers 500 with
32
+ * `useLunora(): no LunoraClient provided`. The fix is dropping `.client` from
33
+ * the filename plus a universal way to read the origin, which the warning says.
34
+ *
35
+ * Takes Nuxt's own resolved plugin list (`app.plugins`, from the `app:resolve`
36
+ * hook) rather than scanning `plugins/` itself. That is the whole point: Nuxt
37
+ * loads plugins with a two-pattern, ONE-level glob — top-level entries plus a
38
+ * subdirectory's `index` file — over every layer's configured plugins dir, so
39
+ * a filesystem scan of its own has to mirror the glob, the extension list,
40
+ * `dir.plugins` and every layer — and gets the answer WRONG in both directions
41
+ * when it doesn't. A recursive scan counts `plugins/lib/make-client.ts` (an
42
+ * ordinary colocated helper Nuxt never loads) as a universal provider and goes
43
+ * silent on a genuinely broken app. Reading `mode` off the resolved entry also
44
+ * drops the `.client` filename rule, since that is what Nuxt derived it from.
45
+ *
46
+ * Detection of the provider itself is the same shape as
47
+ * {@link looksLikeShardDoExport}: a documented keyword test, not a TS parse,
48
+ * because the outcome is a build-time warning. Its imprecision is a
49
+ * `createLunora` mention inside a comment, whose only cost is a warning
50
+ * pointing at a file that is already about the client.
51
+ *
52
+ * Silence requires a provider Nuxt loads on the server — `mode` `"all"` or
53
+ * `"server"` — not merely a working app: an app that confines every Lunora
54
+ * usage to `<ClientOnly>` is correct with a client-only provider and still
55
+ * warns, which is why the message names that case as a reason to ignore it.
56
+ */
57
+ declare const checkClientOnlyProvider: (plugins: ReadonlyArray<ResolvedNuxtPlugin>, warn: (message: string) => void) => void;
14
58
  /** Options for the `@lunora/nuxt` module (configurable under the `lunora` key in `nuxt.config`). */
15
59
  interface ModuleOptions {
16
60
  /**
@@ -31,4 +75,4 @@ type LunoraNuxtModule = typeof defineNuxtModule<ModuleOptions> extends {
31
75
  (): unknown;
32
76
  } ? Result : never;
33
77
  declare const lunoraNuxtModule: LunoraNuxtModule;
34
- export { ModuleOptions, checkWorkerEntry, lunoraNuxtModule as default };
78
+ export { ModuleOptions, ResolvedNuxtPlugin, checkClientOnlyProvider, checkWorkerEntry, lunoraNuxtModule as default };
package/dist/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "configKey": "lunora",
3
3
  "name": "@lunora/nuxt",
4
- "version": "1.0.0-alpha.109"
4
+ "version": "1.0.0-alpha.111"
5
5
  }
package/dist/module.mjs CHANGED
@@ -1 +1 @@
1
- import{existsSync as i,readFileSync as u}from"node:fs";import{join as s,resolve as d,dirname as p}from"node:path";import{defineNuxtModule as h,createResolver as c,addServerHandler as m,useLogger as f}from"@nuxt/kit";const S=(r,t,o)=>r.startsWith("~~/")?s(t,r.slice(3)):r.startsWith("~/")?s(o,r.slice(2)):r.startsWith("./")||r.startsWith("../")?s(t,r):r,v=/\.js$/,D=r=>{const t=s(r,"lunora");return{name:"lunora:nitro-ts-source-resolve",resolveId:{handler(o,e){if(!o.endsWith(".js"))return;let n;if(o.startsWith("#lunora/")?n=s(t,o.slice(8)):o.startsWith(".")&&e!==void 0&&(n=d(p(e),o)),n===void 0)return;const a=n.replace(v,".ts");return i(a)?a:void 0},order:"pre"}}},l='export { default } from "./.output/server/index.mjs"; export { ShardDO } from "./lunora/server";',E=/\bexport\b/u,R=/\bShardDO\b/u,O=/\bexport\s*\*\s*from\s*["'][^"']*lunora[^"']*["']/u,T=r=>E.test(r)?R.test(r)||O.test(r):!1,g=(r,t)=>{const o=s(r,"worker.ts");if(!i(o)){t(`missing worker.ts at the project root — add a wrapper that re-exports Nitro's handler and \`ShardDO\` (\`${l}\`) and point wrangler's \`main\` at it, so the SHARD Durable Object is exported from the deployed worker.`);return}let e;try{e=u(o,"utf8")}catch(n){const a=n instanceof Error?n.message:String(n);t(`could not read worker.ts at the project root (${a}) — skipping the \`ShardDO\` export check.`);return}T(e)||t(`worker.ts at the project root does not appear to export \`ShardDO\` — add \`export { ShardDO } from "./lunora/server";\` (e.g. \`${l}\`) and point wrangler's \`main\` at it, so the SHARD Durable Object is exported from the deployed worker.`)},_="/_lunora",b=h({defaults:{appEntry:"~/lunora/server"},meta:{configKey:"lunora",name:"@lunora/nuxt"},setup(r,t){const o=c(import.meta.url);t.options.alias["#lunora/app"]=S(r.appEntry,t.options.rootDir,t.options.srcDir),t.hook("nitro:config",e=>{const n=[...e.rollupConfig?.plugins??[],D(t.options.rootDir)];e.rollupConfig={...e.rollupConfig,plugins:n}}),m({handler:o.resolve("./runtime/server/lunora"),route:`${_}/**`}),g(t.options.rootDir,e=>{f("@lunora/nuxt").warn(e)})}});export{g as checkWorkerEntry,b as default};
1
+ import{existsSync as u,readFileSync as d}from"node:fs";import{join as s,resolve as h,dirname as p}from"node:path";import{defineNuxtModule as c,createResolver as v,addServerHandler as f,useLogger as i}from"@nuxt/kit";const m=(r,o,t)=>r.startsWith("~~/")?s(o,r.slice(3)):r.startsWith("~/")?s(t,r.slice(2)):r.startsWith("./")||r.startsWith("../")?s(o,r):r,g=/\.js$/,R=r=>{const o=s(r,"lunora");return{name:"lunora:nitro-ts-source-resolve",resolveId:{handler(t,e){if(!t.endsWith(".js"))return;let n;if(t.startsWith("#lunora/")?n=s(o,t.slice(8)):t.startsWith(".")&&e!==void 0&&(n=h(p(e),t)),n===void 0)return;const a=n.replace(g,".ts");return u(a)?a:void 0},order:"pre"}}},l='export { default } from "./.output/server/index.mjs"; export { ShardDO } from "./lunora/server";',S=/\bexport\b/u,E=/\bShardDO\b/u,D=/\bexport\s*\*\s*from\s*["'][^"']*lunora[^"']*["']/u,O=r=>S.test(r)?E.test(r)||D.test(r):!1,w=(r,o)=>{const t=s(r,"worker.ts");if(!u(t)){o(`missing worker.ts at the project root — add a wrapper that re-exports Nitro's handler and \`ShardDO\` (\`${l}\`) and point wrangler's \`main\` at it, so the SHARD Durable Object is exported from the deployed worker.`);return}let e;try{e=d(t,"utf8")}catch(n){const a=n instanceof Error?n.message:String(n);o(`could not read worker.ts at the project root (${a}) — skipping the \`ShardDO\` export check.`);return}O(e)||o(`worker.ts at the project root does not appear to export \`ShardDO\` — add \`export { ShardDO } from "./lunora/server";\` (e.g. \`${l}\`) and point wrangler's \`main\` at it, so the SHARD Durable Object is exported from the deployed worker.`)},T=/\bcreateLunora\b/u,k=r=>{try{return T.test(d(r,"utf8"))}catch{return!1}},_=(r,o)=>{const t=r.filter(e=>k(e.src));t.length===0||t.some(e=>e.mode!=="client")||o(`the only plugin providing a \`LunoraClient\` is client-only (${t.map(e=>e.src).join(", ")}) — \`@lunora/vue\`'s composables resolve the client during SSR too and throw \`useLunora(): no LunoraClient provided\` without one, so the first server-rendered page that touches Lunora answers 500. Drop the \`.client\` from the filename to make the plugin universal, and read the origin with \`useRequestURL().origin\`, which resolves from the incoming request on the server and from \`window.location\` in the browser. Ignore this if every Lunora usage is confined to \`<ClientOnly>\`, which never renders on the server.`)},y="/_lunora",L=c({defaults:{appEntry:"~/lunora/server"},meta:{configKey:"lunora",name:"@lunora/nuxt"},setup(r,o){const t=v(import.meta.url);o.options.alias["#lunora/app"]=m(r.appEntry,o.options.rootDir,o.options.srcDir),o.hook("nitro:config",e=>{const n=[...e.rollupConfig?.plugins??[],R(o.options.rootDir)];e.rollupConfig={...e.rollupConfig,plugins:n}}),f({handler:t.resolve("./runtime/server/lunora"),route:`${y}/**`}),w(o.options.rootDir,e=>{i("@lunora/nuxt").warn(e)}),o.hook("app:resolve",e=>{_(e.plugins,n=>{i("@lunora/nuxt").warn(n)})})}});export{_ as checkClientOnlyProvider,w as checkWorkerEntry,L as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/nuxt",
3
- "version": "1.0.0-alpha.110",
3
+ "version": "1.0.0-alpha.112",
4
4
  "description": "Nuxt module for Lunora — single-worker composition (mounts /_lunora/* into Nitro) plus reactive-loader server helpers",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -51,8 +51,8 @@
51
51
  "access": "public"
52
52
  },
53
53
  "dependencies": {
54
- "@lunora/client": "1.0.0-alpha.81",
55
- "@lunora/runtime": "1.0.0-alpha.96",
54
+ "@lunora/client": "1.0.0-alpha.83",
55
+ "@lunora/runtime": "1.0.0-alpha.98",
56
56
  "@nuxt/kit": "^4.5.2"
57
57
  },
58
58
  "peerDependencies": {