@meekojs/meeko 0.0.3 → 0.0.4

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 (144) hide show
  1. package/README.md +18 -1
  2. package/dist/autoimports-ts.d.ts +26 -0
  3. package/dist/autoimports-ts.js +127 -0
  4. package/dist/autoimports-ts.js.map +1 -0
  5. package/dist/autoimports.d.ts +21 -0
  6. package/dist/autoimports.js +285 -0
  7. package/dist/autoimports.js.map +1 -0
  8. package/dist/check.js +35 -23
  9. package/dist/check.js.map +1 -0
  10. package/dist/cli.js +33 -4
  11. package/dist/cli.js.map +1 -0
  12. package/dist/compiler/import-graph.d.ts +8 -0
  13. package/dist/compiler/import-graph.js +33 -0
  14. package/dist/compiler/import-graph.js.map +1 -0
  15. package/dist/compiler/mapping.js +1 -0
  16. package/dist/compiler/mapping.js.map +1 -0
  17. package/dist/compiler/project-root.d.ts +2 -0
  18. package/dist/compiler/project-root.js +18 -0
  19. package/dist/compiler/project-root.js.map +1 -0
  20. package/dist/compiler/sfc.js +1 -0
  21. package/dist/compiler/sfc.js.map +1 -0
  22. package/dist/compiler/sourcemap.d.ts +3 -0
  23. package/dist/compiler/sourcemap.js +75 -0
  24. package/dist/compiler/sourcemap.js.map +1 -0
  25. package/dist/compiler/template.js +1 -0
  26. package/dist/compiler/template.js.map +1 -0
  27. package/dist/compiler.js +11 -5
  28. package/dist/compiler.js.map +1 -0
  29. package/dist/devtools-ui/index.js +1 -0
  30. package/dist/devtools-ui/index.js.map +1 -0
  31. package/dist/devtools.js +1 -0
  32. package/dist/devtools.js.map +1 -0
  33. package/dist/dom.d.ts +8 -1
  34. package/dist/dom.js +10 -5
  35. package/dist/dom.js.map +1 -0
  36. package/dist/framework/check-app.d.ts +5 -0
  37. package/dist/framework/check-app.js +59 -0
  38. package/dist/framework/check-app.js.map +1 -0
  39. package/dist/framework/client.d.ts +45 -0
  40. package/dist/framework/client.js +146 -0
  41. package/dist/framework/client.js.map +1 -0
  42. package/dist/framework/clients.d.ts +82 -0
  43. package/dist/framework/clients.js +182 -0
  44. package/dist/framework/clients.js.map +1 -0
  45. package/dist/framework/config-type.d.ts +10 -0
  46. package/dist/framework/config-type.js +4 -0
  47. package/dist/framework/config-type.js.map +1 -0
  48. package/dist/framework/config.d.ts +15 -0
  49. package/dist/framework/config.js +138 -0
  50. package/dist/framework/config.js.map +1 -0
  51. package/dist/framework/contracts-generate.d.ts +8 -0
  52. package/dist/framework/contracts-generate.js +227 -0
  53. package/dist/framework/contracts-generate.js.map +1 -0
  54. package/dist/framework/generate.d.ts +7 -0
  55. package/dist/framework/generate.js +67 -0
  56. package/dist/framework/generate.js.map +1 -0
  57. package/dist/framework/init.d.ts +2 -0
  58. package/dist/framework/init.js +362 -0
  59. package/dist/framework/init.js.map +1 -0
  60. package/dist/framework/modules.d.ts +22 -0
  61. package/dist/framework/modules.js +29 -0
  62. package/dist/framework/modules.js.map +1 -0
  63. package/dist/framework/page.d.ts +60 -0
  64. package/dist/framework/page.js +42 -0
  65. package/dist/framework/page.js.map +1 -0
  66. package/dist/framework/prerender.d.ts +14 -0
  67. package/dist/framework/prerender.js +104 -0
  68. package/dist/framework/prerender.js.map +1 -0
  69. package/dist/framework/router.d.ts +39 -0
  70. package/dist/framework/router.js +173 -0
  71. package/dist/framework/router.js.map +1 -0
  72. package/dist/framework/server.d.ts +51 -0
  73. package/dist/framework/server.js +192 -0
  74. package/dist/framework/server.js.map +1 -0
  75. package/dist/framework/socket-contracts-generate.d.ts +5 -0
  76. package/dist/framework/socket-contracts-generate.js +159 -0
  77. package/dist/framework/socket-contracts-generate.js.map +1 -0
  78. package/dist/framework/socket.d.ts +70 -0
  79. package/dist/framework/socket.js +150 -0
  80. package/dist/framework/socket.js.map +1 -0
  81. package/dist/framework/state.d.ts +15 -0
  82. package/dist/framework/state.js +72 -0
  83. package/dist/framework/state.js.map +1 -0
  84. package/dist/framework-server/auto-clients.d.ts +3 -0
  85. package/dist/framework-server/auto-clients.js +27 -0
  86. package/dist/framework-server/auto-clients.js.map +1 -0
  87. package/dist/framework-server/context.d.ts +21 -0
  88. package/dist/framework-server/context.js +22 -0
  89. package/dist/framework-server/context.js.map +1 -0
  90. package/dist/framework-server/contracts.d.ts +64 -0
  91. package/dist/framework-server/contracts.js +129 -0
  92. package/dist/framework-server/contracts.js.map +1 -0
  93. package/dist/framework-server/discovery.d.ts +40 -0
  94. package/dist/framework-server/discovery.js +252 -0
  95. package/dist/framework-server/discovery.js.map +1 -0
  96. package/dist/framework-server/local.d.ts +19 -0
  97. package/dist/framework-server/local.js +98 -0
  98. package/dist/framework-server/local.js.map +1 -0
  99. package/dist/framework-server/node-upgrade.d.ts +23 -0
  100. package/dist/framework-server/node-upgrade.js +78 -0
  101. package/dist/framework-server/node-upgrade.js.map +1 -0
  102. package/dist/framework-server/node-websocket.d.ts +16 -0
  103. package/dist/framework-server/node-websocket.js +125 -0
  104. package/dist/framework-server/node-websocket.js.map +1 -0
  105. package/dist/framework-server/openapi.d.ts +17 -0
  106. package/dist/framework-server/openapi.js +118 -0
  107. package/dist/framework-server/openapi.js.map +1 -0
  108. package/dist/framework-server/session-stores.d.ts +66 -0
  109. package/dist/framework-server/session-stores.js +96 -0
  110. package/dist/framework-server/session-stores.js.map +1 -0
  111. package/dist/framework-server/sessions.d.ts +64 -0
  112. package/dist/framework-server/sessions.js +136 -0
  113. package/dist/framework-server/sessions.js.map +1 -0
  114. package/dist/framework-server/socket.d.ts +83 -0
  115. package/dist/framework-server/socket.js +161 -0
  116. package/dist/framework-server/socket.js.map +1 -0
  117. package/dist/framework-server.d.ts +21 -0
  118. package/dist/framework-server.js +12 -0
  119. package/dist/framework-server.js.map +1 -0
  120. package/dist/framework.d.ts +29 -0
  121. package/dist/framework.js +13 -0
  122. package/dist/framework.js.map +1 -0
  123. package/dist/hmr.js +1 -0
  124. package/dist/hmr.js.map +1 -0
  125. package/dist/index.d.ts +3 -3
  126. package/dist/index.js +2 -1
  127. package/dist/index.js.map +1 -0
  128. package/dist/init.js +4 -2
  129. package/dist/init.js.map +1 -0
  130. package/dist/internal.js +1 -0
  131. package/dist/internal.js.map +1 -0
  132. package/dist/node.d.ts +12 -0
  133. package/dist/node.js +52 -0
  134. package/dist/node.js.map +1 -0
  135. package/dist/reactivity.d.ts +12 -0
  136. package/dist/reactivity.js +40 -3
  137. package/dist/reactivity.js.map +1 -0
  138. package/dist/server.js +1 -0
  139. package/dist/server.js.map +1 -0
  140. package/dist/types.js +23 -8
  141. package/dist/types.js.map +1 -0
  142. package/dist/vite.js +91 -6
  143. package/dist/vite.js.map +1 -0
  144. package/package.json +14 -3
