akanjs 3.0.0-alpha.71 → 3.0.0-alpha.73

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 (188) hide show
  1. package/client/cookie.ts +21 -34
  2. package/client/csrTypes.ts +0 -12
  3. package/client/frameConfig.ts +13 -0
  4. package/common/Logger.ts +13 -6
  5. package/common/TrustedProxy.ts +134 -0
  6. package/common/clamp.ts +2 -0
  7. package/common/dynamicRecord.ts +12 -0
  8. package/common/index.ts +5 -1
  9. package/common/isValidDate.ts +1 -1
  10. package/common/requestOrigin.ts +32 -0
  11. package/common/{httpClient.ts → restClient.ts} +16 -9
  12. package/constant/types.ts +22 -0
  13. package/dictionary/base.dictionary.ts +4 -0
  14. package/dictionary/trans.ts +24 -5
  15. package/document/dataLoader.ts +0 -4
  16. package/document/filterMeta.ts +2 -2
  17. package/document/loaderInfo.ts +4 -1
  18. package/fetch/client/fetchClient.ts +65 -88
  19. package/fetch/client/fetchHandle.ts +57 -0
  20. package/fetch/client/httpClient.ts +42 -14
  21. package/fetch/client/sliceInitHandle.ts +101 -0
  22. package/fetch/fetchType/appliedReturn.type.ts +64 -1
  23. package/fetch/fetchType/sliceFetch.type.ts +5 -5
  24. package/fetch/requestStorage.ts +19 -5
  25. package/index.ts +16 -2
  26. package/local/apps/serverLifecycle/serverLifecycle-local.db-shm +0 -0
  27. package/local/apps/serverLifecycle/serverLifecycle-local_solid.db-shm +0 -0
  28. package/package.json +1 -1
  29. package/server/akanApp.ts +3 -19
  30. package/server/akanAppHeaders.ts +10 -4
  31. package/server/akanOption.ts +14 -1
  32. package/server/akanServer.ts +3 -0
  33. package/server/cachePolicy.ts +2 -11
  34. package/server/decorators.ts +12 -3
  35. package/server/devtools/constantSerializer.ts +8 -1
  36. package/server/di/diLifecycle.ts +21 -1
  37. package/server/di/resolveHierarchy.ts +3 -3
  38. package/server/imageOptimizer.ts +2 -17
  39. package/server/mcp/McpDispatcher.ts +8 -2
  40. package/server/resolver/database.resolver.ts +13 -8
  41. package/server/resolver/signal.resolver.ts +3 -3
  42. package/server/routeTreeBuilder.ts +1 -15
  43. package/server/routing/apiRouter.ts +4 -5
  44. package/server/routing/appWsData.ts +9 -6
  45. package/server/staticPath.ts +34 -0
  46. package/server/webRouter.ts +35 -41
  47. package/service/adapt.ts +1 -5
  48. package/service/predefinedAdaptor/cache.adaptor.ts +8 -4
  49. package/service/predefinedAdaptor/database.adaptor.ts +37 -1766
  50. package/service/predefinedAdaptor/sql/PendingStoreEnsures.ts +22 -0
  51. package/service/predefinedAdaptor/sql/QueryCompiler.ts +225 -0
  52. package/service/predefinedAdaptor/sql/SqlDocumentStore.ts +812 -0
  53. package/service/predefinedAdaptor/sql/UpdateCompiler.ts +67 -0
  54. package/service/predefinedAdaptor/sql/dialect/postgres.ts +151 -0
  55. package/service/predefinedAdaptor/sql/dialect/sqlite.ts +134 -0
  56. package/service/predefinedAdaptor/sql/driver/bunSqlite.ts +29 -0
  57. package/service/predefinedAdaptor/sql/driver/libsql.ts +37 -0
  58. package/service/predefinedAdaptor/sql/driver/postgres.ts +42 -0
  59. package/service/predefinedAdaptor/sql/types.ts +251 -0
  60. package/service/predefinedAdaptor/sql/values.ts +91 -0
  61. package/signal/CrossSiteGuard.ts +71 -0
  62. package/signal/SignalFailure.ts +51 -0
  63. package/signal/endpoint.ts +2 -2
  64. package/signal/exception.ts +43 -6
  65. package/signal/index.ts +2 -0
  66. package/signal/intercept.ts +5 -2
  67. package/signal/internal.ts +10 -2
  68. package/signal/serializer/fetch.serializer.ts +11 -1
  69. package/signal/signalContext.ts +25 -28
  70. package/signal/slice.ts +1 -1
  71. package/store/SliceRequest.ts +23 -0
  72. package/store/action.ts +177 -114
  73. package/store/agent/AgentBridge.ts +3 -1
  74. package/store/agentic/StExposeBuilder.ts +7 -4
  75. package/store/agentic/StStateBuilder.ts +9 -4
  76. package/store/agentic/StToolBuilder.ts +21 -7
  77. package/store/store.ts +1 -1
  78. package/store/storeInstance.ts +3 -3
  79. package/store/storeRegistry.ts +1 -1
  80. package/types/client/cookie.d.ts +13 -2
  81. package/types/client/csrTypes.d.ts +0 -1
  82. package/types/client/frameConfig.d.ts +1 -0
  83. package/types/common/TrustedProxy.d.ts +24 -0
  84. package/types/common/clamp.d.ts +2 -0
  85. package/types/common/dynamicRecord.d.ts +14 -0
  86. package/types/common/index.d.ts +5 -1
  87. package/types/common/requestOrigin.d.ts +14 -0
  88. package/types/common/restClient.d.ts +27 -0
  89. package/types/constant/types.d.ts +13 -0
  90. package/types/dictionary/base.dictionary.d.ts +1 -1
  91. package/types/dictionary/dictionary.d.ts +8 -8
  92. package/types/document/dataLoader.d.ts +0 -3
  93. package/types/document/filterMeta.d.ts +2 -2
  94. package/types/document/loaderInfo.d.ts +2 -2
  95. package/types/fetch/client/fetchHandle.d.ts +24 -0
  96. package/types/fetch/client/httpClient.d.ts +2 -0
  97. package/types/fetch/client/sliceInitHandle.d.ts +29 -0
  98. package/types/fetch/fetchType/appliedReturn.type.d.ts +38 -1
  99. package/types/fetch/fetchType/sliceFetch.type.d.ts +5 -5
  100. package/types/fetch/requestStorage.d.ts +14 -0
  101. package/types/index.d.ts +17 -2
  102. package/types/server/akanOption.d.ts +8 -1
  103. package/types/server/decorators.d.ts +12 -2
  104. package/types/server/di/diLifecycle.d.ts +9 -1
  105. package/types/server/routeTreeBuilder.d.ts +1 -2
  106. package/types/server/routing/appWsData.d.ts +7 -3
  107. package/types/server/staticPath.d.ts +17 -0
  108. package/types/service/adapt.d.ts +1 -1
  109. package/types/service/predefinedAdaptor/database.adaptor.d.ts +15 -407
  110. package/types/service/predefinedAdaptor/sql/PendingStoreEnsures.d.ts +6 -0
  111. package/types/service/predefinedAdaptor/sql/QueryCompiler.d.ts +28 -0
  112. package/types/service/predefinedAdaptor/sql/SqlDocumentStore.d.ts +127 -0
  113. package/types/service/predefinedAdaptor/sql/UpdateCompiler.d.ts +17 -0
  114. package/types/service/predefinedAdaptor/sql/dialect/postgres.d.ts +27 -0
  115. package/types/service/predefinedAdaptor/sql/dialect/sqlite.d.ts +27 -0
  116. package/types/service/predefinedAdaptor/sql/driver/bunSqlite.d.ts +16 -0
  117. package/types/service/predefinedAdaptor/sql/driver/libsql.d.ts +17 -0
  118. package/types/service/predefinedAdaptor/sql/driver/postgres.d.ts +17 -0
  119. package/types/service/predefinedAdaptor/sql/types.d.ts +226 -0
  120. package/types/service/predefinedAdaptor/sql/values.d.ts +13 -0
  121. package/types/signal/CrossSiteGuard.d.ts +44 -0
  122. package/types/signal/SignalFailure.d.ts +28 -0
  123. package/types/signal/exception.d.ts +38 -54774
  124. package/types/signal/index.d.ts +2 -0
  125. package/types/signal/intercept.d.ts +3 -3
  126. package/types/signal/internal.d.ts +5 -1
  127. package/types/signal/serializer/fetch.serializer.d.ts +7 -1
  128. package/types/store/SliceRequest.d.ts +16 -0
  129. package/types/store/agentic/StToolBuilder.d.ts +10 -1
  130. package/types/ui/Agent/Menu.d.ts +1 -1
  131. package/types/ui/Field/Choice.d.ts +52 -0
  132. package/types/ui/Field/Collection.d.ts +51 -0
  133. package/types/ui/Field/DateField.d.ts +32 -0
  134. package/types/ui/Field/Label.d.ts +9 -0
  135. package/types/ui/Field/NumberField.d.ts +43 -0
  136. package/types/ui/Field/Relation.d.ts +80 -0
  137. package/types/ui/Field/Text.d.ts +101 -0
  138. package/types/ui/Field/index.d.ts +50 -0
  139. package/types/ui/Field.d.ts +1 -412
  140. package/types/ui/Load/Edit_Client.d.ts +3 -1
  141. package/types/ui/Load/Stream.d.ts +22 -0
  142. package/types/ui/Load/index.d.ts +2 -0
  143. package/types/ui/System/Root.d.ts +4 -0
  144. package/types/ui/index.d.ts +1 -1
  145. package/types/ui/recipe/badgeRecipe.d.ts +2 -2
  146. package/types/ui/recipe/buttonRecipe.d.ts +2 -2
  147. package/types/webkit/useCamera.d.ts +10 -1
  148. package/types/webkit/usePurchase.d.ts +4 -0
  149. package/ui/Agent/Menu.tsx +2 -2
  150. package/ui/Data/TableList.tsx +1 -1
  151. package/ui/DraggableList.tsx +1 -2
  152. package/ui/Field/Choice.tsx +172 -0
  153. package/ui/Field/Collection.tsx +293 -0
  154. package/ui/Field/DateField.tsx +138 -0
  155. package/ui/Field/Label.tsx +31 -0
  156. package/ui/Field/NumberField.tsx +169 -0
  157. package/ui/Field/Relation.tsx +387 -0
  158. package/ui/Field/Text.tsx +360 -0
  159. package/ui/Field/index.tsx +70 -0
  160. package/ui/Input.tsx +3 -3
  161. package/ui/Load/Edit.tsx +2 -2
  162. package/ui/Load/Edit_Client.tsx +11 -3
  163. package/ui/Load/Pagination.tsx +25 -25
  164. package/ui/Load/Stream.tsx +38 -0
  165. package/ui/Load/Units.tsx +50 -37
  166. package/ui/Load/View.tsx +25 -17
  167. package/ui/Load/index.ts +2 -0
  168. package/ui/Model/EditModal.tsx +7 -7
  169. package/ui/Signal/Message.tsx +7 -7
  170. package/ui/Signal/PubSub.tsx +4 -1
  171. package/ui/System/Client.tsx +0 -2
  172. package/ui/System/Gtag.tsx +1 -1
  173. package/ui/System/Root.tsx +4 -0
  174. package/ui/index.ts +1 -1
  175. package/ui/overlayPosition.ts +1 -2
  176. package/webkit/useCamera.tsx +22 -6
  177. package/webkit/useCodepush.tsx +2 -2
  178. package/webkit/useCsrValues.ts +1 -3
  179. package/webkit/useFetch.ts +4 -3
  180. package/webkit/useFrameRuntime.ts +14 -7
  181. package/webkit/usePurchase.tsx +4 -1
  182. package/fetch/serializer/fetch.serializer.ts +0 -142
  183. package/fetch/serializer/index.ts +0 -1
  184. package/types/common/httpClient.d.ts +0 -20
  185. package/types/fetch/serializer/fetch.serializer.d.ts +0 -14
  186. package/types/fetch/serializer/index.d.ts +0 -1
  187. package/types/fetch/serializer.d.ts +0 -1
  188. package/ui/Field.tsx +0 -1639
