@loadbare/app 0.18.2 → 0.19.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.
Files changed (51) hide show
  1. package/README.md +17 -17
  2. package/dist/build/assemble.d.ts +7 -1
  3. package/dist/build/assemble.d.ts.map +1 -1
  4. package/dist/build/assemble.js +81 -11
  5. package/dist/build/assemble.js.map +1 -1
  6. package/dist/build/cli.d.ts +3 -0
  7. package/dist/build/cli.d.ts.map +1 -1
  8. package/dist/build/cli.js +6 -1
  9. package/dist/build/cli.js.map +1 -1
  10. package/dist/build/declared.d.ts +25 -0
  11. package/dist/build/declared.d.ts.map +1 -0
  12. package/dist/build/declared.js +62 -0
  13. package/dist/build/declared.js.map +1 -0
  14. package/dist/build/pages.d.ts +6 -0
  15. package/dist/build/pages.d.ts.map +1 -1
  16. package/dist/build/pages.js +32 -12
  17. package/dist/build/pages.js.map +1 -1
  18. package/docs/comparison.md +697 -484
  19. package/docs/departures.md +63 -0
  20. package/docs/miswarts.md +140 -0
  21. package/docs/opinions.md +155 -0
  22. package/docs/reference/builder.md +20 -4
  23. package/docs/reference/chrome.md +45 -10
  24. package/docs/reference/css.md +0 -1
  25. package/docs/reference/custom-elements.md +3 -25
  26. package/docs/reference/data-binding.md +265 -48
  27. package/docs/reference/names.md +250 -0
  28. package/docs/reference/overview.md +6 -0
  29. package/docs/reference/page-files.md +77 -9
  30. package/docs/reference/server.md +54 -1
  31. package/docs/roadmap.md +55 -43
  32. package/docs/testing.md +62 -28
  33. package/docs/theory.md +348 -108
  34. package/docs/tutorials/040-displaying-data.md +1 -1
  35. package/package.json +1 -1
  36. package/skills/loadbare-app/SKILL.md +19 -13
  37. package/skills/loadbare-app/references/builder.md +20 -4
  38. package/skills/loadbare-app/references/chrome.md +45 -10
  39. package/skills/loadbare-app/references/css.md +0 -1
  40. package/skills/loadbare-app/references/custom-elements.md +3 -25
  41. package/skills/loadbare-app/references/data-binding.md +265 -48
  42. package/skills/loadbare-app/references/miswarts.md +140 -0
  43. package/skills/loadbare-app/references/names.md +250 -0
  44. package/skills/loadbare-app/references/overview.md +6 -0
  45. package/skills/loadbare-app/references/page-files.md +77 -9
  46. package/skills/loadbare-app/references/server.md +54 -1
  47. package/docs/TECHREF-1.0.md +0 -2312
  48. package/docs/possible-ideas.md +0 -314
  49. package/docs/theory-old.md +0 -839
  50. package/docs/what-does-loadbare-extend.md +0 -124
  51. package/skills/loadbare-app/references/TECHREF-1.0.md +0 -2312
@@ -27,17 +27,9 @@ function relativeImport(outDir, file) {
27
27
  const rel = path.relative(outDir, file).split(path.sep).join("/");
28
28
  return rel.startsWith(".") ? rel : `./${rel}`;
29
29
  }