@@ -0,0 +1,161 @@
1
+ import { createRequestContext } from "./context.js";
2
+ import { ApiError } from "./contracts.js";
3
+ import { serializeJson } from "../server.js";
4
+ export function defineSocketChannel(definition) {
5
+ return definition;
6
+ }
7
+ export class LocalSocketPubSub {
8
+ listeners = new Map();
9
+ async publish(channel, room, message) {
10
+ for (const listener of this.listeners.get(`${channel}\0${room}`) ?? [])
11
+ await listener(message);
12
+ }
13
+ subscribe(channel, room, listener) {
14
+ const key = `${channel}\0${room}`;
15
+ let listeners = this.listeners.get(key);
16
+ if (!listeners) {
17
+ listeners = new Set();
18
+ this.listeners.set(key, listeners);
19
+ }
20
+ listeners.add(listener);
21
+ return () => {
22
+ listeners.delete(listener);
23
+ if (!listeners.size)
24
+ this.listeners.delete(key);
25
+ };
26
+ }
27
+ }
28
+ async function validate(schema, value) {
29
+ const result = await schema["~standard"].validate(value);
30
+ if ("issues" in result && result.issues)
31
+ throw new ApiError("INVALID_SOCKET_PAYLOAD", 400);
32
+ return result.value;
33
+ }
34
+ function channelDefinition(value) {
35
+ if (!value || typeof value !== "object" || !("clientToServer" in value) || !("serverToClient" in value))
36
+ throw new ApiError("UNKNOWN_SOCKET_CHANNEL", 404);
37
+ return value;
38
+ }
39
+ function originAllowed(request, allowedOrigins) {
40
+ const origin = request.headers.get("origin");
41
+ return !!origin && (origin === new URL(request.url).origin || allowedOrigins.includes(origin));
42
+ }
43
+ /** The host performs the HTTP upgrade, then passes its connected peer here. */
44
+ export function createSocketHub(options) {
45
+ const maxMessageBytes = options.maxMessageBytes ?? 64 * 1024;
46
+ const maxBufferBytes = options.maxBufferBytes ?? 1024 * 1024;
47
+ if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0 || !Number.isSafeInteger(maxBufferBytes) || maxBufferBytes <= 0)
48
+ throw new RangeError("Invalid socket limits");
49
+ const pubsub = options.pubsub ?? new LocalSocketPubSub();
50
+ const getDefinition = (name) => channelDefinition(options.channels[name]);
51
+ const authorizeHandshake = async (name, request, roomId) => {
52
+ const definition = getDefinition(name);
53
+ if (!originAllowed(request, options.allowedOrigins ?? []))
54
+ throw new ApiError("INVALID_ORIGIN", 403);
55
+ const session = await options.sessions.load(request);
56
+ if (definition.auth === "required" && !session.current)
57
+ throw new ApiError("UNAUTHENTICATED", 401);
58
+ const services = typeof options.services === "function" ? await options.services(request) : options.services;
59
+ const context = createRequestContext(request, services, session);
60
+ if (definition.authorize && !(await definition.authorize({ context, ...(roomId === undefined ? {} : { roomId }) })))
61
+ throw new ApiError("FORBIDDEN", 403);
62
+ return { definition, services };
63
+ };
64
+ return {
65
+ async preflight(name, request, roomId) { await authorizeHandshake(name, request, roomId); },
66
+ async accept(name, request, peer, roomId) {
67
+ const { definition, services } = await authorizeHandshake(name, request, roomId);
68
+ let closed = false;
69
+ const emit = async (event, payload) => {
70
+ if (closed)
71
+ throw new ApiError("SOCKET_DISCONNECTED", 409);
72
+ const schema = definition.serverToClient[event];
73
+ if (!schema)
74
+ throw new ApiError("UNKNOWN_SOCKET_EVENT", 404);
75
+ const checked = await validate(schema, payload);
76
+ const fresh = await options.sessions.load(request);
77
+ if (definition.auth === "required" && !fresh.current) {
78
+ close(1008, "Session expired");
79
+ throw new ApiError("UNAUTHENTICATED", 401);
80
+ }
81
+ const sendContext = createRequestContext(request, services, fresh);
82
+ if (definition.authorize && !(await definition.authorize({ context: sendContext, ...(roomId === undefined ? {} : { roomId }) })))
83
+ throw new ApiError("FORBIDDEN", 403);
84
+ if (definition.authorizeSend && !(await definition.authorizeSend({ event, payload: checked, context: sendContext, ...(roomId === undefined ? {} : { roomId }) })))
85
+ throw new ApiError("FORBIDDEN", 403);
86
+ const message = serializeJson({ event, payload: checked });
87
+ const messageBytes = new TextEncoder().encode(message).byteLength;
88
+ if (messageBytes > maxMessageBytes || (peer.bufferedAmount ?? 0) + messageBytes > maxBufferBytes) {
89
+ close(1009, "Message too large");
90
+ throw new ApiError("SOCKET_LIMIT_EXCEEDED", 413);
91
+ }
92
+ await peer.send(message);
93
+ };
94
+ const release = pubsub.subscribe(name, roomId ?? "", ({ event, payload }) => emit(event, payload));
95
+ const close = (code, reason) => {
96
+ if (closed)
97
+ return;
98
+ closed = true;
99
+ release();
100
+ peer.close(code, reason);
101
+ };
102
+ return {
103
+ emit,
104
+ close,
105
+ async receive(raw) {
106
+ if (closed)
107
+ throw new ApiError("SOCKET_DISCONNECTED", 409);
108
+ const bytes = typeof raw === "string" ? new TextEncoder().encode(raw) : raw;
109
+ if (bytes.byteLength > maxMessageBytes) {
110
+ close(1009, "Message too large");
111
+ throw new ApiError("SOCKET_LIMIT_EXCEEDED", 413);
112
+ }
113
+ let envelope;
114
+ try {
115
+ envelope = JSON.parse(typeof raw === "string" ? raw : new TextDecoder("utf-8", { fatal: true }).decode(raw));
116
+ }
117
+ catch {
118
+ close(1008, "Invalid message");
119
+ throw new ApiError("INVALID_SOCKET_MESSAGE", 400);
120
+ }
121
+ if (!envelope || typeof envelope !== "object" || typeof envelope.event !== "string" || !("payload" in envelope)) {
122
+ close(1008, "Invalid message");
123
+ throw new ApiError("INVALID_SOCKET_MESSAGE", 400);
124
+ }
125
+ const event = envelope.event;
126
+ const schema = definition.clientToServer[event];
127
+ if (!schema) {
128
+ close(1008, "Unknown event");
129
+ throw new ApiError("UNKNOWN_SOCKET_EVENT", 404);
130
+ }
131
+ const payload = await validate(schema, envelope.payload);
132
+ // Re-read storage and policy for every event, including after a session revocation.
133
+ const fresh = await options.sessions.load(request);
134
+ if (definition.auth === "required" && !fresh.current) {
135
+ close(1008, "Session expired");
136
+ throw new ApiError("UNAUTHENTICATED", 401);
137
+ }
138
+ const eventContext = createRequestContext(request, services, fresh);
139
+ if (definition.authorize && !(await definition.authorize({ context: eventContext, ...(roomId === undefined ? {} : { roomId }) })))
140
+ throw new ApiError("FORBIDDEN", 403);
141
+ if (definition.authorizeEvent && !(await definition.authorizeEvent({ event, payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }) })))
142
+ throw new ApiError("FORBIDDEN", 403);
143
+ const handler = definition.handlers?.[event];
144
+ if (!handler)
145
+ throw new ApiError("UNHANDLED_SOCKET_EVENT", 404);
146
+ await handler({ payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }), emit });
147
+ },
148
+ };
149
+ },
150
+ async broadcast(name, roomId, event, payload) {
151
+ const definition = getDefinition(name);
152
+ const schema = definition.serverToClient[event];
153
+ if (!schema)
154
+ throw new ApiError("UNKNOWN_SOCKET_EVENT", 404);
155
+ const checked = await validate(schema, payload);
156
+ serializeJson({ event, payload: checked });
157
+ await pubsub.publish(name, roomId, { event, payload: checked });
158
+ },
159
+ };
160
+ }
161
+ //# sourceMappingURL=socket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/framework-server/socket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAe,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAsB7C,MAAM,UAAU,mBAAmB,CAAgE,UAAoD;IACrJ,OAAO,UAAU,CAAC;AACpB,CAAC;AAOD,MAAM,OAAO,iBAAiB;IACX,SAAS,GAAG,IAAI,GAAG,EAAuF,CAAC;IAC5H,KAAK,CAAC,OAAO,CAAC,OAAe,EAAE,IAAY,EAAE,OAA4C;QACvF,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,OAAO,KAAK,IAAI,EAAE,CAAC,IAAI,EAAE;YAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClG,CAAC;IACD,SAAS,CAAC,OAAe,EAAE,IAAY,EAAE,QAAgF;QACvH,MAAM,GAAG,GAAG,GAAG,OAAO,KAAK,IAAI,EAAE,CAAC;QAClC,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YAAC,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;YAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAAC,CAAC;QAC9E,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxB,OAAO,GAAG,EAAE;YACV,SAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5B,IAAI,CAAC,SAAU,CAAC,IAAI;gBAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC;IACJ,CAAC;CACF;AAwBD,KAAK,UAAU,QAAQ,CAAC,MAAc,EAAE,KAAc;IACpD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACzD,IAAI,QAAQ,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;IAC3F,OAAQ,MAA6B,CAAC,KAAK,CAAC;AAC9C,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,gBAAgB,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,gBAAgB,IAAI,KAAK,CAAC;QAAE,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;IAC3J,OAAO,KAAsD,CAAC;AAChE,CAAC;AAED,SAAS,aAAa,CAAC,OAAgB,EAAE,cAAiC;IACxE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC7C,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AACjG,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,eAAe,CAAY,OAAoC;IAC7E,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,GAAG,IAAI,CAAC;IAC7D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,eAAe,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,cAAc,IAAI,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,uBAAuB,CAAC,CAAC;IAClL,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;IACzD,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAY,EAAE,OAAgB,EAAE,MAAe,EAAE,EAAE;QACnF,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;YAAE,MAAM,IAAI,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QACrG,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QACnG,MAAM,QAAQ,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,MAAO,OAAO,CAAC,QAAiE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;QACvK,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjE,IAAI,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;YAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC1J,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC;IAClC,CAAC,CAAC;IACF,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,IAAI,MAAM,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC3F,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,OAAgB,EAAE,IAAgB,EAAE,MAAe;YAC5E,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;YACjF,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,MAAM,IAAI,GAAG,KAAK,EAAE,KAAa,EAAE,OAAgB,EAAiB,EAAE;gBACpE,IAAI,MAAM;oBAAE,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;gBAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBAChD,IAAI,CAAC,MAAM;oBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;gBAC7D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAChD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACnD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;oBAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;oBAAC,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;gBAAC,CAAC;gBACrI,MAAM,WAAW,GAAG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACnE,IAAI,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;oBAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;gBACvK,IAAI,UAAU,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;oBAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;gBACxM,MAAM,OAAO,GAAG,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC3D,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;gBAClE,IAAI,YAAY,GAAG,eAAe,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC,GAAG,YAAY,GAAG,cAAc,EAAE,CAAC;oBACjG,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;oBACjC,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;gBACnD,CAAC;gBACD,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;YACnG,MAAM,KAAK,GAAG,CAAC,IAAa,EAAE,MAAe,EAAQ,EAAE;gBACrD,IAAI,MAAM;oBAAE,OAAO;gBACnB,MAAM,GAAG,IAAI,CAAC;gBACd,OAAO,EAAE,CAAC;gBACV,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC3B,CAAC,CAAC;YACF,OAAO;gBACL,IAAI;gBACJ,KAAK;gBACL,KAAK,CAAC,OAAO,CAAC,GAAG;oBACf,IAAI,MAAM;wBAAE,MAAM,IAAI,QAAQ,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;oBAC3D,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;oBAC5E,IAAI,KAAK,CAAC,UAAU,GAAG,eAAe,EAAE,CAAC;wBAAC,KAAK,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;wBAAC,MAAM,IAAI,QAAQ,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;oBAAC,CAAC;oBAC/H,IAAI,QAAiB,CAAC;oBACtB,IAAI,CAAC;wBAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAY,CAAC;oBAAC,CAAC;oBAChI,MAAM,CAAC;wBAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;wBAAC,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;oBAAC,CAAC;oBAC5F,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAQ,QAAgC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,EAAE,CAAC;wBACzI,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;wBAC/B,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;oBACpD,CAAC;oBACD,MAAM,KAAK,GAAI,QAAgC,CAAC,KAAe,CAAC;oBAChE,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;oBAChD,IAAI,CAAC,MAAM,EAAE,CAAC;wBAAC,KAAK,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;wBAAC,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;oBAAC,CAAC;oBAC/F,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAG,QAAiC,CAAC,OAAO,CAAC,CAAC;oBACnF,oFAAoF;oBACpF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;oBACnD,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;wBAAC,KAAK,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;wBAAC,MAAM,IAAI,QAAQ,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;oBAAC,CAAC;oBACrI,MAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;oBACpE,IAAI,UAAU,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;wBAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;oBACxK,IAAI,UAAU,CAAC,cAAc,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;wBAAE,MAAM,IAAI,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;oBAClM,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;oBAC7C,IAAI,CAAC,OAAO;wBAAE,MAAM,IAAI,QAAQ,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAC;oBAChE,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvG,CAAC;aACF,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,MAAc,EAAE,KAAa,EAAE,OAAgB;YAC3E,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAChD,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,QAAQ,CAAC,sBAAsB,EAAE,GAAG,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAChD,aAAa,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAC3C,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { createRequestContext, type RequestContext } from \"./context.js\";\nimport { ApiError, type Schema } from \"./contracts.js\";\nimport { serializeJson } from \"../server.js\";\nimport type { SessionManager } from \"./sessions.js\";\n\ntype Output<S> = S extends Schema<unknown, infer O> ? O : never;\ntype SchemaMap = Readonly<Record<string, Schema>>;\n\nexport interface SocketPeer {\n send(message: string): void | Promise<void>;\n close(code?: number, reason?: string): void;\n readonly bufferedAmount?: number;\n}\n\nexport interface SocketChannelDefinition<C extends SchemaMap, S extends SchemaMap, TServices = unknown> {\n clientToServer: C;\n serverToClient: S;\n auth?: \"required\" | \"optional\";\n authorize?: (args: { context: RequestContext<TServices>; roomId?: string }) => boolean | Promise<boolean>;\n authorizeEvent?: (args: { event: keyof C & string; payload: unknown; context: RequestContext<TServices>; roomId?: string }) => boolean | Promise<boolean>;\n authorizeSend?: (args: { event: keyof S & string; payload: unknown; context: RequestContext<TServices>; roomId?: string }) => boolean | Promise<boolean>;\n handlers?: { [K in keyof C]?: (args: { payload: Output<C[K]>; context: RequestContext<TServices>; roomId?: string; emit: <E extends keyof S & string>(event: E, payload: Output<S[E]>) => Promise<void> }) => void | Promise<void> };\n}\n\nexport function defineSocketChannel<C extends SchemaMap, S extends SchemaMap, TServices = unknown>(definition: SocketChannelDefinition<C, S, TServices>): SocketChannelDefinition<C, S, TServices> {\n return definition;\n}\n\nexport interface SocketPubSub {\n publish(channel: string, room: string, message: { event: string; payload: unknown }): Promise<void>;\n subscribe(channel: string, room: string, listener: (message: { event: string; payload: unknown }) => void | Promise<void>): () => void;\n}\n\nexport class LocalSocketPubSub implements SocketPubSub {\n private readonly listeners = new Map<string, Set<(message: { event: string; payload: unknown }) => void | Promise<void>>>();\n async publish(channel: string, room: string, message: { event: string; payload: unknown }): Promise<void> {\n for (const listener of this.listeners.get(`${channel}\\0${room}`) ?? []) await listener(message);\n }\n subscribe(channel: string, room: string, listener: (message: { event: string; payload: unknown }) => void | Promise<void>): () => void {\n const key = `${channel}\\0${room}`;\n let listeners = this.listeners.get(key);\n if (!listeners) { listeners = new Set(); this.listeners.set(key, listeners); }\n listeners.add(listener);\n return () => {\n listeners!.delete(listener);\n if (!listeners!.size) this.listeners.delete(key);\n };\n }\n}\n\nexport interface SocketConnection {\n receive(message: string | Uint8Array): Promise<void>;\n emit(event: string, payload: unknown): Promise<void>;\n close(code?: number, reason?: string): void;\n}\n\nexport interface SocketHubOptions<TServices = unknown> {\n channels: Readonly<Record<string, unknown>>;\n sessions: SessionManager;\n services: TServices | ((request: Request) => TServices | Promise<TServices>);\n allowedOrigins?: readonly string[];\n maxMessageBytes?: number;\n maxBufferBytes?: number;\n pubsub?: SocketPubSub;\n}\n\nexport interface SocketHub {\n preflight(name: string, request: Request, roomId?: string): Promise<void>;\n accept(name: string, request: Request, peer: SocketPeer, roomId?: string): Promise<SocketConnection>;\n broadcast(name: string, roomId: string, event: string, payload: unknown): Promise<void>;\n}\n\nasync function validate(schema: Schema, value: unknown): Promise<unknown> {\n const result = await schema[\"~standard\"].validate(value);\n if (\"issues\" in result && result.issues) throw new ApiError(\"INVALID_SOCKET_PAYLOAD\", 400);\n return (result as { value: unknown }).value;\n}\n\nfunction channelDefinition(value: unknown): SocketChannelDefinition<SchemaMap, SchemaMap> {\n if (!value || typeof value !== \"object\" || !(\"clientToServer\" in value) || !(\"serverToClient\" in value)) throw new ApiError(\"UNKNOWN_SOCKET_CHANNEL\", 404);\n return value as SocketChannelDefinition<SchemaMap, SchemaMap>;\n}\n\nfunction originAllowed(request: Request, allowedOrigins: readonly string[]): boolean {\n const origin = request.headers.get(\"origin\");\n return !!origin && (origin === new URL(request.url).origin || allowedOrigins.includes(origin));\n}\n\n/** The host performs the HTTP upgrade, then passes its connected peer here. */\nexport function createSocketHub<TServices>(options: SocketHubOptions<TServices>): SocketHub {\n const maxMessageBytes = options.maxMessageBytes ?? 64 * 1024;\n const maxBufferBytes = options.maxBufferBytes ?? 1024 * 1024;\n if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0 || !Number.isSafeInteger(maxBufferBytes) || maxBufferBytes <= 0) throw new RangeError(\"Invalid socket limits\");\n const pubsub = options.pubsub ?? new LocalSocketPubSub();\n const getDefinition = (name: string) => channelDefinition(options.channels[name]);\n const authorizeHandshake = async (name: string, request: Request, roomId?: string) => {\n const definition = getDefinition(name);\n if (!originAllowed(request, options.allowedOrigins ?? [])) throw new ApiError(\"INVALID_ORIGIN\", 403);\n const session = await options.sessions.load(request);\n if (definition.auth === \"required\" && !session.current) throw new ApiError(\"UNAUTHENTICATED\", 401);\n const services = typeof options.services === \"function\" ? await (options.services as (request: Request) => TServices | Promise<TServices>)(request) : options.services;\n const context = createRequestContext(request, services, session);\n if (definition.authorize && !(await definition.authorize({ context, ...(roomId === undefined ? {} : { roomId }) }))) throw new ApiError(\"FORBIDDEN\", 403);\n return { definition, services };\n };\n return {\n async preflight(name, request, roomId) { await authorizeHandshake(name, request, roomId); },\n async accept(name: string, request: Request, peer: SocketPeer, roomId?: string): Promise<SocketConnection> {\n const { definition, services } = await authorizeHandshake(name, request, roomId);\n let closed = false;\n const emit = async (event: string, payload: unknown): Promise<void> => {\n if (closed) throw new ApiError(\"SOCKET_DISCONNECTED\", 409);\n const schema = definition.serverToClient[event];\n if (!schema) throw new ApiError(\"UNKNOWN_SOCKET_EVENT\", 404);\n const checked = await validate(schema, payload);\n const fresh = await options.sessions.load(request);\n if (definition.auth === \"required\" && !fresh.current) { close(1008, \"Session expired\"); throw new ApiError(\"UNAUTHENTICATED\", 401); }\n const sendContext = createRequestContext(request, services, fresh);\n if (definition.authorize && !(await definition.authorize({ context: sendContext, ...(roomId === undefined ? {} : { roomId }) }))) throw new ApiError(\"FORBIDDEN\", 403);\n if (definition.authorizeSend && !(await definition.authorizeSend({ event, payload: checked, context: sendContext, ...(roomId === undefined ? {} : { roomId }) }))) throw new ApiError(\"FORBIDDEN\", 403);\n const message = serializeJson({ event, payload: checked });\n const messageBytes = new TextEncoder().encode(message).byteLength;\n if (messageBytes > maxMessageBytes || (peer.bufferedAmount ?? 0) + messageBytes > maxBufferBytes) {\n close(1009, \"Message too large\");\n throw new ApiError(\"SOCKET_LIMIT_EXCEEDED\", 413);\n }\n await peer.send(message);\n };\n const release = pubsub.subscribe(name, roomId ?? \"\", ({ event, payload }) => emit(event, payload));\n const close = (code?: number, reason?: string): void => {\n if (closed) return;\n closed = true;\n release();\n peer.close(code, reason);\n };\n return {\n emit,\n close,\n async receive(raw) {\n if (closed) throw new ApiError(\"SOCKET_DISCONNECTED\", 409);\n const bytes = typeof raw === \"string\" ? new TextEncoder().encode(raw) : raw;\n if (bytes.byteLength > maxMessageBytes) { close(1009, \"Message too large\"); throw new ApiError(\"SOCKET_LIMIT_EXCEEDED\", 413); }\n let envelope: unknown;\n try { envelope = JSON.parse(typeof raw === \"string\" ? raw : new TextDecoder(\"utf-8\", { fatal: true }).decode(raw)) as unknown; }\n catch { close(1008, \"Invalid message\"); throw new ApiError(\"INVALID_SOCKET_MESSAGE\", 400); }\n if (!envelope || typeof envelope !== \"object\" || typeof (envelope as { event?: unknown }).event !== \"string\" || !(\"payload\" in envelope)) {\n close(1008, \"Invalid message\");\n throw new ApiError(\"INVALID_SOCKET_MESSAGE\", 400);\n }\n const event = (envelope as { event?: unknown }).event as string;\n const schema = definition.clientToServer[event];\n if (!schema) { close(1008, \"Unknown event\"); throw new ApiError(\"UNKNOWN_SOCKET_EVENT\", 404); }\n const payload = await validate(schema, (envelope as { payload: unknown }).payload);\n // Re-read storage and policy for every event, including after a session revocation.\n const fresh = await options.sessions.load(request);\n if (definition.auth === \"required\" && !fresh.current) { close(1008, \"Session expired\"); throw new ApiError(\"UNAUTHENTICATED\", 401); }\n const eventContext = createRequestContext(request, services, fresh);\n if (definition.authorize && !(await definition.authorize({ context: eventContext, ...(roomId === undefined ? {} : { roomId }) }))) throw new ApiError(\"FORBIDDEN\", 403);\n if (definition.authorizeEvent && !(await definition.authorizeEvent({ event, payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }) }))) throw new ApiError(\"FORBIDDEN\", 403);\n const handler = definition.handlers?.[event];\n if (!handler) throw new ApiError(\"UNHANDLED_SOCKET_EVENT\", 404);\n await handler({ payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }), emit });\n },\n };\n },\n async broadcast(name: string, roomId: string, event: string, payload: unknown): Promise<void> {\n const definition = getDefinition(name);\n const schema = definition.serverToClient[event];\n if (!schema) throw new ApiError(\"UNKNOWN_SOCKET_EVENT\", 404);\n const checked = await validate(schema, payload);\n serializeJson({ event, payload: checked });\n await pubsub.publish(name, roomId, { event, payload: checked });\n },\n };\n}\n"]}
@@ -0,0 +1,21 @@
1
+ export { createRequestContext, useRequestState } from "./framework-server/context.js";
2
+ export type { RequestContext, ServerFetch } from "./framework-server/context.js";
3
+ export { createServerClientOptions } from "./framework-server/auto-clients.js";
4
+ export { MemorySessionStore, SessionHandle, SessionManager, SessionSecurityError } from "./framework-server/sessions.js";
5
+ export type { SessionOptions, SessionRecord, SessionStore } from "./framework-server/sessions.js";
6
+ export { RedisSessionStore, SqlSessionStore } from "./framework-server/session-stores.js";
7
+ export type { RedisSessionClient, RedisSessionStoreOptions, SqlSessionDriver, SqlSessionRow, SqlSessionStoreOptions } from "./framework-server/session-stores.js";
8
+ export { ApiError, defineApiRoute, defineRpc, dispatchApiRoute, dispatchRpc, errorResponse, executeApiRoute, executeRpc } from "./framework-server/contracts.js";
9
+ export type { ApiRouteDefinition, RpcDefinition, Schema } from "./framework-server/contracts.js";
10
+ export { createLocalServerFetch, createServerDispatcher, discoverServerManifest, loadSocketChannels } from "./framework-server/discovery.js";
11
+ export type { ApiEndpoint, ApiMethod, RpcEndpoint, SocketEndpoint, ServerDispatcherOptions, ServerManifest } from "./framework-server/discovery.js";
12
+ export { createSocketHub, defineSocketChannel, LocalSocketPubSub } from "./framework-server/socket.js";
13
+ export type { SocketChannelDefinition, SocketConnection, SocketHubOptions, SocketPeer, SocketPubSub } from "./framework-server/socket.js";
14
+ export { createNodeSocketUpgradeHandler } from "./framework-server/node-upgrade.js";
15
+ export type { NodeAcceptedSocket, NodeSocketUpgradeOptions } from "./framework-server/node-upgrade.js";
16
+ export { attachNodeWebSocketServer } from "./framework-server/node-websocket.js";
17
+ export type { NodeWebSocketOptions, NodeWebSocketServer } from "./framework-server/node-websocket.js";
18
+ export { generateOpenApi } from "./framework-server/openapi.js";
19
+ export type { OpenApiOptions } from "./framework-server/openapi.js";
20
+ export { createLocalCalls } from "./framework-server/local.js";
21
+ export type { LocalApiInput, LocalCallOptions } from "./framework-server/local.js";
@@ -0,0 +1,12 @@
1
+ export { createRequestContext, useRequestState } from "./framework-server/context.js";
2
+ export { createServerClientOptions } from "./framework-server/auto-clients.js";
3
+ export { MemorySessionStore, SessionHandle, SessionManager, SessionSecurityError } from "./framework-server/sessions.js";
4
+ export { RedisSessionStore, SqlSessionStore } from "./framework-server/session-stores.js";
5
+ export { ApiError, defineApiRoute, defineRpc, dispatchApiRoute, dispatchRpc, errorResponse, executeApiRoute, executeRpc } from "./framework-server/contracts.js";
6
+ export { createLocalServerFetch, createServerDispatcher, discoverServerManifest, loadSocketChannels } from "./framework-server/discovery.js";
7
+ export { createSocketHub, defineSocketChannel, LocalSocketPubSub } from "./framework-server/socket.js";
8
+ export { createNodeSocketUpgradeHandler } from "./framework-server/node-upgrade.js";
9
+ export { attachNodeWebSocketServer } from "./framework-server/node-websocket.js";
10
+ export { generateOpenApi } from "./framework-server/openapi.js";
11
+ export { createLocalCalls } from "./framework-server/local.js";
12
+ //# sourceMappingURL=framework-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-server.js","sourceRoot":"","sources":["../src/framework-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEtF,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AAEzH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sCAAsC,CAAC;AAE1F,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAEjK,OAAO,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE7I,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAEvG,OAAO,EAAE,8BAA8B,EAAE,MAAM,oCAAoC,CAAC;AAEpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["export { createRequestContext, useRequestState } from \"./framework-server/context.js\";\nexport type { RequestContext, ServerFetch } from \"./framework-server/context.js\";\nexport { createServerClientOptions } from \"./framework-server/auto-clients.js\";\nexport { MemorySessionStore, SessionHandle, SessionManager, SessionSecurityError } from \"./framework-server/sessions.js\";\nexport type { SessionOptions, SessionRecord, SessionStore } from \"./framework-server/sessions.js\";\nexport { RedisSessionStore, SqlSessionStore } from \"./framework-server/session-stores.js\";\nexport type { RedisSessionClient, RedisSessionStoreOptions, SqlSessionDriver, SqlSessionRow, SqlSessionStoreOptions } from \"./framework-server/session-stores.js\";\nexport { ApiError, defineApiRoute, defineRpc, dispatchApiRoute, dispatchRpc, errorResponse, executeApiRoute, executeRpc } from \"./framework-server/contracts.js\";\nexport type { ApiRouteDefinition, RpcDefinition, Schema } from \"./framework-server/contracts.js\";\nexport { createLocalServerFetch, createServerDispatcher, discoverServerManifest, loadSocketChannels } from \"./framework-server/discovery.js\";\nexport type { ApiEndpoint, ApiMethod, RpcEndpoint, SocketEndpoint, ServerDispatcherOptions, ServerManifest } from \"./framework-server/discovery.js\";\nexport { createSocketHub, defineSocketChannel, LocalSocketPubSub } from \"./framework-server/socket.js\";\nexport type { SocketChannelDefinition, SocketConnection, SocketHubOptions, SocketPeer, SocketPubSub } from \"./framework-server/socket.js\";\nexport { createNodeSocketUpgradeHandler } from \"./framework-server/node-upgrade.js\";\nexport type { NodeAcceptedSocket, NodeSocketUpgradeOptions } from \"./framework-server/node-upgrade.js\";\nexport { attachNodeWebSocketServer } from \"./framework-server/node-websocket.js\";\nexport type { NodeWebSocketOptions, NodeWebSocketServer } from \"./framework-server/node-websocket.js\";\nexport { generateOpenApi } from \"./framework-server/openapi.js\";\nexport type { OpenApiOptions } from \"./framework-server/openapi.js\";\nexport { createLocalCalls } from \"./framework-server/local.js\";\nexport type { LocalApiInput, LocalCallOptions } from \"./framework-server/local.js\";\n"]}
@@ -0,0 +1,29 @@
1
+ import type { RouteRecord } from "./framework/router.js";
2
+ export { createNavigator, createRouteManifest, matchRoute } from "./framework/router.js";
3
+ export { defineMeekoConfig } from "./framework/config-type.js";
4
+ export type { MeekoConfig } from "./framework/config-type.js";
5
+ export type { NavigationContext, Navigator, RouteMatch, RouteRecord } from "./framework/router.js";
6
+ export { mountClientApp } from "./framework/client.js";
7
+ export type { ClientApp, ClientAppOptions, ClientComponent, ClientRoute } from "./framework/client.js";
8
+ export { definePage, PageInputError } from "./framework/page.js";
9
+ export type { PageDefinition, PageLoadContext, PageSchema } from "./framework/page.js";
10
+ export { StateStore, useState } from "./framework/state.js";
11
+ export { ClientError, createApiClient, createBrowserClientOptions, createPublicServerManifest, createRpcClient } from "./framework/clients.js";
12
+ export type { ApiClient, ApiOperation, ClientOptions, PublicApiEndpoint, PublicRpcEndpoint, PublicServerManifest, RpcClient, RpcOperation } from "./framework/clients.js";
13
+ export { createSocketClient, createSocketRegistry, useSocket, useSocketChannel } from "./framework/socket.js";
14
+ export type { SocketClient, SocketContract, SocketSchema, SocketClientOptions, SocketRegistry, SocketRegistryOptions } from "./framework/socket.js";
15
+ /** Augmented by generated declarations in .meeko/types/routes.d.ts. */
16
+ export interface GeneratedRoutes {
17
+ }
18
+ type RouteKey = keyof GeneratedRoutes extends never ? string : keyof GeneratedRoutes & string;
19
+ type RouteParams<K extends string> = K extends keyof GeneratedRoutes ? GeneratedRoutes[K] : Record<string, string>;
20
+ type HrefOptions<K extends string> = (keyof RouteParams<K> extends never ? {
21
+ params?: RouteParams<K>;
22
+ } : {
23
+ params: RouteParams<K>;
24
+ }) & {
25
+ search?: Readonly<Record<string, string | number | boolean | null | undefined>>;
26
+ };
27
+ type HrefArguments<K extends string> = K extends keyof GeneratedRoutes ? keyof RouteParams<K> extends never ? [options?: HrefOptions<K>] : [options: HrefOptions<K>] : [options?: HrefOptions<K>];
28
+ /** Builds a checked URL when the project's route declarations are installed. */
29
+ export declare function href<K extends RouteKey>(routes: readonly RouteRecord[], id: K, ...[options]: HrefArguments<K>): string;
@@ -0,0 +1,13 @@
1
+ import { href as runtimeHref } from "./framework/router.js";
2
+ export { createNavigator, createRouteManifest, matchRoute } from "./framework/router.js";
3
+ export { defineMeekoConfig } from "./framework/config-type.js";
4
+ export { mountClientApp } from "./framework/client.js";
5
+ export { definePage, PageInputError } from "./framework/page.js";
6
+ export { StateStore, useState } from "./framework/state.js";
7
+ export { ClientError, createApiClient, createBrowserClientOptions, createPublicServerManifest, createRpcClient } from "./framework/clients.js";
8
+ export { createSocketClient, createSocketRegistry, useSocket, useSocketChannel } from "./framework/socket.js";
9
+ /** Builds a checked URL when the project's route declarations are installed. */
10
+ export function href(routes, id, ...[options]) {
11
+ return runtimeHref(routes, id, options);
12
+ }
13
+ //# sourceMappingURL=framework.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework.js","sourceRoot":"","sources":["../src/framework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,0BAA0B,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE/I,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAiB9G,gFAAgF;AAChF,MAAM,UAAU,IAAI,CAAqB,MAA8B,EAAE,EAAK,EAAE,GAAG,CAAC,OAAO,CAAmB;IAC5G,OAAO,WAAW,CAAC,MAAM,EAAE,EAAE,EAAE,OAAwD,CAAC,CAAC;AAC3F,CAAC","sourcesContent":["import { href as runtimeHref } from \"./framework/router.js\";\nimport type { RouteRecord } from \"./framework/router.js\";\n\nexport { createNavigator, createRouteManifest, matchRoute } from \"./framework/router.js\";\nexport { defineMeekoConfig } from \"./framework/config-type.js\";\nexport type { MeekoConfig } from \"./framework/config-type.js\";\nexport type { NavigationContext, Navigator, RouteMatch, RouteRecord } from \"./framework/router.js\";\nexport { mountClientApp } from \"./framework/client.js\";\nexport type { ClientApp, ClientAppOptions, ClientComponent, ClientRoute } from \"./framework/client.js\";\nexport { definePage, PageInputError } from \"./framework/page.js\";\nexport type { PageDefinition, PageLoadContext, PageSchema } from \"./framework/page.js\";\nexport { StateStore, useState } from \"./framework/state.js\";\nexport { ClientError, createApiClient, createBrowserClientOptions, createPublicServerManifest, createRpcClient } from \"./framework/clients.js\";\nexport type { ApiClient, ApiOperation, ClientOptions, PublicApiEndpoint, PublicRpcEndpoint, PublicServerManifest, RpcClient, RpcOperation } from \"./framework/clients.js\";\nexport { createSocketClient, createSocketRegistry, useSocket, useSocketChannel } from \"./framework/socket.js\";\nexport type { SocketClient, SocketContract, SocketSchema, SocketClientOptions, SocketRegistry, SocketRegistryOptions } from \"./framework/socket.js\";\n\n/** Augmented by generated declarations in .meeko/types/routes.d.ts. */\nexport interface GeneratedRoutes {}\n\ntype RouteKey = keyof GeneratedRoutes extends never ? string : keyof GeneratedRoutes & string;\ntype RouteParams<K extends string> = K extends keyof GeneratedRoutes ? GeneratedRoutes[K] : Record<string, string>;\ntype HrefOptions<K extends string> = (keyof RouteParams<K> extends never\n ? { params?: RouteParams<K> }\n : { params: RouteParams<K> }) & {\n search?: Readonly<Record<string, string | number | boolean | null | undefined>>;\n};\ntype HrefArguments<K extends string> = K extends keyof GeneratedRoutes\n ? keyof RouteParams<K> extends never ? [options?: HrefOptions<K>] : [options: HrefOptions<K>]\n : [options?: HrefOptions<K>];\n\n/** Builds a checked URL when the project's route declarations are installed. */\nexport function href<K extends RouteKey>(routes: readonly RouteRecord[], id: K, ...[options]: HrefArguments<K>): string {\n return runtimeHref(routes, id, options as Parameters<typeof runtimeHref>[2] | undefined);\n}\n"]}
package/dist/hmr.js CHANGED
@@ -135,3 +135,4 @@ export function replaceHotModule(id, next) {
135
135
  }