@@ -55,6 +55,7 @@ import { type RscRedirectMethod, type RscRedirectStatus, type RscRenderResult, R
55
55
  import { createDefaultSitemapXml, getSitemapBasePath } from "./sitemap";
56
56
  import { SsrFromRscRenderer } from "./ssrFromRscRenderer";
57
57
  import type { RscTraceMetadata, SsrManifest } from "./ssrTypes";
58
+ import { resolveStaticPath } from "./staticPath";
58
59
  import { createSubRouteIndexResponse, createSystemPageResponse, getSystemPageHomeHref } from "./systemPages";
59
60
  import { type BaseBuildArtifact, type HttpRoutes, type RenderState, resolveWebConfig } from "./types";
60
61
 
@@ -411,16 +412,14 @@ export class WebRouter {
411
412
  <script type="module" src="/csr.js"></script>
412
413
  </body>
413
414
  </html>`;
414
- return new Response(this.#withCsrHmr(htmlText), {
415
- headers: { "Content-Type": "text/html; charset=utf-8" },
416
- });
415
+ return new Response(this.#withCsrHmr(htmlText), { headers: WebRouter.#htmlResponseHeaders(200) });
417
416
  },
418
417
  }
419
418
  : {}),
420
419
  [`${clientServePrefix}/*`]: async (req) => {
421
420
  this.#requestStats.staticAsset += 1;
422
421
  const url = new URL(req.url);
423
- const filePath = WebRouter.#safeResolve(clientOutputDir, url.pathname.slice(clientServePrefix.length + 1));
422
+ const filePath = resolveStaticPath(clientOutputDir, url.pathname.slice(clientServePrefix.length + 1));
424
423
  if (!filePath) return new Response("Not Found", { status: 404 });
425
424
  return WebRouter.#fileResponse(req, filePath, {
426
425
  contentType: Bun.file(filePath).type || "application/javascript",
@@ -431,7 +430,7 @@ export class WebRouter {
431
430
  this.#requestStats.staticAsset += 1;
432
431
  const url = new URL(req.url);
433
432
  if (this.#prodMode) {
434
- const filePath = WebRouter.#safeResolve(this.#artifactDir, url.pathname.slice("/_akan/".length));
433
+ const filePath = resolveStaticPath(this.#artifactDir, url.pathname.slice("/_akan/".length));
435
434
  if (filePath) {
436
435
  return WebRouter.#fileResponse(req, filePath, {
437
436
  contentType: "text/css; charset=utf-8",
@@ -449,7 +448,7 @@ export class WebRouter {
449
448
  "/_akan/fonts/*": (req) => {
450
449
  this.#requestStats.staticAsset += 1;
451
450
  const url = new URL(req.url);
452
- const filePath = WebRouter.#safeResolve(this.#artifactDir, url.pathname.slice("/_akan/".length));
451
+ const filePath = resolveStaticPath(this.#artifactDir, url.pathname.slice("/_akan/".length));
453
452
  if (!filePath) return new Response("Not Found", { status: 404 });
454
453
  return WebRouter.#fileResponse(req, filePath, {
455
454
  contentType: Bun.file(filePath).type || "font/woff2",
@@ -524,10 +523,10 @@ export class WebRouter {
524
523
  this.#requestStats.staticAsset += 1;
525
524
  const firebaseConfig = await WebRouter.#resolveFirebaseClientConfig();
526
525
  return new Response(WebRouter.#createFirebaseMessagingServiceWorker(firebaseConfig), {
527
- headers: {
528
- "Content-Type": "application/javascript; charset=utf-8",
529
- "Cache-Control": "no-store",
530
- },
526
+ headers: WebRouter.#baseAssetHeaders({
527
+ contentType: "application/javascript; charset=utf-8",
528
+ cacheControl: "no-store",
529
+ }),
531
530
  });
532
531
  },
533
532
  "/*": async (req) => {
@@ -544,12 +543,10 @@ export class WebRouter {
544
543
  const csrHtml = await this.#resolveCsrHtml(csrOutputDir, url.pathname);
545
544
  if (!csrHtml) return this.#csrUnavailableResponse(url.pathname);
546
545
  const html = await Bun.file(csrHtml).text();
547
- return new Response(this.#withCsrHmr(html), {
548
- headers: { "Content-Type": "text/html; charset=utf-8" },
549
- });
546
+ return new Response(this.#withCsrHmr(html), { headers: WebRouter.#htmlResponseHeaders(200) });
550
547
  }
551
548
 
552
- const csrAssetPath = path.extname(url.pathname) ? WebRouter.#safeResolve(csrOutputDir, url.pathname) : null;
549
+ const csrAssetPath = path.extname(url.pathname) ? resolveStaticPath(csrOutputDir, url.pathname) : null;
553
550
  if (csrAssetPath && (await Bun.file(csrAssetPath).exists())) {
554
551
  this.#requestStats.staticAsset += 1;
555
552
  return WebRouter.#fileResponse(req, csrAssetPath, {
@@ -559,7 +556,7 @@ export class WebRouter {
559
556
  }
560
557
  }
561
558
 
562
- const filePath = WebRouter.#safeResolve(publicDir, url.pathname);
559
+ const filePath = resolveStaticPath(publicDir, url.pathname);
563
560
  if (filePath) {
564
561
  if (await Bun.file(filePath).exists()) {
565
562
  this.#requestStats.staticAsset += 1;
@@ -607,12 +604,9 @@ export class WebRouter {
607
604
  const htmlCacheEntry = htmlCacheDecision.entry;
608
605
  const cachedHtml = htmlCacheEntry ? this.#getCachedHtml(htmlCacheEntry.key) : null;
609
606
  if (cachedHtml) {
610
- return new Response(cachedHtml, {
611
- headers: {
612
- "Content-Type": "text/html; charset=utf-8",
613
- "X-Akan-Cache": "HIT",
614
- },
615
- });
607
+ const cachedHeaders = WebRouter.#htmlResponseHeaders(200);
608
+ cachedHeaders.set("X-Akan-Cache", "HIT");
609
+ return new Response(cachedHtml, { headers: cachedHeaders });
616
610
  }
617
611
  const rscResult = await this.#rsc.renderWithMeta(req, {
618
612
  clientManifest: manifest.clientManifest,
@@ -993,7 +987,7 @@ export class WebRouter {
993
987
  static #htmlResponseHeaders(status: number): Headers {
994
988
  const headers = new Headers({ "Content-Type": "text/html; charset=utf-8" });
995
989
  if (status >= 400) headers.set("Cache-Control", "no-store");
996
- return headers;
990
+ return WebRouter.#applySecurityHeaders(headers, { html: true });
997
991
  }
998
992
  #withCsrHmr(html: string): string {
999
993
  if (this.#prodMode) return html;
@@ -1249,7 +1243,7 @@ self.addEventListener("notificationclick", (event) => {
1249
1243
  i18n: artifact.i18n,
1250
1244
  });
1251
1245
  const filename = basePath ? `${basePath}.html` : "index.html";
1252
- const filePath = WebRouter.#safeResolve(csrOutputDir, filename);
1246
+ const filePath = resolveStaticPath(csrOutputDir, filename);
1253
1247
  return filePath && fs.existsSync(filePath) ? filePath : null;
1254
1248
  }
1255
1249
 
@@ -1334,10 +1328,27 @@ self.addEventListener("notificationclick", (event) => {
1334
1328
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer;
1335
1329
  }
1336
1330
 
1331
+ /**
1332
+ * Headers every response carries, whatever it is.
1333
+ *
1334
+ * `nosniff` because `Bun.file().type` falls back to `application/octet-stream` for an extension it does not
1335
+ * know, and a sniffing browser then guesses again — on a `public/` tree the app serves from its own origin,
1336
+ * that guess is script execution. `Referrer-Policy` because route paths carry ids.
1337
+ *
1338
+ * `X-Frame-Options` is on the HTML only: framing an image or a stylesheet means nothing, and the header is
1339
+ * what stops a page authenticated by a `SameSite=None` cookie from being clickjacked inside somebody else's.
1340
+ */
1341
+ static #applySecurityHeaders(headers: Headers, { html = false } = {}): Headers {
1342
+ headers.set("X-Content-Type-Options", "nosniff");
1343
+ headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
1344
+ if (html) headers.set("X-Frame-Options", "SAMEORIGIN");
1345
+ return headers;
1346
+ }
1347
+
1337
1348
  static #baseAssetHeaders(options: { contentType: string; cacheControl?: string }): Headers {
1338
1349
  const headers = new Headers({ "Content-Type": options.contentType });
1339
1350
  if (options.cacheControl) headers.set("Cache-Control", options.cacheControl);
1340
- return headers;
1351
+ return WebRouter.#applySecurityHeaders(headers);
1341
1352
  }
