@fougere/core 0.3.0-alpha.0 → 0.4.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/README.md +1 -1
  2. package/dist/boot/HandlerFacade.js +2 -2
  3. package/dist/boot/HandlerFacade.js.map +1 -1
  4. package/dist/boot/apply.d.ts.map +1 -1
  5. package/dist/boot/apply.js +2 -12
  6. package/dist/boot/apply.js.map +1 -1
  7. package/dist/boot/binding.js +4 -4
  8. package/dist/boot/binding.js.map +1 -1
  9. package/dist/boot/boot.d.ts +1 -1
  10. package/dist/boot/boot.d.ts.map +1 -1
  11. package/dist/boot/bootstrap.d.ts.map +1 -1
  12. package/dist/boot/bootstrap.js +14 -13
  13. package/dist/boot/bootstrap.js.map +1 -1
  14. package/dist/boot/frame.d.ts +1 -1
  15. package/dist/boot/frame.d.ts.map +1 -1
  16. package/dist/boot/frame.js +5 -14
  17. package/dist/boot/frame.js.map +1 -1
  18. package/dist/boot/ownership.d.ts.map +1 -1
  19. package/dist/boot/ownership.js +5 -5
  20. package/dist/boot/ownership.js.map +1 -1
  21. package/dist/boot/remote.d.ts.map +1 -1
  22. package/dist/boot/remote.js +2 -2
  23. package/dist/boot/remote.js.map +1 -1
  24. package/dist/boot/together.d.ts.map +1 -1
  25. package/dist/boot/together.js +6 -6
  26. package/dist/boot/together.js.map +1 -1
  27. package/dist/boot/types.d.ts +2 -2
  28. package/dist/boot/types.d.ts.map +1 -1
  29. package/dist/contract.d.ts +1 -1
  30. package/dist/contract.d.ts.map +1 -1
  31. package/dist/contract.js +3 -3
  32. package/dist/contract.js.map +1 -1
  33. package/dist/dispatch/InFlight.d.ts.map +1 -1
  34. package/dist/dispatch/InFlight.js.map +1 -1
  35. package/dist/dispatch/InputValidator.d.ts.map +1 -1
  36. package/dist/dispatch/InputValidator.js +3 -2
  37. package/dist/dispatch/InputValidator.js.map +1 -1
  38. package/dist/dispatch/OutputProjector.js +2 -2
  39. package/dist/dispatch/OutputProjector.js.map +1 -1
  40. package/dist/dispatch/StorageGuard.d.ts.map +1 -1
  41. package/dist/dispatch/StorageGuard.js +2 -2
  42. package/dist/dispatch/StorageGuard.js.map +1 -1
  43. package/dist/effective-operation.js +4 -5
  44. package/dist/effective-operation.js.map +1 -1
  45. package/dist/emit.d.ts +2 -2
  46. package/dist/emit.d.ts.map +1 -1
  47. package/dist/emit.js +2 -2
  48. package/dist/emit.js.map +1 -1
  49. package/dist/identity.js +1 -1
  50. package/dist/identity.js.map +1 -1
  51. package/dist/imports.d.ts +1 -1
  52. package/dist/imports.d.ts.map +1 -1
  53. package/dist/imports.js.map +1 -1
  54. package/dist/orm.d.ts.map +1 -1
  55. package/dist/orm.js +4 -4
  56. package/dist/orm.js.map +1 -1
  57. package/dist/prefab/collector.js +2 -2
  58. package/dist/prefab/collector.js.map +1 -1
  59. package/dist/prefab/mirror.d.ts.map +1 -1
  60. package/dist/prefab/mirror.js +2 -2
  61. package/dist/prefab/mirror.js.map +1 -1
  62. package/dist/prefab/presenter.d.ts.map +1 -1
  63. package/dist/prefab/presenter.js +2 -2
  64. package/dist/prefab/presenter.js.map +1 -1
  65. package/dist/prefab/repository.d.ts.map +1 -1
  66. package/dist/prefab/repository.js +2 -2
  67. package/dist/prefab/repository.js.map +1 -1
  68. package/dist/scan/emit.d.ts.map +1 -1
  69. package/dist/scan/emit.js +3 -2
  70. package/dist/scan/emit.js.map +1 -1
  71. package/dist/scan/handler-parser.d.ts +2 -0
  72. package/dist/scan/handler-parser.d.ts.map +1 -1
  73. package/dist/scan/handler-parser.js +52 -12
  74. package/dist/scan/handler-parser.js.map +1 -1
  75. package/dist/scan/scanner.d.ts.map +1 -1
  76. package/dist/scan/scanner.js +37 -10
  77. package/dist/scan/scanner.js.map +1 -1
  78. package/dist/verify.js +2 -2
  79. package/dist/verify.js.map +1 -1
  80. package/dist/wire/call.d.ts +7 -7
  81. package/dist/wire/call.d.ts.map +1 -1
  82. package/dist/wire/call.js +6 -6
  83. package/dist/wire/call.js.map +1 -1
  84. package/package.json +6 -4
  85. package/src/boot/AppLifecycle.ts +50 -0
  86. package/src/boot/Emissions.ts +263 -0
  87. package/src/boot/HandlerFacade.ts +242 -0
  88. package/src/boot/Lifecycle.ts +3 -0
  89. package/src/boot/ambient-port.ts +41 -0
  90. package/src/boot/ambient.als.ts +43 -0
  91. package/src/boot/ambient.queue.ts +75 -0
  92. package/src/boot/apply.ts +47 -0
  93. package/src/boot/auth.ts +55 -0
  94. package/src/boot/binding.ts +182 -0
  95. package/src/boot/boot.ts +125 -0
  96. package/src/boot/bootstrap.ts +839 -0
  97. package/src/boot/frame.ts +210 -0
  98. package/src/boot/ownership.ts +140 -0
  99. package/src/boot/ports.ts +66 -0
  100. package/src/boot/remote.ts +179 -0
  101. package/src/boot/seed.ts +158 -0
  102. package/src/boot/together.ts +215 -0
  103. package/src/boot/types.ts +261 -0
  104. package/src/builtins/config.ts +19 -0
  105. package/src/builtins/logger.ts +175 -0
  106. package/src/config-loader.ts +146 -0
  107. package/src/contract/Call.ts +18 -0
  108. package/src/contract/Invocation.ts +72 -0
  109. package/src/contract/RouteAddress.ts +49 -0
  110. package/src/contract.ts +74 -0
  111. package/src/crypto/encoding.ts +59 -0
  112. package/src/crypto/node.ts +30 -0
  113. package/src/crypto/port.ts +45 -0
  114. package/src/crypto/webcrypto.ts +55 -0
  115. package/src/define.ts +10 -0
  116. package/src/dispatch/ArgumentResolver.ts +17 -0
  117. package/src/dispatch/ArrayResult.ts +10 -0
  118. package/src/dispatch/DispatchEvent.ts +38 -0
  119. package/src/dispatch/DispatchLifecycle.ts +23 -0
  120. package/src/dispatch/DispatchPort.ts +6 -0
  121. package/src/dispatch/Dispatcher.ts +48 -0
  122. package/src/dispatch/InFlight.ts +49 -0
  123. package/src/dispatch/InputValidator.ts +28 -0
  124. package/src/dispatch/LocalRoutePolicy.ts +34 -0
  125. package/src/dispatch/OperationExecutor.ts +60 -0
  126. package/src/dispatch/OperationRoute.ts +18 -0
  127. package/src/dispatch/OutputProjector.ts +32 -0
  128. package/src/dispatch/OutputView.ts +9 -0
  129. package/src/dispatch/PresenterArgumentResolver.ts +25 -0
  130. package/src/dispatch/PresenterExecutor.ts +55 -0
  131. package/src/dispatch/RemoteRouteResolver.ts +21 -0
  132. package/src/dispatch/Route.ts +11 -0
  133. package/src/dispatch/RouteNotFoundError.ts +29 -0
  134. package/src/dispatch/RoutePolicy.ts +8 -0
  135. package/src/dispatch/RouteRegistry.ts +73 -0
  136. package/src/dispatch/RouteResolver.ts +7 -0
  137. package/src/dispatch/StorageGuard.ts +71 -0
  138. package/src/effective-operation.ts +597 -0
  139. package/src/emit.ts +90 -0
  140. package/src/entry/DynamicFacade.ts +28 -0
  141. package/src/entry/FacadeEntry.ts +32 -0
  142. package/src/entry/TransportEntry.ts +30 -0
  143. package/src/frond-config.ts +138 -0
  144. package/src/graph.ts +180 -0
  145. package/src/identity-keys.ts +43 -0
  146. package/src/identity.ts +235 -0
  147. package/src/imports.ts +123 -0
  148. package/src/index.ts +106 -0
  149. package/src/loader.ts +41 -0
  150. package/src/node.ts +28 -0
  151. package/src/orm.ts +252 -0
  152. package/src/prefab/collector.ts +36 -0
  153. package/src/prefab/crud.ts +188 -0
  154. package/src/prefab/mirror.ts +122 -0
  155. package/src/prefab/prefab.ts +46 -0
  156. package/src/prefab/presenter.ts +63 -0
  157. package/src/prefab/repository.ts +170 -0
  158. package/src/scan/Fronds.ts +73 -0
  159. package/src/scan/conventions.ts +122 -0
  160. package/src/scan/emit.ts +231 -0
  161. package/src/scan/frond.ts +235 -0
  162. package/src/scan/handler-parser.ts +818 -0
  163. package/src/scan/scan-cache.ts +115 -0
  164. package/src/scan/scanner.ts +758 -0
  165. package/src/verify.ts +193 -0
  166. package/src/wire/call.ts +369 -0
  167. package/src/wire/errors.ts +124 -0
  168. package/src/wire/http-error.ts +77 -0
  169. package/src/wire/invocation.ts +10 -0
  170. package/src/wire/loggerMiddleware.ts +29 -0
  171. package/src/wire/middleware.ts +47 -0
  172. package/src/wire/operation.ts +258 -0
  173. package/dist/boot/egress.d.ts +0 -8
  174. package/dist/boot/egress.d.ts.map +0 -1
  175. package/dist/boot/egress.js +0 -11
  176. package/dist/boot/egress.js.map +0 -1