136
136
  replaceHotStyle(id, component.css ?? "");
137
137
  }
138
+ //# sourceMappingURL=hmr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"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","sourcesContent":["import { isWritableSignal } from \"./reactivity.js\";\nimport type { DomScope } from \"./dom.js\";\n\n/** Valores de señales transferidos en memoria entre versiones de un componente. */\nexport type HotState = Record<string, unknown>;\n\n/** Contrato mínimo de un módulo Meeko reemplazable en desarrollo. */\nexport interface HotComponent<Props = unknown> {\n renderToString(props: Props, state?: HotState): string;\n hydrate(root: Element, props: Props, state?: HotState): () => void;\n hydrateScope?(scope: DomScope, props: Props, state?: HotState): () => void;\n css?: string;\n}\n\ninterface HotInstance {\n target: { kind: \"root\"; root: Element } | { kind: \"scope\"; scope: DomScope };\n props: unknown;\n component: HotComponent;\n snapshot: () => HotState;\n dispose: () => void;\n}\n\ninterface HotSlot {\n current: HotInstance;\n stop: () => void;\n}\n\nconst enabled = new Set<string>();\nconst instances = new Map<string, Map<Element | Comment, HotSlot>>();\n\n/** Copia solo las señales editables de un setup, sin serializarlas. */\nexport function snapshotSignals(bindings: Record<string, unknown>): HotState {\n const state: HotState = {};\n for (const [name, value] of Object.entries(bindings)) {\n if (isWritableSignal(value)) state[name] = value.value;\n }\n return state;\n}\n\n/** Restaura señales compatibles antes de renderizar o hidratar la nueva versión. */\nexport function restoreSignals(bindings: Record<string, unknown>, state?: HotState): void {\n if (!state) return;\n for (const [name, value] of Object.entries(state)) {\n const target = bindings[name];\n if (isWritableSignal(target)) target.value = value;\n }\n}\n\n/** Activa el seguimiento de instancias solo para módulos servidos por Vite. */\nexport function enableHotModule(id: string): void {\n enabled.add(id);\n}\n\nfunction registerHotTarget<Props>(id: string, key: Element | Comment, target: HotInstance[\"target\"], props: Props, component: HotComponent<Props>, snapshot: () => HotState, dispose: () => void): () => void {\n if (!enabled.has(id)) return dispose;\n const entry: HotInstance = { target, props, component: component as HotComponent, snapshot, dispose };\n let group = instances.get(id);\n if (!group) {\n group = new Map();\n instances.set(id, group);\n }\n const existing = group.get(key);\n if (existing) {\n existing.current = entry;\n return existing.stop;\n }\n const slot: HotSlot = {\n current: entry,\n stop: () => {\n if (group.get(key) !== slot) return;\n group.delete(key);\n if (group.size === 0) instances.delete(id);\n slot.current.dispose();\n },\n };\n group.set(key, slot);\n return slot.stop;\n}\n\n/** Registra una raíz hidratada y elimina el registro al liberarla. */\nexport function registerHotInstance<Props>(id: string, root: Element, props: Props, component: HotComponent<Props>, snapshot: () => HotState, dispose: () => void): () => void {\n return registerHotTarget(id, root, { kind: \"root\", root }, props, component, snapshot, dispose);\n}\n\n/** Registra un componente hijo delimitado por comentarios para actualizarlo sin tocar al padre. */\nexport function registerHotScope<Props>(id: string, scope: DomScope, props: Props, component: HotComponent<Props>, snapshot: () => HotState, dispose: () => void): () => void {\n if (!scope.start || !scope.end) throw new Error(\"Hot child component requires a bounded scope\");\n return registerHotTarget(id, scope.start, { kind: \"scope\", scope }, props, component, snapshot, dispose);\n}\n\nfunction scopeRange(scope: DomScope): Range {\n if (!scope.start || !scope.end) throw new Error(\"Hot child component lost its markers\");\n const range = scope.start.ownerDocument.createRange();\n range.setStartAfter(scope.start);\n range.setEndBefore(scope.end);\n return range;\n}\n\nfunction replaceScope(scope: DomScope, html: string): void {\n const range = scopeRange(scope);\n const content = range.createContextualFragment(html);\n range.deleteContents();\n range.insertNode(content);\n}\n\n/** Aplica CSS nuevo después de la hoja virtual cargada por Vite. */\nexport function replaceHotStyle(id: string, css: string): void {\n if (typeof document === \"undefined\") return;\n let style = document.querySelector<HTMLStyleElement>(`style[data-meeko-hot=\"${id}\"]`);\n if (!style) {\n style = document.createElement(\"style\");\n style.dataset.meekoHot = id;\n document.head.appendChild(style);\n }\n style.textContent = css;\n}\n\n/** Sustituye las instancias activas sin recargar la página y conserva señales editables. */\nexport function replaceHotModule(id: string, next: unknown): void {\n if (typeof next !== \"object\" || next === null || !(\"renderToString\" in next) || !(\"hydrate\" in next)\n || typeof next.renderToString !== \"function\" || typeof next.hydrate !== \"function\") {\n throw new TypeError(\"Invalid Meeko hot module\");\n }\n const component = next as HotComponent;\n const prepared = [...(instances.get(id)?.values() ?? [])].map((slot) => {\n const entry = slot.current;\n const state = entry.snapshot();\n const previous = entry.target.kind === \"root\" ? entry.target.root.innerHTML : scopeRange(entry.target.scope).cloneContents();\n return { slot, entry, state, html: component.renderToString(entry.props, state), previous };\n });\n for (const { slot, entry, state, html, previous } of prepared) {\n entry.dispose();\n if (entry.target.kind === \"root\") entry.target.root.innerHTML = html;\n else replaceScope(entry.target.scope, html);\n try {\n if (entry.target.kind === \"root\") component.hydrate(entry.target.root, entry.props, state);\n else {\n if (!component.hydrateScope) throw new Error(\"Updated Meeko child component has no hydrateScope export\");\n component.hydrateScope(entry.target.scope, entry.props, state);\n }\n if (slot.current === entry) throw new Error(\"Updated Meeko component did not register its hydrated instance\");\n } catch (error) {\n if (entry.target.kind === \"root\") entry.target.root.innerHTML = previous as string;\n else {\n const range = scopeRange(entry.target.scope);\n range.deleteContents();\n range.insertNode(previous as DocumentFragment);\n }\n if (entry.target.kind === \"root\") entry.component.hydrate(entry.target.root, entry.props, state);\n else entry.component.hydrateScope?.(entry.target.scope, entry.props, state);\n throw error;\n }\n }\n replaceHotStyle(id, component.css ?? \"\");\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { batch, computed, createRoot, effect, signal, untrack } from "./reactivity.js";
2
- export type { ReadonlySignal, Signal } from "./reactivity.js";
1
+ export { batch, computed, createContext, createRoot, effect, inject, onCleanup, provide, signal, untrack } from "./reactivity.js";
2
+ export type { ContextKey, ReadonlySignal, Signal } from "./reactivity.js";
3
3
  export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