1342
1353
 
1343
1354
  static #weakEtag(size: number, mtimeMs: number): string {
@@ -1359,21 +1370,4 @@ self.addEventListener("notificationclick", (event) => {
1359
1370
  const sinceMs = Date.parse(ifModifiedSince);
1360
1371
  return Number.isFinite(sinceMs) && sinceMs >= lastModifiedMs;
1361
1372
  }
1362
-
1363
- static #safeResolve(baseDir: string, urlPath: string): string | null {
1364
- let decoded: string;
1365
- try {
1366
- decoded = decodeURIComponent(urlPath);
1367
- } catch {
1368
- return null;
1369
- }
1370
- if (decoded.includes("\0")) return null;
1371
- const normalizedBase = path.resolve(baseDir);
1372
- const rel = decoded.replace(/^[/\\]+/, "");
1373
- const resolved = path.resolve(normalizedBase, rel);
1374
- if (resolved === normalizedBase) return resolved;
1375
- const baseWithSep = normalizedBase.endsWith(path.sep) ? normalizedBase : normalizedBase + path.sep;
1376
- if (!resolved.startsWith(baseWithSep)) return null;
1377
- return resolved;
1378
- }
1379
1373
  }
package/service/adapt.ts CHANGED
@@ -8,11 +8,7 @@ export interface Adaptor {
8
8
  onDestroy(): Promise<void> | void;
9
9
  }
