redweb 0.13.5 → 0.14.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/README.md +20 -32
  3. package/docs/APPLICATION.md +98 -0
  4. package/docs/CLI.md +1 -1
  5. package/docs/COVERAGE_SCOPE_AUDIT.md +7 -0
  6. package/docs/DEFINE_APP_VERIFICATION.md +101 -0
  7. package/docs/DEVELOPMENT.md +1 -1
  8. package/docs/GETTING_STARTED.md +1 -1
  9. package/docs/LIVE_HTML.md +2 -2
  10. package/docs/MIGRATION.md +1 -1
  11. package/docs/MULTIPLAYER_OPERATIONS.md +6 -0
  12. package/docs/RELEASE_TRUST.md +4 -4
  13. package/docs/RUNTIME_DIAGNOSTICS.md +1 -1
  14. package/docs/SOCKET_CONTRACTS.md +2 -2
  15. package/docs/STARTER_LIFECYCLE_VERIFICATION.md +9 -0
  16. package/docs/generated.json +325 -271
  17. package/docs/guides/http-websocket.md +4 -4
  18. package/docs/guides/jsx-without-react.md +1 -1
  19. package/docs/reference.json +40 -1
  20. package/docs/releases/0.14.0.json +2208 -0
  21. package/docs/topics.json +1 -0
  22. package/examples/live-html/cards.js +87 -86
  23. package/examples/live-html/cards.ts +3 -2
  24. package/examples/live-html/chatroom.js +210 -207
  25. package/examples/live-html/chatroom.tsx +6 -2
  26. package/examples/live-html/components.js +103 -102
  27. package/examples/live-html/components.ts +3 -2
  28. package/examples/live-html/counter.js +74 -73
  29. package/examples/live-html/counter.ts +3 -2
  30. package/examples/live-html/jsx-page.js +2 -1
  31. package/examples/live-html/jsx-page.tsx +3 -2
  32. package/index.d.ts +53 -5
  33. package/index.js +3 -0
  34. package/package.json +3 -3
  35. package/recipes/chat/app.test.cjs +3 -1
  36. package/recipes/chat/app.tsx +4 -7
  37. package/recipes/dashboard/app.test.cjs +10 -10
  38. package/recipes/dashboard/app.tsx +29 -29
  39. package/recipes/http-ws/README.md +1 -1
  40. package/recipes/http-ws/app.test.cjs +8 -10
  41. package/recipes/http-ws/app.tsx +9 -20
  42. package/recipes/realtime/app.tsx +3 -6
  43. package/recipes/shared/README.md +3 -1
  44. package/recipes/shared/lifecycle.test.cjs +81 -0
  45. package/recipes/shared/network.cjs +10 -5
  46. package/recipes/site/app.tsx +3 -6
  47. package/recipes/socket/app.tsx +3 -10
  48. package/src/Application.js +239 -0
  49. package/src/StartupCleanup.js +24 -0
  50. package/src/cli/SourceInspector.js +5 -0
  51. package/src/cli/templates.js +3 -4
  52. package/src/htmx/LiveHtmlServer.js +14 -5
  53. package/src/htmx/PageManager.js +3 -1
  54. package/src/ws/BaseSocketServer.js +13 -13
  55. package/src/ws/SocketRoute.js +6 -2
  56. package/recipes/shared/run-app.test.cjs +0 -158
  57. package/recipes/shared/run-app.ts +0 -50
