@mionjs/router 0.8.6 → 0.8.8

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 (141) hide show
  1. package/.dist/cjs/index.d.ts +1 -0
  2. package/.dist/cjs/index.d.ts.map +1 -0
  3. package/.dist/cjs/src/aot/aotCacheLoader.d.ts +1 -0
  4. package/.dist/cjs/src/aot/aotCacheLoader.d.ts.map +1 -0
  5. package/.dist/cjs/src/callContext.d.ts +1 -0
  6. package/.dist/cjs/src/callContext.d.ts.map +1 -0
  7. package/.dist/cjs/src/constants.d.ts +1 -0
  8. package/.dist/cjs/src/constants.d.ts.map +1 -0
  9. package/.dist/cjs/src/defaultRoutes.d.ts +1 -0
  10. package/.dist/cjs/src/defaultRoutes.d.ts.map +1 -0
  11. package/.dist/cjs/src/dispatch.d.ts +1 -0
  12. package/.dist/cjs/src/dispatch.d.ts.map +1 -0
  13. package/.dist/cjs/src/lib/aotEmitter.d.ts +1 -0
  14. package/.dist/cjs/src/lib/aotEmitter.d.ts.map +1 -0
  15. package/.dist/cjs/src/lib/dispatchError.d.ts +1 -0
  16. package/.dist/cjs/src/lib/dispatchError.d.ts.map +1 -0
  17. package/.dist/cjs/src/lib/handlers.d.ts +1 -0
  18. package/.dist/cjs/src/lib/handlers.d.ts.map +1 -0
  19. package/.dist/cjs/src/lib/headers.d.ts +1 -0
  20. package/.dist/cjs/src/lib/headers.d.ts.map +1 -0
  21. package/.dist/cjs/src/lib/methodsCache.d.ts +1 -0
  22. package/.dist/cjs/src/lib/methodsCache.d.ts.map +1 -0
  23. package/.dist/cjs/src/lib/queryBody.d.ts +1 -0
  24. package/.dist/cjs/src/lib/queryBody.d.ts.map +1 -0
  25. package/.dist/cjs/src/lib/reflection.d.ts +1 -0
  26. package/.dist/cjs/src/lib/reflection.d.ts.map +1 -0
  27. package/.dist/cjs/src/lib/remoteMethods.d.ts +1 -0
  28. package/.dist/cjs/src/lib/remoteMethods.d.ts.map +1 -0
  29. package/.dist/cjs/src/lib/test/aotEmitter-test-router.d.ts +1 -0
  30. package/.dist/cjs/src/lib/test/aotEmitter-test-router.d.ts.map +1 -0
  31. package/.dist/cjs/src/router.d.ts +1 -0
  32. package/.dist/cjs/src/router.d.ts.map +1 -0
  33. package/.dist/cjs/src/routes/client.routes.d.ts +1 -0
  34. package/.dist/cjs/src/routes/client.routes.d.ts.map +1 -0
  35. package/.dist/cjs/src/routes/errors.routes.d.ts +1 -0
  36. package/.dist/cjs/src/routes/errors.routes.d.ts.map +1 -0
  37. package/.dist/cjs/src/routes/mion.routes.d.ts +1 -0
  38. package/.dist/cjs/src/routes/mion.routes.d.ts.map +1 -0
  39. package/.dist/cjs/src/routes/serializer.routes.d.ts +1 -0
  40. package/.dist/cjs/src/routes/serializer.routes.d.ts.map +1 -0
  41. package/.dist/cjs/src/routesFlow.d.ts +1 -0
  42. package/.dist/cjs/src/routesFlow.d.ts.map +1 -0
  43. package/.dist/cjs/src/types/context.d.ts +1 -0
  44. package/.dist/cjs/src/types/context.d.ts.map +1 -0
  45. package/.dist/cjs/src/types/definitions.d.ts +1 -0
  46. package/.dist/cjs/src/types/definitions.d.ts.map +1 -0
  47. package/.dist/cjs/src/types/general.d.ts +1 -0
  48. package/.dist/cjs/src/types/general.d.ts.map +1 -0
  49. package/.dist/cjs/src/types/guards.d.ts +1 -0
  50. package/.dist/cjs/src/types/guards.d.ts.map +1 -0
  51. package/.dist/cjs/src/types/handlers.d.ts +1 -0
  52. package/.dist/cjs/src/types/handlers.d.ts.map +1 -0
  53. package/.dist/cjs/src/types/publicMethods.d.ts +1 -0
  54. package/.dist/cjs/src/types/publicMethods.d.ts.map +1 -0
  55. package/.dist/cjs/src/types/remoteMethods.d.ts +1 -0
  56. package/.dist/cjs/src/types/remoteMethods.d.ts.map +1 -0
  57. package/.dist/esm/index.d.ts +1 -0
  58. package/.dist/esm/index.d.ts.map +1 -0
  59. package/.dist/esm/src/aot/aotCacheLoader.d.ts +1 -0
  60. package/.dist/esm/src/aot/aotCacheLoader.d.ts.map +1 -0
  61. package/.dist/esm/src/callContext.d.ts +1 -0
  62. package/.dist/esm/src/callContext.d.ts.map +1 -0
  63. package/.dist/esm/src/constants.d.ts +1 -0
  64. package/.dist/esm/src/constants.d.ts.map +1 -0
  65. package/.dist/esm/src/defaultRoutes.d.ts +1 -0
  66. package/.dist/esm/src/defaultRoutes.d.ts.map +1 -0
  67. package/.dist/esm/src/dispatch.d.ts +1 -0
  68. package/.dist/esm/src/dispatch.d.ts.map +1 -0
  69. package/.dist/esm/src/lib/aotEmitter.d.ts +1 -0
  70. package/.dist/esm/src/lib/aotEmitter.d.ts.map +1 -0
  71. package/.dist/esm/src/lib/dispatchError.d.ts +1 -0
  72. package/.dist/esm/src/lib/dispatchError.d.ts.map +1 -0
  73. package/.dist/esm/src/lib/handlers.d.ts +1 -0
  74. package/.dist/esm/src/lib/handlers.d.ts.map +1 -0
  75. package/.dist/esm/src/lib/headers.d.ts +1 -0
  76. package/.dist/esm/src/lib/headers.d.ts.map +1 -0
  77. package/.dist/esm/src/lib/methodsCache.d.ts +1 -0
  78. package/.dist/esm/src/lib/methodsCache.d.ts.map +1 -0
  79. package/.dist/esm/src/lib/queryBody.d.ts +1 -0
  80. package/.dist/esm/src/lib/queryBody.d.ts.map +1 -0
  81. package/.dist/esm/src/lib/reflection.d.ts +1 -0
  82. package/.dist/esm/src/lib/reflection.d.ts.map +1 -0
  83. package/.dist/esm/src/lib/remoteMethods.d.ts +1 -0
  84. package/.dist/esm/src/lib/remoteMethods.d.ts.map +1 -0
  85. package/.dist/esm/src/lib/test/aotEmitter-test-router.d.ts +1 -0
  86. package/.dist/esm/src/lib/test/aotEmitter-test-router.d.ts.map +1 -0
  87. package/.dist/esm/src/router.d.ts +1 -0
  88. package/.dist/esm/src/router.d.ts.map +1 -0
  89. package/.dist/esm/src/routes/client.routes.d.ts +1 -0
  90. package/.dist/esm/src/routes/client.routes.d.ts.map +1 -0
  91. package/.dist/esm/src/routes/errors.routes.d.ts +1 -0
  92. package/.dist/esm/src/routes/errors.routes.d.ts.map +1 -0
  93. package/.dist/esm/src/routes/mion.routes.d.ts +1 -0
  94. package/.dist/esm/src/routes/mion.routes.d.ts.map +1 -0
  95. package/.dist/esm/src/routes/serializer.routes.d.ts +1 -0
  96. package/.dist/esm/src/routes/serializer.routes.d.ts.map +1 -0
  97. package/.dist/esm/src/routesFlow.d.ts +1 -0
  98. package/.dist/esm/src/routesFlow.d.ts.map +1 -0
  99. package/.dist/esm/src/types/context.d.ts +1 -0
  100. package/.dist/esm/src/types/context.d.ts.map +1 -0
  101. package/.dist/esm/src/types/definitions.d.ts +1 -0
  102. package/.dist/esm/src/types/definitions.d.ts.map +1 -0
  103. package/.dist/esm/src/types/general.d.ts +1 -0
  104. package/.dist/esm/src/types/general.d.ts.map +1 -0
  105. package/.dist/esm/src/types/guards.d.ts +1 -0
  106. package/.dist/esm/src/types/guards.d.ts.map +1 -0
  107. package/.dist/esm/src/types/handlers.d.ts +1 -0
  108. package/.dist/esm/src/types/handlers.d.ts.map +1 -0
  109. package/.dist/esm/src/types/publicMethods.d.ts +1 -0
  110. package/.dist/esm/src/types/publicMethods.d.ts.map +1 -0
  111. package/.dist/esm/src/types/remoteMethods.d.ts +1 -0
  112. package/.dist/esm/src/types/remoteMethods.d.ts.map +1 -0
  113. package/index.ts +29 -0
  114. package/package.json +9 -5
  115. package/src/aot/aotCacheLoader.ts +15 -0
  116. package/src/callContext.ts +193 -0
  117. package/src/constants.ts +45 -0
  118. package/src/defaultRoutes.ts +37 -0
  119. package/src/dispatch.ts +204 -0
  120. package/src/lib/aotEmitter.ts +140 -0
  121. package/src/lib/dispatchError.ts +60 -0
  122. package/src/lib/handlers.ts +75 -0
  123. package/src/lib/headers.ts +102 -0
  124. package/src/lib/methodsCache.ts +72 -0
  125. package/src/lib/queryBody.ts +40 -0
  126. package/src/lib/reflection.ts +517 -0
  127. package/src/lib/remoteMethods.ts +180 -0
  128. package/src/lib/test/aotEmitter-test-router.ts +40 -0
  129. package/src/router.ts +656 -0
  130. package/src/routes/client.routes.ts +108 -0
  131. package/src/routes/errors.routes.ts +51 -0
  132. package/src/routes/mion.routes.ts +11 -0
  133. package/src/routes/serializer.routes.ts +225 -0
  134. package/src/routesFlow.ts +320 -0
  135. package/src/types/context.ts +119 -0
  136. package/src/types/definitions.ts +53 -0
  137. package/src/types/general.ts +84 -0
  138. package/src/types/guards.ts +71 -0
  139. package/src/types/handlers.ts +49 -0
  140. package/src/types/publicMethods.ts +83 -0
  141. package/src/types/remoteMethods.ts +54 -0