10
10
 
11
- export type AdaptorCls<
12
- Methods = any,
13
-
14
- InjectMap extends Record<string, InjectInfo> = {},
15
- > = Cls<
11
+ export type AdaptorCls<Methods = any, InjectMap extends Record<string, InjectInfo> = Record<never, never>> = Cls<
16
12
  Methods & ExtractInjectInfoObject<InjectMap> & Adaptor,
17
13
  { readonly [INJECT_META]: InjectMap; readonly refName: string }
18
14
  >;
@@ -39,7 +39,6 @@ export class RedisCache
39
39
  operationMode,
40
40
  repoName,
41
41
  redis = {
42
-
43
42
  sshOptions: {
44
43
  host: `${appName}-${environment}.${serveDomain}`,
45
44
  port: 32767,
@@ -51,9 +50,14 @@ export class RedisCache
51
50
  }: RedisEnv) => {
52
51
  const createRedis = async (url: string) => {
53
52
  const { Redis } = await import("ioredis");
54
- const redis = new Redis(url, { lazyConnect: true });
55
- await redis.connect();
56
- return redis;
53
+
54
+ const client = new Redis(url, {
55
+ lazyConnect: true,
56
+ ...(redis.username ? { username: redis.username } : {}),
57
+ ...(redis.password ? { password: redis.password } : {}),
58
+ });
59
+ await client.connect();
60
+ return client;
57
61
  };
58
62
  if (process.env.REDIS_URI) return await createRedis(process.env.REDIS_URI);
59
63
  else if (environment === "local") return await createRedis("redis://localhost:6379");