4
4
  export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
5
- export type { ComponentModule, ComponentRelease, DomScope } from "./dom.js";
5
+ export type { Component, ComponentModule, ComponentRelease, DomScope } from "./dom.js";
6
6
  export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
7
7
  export type { HotComponent, HotState } from "./hmr.js";
8
8
  export { registerDevtoolsInstance } from "./devtools.js";
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
- export { batch, computed, createRoot, effect, signal, untrack } from "./reactivity.js";
1
+ export { batch, computed, createContext, createRoot, effect, inject, onCleanup, provide, signal, untrack } from "./reactivity.js";
2
2
  export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
3
3
  export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
4
4
  export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
5
5
  export { registerDevtoolsInstance } from "./devtools.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAElI,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEjK,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtJ,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["export { batch, computed, createContext, createRoot, effect, inject, onCleanup, provide, signal, untrack } from \"./reactivity.js\";\nexport type { ContextKey, ReadonlySignal, Signal } from \"./reactivity.js\";\nexport { attributeValue, escapeHtml, renderAttribute, serializeJson } from \"./server.js\";\nexport { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from \"./dom.js\";\nexport type { Component, ComponentModule, ComponentRelease, DomScope } from \"./dom.js\";\nexport { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from \"./hmr.js\";\nexport type { HotComponent, HotState } from \"./hmr.js\";\nexport { registerDevtoolsInstance } from \"./devtools.js\";\nexport type { DevtoolsEvent, DevtoolsHook, DevtoolsInstance, DevtoolsRegistration, DevtoolsSnapshot, DevtoolsValue } from \"./devtools.js\";\n"]}
