@meekojs/meeko 0.0.3 → 0.1.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.
- package/README.md +35 -16
- package/dist/autoimports-ts.d.ts +26 -0
- package/dist/autoimports-ts.js +183 -0
- package/dist/autoimports-ts.js.map +1 -0
- package/dist/autoimports.d.ts +21 -0
- package/dist/autoimports.js +301 -0
- package/dist/autoimports.js.map +1 -0
- package/dist/check.js +74 -33
- package/dist/check.js.map +1 -0
- package/dist/cli.js +67 -5
- package/dist/cli.js.map +1 -0
- package/dist/compiler/events.d.ts +2 -0
- package/dist/compiler/events.js +6 -0
- package/dist/compiler/events.js.map +1 -0
- package/dist/compiler/import-graph.d.ts +8 -0
- package/dist/compiler/import-graph.js +33 -0
- package/dist/compiler/import-graph.js.map +1 -0
- package/dist/compiler/mapping.js +1 -0
- package/dist/compiler/mapping.js.map +1 -0
- package/dist/compiler/project-root.d.ts +2 -0
- package/dist/compiler/project-root.js +18 -0
- package/dist/compiler/project-root.js.map +1 -0
- package/dist/compiler/props.d.ts +12 -0
- package/dist/compiler/props.js +32 -0
- package/dist/compiler/props.js.map +1 -0
- package/dist/compiler/sfc.js +1 -0
- package/dist/compiler/sfc.js.map +1 -0
- package/dist/compiler/sourcemap.d.ts +3 -0
- package/dist/compiler/sourcemap.js +75 -0
- package/dist/compiler/sourcemap.js.map +1 -0
- package/dist/compiler/template.js +1 -0
- package/dist/compiler/template.js.map +1 -0
- package/dist/compiler.js +66 -17
- package/dist/compiler.js.map +1 -0
- package/dist/component-errors.d.ts +18 -0
- package/dist/component-errors.js +65 -0
- package/dist/component-errors.js.map +1 -0
- package/dist/devtools-ui/index.js +1 -0
- package/dist/devtools-ui/index.js.map +1 -0
- package/dist/devtools.js +3 -4
- package/dist/devtools.js.map +1 -0
- package/dist/dom.d.ts +18 -5
- package/dist/dom.js +295 -90
- package/dist/dom.js.map +1 -0
- package/dist/error-observer.d.ts +6 -0
- package/dist/error-observer.js +41 -0
- package/dist/error-observer.js.map +1 -0
- package/dist/framework/check-app.d.ts +5 -0
- package/dist/framework/check-app.js +214 -0
- package/dist/framework/check-app.js.map +1 -0
- package/dist/framework/check-project.d.ts +4 -0
- package/dist/framework/check-project.js +42 -0
- package/dist/framework/check-project.js.map +1 -0
- package/dist/framework/client.d.ts +48 -0
- package/dist/framework/client.js +249 -0
- package/dist/framework/client.js.map +1 -0
- package/dist/framework/clients.d.ts +82 -0
- package/dist/framework/clients.js +190 -0
- package/dist/framework/clients.js.map +1 -0
- package/dist/framework/config-type.d.ts +10 -0
- package/dist/framework/config-type.js +4 -0
- package/dist/framework/config-type.js.map +1 -0
- package/dist/framework/config.d.ts +15 -0
- package/dist/framework/config.js +138 -0
- package/dist/framework/config.js.map +1 -0
- package/dist/framework/contracts-generate.d.ts +8 -0
- package/dist/framework/contracts-generate.js +290 -0
- package/dist/framework/contracts-generate.js.map +1 -0
- package/dist/framework/generate.d.ts +7 -0
- package/dist/framework/generate.js +67 -0
- package/dist/framework/generate.js.map +1 -0
- package/dist/framework/init.d.ts +2 -0
- package/dist/framework/init.js +183 -0
- package/dist/framework/init.js.map +1 -0
- package/dist/framework/middleware.d.ts +14 -0
- package/dist/framework/middleware.js +16 -0
- package/dist/framework/middleware.js.map +1 -0
- package/dist/framework/modules.d.ts +22 -0
- package/dist/framework/modules.js +29 -0
- package/dist/framework/modules.js.map +1 -0
- package/dist/framework/page-contracts-check.d.ts +8 -0
- package/dist/framework/page-contracts-check.js +110 -0
- package/dist/framework/page-contracts-check.js.map +1 -0
- package/dist/framework/page-contracts-generate.d.ts +2 -0
- package/dist/framework/page-contracts-generate.js +94 -0
- package/dist/framework/page-contracts-generate.js.map +1 -0
- package/dist/framework/page.d.ts +64 -0
- package/dist/framework/page.js +44 -0
- package/dist/framework/page.js.map +1 -0
- package/dist/framework/prerender.d.ts +14 -0
- package/dist/framework/prerender.js +110 -0
- package/dist/framework/prerender.js.map +1 -0
- package/dist/framework/project-templates.d.ts +3 -0
- package/dist/framework/project-templates.js +119 -0
- package/dist/framework/project-templates.js.map +1 -0
- package/dist/framework/project.d.ts +9 -0
- package/dist/framework/project.js +272 -0
- package/dist/framework/project.js.map +1 -0
- package/dist/framework/router.d.ts +41 -0
- package/dist/framework/router.js +259 -0
- package/dist/framework/router.js.map +1 -0
- package/dist/framework/server.d.ts +65 -0
- package/dist/framework/server.js +239 -0
- package/dist/framework/server.js.map +1 -0
- package/dist/framework/socket-contracts-generate.d.ts +5 -0
- package/dist/framework/socket-contracts-generate.js +162 -0
- package/dist/framework/socket-contracts-generate.js.map +1 -0
- package/dist/framework/socket.d.ts +72 -0
- package/dist/framework/socket.js +252 -0
- package/dist/framework/socket.js.map +1 -0
- package/dist/framework/standard-schema-types.d.ts +7 -0
- package/dist/framework/standard-schema-types.js +69 -0
- package/dist/framework/standard-schema-types.js.map +1 -0
- package/dist/framework/state.d.ts +22 -0
- package/dist/framework/state.js +136 -0
- package/dist/framework/state.js.map +1 -0
- package/dist/framework/styles.d.ts +2 -0
- package/dist/framework/styles.js +6 -0
- package/dist/framework/styles.js.map +1 -0
- package/dist/framework/type-declarations.d.ts +5 -0
- package/dist/framework/type-declarations.js +84 -0
- package/dist/framework/type-declarations.js.map +1 -0
- package/dist/framework-server/auto-clients.d.ts +3 -0
- package/dist/framework-server/auto-clients.js +27 -0
- package/dist/framework-server/auto-clients.js.map +1 -0
- package/dist/framework-server/context.d.ts +21 -0
- package/dist/framework-server/context.js +22 -0
- package/dist/framework-server/context.js.map +1 -0
- package/dist/framework-server/contracts.d.ts +73 -0
- package/dist/framework-server/contracts.js +184 -0
- package/dist/framework-server/contracts.js.map +1 -0
- package/dist/framework-server/discovery.d.ts +43 -0
- package/dist/framework-server/discovery.js +257 -0
- package/dist/framework-server/discovery.js.map +1 -0
- package/dist/framework-server/local.d.ts +21 -0
- package/dist/framework-server/local.js +100 -0
- package/dist/framework-server/local.js.map +1 -0
- package/dist/framework-server/middleware.d.ts +4 -0
- package/dist/framework-server/middleware.js +56 -0
- package/dist/framework-server/middleware.js.map +1 -0
- package/dist/framework-server/node-upgrade.d.ts +23 -0
- package/dist/framework-server/node-upgrade.js +96 -0
- package/dist/framework-server/node-upgrade.js.map +1 -0
- package/dist/framework-server/node-websocket.d.ts +16 -0
- package/dist/framework-server/node-websocket.js +127 -0
- package/dist/framework-server/node-websocket.js.map +1 -0
- package/dist/framework-server/openapi.d.ts +17 -0
- package/dist/framework-server/openapi.js +118 -0
- package/dist/framework-server/openapi.js.map +1 -0
- package/dist/framework-server/session-stores.d.ts +73 -0
- package/dist/framework-server/session-stores.js +122 -0
- package/dist/framework-server/session-stores.js.map +1 -0
- package/dist/framework-server/sessions.d.ts +70 -0
- package/dist/framework-server/sessions.js +167 -0
- package/dist/framework-server/sessions.js.map +1 -0
- package/dist/framework-server/socket.d.ts +83 -0
- package/dist/framework-server/socket.js +196 -0
- package/dist/framework-server/socket.js.map +1 -0
- package/dist/framework-server.d.ts +23 -0
- package/dist/framework-server.js +13 -0
- package/dist/framework-server.js.map +1 -0
- package/dist/framework.d.ts +31 -0
- package/dist/framework.js +14 -0
- package/dist/framework.js.map +1 -0
- package/dist/hmr.js +75 -24
- package/dist/hmr.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -0
- package/dist/init.js +31 -3
- package/dist/init.js.map +1 -0
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +3 -2
- package/dist/internal.js.map +1 -0
- package/dist/node.d.ts +16 -0
- package/dist/node.js +122 -0
- package/dist/node.js.map +1 -0
- package/dist/reactivity.d.ts +22 -1
- package/dist/reactivity.js +132 -18
- package/dist/reactivity.js.map +1 -0
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +26 -9
- package/dist/types.js.map +1 -0
- package/dist/vite.js +112 -7
- package/dist/vite.js.map +1 -0
- package/package.json +15 -4
|
@@ -0,0 +1,196 @@
|
|
|
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
|
+
const errors = [];
|
|
11
|
+
for (const listener of this.listeners.get(`${channel}\0${room}`) ?? []) {
|
|
12
|
+
try {
|
|
13
|
+
await listener(message);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
errors.push(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (errors.length === 1)
|
|
20
|
+
throw errors[0];
|
|
21
|
+
if (errors.length > 1)
|
|
22
|
+
throw new AggregateError(errors, "Socket delivery failed for multiple peers");
|
|
23
|
+
}
|
|
24
|
+
subscribe(channel, room, listener) {
|
|
25
|
+
const key = `${channel}\0${room}`;
|
|
26
|
+
let listeners = this.listeners.get(key);
|
|
27
|
+
if (!listeners) {
|
|
28
|
+
listeners = new Set();
|
|
29
|
+
this.listeners.set(key, listeners);
|
|
30
|
+
}
|
|
31
|
+
listeners.add(listener);
|
|
32
|
+
return () => {
|
|
33
|
+
listeners.delete(listener);
|
|
34
|
+
if (!listeners.size)
|
|
35
|
+
this.listeners.delete(key);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function validate(schema, value) {
|
|
40
|
+
const result = await schema["~standard"].validate(value);
|
|
41
|
+
if ("issues" in result && result.issues)
|
|
42
|
+
throw new ApiError("INVALID_SOCKET_PAYLOAD", 400);
|
|
43
|
+
return result.value;
|
|
44
|
+
}
|
|
45
|
+
function channelDefinition(value) {
|
|
46
|
+
if (!value || typeof value !== "object" || !("clientToServer" in value) || !("serverToClient" in value))
|
|
47
|
+
throw new ApiError("UNKNOWN_SOCKET_CHANNEL", 404);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function originAllowed(request, allowedOrigins) {
|
|
51
|
+
const origin = request.headers.get("origin");
|
|
52
|
+
return !!origin && (origin === new URL(request.url).origin || allowedOrigins.includes(origin));
|
|
53
|
+
}
|
|
54
|
+
/** The host performs the HTTP upgrade, then passes its connected peer here. */
|
|
55
|
+
export function createSocketHub(options) {
|
|
56
|
+
const maxMessageBytes = options.maxMessageBytes ?? 64 * 1024;
|
|
57
|
+
const maxBufferBytes = options.maxBufferBytes ?? 1024 * 1024;
|
|
58
|
+
if (!Number.isSafeInteger(maxMessageBytes) || maxMessageBytes <= 0 || !Number.isSafeInteger(maxBufferBytes) || maxBufferBytes <= 0)
|
|
59
|
+
throw new RangeError("Invalid socket limits");
|
|
60
|
+
const pubsub = options.pubsub ?? new LocalSocketPubSub();
|
|
61
|
+
const getDefinition = (name) => channelDefinition(options.channels[name]);
|
|
62
|
+
const authorizeHandshake = async (name, request, roomId) => {
|
|
63
|
+
const definition = getDefinition(name);
|
|
64
|
+
if (!originAllowed(request, options.allowedOrigins ?? []))
|
|
65
|
+
throw new ApiError("INVALID_ORIGIN", 403);
|
|
66
|
+
const session = await options.sessions.load(request);
|
|
67
|
+
if (definition.auth === "required" && !session.current)
|
|
68
|
+
throw new ApiError("UNAUTHENTICATED", 401);
|
|
69
|
+
const services = typeof options.services === "function" ? await options.services(request) : options.services;
|
|
70
|
+
const context = createRequestContext(request, services, session);
|
|
71
|
+
if (definition.authorize && !(await definition.authorize({ context, ...(roomId === undefined ? {} : { roomId }) })))
|
|
72
|
+
throw new ApiError("FORBIDDEN", 403);
|
|
73
|
+
return { definition, services };
|
|
74
|
+
};
|
|
75
|
+
return {
|
|
76
|
+
async preflight(name, request, roomId) { await authorizeHandshake(name, request, roomId); },
|
|
77
|
+
async accept(name, request, peer, roomId) {
|
|
78
|
+
const { definition, services } = await authorizeHandshake(name, request, roomId);
|
|
79
|
+
let closed = false;
|
|
80
|
+
const emit = async (event, payload) => {
|
|
81
|
+
if (closed)
|
|
82
|
+
throw new ApiError("SOCKET_DISCONNECTED", 409);
|
|
83
|
+
const schema = definition.serverToClient[event];
|
|
84
|
+
if (!schema)
|
|
85
|
+
throw new ApiError("UNKNOWN_SOCKET_EVENT", 404);
|
|
86
|
+
const checked = await validate(schema, payload);
|
|
87
|
+
const fresh = await options.sessions.load(request);
|
|
88
|
+
if (definition.auth === "required" && !fresh.current)
|
|
89
|
+
failAndClose(new ApiError("UNAUTHENTICATED", 401), 1008, "Session expired");
|
|
90
|
+
const sendContext = createRequestContext(request, services, fresh);
|
|
91
|
+
if (definition.authorize && !(await definition.authorize({ context: sendContext, ...(roomId === undefined ? {} : { roomId }) })))
|
|
92
|
+
throw new ApiError("FORBIDDEN", 403);
|
|
93
|
+
if (definition.authorizeSend && !(await definition.authorizeSend({ event, payload: checked, context: sendContext, ...(roomId === undefined ? {} : { roomId }) })))
|
|
94
|
+
throw new ApiError("FORBIDDEN", 403);
|
|
95
|
+
const message = serializeJson({ event, payload: checked });
|
|
96
|
+
const messageBytes = new TextEncoder().encode(message).byteLength;
|
|
97
|
+
if (messageBytes > maxMessageBytes || (peer.bufferedAmount ?? 0) + messageBytes > maxBufferBytes) {
|
|
98
|
+
failAndClose(new ApiError("SOCKET_LIMIT_EXCEEDED", 413), 1009, "Message too large");
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await peer.send(message);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
try {
|
|
105
|
+
close(1011, "Send failed");
|
|
106
|
+
}
|
|
107
|
+
catch (closeError) {
|
|
108
|
+
throw new AggregateError([error, closeError], "Socket send and close failed");
|
|
109
|
+
}
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const release = pubsub.subscribe(name, roomId ?? "", ({ event, payload }) => emit(event, payload));
|
|
114
|
+
const close = (code, reason) => {
|
|
115
|
+
if (closed)
|
|
116
|
+
return;
|
|
117
|
+
closed = true;
|
|
118
|
+
const failures = [];
|
|
119
|
+
try {
|
|
120
|
+
release();
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
failures.push(error);
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
peer.close(code, reason);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
failures.push(error);
|
|
130
|
+
}
|
|
131
|
+
if (failures.length === 1)
|
|
132
|
+
throw failures[0];
|
|
133
|
+
if (failures.length > 1)
|
|
134
|
+
throw new AggregateError(failures, "Socket unsubscribe and peer close failed");
|
|
135
|
+
};
|
|
136
|
+
function failAndClose(error, code, reason) {
|
|
137
|
+
try {
|
|
138
|
+
close(code, reason);
|
|
139
|
+
}
|
|
140
|
+
catch (cleanupError) {
|
|
141
|
+
error.cause = cleanupError;
|
|
142
|
+
}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
emit,
|
|
147
|
+
close,
|
|
148
|
+
async receive(raw) {
|
|
149
|
+
if (closed)
|
|
150
|
+
throw new ApiError("SOCKET_DISCONNECTED", 409);
|
|
151
|
+
const bytes = typeof raw === "string" ? new TextEncoder().encode(raw) : raw;
|
|
152
|
+
if (bytes.byteLength > maxMessageBytes)
|
|
153
|
+
failAndClose(new ApiError("SOCKET_LIMIT_EXCEEDED", 413), 1009, "Message too large");
|
|
154
|
+
let envelope;
|
|
155
|
+
try {
|
|
156
|
+
envelope = JSON.parse(typeof raw === "string" ? raw : new TextDecoder("utf-8", { fatal: true }).decode(raw));
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
failAndClose(new ApiError("INVALID_SOCKET_MESSAGE", 400), 1008, "Invalid message");
|
|
160
|
+
}
|
|
161
|
+
if (!envelope || typeof envelope !== "object" || typeof envelope.event !== "string" || !("payload" in envelope)) {
|
|
162
|
+
failAndClose(new ApiError("INVALID_SOCKET_MESSAGE", 400), 1008, "Invalid message");
|
|
163
|
+
}
|
|
164
|
+
const event = envelope.event;
|
|
165
|
+
const schema = definition.clientToServer[event];
|
|
166
|
+
if (!schema)
|
|
167
|
+
failAndClose(new ApiError("UNKNOWN_SOCKET_EVENT", 404), 1008, "Unknown event");
|
|
168
|
+
const payload = await validate(schema, envelope.payload);
|
|
169
|
+
// Re-read storage and policy for every event, including after a session revocation.
|
|
170
|
+
const fresh = await options.sessions.load(request);
|
|
171
|
+
if (definition.auth === "required" && !fresh.current)
|
|
172
|
+
failAndClose(new ApiError("UNAUTHENTICATED", 401), 1008, "Session expired");
|
|
173
|
+
const eventContext = createRequestContext(request, services, fresh);
|
|
174
|
+
if (definition.authorize && !(await definition.authorize({ context: eventContext, ...(roomId === undefined ? {} : { roomId }) })))
|
|
175
|
+
throw new ApiError("FORBIDDEN", 403);
|
|
176
|
+
if (definition.authorizeEvent && !(await definition.authorizeEvent({ event, payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }) })))
|
|
177
|
+
throw new ApiError("FORBIDDEN", 403);
|
|
178
|
+
const handler = definition.handlers?.[event];
|
|
179
|
+
if (!handler)
|
|
180
|
+
throw new ApiError("UNHANDLED_SOCKET_EVENT", 404);
|
|
181
|
+
await handler({ payload, context: eventContext, ...(roomId === undefined ? {} : { roomId }), emit });
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
},
|
|
185
|
+
async broadcast(name, roomId, event, payload) {
|
|
186
|
+
const definition = getDefinition(name);
|
|
187
|
+
const schema = definition.serverToClient[event];
|
|
188
|
+
if (!schema)
|
|
189
|
+
throw new ApiError("UNKNOWN_SOCKET_EVENT", 404);
|
|
190
|
+
const checked = await validate(schema, payload);
|
|
191
|
+
serializeJson({ event, payload: checked });
|
|
192
|
+
await pubsub.publish(name, roomId, { event, payload: checked });
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=socket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"socket.js","sourceRoot":"","sources":["../../src/framework-server/socket.ts"],"names":[],"mappings":"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","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 const errors: unknown[] = [];\n for (const listener of this.listeners.get(`${channel}\\0${room}`) ?? []) {\n try { await listener(message); }\n catch (error) { errors.push(error); }\n }\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) throw new AggregateError(errors, \"Socket delivery failed for multiple peers\");\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) failAndClose(new ApiError(\"UNAUTHENTICATED\", 401), 1008, \"Session expired\");\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 failAndClose(new ApiError(\"SOCKET_LIMIT_EXCEEDED\", 413), 1009, \"Message too large\");\n }\n try { await peer.send(message); }\n catch (error) {\n try { close(1011, \"Send failed\"); }\n catch (closeError) { throw new AggregateError([error, closeError], \"Socket send and close failed\"); }\n throw error;\n }\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 const failures: unknown[] = [];\n try { release(); }\n catch (error) { failures.push(error); }\n try { peer.close(code, reason); }\n catch (error) { failures.push(error); }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, \"Socket unsubscribe and peer close failed\");\n };\n function failAndClose(error: ApiError, code: number, reason: string): never {\n try { close(code, reason); }\n catch (cleanupError) { error.cause = cleanupError; }\n throw error;\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) failAndClose(new ApiError(\"SOCKET_LIMIT_EXCEEDED\", 413), 1009, \"Message too large\");\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 { failAndClose(new ApiError(\"INVALID_SOCKET_MESSAGE\", 400), 1008, \"Invalid message\"); }\n if (!envelope || typeof envelope !== \"object\" || typeof (envelope as { event?: unknown }).event !== \"string\" || !(\"payload\" in envelope)) {\n failAndClose(new ApiError(\"INVALID_SOCKET_MESSAGE\", 400), 1008, \"Invalid message\");\n }\n const event = (envelope as { event?: unknown }).event as string;\n const schema = definition.clientToServer[event];\n if (!schema) failAndClose(new ApiError(\"UNKNOWN_SOCKET_EVENT\", 404), 1008, \"Unknown event\");\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) failAndClose(new ApiError(\"UNAUTHENTICATED\", 401), 1008, \"Session expired\");\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,23 @@
|
|
|
1
|
+
export { createRequestContext, useRequestState } from "./framework-server/context.js";
|
|
2
|
+
export { defineServerMiddleware, composeServerMiddleware } from "./framework-server/middleware.js";
|
|
3
|
+
export type { ServerMiddleware } from "./framework-server/middleware.js";
|
|
4
|
+
export type { RequestContext, ServerFetch } from "./framework-server/context.js";
|
|
5
|
+
export { createServerClientOptions } from "./framework-server/auto-clients.js";
|
|
6
|
+
export { MemorySessionStore, SessionHandle, SessionManager, SessionSecurityError } from "./framework-server/sessions.js";
|
|
7
|
+
export type { SessionOptions, SessionRecord, SessionStore } from "./framework-server/sessions.js";
|
|
8
|
+
export { RedisSessionStore, SqlSessionStore } from "./framework-server/session-stores.js";
|
|
9
|
+
export type { RedisSessionClient, RedisSessionStoreOptions, SqlSessionDriver, SqlSessionRow, SqlSessionStoreOptions } from "./framework-server/session-stores.js";
|
|
10
|
+
export { ApiError, defineApiRoute, defineRpc, dispatchApiRoute, dispatchRpc, errorResponse, executeApiRoute, executeRpc } from "./framework-server/contracts.js";
|
|
11
|
+
export type { ApiRouteDefinition, RpcDefinition, Schema } from "./framework-server/contracts.js";
|
|
12
|
+
export { createLocalServerFetch, createServerDispatcher, discoverServerManifest, loadSocketChannels } from "./framework-server/discovery.js";
|
|
13
|
+
export type { ApiEndpoint, ApiMethod, RpcEndpoint, SocketEndpoint, ServerDispatcherOptions, ServerManifest } from "./framework-server/discovery.js";
|
|
14
|
+
export { createSocketHub, defineSocketChannel, LocalSocketPubSub } from "./framework-server/socket.js";
|
|
15
|
+
export type { SocketChannelDefinition, SocketConnection, SocketHubOptions, SocketPeer, SocketPubSub } from "./framework-server/socket.js";
|
|
16
|
+
export { createNodeSocketUpgradeHandler } from "./framework-server/node-upgrade.js";
|
|
17
|
+
export type { NodeAcceptedSocket, NodeSocketUpgradeOptions } from "./framework-server/node-upgrade.js";
|
|
18
|
+
export { attachNodeWebSocketServer } from "./framework-server/node-websocket.js";
|
|
19
|
+
export type { NodeWebSocketOptions, NodeWebSocketServer } from "./framework-server/node-websocket.js";
|
|
20
|
+
export { generateOpenApi } from "./framework-server/openapi.js";
|
|
21
|
+
export type { OpenApiOptions } from "./framework-server/openapi.js";
|
|
22
|
+
export { createLocalCalls } from "./framework-server/local.js";
|
|
23
|
+
export type { LocalApiInput, LocalCallOptions } from "./framework-server/local.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { createRequestContext, useRequestState } from "./framework-server/context.js";
|
|
2
|
+
export { defineServerMiddleware, composeServerMiddleware } from "./framework-server/middleware.js";
|
|
3
|
+
export { createServerClientOptions } from "./framework-server/auto-clients.js";
|
|
4
|
+
export { MemorySessionStore, SessionHandle, SessionManager, SessionSecurityError } from "./framework-server/sessions.js";
|
|
5
|
+
export { RedisSessionStore, SqlSessionStore } from "./framework-server/session-stores.js";
|
|
6
|
+
export { ApiError, defineApiRoute, defineRpc, dispatchApiRoute, dispatchRpc, errorResponse, executeApiRoute, executeRpc } from "./framework-server/contracts.js";
|
|
7
|
+
export { createLocalServerFetch, createServerDispatcher, discoverServerManifest, loadSocketChannels } from "./framework-server/discovery.js";
|
|
8
|
+
export { createSocketHub, defineSocketChannel, LocalSocketPubSub } from "./framework-server/socket.js";
|
|
9
|
+
export { createNodeSocketUpgradeHandler } from "./framework-server/node-upgrade.js";
|
|
10
|
+
export { attachNodeWebSocketServer } from "./framework-server/node-websocket.js";
|
|
11
|
+
export { generateOpenApi } from "./framework-server/openapi.js";
|
|
12
|
+
export { createLocalCalls } from "./framework-server/local.js";
|
|
13
|
+
//# 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;AACtF,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAGnG,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 { defineServerMiddleware, composeServerMiddleware } from \"./framework-server/middleware.js\";\nexport type { ServerMiddleware } from \"./framework-server/middleware.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,31 @@
|
|
|
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 { defineRouteMiddleware } from "./framework/middleware.js";
|
|
12
|
+
export type { RouteMiddleware, RouteMiddlewareContext } from "./framework/middleware.js";
|
|
13
|
+
export { ClientError, createApiClient, createBrowserClientOptions, createPublicServerManifest, createRpcClient } from "./framework/clients.js";
|
|
14
|
+
export type { ApiClient, ApiOperation, ClientOptions, PublicApiEndpoint, PublicRpcEndpoint, PublicServerManifest, RpcClient, RpcOperation } from "./framework/clients.js";
|
|
15
|
+
export { createSocketClient, createSocketRegistry, useSocket, useSocketChannel } from "./framework/socket.js";
|
|
16
|
+
export type { SocketClient, SocketContract, SocketSchema, SocketClientOptions, SocketRegistry, SocketRegistryOptions } from "./framework/socket.js";
|
|
17
|
+
/** Augmented by generated declarations in .meeko/types/routes.d.ts. */
|
|
18
|
+
export interface GeneratedRoutes {
|
|
19
|
+
}
|
|
20
|
+
type RouteKey = keyof GeneratedRoutes extends never ? string : keyof GeneratedRoutes & string;
|
|
21
|
+
type RouteParams<K extends string> = K extends keyof GeneratedRoutes ? GeneratedRoutes[K] : Record<string, string>;
|
|
22
|
+
type HrefOptions<K extends string> = (keyof RouteParams<K> extends never ? {
|
|
23
|
+
params?: never;
|
|
24
|
+
} : {
|
|
25
|
+
params: RouteParams<K>;
|
|
26
|
+
}) & {
|
|
27
|
+
search?: Readonly<Record<string, string | number | boolean | null | undefined>>;
|
|
28
|
+
};
|
|
29
|
+
type HrefArguments<K extends string> = K extends keyof GeneratedRoutes ? keyof RouteParams<K> extends never ? [options?: HrefOptions<K>] : [options: HrefOptions<K>] : [options?: HrefOptions<K>];
|
|
30
|
+
/** Builds a checked URL when the project's route declarations are installed. */
|
|
31
|
+
export declare function href<K extends RouteKey>(routes: readonly RouteRecord[], id: K, ...[options]: HrefArguments<K>): string;
|
|
@@ -0,0 +1,14 @@
|
|
|
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 { defineRouteMiddleware } from "./framework/middleware.js";
|
|
8
|
+
export { ClientError, createApiClient, createBrowserClientOptions, createPublicServerManifest, createRpcClient } from "./framework/clients.js";
|
|
9
|
+
export { createSocketClient, createSocketRegistry, useSocket, useSocketChannel } from "./framework/socket.js";
|
|
10
|
+
/** Builds a checked URL when the project's route declarations are installed. */
|
|
11
|
+
export function href(routes, id, ...[options]) {
|
|
12
|
+
return runtimeHref(routes, id, options);
|
|
13
|
+
}
|
|
14
|
+
//# 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,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,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 { defineRouteMiddleware } from \"./framework/middleware.js\";\nexport type { RouteMiddleware, RouteMiddlewareContext } from \"./framework/middleware.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?: never }\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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isWritableSignal } from "./reactivity.js";
|
|
1
|
+
import { captureParentOwner, isWritableSignal } from "./reactivity.js";
|
|
2
2
|
const enabled = new Set();
|
|
3
3
|
const instances = new Map();
|
|
4
4
|
/** Copia solo las señales editables de un setup, sin serializarlas. */
|
|
@@ -27,7 +27,7 @@ export function enableHotModule(id) {
|
|
|
27
27
|
function registerHotTarget(id, key, target, props, component, snapshot, dispose) {
|
|
28
28
|
if (!enabled.has(id))
|
|
29
29
|
return dispose;
|
|
30
|
-
const entry = { target, props, component: component, snapshot, dispose };
|
|
30
|
+
const entry = { target, props, component: component, snapshot, dispose, withParent: captureParentOwner() };
|
|
31
31
|
let group = instances.get(id);
|
|
32
32
|
if (!group) {
|
|
33
33
|
group = new Map();
|
|
@@ -40,12 +40,17 @@ function registerHotTarget(id, key, target, props, component, snapshot, dispose)
|
|
|
40
40
|
}
|
|
41
41
|
const slot = {
|
|
42
42
|
current: entry,
|
|
43
|
-
|
|
43
|
+
forget: () => {
|
|
44
44
|
if (group.get(key) !== slot)
|
|
45
45
|
return;
|
|
46
46
|
group.delete(key);
|
|
47
47
|
if (group.size === 0)
|
|
48
48
|
instances.delete(id);
|
|
49
|
+
},
|
|
50
|
+
stop: () => {
|
|
51
|
+
if (group.get(key) !== slot)
|
|
52
|
+
return;
|
|
53
|
+
slot.forget();
|
|
49
54
|
slot.current.dispose();
|
|
50
55
|
},
|
|
51
56
|
};
|
|
@@ -80,7 +85,9 @@ function replaceScope(scope, html) {
|
|
|
80
85
|
export function replaceHotStyle(id, css) {
|
|
81
86
|
if (typeof document === "undefined")
|
|
82
87
|
return;
|
|
83
|
-
|
|
88
|
+
// Module IDs are file paths and may contain CSS selector metacharacters.
|
|
89
|
+
let style = [...document.querySelectorAll("style[data-meeko-hot]")]
|
|
90
|
+
.find((candidate) => candidate.dataset.meekoHot === id);
|
|
84
91
|
if (!style) {
|
|
85
92
|
style = document.createElement("style");
|
|
86
93
|
style.dataset.meekoHot = id;
|
|
@@ -99,26 +106,20 @@ export function replaceHotModule(id, next) {
|
|
|
99
106
|
const entry = slot.current;
|
|
100
107
|
const state = entry.snapshot();
|
|
101
108
|
const previous = entry.target.kind === "root" ? entry.target.root.innerHTML : scopeRange(entry.target.scope).cloneContents();
|
|
102
|
-
return { slot, entry, state, html: component.renderToString(entry.props, state), previous };
|
|
109
|
+
return { slot, entry, state, html: entry.withParent(() => component.renderToString(entry.props, state)), previous };
|
|
103
110
|
});
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
else {
|
|
114
|
-
if (!component.hydrateScope)
|
|
115
|
-
throw new Error("Updated Meeko child component has no hydrateScope export");
|
|
116
|
-
component.hydrateScope(entry.target.scope, entry.props, state);
|
|
111
|
+
const committed = [];
|
|
112
|
+
const rollback = ({ slot, entry, state, previous }, failures) => {
|
|
113
|
+
const partial = slot.current !== entry ? slot.current : undefined;
|
|
114
|
+
if (partial) {
|
|
115
|
+
try {
|
|
116
|
+
partial.dispose();
|
|
117
|
+
}
|
|
118
|
+
catch (cleanupError) {
|
|
119
|
+
failures.push(cleanupError);
|
|
117
120
|
}
|
|
118
|
-
if (slot.current === entry)
|
|
119
|
-
throw new Error("Updated Meeko component did not register its hydrated instance");
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
+
try {
|
|
122
123
|
if (entry.target.kind === "root")
|
|
123
124
|
entry.target.root.innerHTML = previous;
|
|
124
125
|
else {
|
|
@@ -126,12 +127,62 @@ export function replaceHotModule(id, next) {
|
|
|
126
127
|
range.deleteContents();
|
|
127
128
|
range.insertNode(previous);
|
|
128
129
|
}
|
|
130
|
+
if (entry.target.kind === "root") {
|
|
131
|
+
const { root } = entry.target;
|
|
132
|
+
entry.withParent(() => entry.component.hydrate(root, entry.props, state));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
const { scope } = entry.target;
|
|
136
|
+
entry.withParent(() => entry.component.hydrateScope?.(scope, entry.props, state));
|
|
137
|
+
}
|
|
138
|
+
if (slot.current === entry || slot.current === partial)
|
|
139
|
+
throw new Error("Restored Meeko component did not register its hydrated instance");
|
|
140
|
+
}
|
|
141
|
+
catch (rollbackError) {
|
|
142
|
+
failures.push(rollbackError);
|
|
143
|
+
if (slot.current !== entry && slot.current !== partial) {
|
|
144
|
+
try {
|
|
145
|
+
slot.current.dispose();
|
|
146
|
+
}
|
|
147
|
+
catch (cleanupError) {
|
|
148
|
+
failures.push(cleanupError);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
slot.forget();
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
for (const item of prepared) {
|
|
155
|
+
const { slot, entry, state, html } = item;
|
|
156
|
+
try {
|
|
157
|
+
entry.dispose();
|
|
129
158
|
if (entry.target.kind === "root")
|
|
130
|
-
entry.
|
|
159
|
+
entry.target.root.innerHTML = html;
|
|
131
160
|
else
|
|
132
|
-
|
|
133
|
-
|
|
161
|
+
replaceScope(entry.target.scope, html);
|
|
162
|
+
if (entry.target.kind === "root") {
|
|
163
|
+
const { root } = entry.target;
|
|
164
|
+
entry.withParent(() => component.hydrate(root, entry.props, state));
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
if (!component.hydrateScope)
|
|
168
|
+
throw new Error("Updated Meeko child component has no hydrateScope export");
|
|
169
|
+
const { scope } = entry.target;
|
|
170
|
+
entry.withParent(() => component.hydrateScope(scope, entry.props, state));
|
|
171
|
+
}
|
|
172
|
+
if (slot.current === entry)
|
|
173
|
+
throw new Error("Updated Meeko component did not register its hydrated instance");
|
|
174
|
+
committed.push(item);
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
const failures = [error];
|
|
178
|
+
rollback(item, failures);
|
|
179
|
+
for (const previous of committed.reverse())
|
|
180
|
+
rollback(previous, failures);
|
|
181
|
+
if (failures.length === 1)
|
|
182
|
+
throw error;
|
|
183
|
+
throw new AggregateError(failures, "Meeko hot replacement and recovery failed");
|
|
134
184
|
}
|
|
135
185
|
}
|
|
136
186
|
replaceHotStyle(id, component.css ?? "");
|
|
137
187
|
}
|
|
188
|
+
//# sourceMappingURL=hmr.js.map
|
package/dist/hmr.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hmr.js","sourceRoot":"","sources":["../src/hmr.ts"],"names":[],"mappings":"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","sourcesContent":["import { captureParentOwner, 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 withParent: <T>(work: () => T) => T;\n}\n\ninterface HotSlot {\n current: HotInstance;\n stop: () => void;\n forget: () => 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, withParent: captureParentOwner() };\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 forget: () => {\n if (group.get(key) !== slot) return;\n group.delete(key);\n if (group.size === 0) instances.delete(id);\n },\n stop: () => {\n if (group.get(key) !== slot) return;\n slot.forget();\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 // Module IDs are file paths and may contain CSS selector metacharacters.\n let style = [...document.querySelectorAll<HTMLStyleElement>(\"style[data-meeko-hot]\")]\n .find((candidate) => candidate.dataset.meekoHot === 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: entry.withParent(() => component.renderToString(entry.props, state)), previous };\n });\n type Prepared = (typeof prepared)[number];\n const committed: Prepared[] = [];\n const rollback = ({ slot, entry, state, previous }: Prepared, failures: unknown[]): void => {\n const partial = slot.current !== entry ? slot.current : undefined;\n if (partial) {\n try { partial.dispose(); }\n catch (cleanupError) { failures.push(cleanupError); }\n }\n try {\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\") {\n const { root } = entry.target;\n entry.withParent(() => entry.component.hydrate(root, entry.props, state));\n } else {\n const { scope } = entry.target;\n entry.withParent(() => entry.component.hydrateScope?.(scope, entry.props, state));\n }\n if (slot.current === entry || slot.current === partial) throw new Error(\"Restored Meeko component did not register its hydrated instance\");\n } catch (rollbackError) {\n failures.push(rollbackError);\n if (slot.current !== entry && slot.current !== partial) {\n try { slot.current.dispose(); }\n catch (cleanupError) { failures.push(cleanupError); }\n }\n slot.forget();\n }\n };\n for (const item of prepared) {\n const { slot, entry, state, html } = item;\n try {\n entry.dispose();\n if (entry.target.kind === \"root\") entry.target.root.innerHTML = html;\n else replaceScope(entry.target.scope, html);\n if (entry.target.kind === \"root\") {\n const { root } = entry.target;\n entry.withParent(() => component.hydrate(root, entry.props, state));\n }\n else {\n if (!component.hydrateScope) throw new Error(\"Updated Meeko child component has no hydrateScope export\");\n const { scope } = entry.target;\n entry.withParent(() => component.hydrateScope!(scope, entry.props, state));\n }\n if (slot.current === entry) throw new Error(\"Updated Meeko component did not register its hydrated instance\");\n committed.push(item);\n } catch (error) {\n const failures: unknown[] = [error];\n rollback(item, failures);\n for (const previous of committed.reverse()) rollback(previous, failures);\n if (failures.length === 1) throw error;\n throw new AggregateError(failures, \"Meeko hot replacement and recovery failed\");\n }\n }\n replaceHotStyle(id, component.css ?? \"\");\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
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
|
+
export { provideErrorHandler } from "./component-errors.js";
|
|
4
|
+
export type { ComponentErrorHandler } from "./component-errors.js";
|
|
3
5
|
export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
|
|
4
6
|
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
5
|
-
export type { ComponentModule, ComponentRelease, DomScope } from "./dom.js";
|
|
7
|
+
export type { Component, ComponentModule, ComponentRelease, DomScope } from "./dom.js";
|
|
6
8
|
export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
|
|
7
9
|
export type { HotComponent, HotState } from "./hmr.js";
|
|
8
10
|
export { registerDevtoolsInstance } from "./devtools.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
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
|
+
export { provideErrorHandler } from "./component-errors.js";
|
|
2
3
|
export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
|
|
3
4
|
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
4
5
|
export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
|
|
5
6
|
export { registerDevtoolsInstance } from "./devtools.js";
|
|
7
|
+
//# 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,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,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 { provideErrorHandler } from \"./component-errors.js\";\nexport type { ComponentErrorHandler } from \"./component-errors.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"]}
|