@@ -0,0 +1,180 @@
1
+ /* ########
2
+ * 2023 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ import {type RouterEntry, type Routes} from '../types/general.ts';
9
+ import {type RemoteMethod} from '../types/remoteMethods.ts';
10
+ import type {PublicApi} from '../types/publicMethods.ts';
11
+ import type {
12
+ AnyObject,
13
+ JitCompiledFn,
14
+ JitCompiledFnData,
15
+ PureFunctionData,
16
+ MethodWithOptions,
17
+ PureFnsDataCache,
18
+ } from '@mionjs/core';
19
+ import {isRoute, isHeadersMiddleFnDef, isMiddleFnDef} from '../types/guards.ts';
20
+ import {getMiddleFnExecutable, getRouteExecutable, isPrivateDefinition} from '../router.ts';
21
+ import {getRouterItemId, MAX_STACK_DEPTH, getJitFnHashes, getJitUtils, EMPTY_HASH} from '@mionjs/core';
22
+
23
+ // ############# PRIVATE STATE #############
24
+ const publicMethods: Map<string, MethodWithOptions> = new Map();
25
+
26
+ // ############# PUBLIC METHODS #############
27
+ export function resetRemoteMethodsMetadata() {
28
+ publicMethods.clear();
29
+ }
30
+
31
+ /**
32
+ * Returns a data structure containing all public information and types of the routes.
33
+ * This data and types can be used to generate router clients, etc...
34
+ */
35
+ export function getPublicApi<R extends Routes>(routes: R): PublicApi<R> {
36
+ return recursiveGetSerializableRoutes(routes) as PublicApi<R>;
37
+ }
38
+
39
+ // ############# PRIVATE METHODS #############
40
+
41
+ function recursiveGetSerializableRoutes<R extends Routes>(
42
+ routes: R,
43
+ currentPointer: string[] = [],
44
+ publicData: AnyObject = {}
45
+ ): AnyObject {
46
+ const entries = Object.entries(routes);
47
+ entries.forEach(([key, item]: [string, RouterEntry]) => {
48
+ const itemPointer = [...currentPointer, key];
49
+ const id = getRouterItemId(itemPointer);
50
+
51
+ if (isPrivateDefinition(item, id)) {
52
+ publicData[key] = null; // middleFns that don't receive or return data are not public
53
+ } else if (isMiddleFnDef(item) || isHeadersMiddleFnDef(item) || isRoute(item)) {
54
+ const executable = getMiddleFnExecutable(id) || getRouteExecutable(id);
55
+ if (!executable)
56
+ throw new Error(`Route or MiddleFn ${id} not found. Please check you have called router.registerRoutes first.`);
57
+ publicData[key] = getSerializableMethod(executable as RemoteMethod);
58
+ } else {
59
+ const subRoutes: Routes = routes[key] as Routes;
60
+ publicData[key] = recursiveGetSerializableRoutes(subRoutes, itemPointer);
61
+ }
62
+ });
63
+
64
+ return publicData;
65
+ }
66
+
67
+ export function getSerializableMethod(executable: RemoteMethod): MethodWithOptions {
68
+ const existing = publicMethods.get(executable.id);
69
+ if (existing) return existing as MethodWithOptions;
70
+
71
+ const newRemoteMethod: MethodWithOptions = {
72
+ type: executable.type,
73
+ id: executable.id,
74
+ nestLevel: executable.nestLevel,
75
+ isAsync: executable.isAsync,
76
+ hasReturnData: executable.hasReturnData,
77
+ paramsJitHash: executable.paramsJitHash,
78
+ returnJitHash: executable.returnJitHash,
79
+ pointer: executable.pointer,
80
+ ...(executable.paramNames ? {paramNames: executable.paramNames} : {}),
81
+ options: executable.options,
82
+ };
83
+ if (executable.headersParam) newRemoteMethod.headersParam = executable.headersParam;
84
+ if (executable.middleFnIds) newRemoteMethod.middleFnIds = executable.middleFnIds;
85
+ publicMethods.set(executable.id, newRemoteMethod);
86
+ return newRemoteMethod as MethodWithOptions;
87
+ }
88
+
89
+ /** Serializes pure function dependencies into a namespaced cache structure.
90
+ * @param namespacedDepHash - Pure function dependency in format "namespace::fnHash"
91
+ * @param purFnDeps - Namespaced cache to store serialized pure functions
92
+ * @param depth - Current recursion depth for stack overflow protection
93
+ */
94
+ export function serializePureDeps(namespacedDepHash: string, purFnDeps: PureFnsDataCache, depth = 0) {
95
+ if (depth >= MAX_STACK_DEPTH)
96
+ throw new Error(`Max depth reached serializing pure function dependencies, for: ${namespacedDepHash}`);
97
+ // Parse "namespace::fnHash" format
98
+ const parts = namespacedDepHash.split('::');
99
+ if (parts.length !== 2)
100
+ throw new Error(`Invalid pure function dependency format: ${namespacedDepHash}, expected "namespace::fnHash"`);
101
+ const [namespace, fnHash] = parts;
102
+ // Ensure namespace exists in the cache
103
+ if (!purFnDeps[namespace]) purFnDeps[namespace] = {};
104
+ // Check if already serialized (prevent infinite recursion on circular dependencies)
105
+ if (purFnDeps[namespace][fnHash]) return;
106
+ const pureDep = getJitUtils().getCompiledPureFn(namespace, fnHash);
107
+ if (!pureDep) throw new Error(`Pure function ${fnHash} not found in namespace ${namespace}`);
108
+ const serializedPureDep: PureFunctionData = {
109
+ ...pureDep,
110
+ pureFnDependencies: pureDep.pureFnDependencies ? [...pureDep.pureFnDependencies] : undefined,
111
+ };
112
+ purFnDeps[namespace][fnHash] = serializedPureDep;
113
+ // Dependencies within the same namespace are stored as just fnHash, not namespaced
114
+ pureDep.pureFnDependencies?.forEach((depFnHash) => serializePureDeps(`${namespace}::${depFnHash}`, purFnDeps, depth + 1));
115
+ }
116
+
117
+ export function serializeJitFn(
118
+ jitFnHash: string,
119
+ deps: Record<string, JitCompiledFnData>,
120
+ purFnDeps: PureFnsDataCache,
121
+ depth = 0
122
+ ) {
123
+ if (depth >= MAX_STACK_DEPTH)
124
+ throw new Error(`Max depth reached serializing jit function dependencies for jitHash: ${jitFnHash}`);
125
+ const jitFn = getJitUtils().getJIT(jitFnHash);
126
+ if (!jitFn) throw new Error(`Jit function ${jitFnHash} not found`);
127
+ if (deps[jitFnHash]) return; // already serialized and prevent infinite recursion on circular dependencies
128
+ const serializedJitFn = getSerializableJitCompiler(jitFn);
129
+ deps[jitFnHash] = serializedJitFn;
130
+ jitFn.jitDependencies?.forEach((h) => serializeJitFn(h, deps, purFnDeps, depth + 1));
131
+ jitFn.pureFnDependencies?.forEach((h) => serializePureDeps(h, purFnDeps));
132
+ }
133
+
134
+ export function serializeMethodDeps(
135
+ method: MethodWithOptions,
136
+ deps: Record<string, JitCompiledFnData>,
137
+ purFnDeps: PureFnsDataCache
138
+ ) {
139
+ const {paramsJitHash, returnJitHash} = method;
140
+ // Skip serialization for empty hashes (no params or void return)
141
+ // Always request binary hashes so they are included when available (e.g. middleware in binary routes).
142
+ // serializeJitFn is only called when the JIT function exists in the store, so non-binary methods are unaffected.
143
+ if (paramsJitHash !== EMPTY_HASH) {
144
+ const paramsJitHashes = getJitFnHashes(paramsJitHash, true);
145
+ for (const k in paramsJitHashes) {
146
+ if (getJitUtils().getJIT(paramsJitHashes[k])) serializeJitFn(paramsJitHashes[k], deps, purFnDeps);
147
+ }
148
+ }
149
+ if (returnJitHash !== EMPTY_HASH) {
150
+ const returnJitHashes = getJitFnHashes(returnJitHash, true);
151
+ let foundAny = false;
152
+ for (const k in returnJitHashes) {
153
+ if (getJitUtils().getJIT(returnJitHashes[k])) {
154
+ serializeJitFn(returnJitHashes[k], deps, purFnDeps);
155
+ foundAny = true;
156
+ }
157
+ }
158
+ if (!foundAny) {
159
+ throw new Error(
160
+ `Method "${method.id}" declares returnJitHash="${returnJitHash}" but no JIT functions are registered under that hash. ` +
161
+ `This usually means a Promise/Function return type was not unwrapped before computing the hash.`
162
+ );
163
+ }
164
+ }
165
+ }
166
+
167
+ function getSerializableJitCompiler(comp: JitCompiledFn): JitCompiledFnData {
168
+ return {
169
+ typeName: comp.typeName,
170
+ fnID: comp.fnID,
171
+ jitFnHash: comp.jitFnHash,
172
+ args: structuredClone(comp.args),
173
+ isNoop: comp.isNoop,
174
+ defaultParamValues: structuredClone(comp.defaultParamValues),
175
+ code: comp.code,
176
+ jitDependencies: comp.jitDependencies ? [...comp.jitDependencies] : undefined,
177
+ pureFnDependencies: comp.pureFnDependencies ? [...comp.pureFnDependencies] : undefined,
178
+ ...(comp.paramNames ? {paramNames: [...comp.paramNames]} : {}),
179
+ };
180
+ }
@@ -0,0 +1,40 @@
1
+ /* ########
2
+ * 2025 mion
3
+ * Author: Ma-jerez
4
+ * License: MIT
5
+ * The software is provided "as is", without warranty of any kind.
6
+ * ######## */
7
+
8
+ /**
9
+ * Test router script for AOT emitter tests.
10
+ * This script is spawned as a child process with MION_COMPILE=buildOnly
11
+ * to test that emitAOTCaches() correctly sends IPC messages.
12
+ *
13
+ * Uses initMionRouter which automatically calls emitAOTCaches() when MION_COMPILE=buildOnly.
14
+ */
15
+
16
+ import {initMionRouter, route, middleFn, Routes, PublicApi} from '@mionjs/router';
17
+
18
+ interface User {
19
+ id: string;
20
+ name: string;
21
+ }
22
+
23
+ const routes = {
24
+ users: {
25
+ getUser: route((ctx, id: string): User => ({id, name: 'Test User'})),
26
+ createUser: route((ctx, user: User): string => `Created user ${user.name}`),
27
+ },
28
+ utils: {
29
+ sum: route((ctx, a: number, b: number): number => a + b),
30
+ },
31
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
32
+ log: middleFn((ctx): void => {
33
+ // Log middleFn
34
+ }),
35
+ } satisfies Routes;
36
+
37
+ // Initialize the router - this will call emitAOTCaches() automatically when MION_COMPILE=buildOnly
38
+ export const testApiPromise: Promise<PublicApi<typeof routes>> = initMionRouter(routes, {basePath: 'api/v1'});
39
+
40
+ export {routes};