30
- /**
31
- * `undefined` when no page has a requests or queries file — the caller writes
32
- * nothing in that case, the same way an app with no custom elements gets no
33
- * client entry beyond the built-ins.
34
- */
35
- export function pagesSource(pages, pageSources, outDir, packageName) {
36
- if (pageSources.size === 0)
37
- return undefined;
38
- const imports = [
39
- `import { createHub } from ${JSON.stringify(`${packageName}/server`)};`,
40
- ];
30
+ /** An import of each page's modules, and its `Pages` entry naming them. */
31
+ function pageEntries(pages, pageSources, outDir) {
32
+ const imports = [];
41
33
  const entries = [];
42
34
  for (const { name } of pages) {
43
35
  const source = pageSources.get(name);
@@ -55,6 +47,34 @@ export function pagesSource(pages, pageSources, outDir, packageName) {
55
47
  }
56
48
  entries.push(` ${JSON.stringify(name)}: { requests: ${requestsId ?? "{}"}, queries: ${queriesId ?? "{}"} },`);
57
49
  }
58
- return ([...imports, "", "export const hub = createHub({", ...entries, "});"].join("\n") + "\n");
50
+ return { imports, entries };
51
+ }
52
+ /**
53
+ * `undefined` when no page has a requests or queries file — the caller writes
54
+ * nothing in that case, the same way an app with no custom elements gets no
55
+ * client entry beyond the built-ins.
56
+ */
57
+ export function pagesSource(pages, pageSources, outDir, packageName) {
58
+ if (pageSources.size === 0)
59
+ return undefined;
60
+ const { imports, entries } = pageEntries(pages, pageSources, outDir);
61
+ return ([
62
+ `import { createHub } from ${JSON.stringify(`${packageName}/server`)};`,
63
+ ...imports,
64
+ "",
65
+ "export const hub = createHub({",
66
+ ...entries,
67
+ "});",
68
+ ].join("\n") + "\n");
69
+ }
70
+ /**
71
+ * The same registry with no `createHub()`, exporting the `Pages` object
72
+ * itself, so the builder can read what each page declares — see
73
+ * build/declared.ts. Resolved from `outDir`, as `pages.ts` is.
74
+ */
75
+ export function declaredSource(pages, pageSources, outDir) {
76
+ const { imports, entries } = pageEntries(pages, pageSources, outDir);
77
+ return ([...imports, "", "export const pages = {", ...entries, "};"].join("\n") +
78
+ "\n");
59
79
  }
60
80
  //# sourceMappingURL=pages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../build/pages.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,qFAAqF;AACrF,SAAS,UAAU,CAAC,IAAY,EAAE,MAA8B;IAC9D,OAAO,QAAQ,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,IAAI,MAAM,EAAE,CAAC;AAChE,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,IAAY;IAClD,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClE,OAAO,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;AAChD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CACzB,KAAiB,EACjB,WAAoC,EACpC,MAAc,EACd,WAAmB;IAEnB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE7C,MAAM,OAAO,GAAa;QACxB,6BAA6B,IAAI,CAAC,SAAS,CAAC,GAAG,WAAW,SAAS,CAAC,GAAG;KACxE,CAAC;IACF,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ;YAChC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC;YAC9B,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE3E,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CACV,wBAAwB,UAAU,WAAW,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CACxG,CAAC;QACJ,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CACV,uBAAuB,SAAS,WAAW,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CACrG,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,IAAI,CACV,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,UAAU,IAAI,IAAI,cAAc,SAAS,IAAI,IAAI,KAAK,CACjG,CAAC;IACJ,CAAC;IAED,OAAO,CACL,CAAC,GAAG,OAAO,EAAE,EAAE,EAAE,gCAAgC,EAAE,GAAG,OAAO,EAAE,KAAK,CAAC,CAAC,IAAI,CACxE,IAAI,CACL,GAAG,IAAI,CACT,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Generating the hub's page registry — the server-side counterpart to\n * build/elements.ts's client entry point.\n *\n * `*.requests.ts` and `*.queries.ts` are ordinary TypeScript, found by\n * build/locations.ts and handed here already paired by page name. This\n * module writes an import of each pair, a `Pages` object naming them by\n * page, and the one `createHub()` call. It is written to `<out>/pages.ts` rather than compiled\n * — the application runs it directly, exactly as it does its own server\n * code, so it never needs a bundler step the way the browser-bound client\n * entry does.\n *\n * Each import keeps its `.ts` extension. Node's loader, including its own\n * type stripping, looks for exactly the path it is given and never tries an\n * extension, so a path without one runs under tsx and nowhere else.\n *\n * Nothing here is emitted for a page with neither a requests nor a queries\n * file — a purely static page needs no hub entry, and createHub is only\n * called at all when there is at least one.\n */\n\nimport path from \"node:path\";\nimport type { PageFile, PageSource } from \"./locations.js\";\n\n/** A page name may contain anything a filename can; an import identifier may not. */\nfunction identifier(name: string, suffix: \"Requests\" | \"Queries\"): string {\n return `page_${name.replace(/[^a-zA-Z0-9]/g, \"_\")}_${suffix}`;\n}\n\nfunction relativeImport(outDir: string, file: string): string {\n const rel = path.relative(outDir, file).split(path.sep).join(\"/\");\n return rel.startsWith(\".\") ? rel : `./${rel}`;\n}\n\n/**\n * `undefined` when no page has a requests or queries file — the caller writes\n * nothing in that case, the same way an app with no custom elements gets no\n * client entry beyond the built-ins.\n */\nexport function pagesSource(\n pages: PageFile[],\n pageSources: Map<string, PageSource>,\n outDir: string,\n packageName: string,\n): string | undefined {\n if (pageSources.size === 0) return undefined;\n\n const imports: string[] = [\n `import { createHub } from ${JSON.stringify(`${packageName}/server`)};`,\n ];\n const entries: string[] = [];\n\n for (const { name } of pages) {\n const source = pageSources.get(name);\n if (!source) continue;\n\n const requestsId = source.requests\n ? identifier(name, \"Requests\")\n : undefined;\n const queriesId = source.queries ? identifier(name, \"Queries\") : undefined;\n\n if (source.requests) {\n imports.push(\n `import { requests as ${requestsId} } from ${JSON.stringify(relativeImport(outDir, source.requests))};`,\n );\n }\n if (source.queries) {\n imports.push(\n `import { queries as ${queriesId} } from ${JSON.stringify(relativeImport(outDir, source.queries))};`,\n );\n }\n\n entries.push(\n ` ${JSON.stringify(name)}: { requests: ${requestsId ?? \"{}\"}, queries: ${queriesId ?? \"{}\"} },`,\n );\n }\n\n return (\n [...imports, \"\", \"export const hub = createHub({\", ...entries, \"});\"].join(\n \"\\n\",\n ) + \"\\n\"\n );\n}\n"]}
1
+ {"version":3,"file":"pages.js","sourceRoot":"","sources":["../../build/pages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generating the hub's page registry — the server-side counterpart to\n * build/elements.ts's client entry point.\n *\n * `*.requests.ts` and `*.queries.ts` are ordinary TypeScript, found by\n * build/locations.ts and handed here already paired by page name. This\n * module writes an import of each pair, a `Pages` object naming them by\n * page, and the one `createHub()` call. It is written to `<out>/pages.ts` rather than compiled\n * — the application runs it directly, exactly as it does its own server\n * code, so it never needs a bundler step the way the browser-bound client\n * entry does.\n *\n * Each import keeps its `.ts` extension. Node's loader, including its own\n * type stripping, looks for exactly the path it is given and never tries an\n * extension, so a path without one runs under tsx and nowhere else.\n *\n * Nothing here is emitted for a page with neither a requests nor a queries\n * file — a purely static page needs no hub entry, and createHub is only\n * called at all when there is at least one.\n */\n\nimport path from \"node:path\";\nimport type { PageFile, PageSource } from \"./locations.js\";\n\n/** A page name may contain anything a filename can; an import identifier may not. */\nfunction identifier(name: string, suffix: \"Requests\" | \"Queries\"): string {\n return `page_${name.replace(/[^a-zA-Z0-9]/g, \"_\")}_${suffix}`;\n}\n\nfunction relativeImport(outDir: string, file: string): string {\n const rel = path.relative(outDir, file).split(path.sep).join(\"/\");\n return rel.startsWith(\".\") ? rel : `./${rel}`;\n}\n\n/** An import of each page's modules, and its `Pages` entry naming them. */\nfunction pageEntries(\n pages: PageFile[],\n pageSources: Map<string, PageSource>,\n outDir: string,\n): { imports: string[]; entries: string[] } {\n const imports: string[] = [];\n const entries: string[] = [];\n\n for (const { name } of pages) {\n const source = pageSources.get(name);\n if (!source) continue;\n\n const requestsId = source.requests\n ? identifier(name, \"Requests\")\n : undefined;\n const queriesId = source.queries ? identifier(name, \"Queries\") : undefined;\n\n if (source.requests) {\n imports.push(\n `import { requests as ${requestsId} } from ${JSON.stringify(relativeImport(outDir, source.requests))};`,\n );\n }\n if (source.queries) {\n imports.push(\n `import { queries as ${queriesId} } from ${JSON.stringify(relativeImport(outDir, source.queries))};`,\n );\n }\n\n entries.push(\n ` ${JSON.stringify(name)}: { requests: ${requestsId ?? \"{}\"}, queries: ${queriesId ?? \"{}\"} },`,\n );\n }\n return { imports, entries };\n}\n\n/**\n * `undefined` when no page has a requests or queries file — the caller writes\n * nothing in that case, the same way an app with no custom elements gets no\n * client entry beyond the built-ins.\n */\nexport function pagesSource(\n pages: PageFile[],\n pageSources: Map<string, PageSource>,\n outDir: string,\n packageName: string,\n): string | undefined {\n if (pageSources.size === 0) return undefined;\n\n const { imports, entries } = pageEntries(pages, pageSources, outDir);\n return (\n [\n `import { createHub } from ${JSON.stringify(`${packageName}/server`)};`,\n ...imports,\n \"\",\n \"export const hub = createHub({\",\n ...entries,\n \"});\",\n ].join(\"\\n\") + \"\\n\"\n );\n}\n\n/**\n * The same registry with no `createHub()`, exporting the `Pages` object\n * itself, so the builder can read what each page declares — see\n * build/declared.ts. Resolved from `outDir`, as `pages.ts` is.\n */\nexport function declaredSource(\n pages: PageFile[],\n pageSources: Map<string, PageSource>,\n outDir: string,\n): string {\n const { imports, entries } = pageEntries(pages, pageSources, outDir);\n return (\n [...imports, \"\", \"export const pages = {\", ...entries, \"};\"].join(\"\\n\") +\n \"\\n\"\n );\n}\n"]}