package/dist/init.js CHANGED
@@ -8,7 +8,7 @@ function isRecord(value) {
8
8
  }
9
9
  /** Archivos autocontenidos del proyecto inicial, incluidos en la CLI publicada. */
10
10
  const starterFiles = {
11
- ".gitignore": "node_modules/\ndist/\n*.d.meeko.ts\n",
11
+ ".gitignore": "node_modules/\ndist/\n.meeko/\n",
12
12
  "index.html": `<!doctype html>
13
13
  <html lang="es">
14
14
  <head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Meeko SSR</title></head>
@@ -25,9 +25,10 @@ export default defineConfig({ plugins: [meeko()] });
25
25
  "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext",
26
26
  "lib": ["ES2022", "DOM"], "types": ["node", "vite/client"],
27
27
  "strict": true, "noEmit": true, "allowArbitraryExtensions": true,
28
+ "rootDirs": ["src", ".meeko/types/src"],
28
29
  "skipLibCheck": true
29
30
  },
30
- "include": ["src/**/*.ts", "vite.config.ts"]
31
+ "include": ["src/**/*.ts", "vite.config.ts", ".meeko/types/routes.d.ts"]
31
32
  }
32
33
  `,
33
34
  "src/App.meeko": `<script lang="ts">
@@ -205,3 +206,4 @@ export async function initProject(directory) {
205
206
  await writeFile(join(target, "package.json"), packageFile, { encoding: "utf8", flag: existingEntries.includes("package.json") ? "w" : "wx" });
206
207
  return target;
207
208
  }
209
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, readdir, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\n/** Entradas que puede dejar un gestor de paquetes antes de generar el proyecto. */\nconst packageScaffoldEntries = new Set([\"package.json\", \"package-lock.json\", \"pnpm-lock.yaml\", \"pnpm-workspace.yaml\", \"yarn.lock\", \"bun.lock\", \"bun.lockb\", \"node_modules\", \".npmrc\", \".git\"]);\n\n/** Comprueba que un valor JSON sea un objeto de configuración. */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Archivos autocontenidos del proyecto inicial, incluidos en la CLI publicada. */\nconst starterFiles: Readonly<Record<string, string>> = {\n \".gitignore\": \"node_modules/\\ndist/\\n.meeko/\\n\",\n \"index.html\": `<!doctype html>\n<html lang=\"es\">\n <head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Meeko SSR</title></head>\n <body><div id=\"app\"></div><script type=\"module\" src=\"/src/entry-client.ts\"></script></body>\n</html>\n`,\n \"vite.config.ts\": `import { defineConfig } from \"vite\";\nimport { meeko } from \"@meekojs/meeko/vite\";\n\nexport default defineConfig({ plugins: [meeko()] });\n`,\n \"tsconfig.json\": `{\n \"compilerOptions\": {\n \"target\": \"ES2022\", \"module\": \"NodeNext\", \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\", \"DOM\"], \"types\": [\"node\", \"vite/client\"],\n \"strict\": true, \"noEmit\": true, \"allowArbitraryExtensions\": true,\n \"rootDirs\": [\"src\", \".meeko/types/src\"],\n \"skipLibCheck\": true\n },\n \"include\": [\"src/**/*.ts\", \"vite.config.ts\", \".meeko/types/routes.d.ts\"]\n}\n`,\n \"src/App.meeko\": `<script lang=\"ts\">\nimport { signal } from \"@meekojs/meeko\";\n\n/** Propiedades transferidas desde el servidor. */\nexport interface Props { initial: number }\n\nconst props = defineProps<Props>();\nconst count = signal(props.initial);\n</script>\n\n<template>\n <main>\n <h1>Meeko SSR</h1>\n <button type=\"button\" on:click=\"() => count.value++\">Contador: {count.value}</button>\n </main>\n</template>\n\n<style scoped>\nmain { max-width: 40rem; margin: 4rem auto; font: 1.2rem system-ui; }\nbutton { cursor: pointer; padding: .65rem 1rem; }\n</style>\n`,\n \"src/entry-server.ts\": `import { serializeJson } from \"@meekojs/meeko\";\nimport { css, renderWithState } from \"./App.meeko\";\n\n/** Genera HTML y estado inicial desde el mismo componente que hidrata el cliente. */\nexport function renderPage(clientSource: string, initial = 1): string {\n const props = { initial };\n const rendered = renderWithState(props);\n return '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Meeko SSR</title><style>'\n + css + '</style></head><body><div id=\"app\">' + rendered.html + '</div><script id=\"meeko-payload\" type=\"application/json\">'\n + serializeJson({ props, state: rendered.state }) + '</script><script type=\"module\" src=\"' + clientSource + '\"></script></body></html>';\n}\n`,\n \"src/entry-client.ts\": `import { hydrate } from \"./App.meeko\";\nimport type { HotState } from \"@meekojs/meeko\";\n\nconst root = document.getElementById(\"app\");\nconst payloadNode = document.getElementById(\"meeko-payload\");\nif (!root || !payloadNode?.textContent) throw new Error(\"Missing SSR root or payload\");\nconst payload: unknown = JSON.parse(payloadNode.textContent);\nif (typeof payload !== \"object\" || payload === null || !(\"props\" in payload) || !(\"state\" in payload)) throw new TypeError(\"Invalid SSR payload\");\nconst { props, state } = payload;\nif (typeof props !== \"object\" || props === null || !(\"initial\" in props) || typeof props.initial !== \"number\" || !Number.isFinite(props.initial)) throw new TypeError(\"Invalid SSR props\");\nif (typeof state !== \"object\" || state === null || !(\"count\" in state) || typeof state.count !== \"number\" || !Number.isFinite(state.count)) throw new TypeError(\"Invalid SSR state\");\nhydrate(root, { initial: props.initial }, { count: state.count } satisfies HotState);\n`,\n \"server.mjs\": `import { createServer } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, extname, resolve, sep } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { createServer as createViteServer } from \"vite\";\n\nconst root = dirname(fileURLToPath(import.meta.url));\nconst production = process.argv.includes(\"--production\");\nconst vite = production ? undefined : await createViteServer({ root, server: { middlewareMode: true }, appType: \"custom\" });\nconst clientRoot = resolve(root, \"dist/client\");\nlet clientSource = \"/src/entry-client.ts\";\nif (production) {\n const manifest = JSON.parse(await readFile(resolve(clientRoot, \".vite/manifest.json\"), \"utf8\"));\n const entry = manifest[\"index.html\"];\n if (!entry?.file) throw new Error(\"Missing Vite client entry\");\n clientSource = \"/\" + entry.file;\n}\n\nconst contentTypes = { \".js\": \"text/javascript\", \".css\": \"text/css\", \".png\": \"image/png\", \".svg\": \"image/svg+xml\", \".ico\": \"image/x-icon\" };\nconst server = createServer(async (request, response) => {\n try {\n const path = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n if (path === \"/\") {\n const module = vite ? await vite.ssrLoadModule(\"/src/entry-server.ts\") : await import(pathToFileURL(resolve(root, \"dist/server/entry-server.js\")).href);\n const html = module.renderPage(clientSource);\n response.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n response.end(vite ? await vite.transformIndexHtml(path, html) : html);\n return;\n }\n if (vite) {\n vite.middlewares(request, response, () => { response.writeHead(404); response.end(); });\n return;\n }\n const file = resolve(clientRoot, \".\" + path);\n if (!file.startsWith(clientRoot + sep)) { response.writeHead(403); response.end(); return; }\n const body = await readFile(file);\n response.writeHead(200, { \"content-type\": contentTypes[extname(file)] ?? \"application/octet-stream\" });\n response.end(body);\n } catch (error) {\n console.error(error);\n response.writeHead(500);\n response.end(\"Internal server error\");\n }\n});\n\nconst port = Number(process.env.PORT ?? 4173);\nserver.listen(port, \"127.0.0.1\", () => console.log(\"http://127.0.0.1:\" + port));\nprocess.on(\"SIGINT\", () => { server.close(); void vite?.close(); });\n`,\n \"README.md\": `# Meeko SSR starter\n\nProyecto inicial con renderizado en servidor e hidratación del mismo componente \\`.meeko\\`.\n\n\\`\\`\\`sh\nnpm install\nnpm run dev\n\\`\\`\\`\n\nAbre http://127.0.0.1:4173. El servidor produce HTML y transfiere las props y señales al navegador.\n\n\\`npm run check\\` genera los tipos del componente y comprueba TypeScript. \\`npm run build\\` compila cliente y servidor; \\`npm start\\` sirve ambas compilaciones con SSR.\n`,\n};\n\n/** Crea un proyecto SSR independiente sin sobrescribir archivos del usuario. */\nexport async function initProject(directory: string): Promise<string> {\n const target = resolve(directory);\n const name = basename(target).toLowerCase().replace(/[^a-z0-9._-]+/g, \"-\").replace(/^[._-]+|[._-]+$/g, \"\") || \"meeko-app\";\n const packageMetadata: unknown = JSON.parse(await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"));\n if (typeof packageMetadata !== \"object\" || packageMetadata === null || !(\"version\" in packageMetadata) || typeof packageMetadata.version !== \"string\") {\n throw new Error(\"Meeko package version is unavailable\");\n }\n let existingEntries: string[] = [];\n try {\n if (!(await stat(target)).isDirectory()) throw new Error(`Destination is not a directory: ${target}`);\n existingEntries = await readdir(target);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n const unexpected = existingEntries.filter((entry) => !packageScaffoldEntries.has(entry));\n if (unexpected.length > 0 || (existingEntries.length > 0 && !existingEntries.includes(\"package.json\"))) {\n throw new Error(`Destination is not empty: ${target}${unexpected.length > 0 ? ` (${unexpected.join(\", \")})` : \"\"}`);\n }\n const existing: unknown = existingEntries.includes(\"package.json\") ? JSON.parse(await readFile(join(target, \"package.json\"), \"utf8\")) : {};\n if (!isRecord(existing)) throw new Error(`Invalid package.json in ${target}`);\n const existingScripts = existing.scripts ?? {};\n const existingDependencies = existing.dependencies ?? {};\n const existingDevDependencies = existing.devDependencies ?? {};\n const existingEngines = existing.engines ?? {};\n if (!isRecord(existingScripts) || !isRecord(existingDependencies) || !isRecord(existingDevDependencies) || !isRecord(existingEngines)) {\n throw new Error(`Invalid package.json in ${target}`);\n }\n const scripts = {\n dev: \"node server.mjs\",\n check: \"meeko types src/App.meeko && tsc --noEmit\",\n build: \"npm run check && vite build --outDir dist/client --manifest && vite build --ssr src/entry-server.ts --outDir dist/server\",\n start: \"node server.mjs --production\",\n };\n const devDependencies = { \"@types/node\": \"^24.0.0\", typescript: \"^7.0.2\", vite: \"^8.3.5\" };\n for (const command of Object.keys(scripts)) {\n if (command in existingScripts) throw new Error(`Destination already defines the ${command} script: ${target}`);\n }\n if (Object.keys(existingDependencies).some((dependency) => dependency !== \"@meekojs/meeko\") || Object.keys(existingDevDependencies).some((dependency) => !(dependency in devDependencies))) {\n throw new Error(`Destination contains other dependencies: ${target}`);\n }\n const packageFile = JSON.stringify({\n ...existing,\n name: typeof existing.name === \"string\" ? existing.name : name,\n private: true,\n type: \"module\",\n engines: { ...existingEngines, node: \">=24\" },\n scripts: { ...existingScripts, ...scripts },\n dependencies: { ...existingDependencies, \"@meekojs/meeko\": packageMetadata.version },\n devDependencies: { ...existingDevDependencies, ...devDependencies },\n }, null, 2) + \"\\n\";\n await mkdir(target, { recursive: true });\n for (const [filename, content] of Object.entries(starterFiles)) {\n const path = join(target, filename);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, { encoding: \"utf8\", flag: \"wx\" });\n }\n await writeFile(join(target, \"package.json\"), packageFile, { encoding: \"utf8\", flag: existingEntries.includes(\"package.json\") ? \"w\" : \"wx\" });\n return target;\n}\n"]}
package/dist/internal.js CHANGED
@@ -9,3 +9,4 @@ export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./se
9
9
  export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