package/docs/topics.json CHANGED
@@ -1,5 +1,6 @@
1
1
  [
2
2
  { "id": "getting-started", "title": "Choose a starter and build a working app", "summary": "Requirements, fit, development, tests, and production boundaries.", "source": "docs/GETTING_STARTED.md" },
3
+ { "id": "application", "title": "One application, one listener", "summary": "Define pages, socket routes and application services together; run and shut down one owned HTTP/WebSocket listener.", "source": "docs/APPLICATION.md" },
3
4
  { "id": "guides/realtime-dashboard", "title": "Build a private realtime dashboard", "summary": "Persistent SQLite cards, account-private updates and sign-out across tabs, with explicit single-process limits.", "source": "docs/guides/realtime-dashboard.md", "recipe": { "template": "dashboard", "file": "src/cards.tsx" } },
4
5
  { "id": "guides/jsx-without-react", "title": "Render JSX without React", "summary": "TypeScript pages, a shared layout and external CSS, rendered on the server without browser framework code.", "source": "docs/guides/jsx-without-react.md", "recipe": { "template": "site", "file": "src/app.tsx" } },
5
6
  { "id": "guides/chatroom", "title": "Build a chatroom with live presence", "summary": "Reusable server-side components, validated forms and disconnect-aware presence, without custom browser socket glue.", "source": "docs/guides/chatroom.md", "recipe": { "template": "chat", "file": "src/chatroom.tsx" } },
@@ -1,91 +1,92 @@
1
- "use strict";
2
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
3
- var useValue = arguments.length > 2;
4
- for (var i = 0; i < initializers.length; i++) {
5
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6
- }
7
- return useValue ? value : void 0;
8
- };
9
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
10
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
11
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
12
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
13
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
14
- var _, done = false;
15
- for (var i = decorators.length - 1; i >= 0; i--) {
16
- var context = {};
17
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
18
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
19
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
20
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
21
- if (kind === "accessor") {
22
- if (result === void 0) continue;
23
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
24
- if (_ = accept(result.get)) descriptor.get = _;
25
- if (_ = accept(result.set)) descriptor.set = _;
26
- if (_ = accept(result.init)) initializers.unshift(_);
27
- }
28
- else if (_ = accept(result)) {
29
- if (kind === "field") initializers.unshift(_);
30
- else descriptor[key] = _;
31
- }
32
- }
33
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
34
- done = true;
35
- };
36
- Object.defineProperty(exports, "__esModule", { value: true });
37
- exports.CardsPage = void 0;
38
- const redweb_1 = require('../..');
39
- let CardsPage = (() => {
40
- let _classDecorators = [(0, redweb_1.page)('/', { template: 'cards.html', css: 'cards.css', shared: true })];
41
- let _classDescriptor;
42
- let _classExtraInitializers = [];
43
- let _classThis;
44
- let _instanceExtraInitializers = [];
45
- let _cards_decorators;
46
- let _cards_initializers = [];
47
- let _cards_extraInitializers = [];
48
- let _card_decorators;
49
- let _add_decorators;
50
- var CardsPage = class {
51
- static { _classThis = this; }
52
- static {
53
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
54
- _cards_decorators = [(0, redweb_1.state)()];
55
- _card_decorators = [(0, redweb_1.view)('cards')];
56
- _add_decorators = [(0, redweb_1.action)()];
57
- __esDecorate(this, null, _card_decorators, { kind: "method", name: "card", static: false, private: false, access: { has: obj => "card" in obj, get: obj => obj.card }, metadata: _metadata }, null, _instanceExtraInitializers);
58
- __esDecorate(this, null, _add_decorators, { kind: "method", name: "add", static: false, private: false, access: { has: obj => "add" in obj, get: obj => obj.add }, metadata: _metadata }, null, _instanceExtraInitializers);
59
- __esDecorate(null, null, _cards_decorators, { kind: "field", name: "cards", static: false, private: false, access: { has: obj => "cards" in obj, get: obj => obj.cards, set: (obj, value) => { obj.cards = value; } }, metadata: _metadata }, _cards_initializers, _cards_extraInitializers);
60
- __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
61
- CardsPage = _classThis = _classDescriptor.value;
62
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
63
- __runInitializers(_classThis, _classExtraInitializers);
64
- }
65
- cards = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _cards_initializers, [
66
- { title: 'Realtime', description: 'State changes arrive over the existing socket.' },
67
- { title: 'Safe HTML', description: 'Card values are escaped by default.' },
68
- ]));
69
- card(card) {
1
+ "use strict";
2
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
3
+ var useValue = arguments.length > 2;
4
+ for (var i = 0; i < initializers.length; i++) {
5
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
6
+ }
7
+ return useValue ? value : void 0;
8
+ };
9
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
10
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
11
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
12
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
13
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
14
+ var _, done = false;
15
+ for (var i = decorators.length - 1; i >= 0; i--) {
16
+ var context = {};
17
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
18
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
19
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
20
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
21
+ if (kind === "accessor") {
22
+ if (result === void 0) continue;
23
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
24
+ if (_ = accept(result.get)) descriptor.get = _;
25
+ if (_ = accept(result.set)) descriptor.set = _;
26
+ if (_ = accept(result.init)) initializers.unshift(_);
27
+ }
28
+ else if (_ = accept(result)) {
29
+ if (kind === "field") initializers.unshift(_);
30
+ else descriptor[key] = _;
31
+ }
32
+ }
33
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
34
+ done = true;
35
+ };
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.CardsPage = void 0;
38
+ const redweb_1 = require('../..');
39
+ let CardsPage = (() => {
40
+ let _classDecorators = [(0, redweb_1.page)('/', { template: 'cards.html', css: 'cards.css', shared: true })];
41
+ let _classDescriptor;
42
+ let _classExtraInitializers = [];
43
+ let _classThis;
44
+ let _instanceExtraInitializers = [];
45
+ let _cards_decorators;
46
+ let _cards_initializers = [];
47
+ let _cards_extraInitializers = [];
48
+ let _card_decorators;
49
+ let _add_decorators;
50
+ var CardsPage = class {
51
+ static { _classThis = this; }
52
+ static {
53
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
54
+ _cards_decorators = [(0, redweb_1.state)()];
55
+ _card_decorators = [(0, redweb_1.view)('cards')];
56
+ _add_decorators = [(0, redweb_1.action)()];
57
+ __esDecorate(this, null, _card_decorators, { kind: "method", name: "card", static: false, private: false, access: { has: obj => "card" in obj, get: obj => obj.card }, metadata: _metadata }, null, _instanceExtraInitializers);
58
+ __esDecorate(this, null, _add_decorators, { kind: "method", name: "add", static: false, private: false, access: { has: obj => "add" in obj, get: obj => obj.add }, metadata: _metadata }, null, _instanceExtraInitializers);
59
+ __esDecorate(null, null, _cards_decorators, { kind: "field", name: "cards", static: false, private: false, access: { has: obj => "cards" in obj, get: obj => obj.cards, set: (obj, value) => { obj.cards = value; } }, metadata: _metadata }, _cards_initializers, _cards_extraInitializers);
60
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
61
+ CardsPage = _classThis = _classDescriptor.value;
62
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
63
+ __runInitializers(_classThis, _classExtraInitializers);
64
+ }
65
+ cards = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _cards_initializers, [
66
+ { title: 'Realtime', description: 'State changes arrive over the existing socket.' },
67
+ { title: 'Safe HTML', description: 'Card values are escaped by default.' },
68
+ ]));
69
+ card(card) {
70
70
  return (0, redweb_1.html) `
71
71
  <article class="card">
72
72
  <h2>${card.title}</h2>
73
73
  <p>${card.description}</p>
74
74
  </article>
75
- `;
76
- }
77
- add() {
78
- this.cards = [...this.cards, {
79
- title: `Card ${this.cards.length + 1}`,
80
- description: 'Rendered on the server and synchronized without client code.',
81
- }];
82
- }
83
- constructor() {
84
- __runInitializers(this, _cards_extraInitializers);
85
- }
86
- };
87
- return CardsPage = _classThis;
88
- })();
89
- exports.CardsPage = CardsPage;
90
- if (require.main === module)
91
- (0, redweb_1.start)(CardsPage, { port: 8080 });
75
+ `;
76
+ }
77
+ add() {
78
+ this.cards = [...this.cards, {
79
+ title: `Card ${this.cards.length + 1}`,
80
+ description: 'Rendered on the server and synchronized without client code.',
81
+ }];
82
+ }
83
+ constructor() {
84
+ __runInitializers(this, _cards_extraInitializers);
85
+ }
86
+ };
87
+ return CardsPage = _classThis;
88
+ })();
89
+ exports.CardsPage = CardsPage;
90
+ if (require.main === module)
91
+ void (0, redweb_1.defineApp)({ pages: [CardsPage], port: 8080 }).run()
92
+ .catch(error => { console.error(error); process.exitCode = 1; });
@@ -1,4 +1,4 @@
1
- import { action, html, page, start, state, view } from 'redweb';
1
+ import { action, defineApp, html, page, state, view } from 'redweb';
2
2
 
3
3
  interface Card {
4
4
  title: string;
@@ -32,4 +32,5 @@ export class CardsPage {
32
32
  }
33
33
  }
34
34
 
35
- if (require.main === module) start(CardsPage, { port: 8080 });
35
+ if (require.main === module) void defineApp({ pages: [CardsPage], port: 8080 }).run()
36
+ .catch(error => { console.error(error); process.exitCode = 1; });