@@ -0,0 +1,115 @@
1
+ /**
2
+ * A parse kept per file, so an unchanged source never loads TypeScript again.
3
+ *
4
+ * The envelope carries PARSER_VERSION, and a mismatch drops the whole file. The hash
5
+ * answers "did this source change?"; it cannot answer "does the parser still read it the
6
+ * same way?". A parser fix therefore left every unchanged handler serving the OLD parse,
7
+ * indefinitely and without a word — that is how `Crud`'s inherited ops stayed silently
8
+ * underived for weeks, until someone deleted `.fougere/` by hand and the tests went red.
9
+ *
10
+ * Bump PARSER_VERSION whenever the parser's OUTPUT for unchanged source can differ.
11
+ */
12
+ import { createHash } from 'node:crypto';
13
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
14
+ import { join } from 'node:path';
15
+
16
+ /**
17
+ * Bump when the parser can read unchanged source differently.
18
+ *
19
+ * 2 — `handler-parser` unwraps a class returned through a call/assertion, so a mixin
20
+ * like `asCrudConstructor(class { … })` yields its methods again.
21
+ * 3 — parsed array types carry `arrayDepth`, used to distinguish a presenter page
22
+ * returning scalar fields from one returning list fields.
23
+ */
24
+ // 4 — the parse became a pair (methods + unresolvedHeritage); a v3 entry
25
+ // would answer with an array and lose the half that reports what it could not open.
26
+ // 5 — a method carried `readOnly`, read off its body. REMOVED (2026-08-16): it answered
27
+ // "does this touch storage", not "is this a read", so a read that wrote an audit row
28
+ // was published as a mutation. The number stays taken; going back to 4 would revive
29
+ // a v4 cache written before 5, which is the same shape but not the same history.
30
+ // 7 — parsed types carry checked, alias-resolved meaning and distinguish `undefined`
31
+ // from `null`; a v6 entry contains only the syntax that happened to be written.
32
+ const PARSER_VERSION = 7;
33
+
34
+ interface CacheEntry {
35
+ hash: string;
36
+ data: unknown;
37
+ }
38
+
39
+ interface CacheFile {
40
+ parser: number;
41
+ entries: Record<string, CacheEntry>;
42
+ }
43
+
44
+ type CacheData = Record<string, CacheEntry>;
45
+
46
+ let root = process.cwd();
47
+ let cache: CacheData | null = null;
48
+ let dirty = false;
49
+
50
+ function cachePath(): string {
51
+ return join(root, '.fougere', 'scan-cache.json');
52
+ }
53
+
54
+ export function setCacheRoot(dir: string): void {
55
+ root = dir;
56
+ cache = null;
57
+ }
58
+
59
+ function load(): CacheData {
60
+ if (cache) return cache;
61
+ const path = cachePath();
62
+ if (existsSync(path)) {
63
+ try {
64
+ const file = JSON.parse(readFileSync(path, 'utf-8')) as Partial<CacheFile>;
65
+ // A stamp from another parser is not stale data to refresh entry by entry — every
66
+ // entry in the file was produced by it. Drop the lot; the next scan is cold once.
67
+ if (file.parser === PARSER_VERSION && file.entries) {
68
+ cache = file.entries;
69
+ return cache;
70
+ }
71
+ } catch {
72
+ // Corrupted cache — start fresh
73
+ }
74
+ }
75
+ cache = {};
76
+ return cache;
77
+ }
78
+
79
+ function hashFile(filePath: string): string {
80
+ const content = readFileSync(filePath, 'utf-8');
81
+ return createHash('sha1').update(content).digest('hex').slice(0, 16);
82
+ }
83
+
84
+ /**
85
+ * The parse of a file, or the parse again if the file changed — the one gesture, so a
86
+ * caller never assembles the pieces.
87
+ *
88
+ * It handed out `hashFile` + `getCached` + `setCached` and every caller wrote the same
89
+ * five lines in the same order; the scanner wrote them three times, once inline inside a
90
+ * `try`. Three assemblies of one question, each free to forget the half that stores.
91
+ *
92
+ * `key` and not the path alone: one file is parsed several ways (its constructor, its
93
+ * methods, its methods with heritage resolved) and each reading is its own entry.
94
+ */
95
+ export async function cachedParse<T>(key: string, filePath: string, parse: () => Promise<T>): Promise<T> {
96
+ const hash = hashFile(filePath);
97
+ const store = load();
98
+ const entry = store[key];
99
+ if (entry && entry.hash === hash) return entry.data as T;
100
+
101
+ const data = await parse();
102
+ store[key] = { hash, data };
103
+ dirty = true;
104
+ return data;
105
+ }
106
+
107
+ /** Write cache to disk if modified. */
108
+ export function flushCache(): void {
109
+ if (!dirty || !cache) return;
110
+ const path = cachePath();
111
+ mkdirSync(join(root, '.fougere'), { recursive: true });
112
+ const file: CacheFile = { parser: PARSER_VERSION, entries: cache };
113
+ writeFileSync(path, JSON.stringify(file, null, 2));
114
+ dirty = false;
115
+ }