10
10
  export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
11
11
  export { registerDevtoolsInstance } from "./devtools.js";
12
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEjK,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtJ,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * Contrato del runtime generado por el compilador Meeko.\n *\n * Esta ruta es interna y puede cambiar junto con el compilador. Las aplicaciones\n * deben importar las API documentadas desde la raíz del paquete.\n */\nexport { createRoot } from \"./reactivity.js\";\nexport { attributeValue, escapeHtml, renderAttribute, serializeJson } from \"./server.js\";\nexport { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from \"./dom.js\";\nexport type { ComponentModule, ComponentRelease, DomScope } from \"./dom.js\";\nexport { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from \"./hmr.js\";\nexport type { HotComponent, HotState } from \"./hmr.js\";\nexport { registerDevtoolsInstance } from \"./devtools.js\";\n"]}
package/dist/node.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ export { discoverRoutes, createFrameworkHandler } from "./framework/server.js";
3
+ export type { FrameworkHandlerOptions, PageModule, PageRoute, PageRequestContext } from "./framework/server.js";
4
+ export { composeFrameworkRoutes } from "./framework/modules.js";
5
+ export { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from "./framework/config.js";
6
+ export type { MeekoConfig, ConfigSource } from "./framework/config.js";
7
+ export type { RouteLayer, RouteModule, ComposeRoutesOptions } from "./framework/modules.js";
8
+ export { prerenderRoutes, prerenderProject } from "./framework/prerender.js";
9
+ export type { PrerenderOptions } from "./framework/prerender.js";
10
+ export * from "./framework-server.js";
11
+ /** Adapts a portable Fetch handler to Node 24's HTTP server callback. */
12
+ export declare function toNodeListener(handler: (request: Request) => Promise<Response> | Response): (request: IncomingMessage, response: ServerResponse) => void;
package/dist/node.js ADDED
@@ -0,0 +1,52 @@
1
+ import { Readable } from "node:stream";
2
+ import { TLSSocket } from "node:tls";
3
+ export { discoverRoutes, createFrameworkHandler } from "./framework/server.js";
4
+ export { composeFrameworkRoutes } from "./framework/modules.js";
5
+ export { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from "./framework/config.js";
6
+ export { prerenderRoutes, prerenderProject } from "./framework/prerender.js";
7
+ export * from "./framework-server.js";
8
+ /** Adapts a portable Fetch handler to Node 24's HTTP server callback. */
9
+ export function toNodeListener(handler) {
10
+ return (incoming, outgoing) => {
11
+ void (async () => {
12
+ const controller = new AbortController();
13
+ const abort = () => controller.abort();
14
+ incoming.once("aborted", abort);
15
+ outgoing.once("close", abort);
16
+ try {
17
+ const authority = incoming.headers.host ?? "localhost";
18
+ const protocol = incoming.socket instanceof TLSSocket ? "https" : "http";
19
+ const url = new URL(incoming.url ?? "/", `${protocol}://${authority}`);
20
+ const method = incoming.method ?? "GET";
21
+ const headers = new Headers();
22
+ for (const [name, value] of Object.entries(incoming.headers)) {
23
+ if (value !== undefined)
24
+ headers.set(name, Array.isArray(value) ? value.join(", ") : value);
25
+ }
26
+ const hasBody = method !== "GET" && method !== "HEAD";
27
+ const request = new Request(url, {
28
+ method, headers, signal: controller.signal,
29
+ ...(hasBody ? { body: Readable.toWeb(incoming), duplex: "half" } : {}),
30
+ });
31
+ const result = await handler(request);
32
+ outgoing.writeHead(result.status, Object.fromEntries(result.headers));
33
+ if (method === "HEAD" || !result.body) {
34
+ outgoing.end();
35
+ return;
36
+ }
37
+ for await (const chunk of result.body)
38
+ outgoing.write(chunk);
39
+ outgoing.end();
40
+ }
41
+ finally {
42
+ incoming.off("aborted", abort);
43
+ outgoing.off("close", abort);
44
+ }
45
+ })().catch(() => {
46
+ if (!outgoing.headersSent)
47
+ outgoing.writeHead(500, { "content-type": "text/plain; charset=utf-8" });
48
+ outgoing.end("Internal server error");
49
+ });
50
+ };
51
+ }
52
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { Readable } from \"node:stream\";\nimport { TLSSocket } from \"node:tls\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport { discoverRoutes, createFrameworkHandler } from \"./framework/server.js\";\nexport type { FrameworkHandlerOptions, PageModule, PageRoute, PageRequestContext } from \"./framework/server.js\";\nexport { composeFrameworkRoutes } from \"./framework/modules.js\";\nexport { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from \"./framework/config.js\";\nexport type { MeekoConfig, ConfigSource } from \"./framework/config.js\";\nexport type { RouteLayer, RouteModule, ComposeRoutesOptions } from \"./framework/modules.js\";\nexport { prerenderRoutes, prerenderProject } from \"./framework/prerender.js\";\nexport type { PrerenderOptions } from \"./framework/prerender.js\";\nexport * from \"./framework-server.js\";\n\n/** Adapts a portable Fetch handler to Node 24's HTTP server callback. */\nexport function toNodeListener(handler: (request: Request) => Promise<Response> | Response): (request: IncomingMessage, response: ServerResponse) => void {\n return (incoming, outgoing) => {\n void (async () => {\n const controller = new AbortController();\n const abort = () => controller.abort();\n incoming.once(\"aborted\", abort);\n outgoing.once(\"close\", abort);\n try {\n const authority = incoming.headers.host ?? \"localhost\";\n const protocol = incoming.socket instanceof TLSSocket ? \"https\" : \"http\";\n const url = new URL(incoming.url ?? \"/\", `${protocol}://${authority}`);\n const method = incoming.method ?? \"GET\";\n const headers = new Headers();\n for (const [name, value] of Object.entries(incoming.headers)) {\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(\", \") : value);\n }\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const request = new Request(url, {\n method, headers, signal: controller.signal,\n ...(hasBody ? { body: Readable.toWeb(incoming) as ReadableStream<Uint8Array>, duplex: \"half\" as const } : {}),\n });\n const result = await handler(request);\n outgoing.writeHead(result.status, Object.fromEntries(result.headers));\n if (method === \"HEAD\" || !result.body) { outgoing.end(); return; }\n for await (const chunk of result.body) outgoing.write(chunk);\n outgoing.end();\n } finally {\n incoming.off(\"aborted\", abort);\n outgoing.off(\"close\", abort);\n }\n })().catch(() => {\n if (!outgoing.headersSent) outgoing.writeHead(500, { \"content-type\": \"text/plain; charset=utf-8\" });\n outgoing.end(\"Internal server error\");\n });\n };\n}\n"]}
@@ -6,6 +6,12 @@ export interface ReadonlySignal<T> {
6
6
  export interface Signal<T> extends ReadonlySignal<T> {
7
7
  value: T;
8
8
  }
9
+ /** Clave nominal para compartir un valor tipado entre instancias anidadas. */
10
+ export type ContextKey<T> = symbol & {
11
+ readonly __meekoValue?: (value: T) => T;
12
+ };
13
+ /** Crea una clave única; el tipo no se infiere de un valor global compartido. */
14
+ export declare function createContext<T>(description?: string): ContextKey<T>;
9
15
  /** Ubicación de una expresión de plantilla que lee una señal durante desarrollo. */
10
16
  export interface EffectSource {
11
17
  file: string;
@@ -16,6 +22,12 @@ export interface EffectSource {
16
22
  }
17
23
  /** Identifica señales editables creadas por Meeko para conservarlas durante HMR. */
18
24
  export declare function isWritableSignal(value: unknown): value is Signal<unknown>;
25
+ /** Publica un valor en la instancia activa y sus descendientes. */
26
+ export declare function provide<T>(key: ContextKey<T>, value: T): void;
27
+ /** Lee el proveedor más cercano; falla si falta para evitar un valor implícito. */
28
+ export declare function inject<T>(key: ContextKey<T>): T;
29
+ /** Registers an external resource to be released with the current component root. */
30
+ export declare function onCleanup(release: () => void): void;
19
31
  /** Crea un valor observable. Las escrituras iguales no notifican cambios. */
20
32
  export declare function signal<T>(initial: T): Signal<T>;
21
33
  /** Ejecuta una función cuando cambian las señales leídas por ella. */