apps 0.0.1-beta.8 → 0.0.1-beta.81

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 (180) hide show
  1. package/README.md +25 -22
  2. package/framework-reference.json +1 -1
  3. package/js/{chunk-72JNVHPK.js → chunk-4NFSABEA.js} +4 -3
  4. package/js/chunk-5FHWNLCI.js +88 -0
  5. package/js/chunk-5WGONRKQ.js +426 -0
  6. package/js/{chunk-M3B3DE4K.js → chunk-74YVXBKY.js} +463 -218
  7. package/js/chunk-CDXQDN7W.js +92 -0
  8. package/js/{chunk-UK573G7W.js → chunk-EOPQ727L.js} +87 -51
  9. package/js/{chunk-27F7W2LG.js → chunk-H2CJWXA3.js} +2 -2
  10. package/js/{chunk-JU7VHODU.js → chunk-H72MEDMN.js} +65 -10
  11. package/js/{chunk-FL2QR3XW.js → chunk-HJG4RBYM.js} +333 -69
  12. package/js/chunk-I6Q7ZPKJ.js +49 -0
  13. package/js/{chunk-CDL5PM2Q.js → chunk-IFJU5SYQ.js} +19082 -18402
  14. package/js/{chunk-VFZKSM3T.js → chunk-JPEUKEV4.js} +3 -3
  15. package/js/{chunk-5T57N25Q.js → chunk-KGCTYL2S.js} +511 -63
  16. package/js/{chunk-KUMBKVJD.js → chunk-KLYSEHUD.js} +2 -2
  17. package/js/{chunk-WLE7WX2U.js → chunk-NG56RPCA.js} +2348 -472
  18. package/js/chunk-OD3KFKZD.js +1617 -0
  19. package/js/{chunk-Z5M2LQOZ.js → chunk-OY47QPQY.js} +67 -55
  20. package/js/{chunk-57RKNWL2.js → chunk-PD6I2SDG.js} +4 -4
  21. package/js/chunk-PL5KOEZD.js +334 -0
  22. package/js/chunk-Q4IZAUIF.js +285 -0
  23. package/js/{chunk-RJDDBDSN.js → chunk-QWQM3CLH.js} +795 -177
  24. package/js/{chunk-RFVIONFX.js → chunk-TE25A7D6.js} +123 -44
  25. package/js/{chunk-IJX4CYZO.js → chunk-TUMGL2OC.js} +228 -264
  26. package/js/chunk-W6XCQAXP.js +171 -0
  27. package/js/chunk-WCGAO3X5.js +348 -0
  28. package/js/{chunk-IPI4MFSN.js → chunk-XBG7HHXC.js} +2 -2
  29. package/js/{chunk-CMYUWAX7.js → chunk-YQUG4CES.js} +126 -31
  30. package/js/{chunk-UESPOTUI.js → chunk-Z2SWTZCF.js} +861 -231
  31. package/js/client.js +142 -94
  32. package/js/contracts.js +127 -26
  33. package/js/effect.js +19 -19
  34. package/js/{es-APDZKREY.js → es-DIULA3ZF.js} +62 -1659
  35. package/js/graphql.js +50 -40
  36. package/js/host.js +83 -58
  37. package/js/index.js +131 -46
  38. package/js/mcp/effect.js +23 -21
  39. package/js/mcp/stdio.js +44 -34
  40. package/js/mcp.js +76 -53
  41. package/js/openapi.js +4071 -1357
  42. package/js/react.js +2 -3
  43. package/js/skills/effect.js +6 -3
  44. package/js/skills.js +208 -81
  45. package/js/storage/facet.js +1 -540
  46. package/js/ui/auth/contracts.js +2 -2
  47. package/js/ui/auth.js +5 -5
  48. package/js/ui/contracts.js +5 -4
  49. package/js/ui/serving.js +8604 -223
  50. package/package.json +3 -4
  51. package/runtime.json +1 -1
  52. package/types/app-cache/src/contracts/cache.d.ts +18 -0
  53. package/types/app-cache/src/index.d.ts +34 -2
  54. package/types/apps/src/contracts/api-response-error.d.ts +4 -0
  55. package/types/apps/src/contracts/app.d.ts +7 -3
  56. package/types/apps/src/contracts/cache.d.ts +20 -0
  57. package/types/apps/src/contracts/context.d.ts +19 -11
  58. package/types/apps/src/contracts/elicitation.d.ts +23 -7
  59. package/types/apps/src/contracts/events.d.ts +93 -0
  60. package/types/apps/src/contracts/failure.d.ts +30 -1
  61. package/types/apps/src/contracts/graphql.d.ts +2 -1
  62. package/types/apps/src/contracts/host.d.ts +649 -17
  63. package/types/apps/src/contracts/live.d.ts +2 -0
  64. package/types/apps/src/contracts/mcp.d.ts +80 -10
  65. package/types/apps/src/contracts/network.d.ts +120 -0
  66. package/types/apps/src/contracts/openapi-compile.d.ts +82 -3
  67. package/types/apps/src/contracts/openapi.d.ts +41 -9
  68. package/types/apps/src/contracts/operations.d.ts +8 -4
  69. package/types/apps/src/contracts/placement.d.ts +102 -0
  70. package/types/apps/src/contracts/protocol-version.d.ts +2 -2
  71. package/types/apps/src/contracts/protocols/1.d.ts +733 -81
  72. package/types/apps/src/contracts/protocols/10.d.ts +1450 -0
  73. package/types/apps/src/contracts/protocols/2.d.ts +69 -26
  74. package/types/apps/src/contracts/protocols/3.d.ts +133 -33
  75. package/types/apps/src/contracts/protocols/4.d.ts +122 -45
  76. package/types/apps/src/contracts/protocols/5.d.ts +157 -47
  77. package/types/apps/src/contracts/protocols/6.d.ts +1629 -0
  78. package/types/apps/src/contracts/protocols/7.d.ts +1785 -0
  79. package/types/apps/src/contracts/protocols/8.d.ts +1182 -0
  80. package/types/apps/src/contracts/protocols/9.d.ts +1104 -0
  81. package/types/apps/src/contracts/protocols/current.d.ts +3843 -0
  82. package/types/apps/src/contracts/protocols/oauth-6.d.ts +74 -0
  83. package/types/apps/src/contracts/protocols/oauth.d.ts +134 -0
  84. package/types/apps/src/contracts/provider-error.d.ts +9 -0
  85. package/types/apps/src/contracts/provider.d.ts +90 -6
  86. package/types/apps/src/contracts/skills.d.ts +50 -13
  87. package/types/apps/src/contracts/sql.d.ts +63 -0
  88. package/types/apps/src/contracts/ui.d.ts +37 -3
  89. package/types/apps/src/contracts/workflows.d.ts +6 -0
  90. package/types/apps/src/facet.d.ts +4 -5
  91. package/types/apps/src/host.d.ts +5 -0
  92. package/types/apps/src/implementation/account-router.d.ts +4 -3
  93. package/types/apps/src/implementation/authoring.d.ts +25 -5
  94. package/types/apps/src/implementation/browser-scripts.gen.d.ts +6 -0
  95. package/types/apps/src/implementation/cache.d.ts +28 -1
  96. package/types/apps/src/implementation/catalog-cache.d.ts +35 -4
  97. package/types/apps/src/implementation/elicitation.d.ts +18 -15
  98. package/types/apps/src/implementation/events.d.ts +59 -0
  99. package/types/apps/src/implementation/failure-detail.d.ts +25 -3
  100. package/types/apps/src/implementation/graphql-catalog.d.ts +3 -3
  101. package/types/apps/src/implementation/graphql.d.ts +4 -3
  102. package/types/apps/src/implementation/input-problems.d.ts +6 -2
  103. package/types/apps/src/implementation/invocation-timing.d.ts +18 -0
  104. package/types/apps/src/implementation/live.d.ts +2 -2
  105. package/types/apps/src/implementation/mcp-call.d.ts +6 -5
  106. package/types/apps/src/implementation/mcp-catalog.d.ts +6 -4
  107. package/types/apps/src/implementation/mcp-client.d.ts +17 -9
  108. package/types/apps/src/implementation/mcp-stdio.d.ts +1 -1
  109. package/types/apps/src/implementation/mcp-tools.d.ts +2 -1
  110. package/types/apps/src/implementation/mcp.d.ts +20 -9
  111. package/types/apps/src/implementation/network.d.ts +16 -0
  112. package/types/apps/src/implementation/openapi-compile.d.ts +26 -6
  113. package/types/apps/src/implementation/openapi-document.d.ts +46 -19
  114. package/types/apps/src/implementation/openapi-names.d.ts +9 -4
  115. package/types/apps/src/implementation/openapi-request.d.ts +10 -2
  116. package/types/apps/src/implementation/openapi-source.d.ts +18 -0
  117. package/types/apps/src/implementation/openapi-upgrade.d.ts +4 -0
  118. package/types/apps/src/implementation/operations.d.ts +17 -2
  119. package/types/apps/src/implementation/optimistic.d.ts +1 -1
  120. package/types/apps/src/implementation/placement.d.ts +60 -0
  121. package/types/apps/src/implementation/protocol-operations.d.ts +3 -0
  122. package/types/apps/src/implementation/provider-error.d.ts +28 -1
  123. package/types/apps/src/implementation/provider.d.ts +18 -3
  124. package/types/apps/src/implementation/query-commit.d.ts +1 -1
  125. package/types/apps/src/implementation/router-catalog.d.ts +11 -13
  126. package/types/apps/src/implementation/router.d.ts +16 -5
  127. package/types/apps/src/implementation/runtime-yield.d.ts +7 -0
  128. package/types/apps/src/implementation/schema.d.ts +90 -10
  129. package/types/apps/src/implementation/skills.d.ts +18 -24
  130. package/types/apps/src/implementation/sql.d.ts +71 -0
  131. package/types/apps/src/implementation/ui-account-notice.d.ts +9 -0
  132. package/types/apps/src/implementation/ui-auth.d.ts +1 -1
  133. package/types/apps/src/implementation/ui-client.d.ts +2 -2
  134. package/types/apps/src/implementation/ui-document.d.ts +5 -0
  135. package/types/apps/src/implementation/ui-errors.d.ts +1 -1
  136. package/types/apps/src/implementation/ui-serving.d.ts +28 -9
  137. package/types/apps/src/implementation/ui-watch.d.ts +1 -1
  138. package/types/apps/src/implementation/upstream-error.d.ts +7 -0
  139. package/types/apps/src/implementation/webhooks.d.ts +1 -1
  140. package/types/apps/src/implementation/workflows.d.ts +1 -1
  141. package/types/apps/src/index.d.ts +55 -13
  142. package/types/apps/src/mcp.d.ts +20 -1
  143. package/types/apps/src/openapi.d.ts +1 -1
  144. package/types/apps/src/react.d.ts +1 -1
  145. package/types/apps/src/skills.d.ts +10 -8
  146. package/types/apps/src/ui-serving.d.ts +1 -1
  147. package/types/telemetry/src/app-records.d.ts +42 -0
  148. package/types/telemetry/src/browser-operations.d.ts +2 -2
  149. package/types/telemetry/src/browser.d.ts +8 -3
  150. package/types/telemetry/src/config.d.ts +2 -2
  151. package/types/telemetry/src/index.d.ts +2 -1
  152. package/types/telemetry/src/layer.d.ts +10 -4
  153. package/types/telemetry/src/measurements.d.ts +1 -1
  154. package/types/telemetry/src/ownership.d.ts +60 -0
  155. package/types/telemetry/src/recorded-failure.d.ts +29 -0
  156. package/types/telemetry/src/relay.d.ts +16 -6
  157. package/types/telemetry/src/span-attributes.d.ts +17 -1
  158. package/types/telemetry/src/transport.d.ts +8 -1
  159. package/types/utils/src/api-error.d.ts +55 -0
  160. package/types/utils/src/connection-failure.d.ts +33 -0
  161. package/types/utils/src/recorded-message.d.ts +18 -0
  162. package/types/utils/src/user-facing-error.d.ts +83 -0
  163. package/js/chunk-MKWZPDR6.js +0 -63
  164. package/js/chunk-N7YDVXYJ.js +0 -186
  165. package/js/chunk-NKLWZJLE.js +0 -172
  166. package/js/chunk-OCYUEU47.js +0 -224
  167. package/js/chunk-PJJ24GU7.js +0 -877
  168. package/js/chunk-PZB6T6KU.js +0 -19
  169. package/js/chunk-R3EV5FTO.js +0 -97
  170. package/js/chunk-YXQHV65J.js +0 -242
  171. package/js/chunk-ZQINWV4W.js +0 -630
  172. package/types/app-data/src/implementation/cursor.d.ts +0 -10
  173. package/types/app-data/src/implementation/index-key.d.ts +0 -7
  174. package/types/app-data/src/implementation/promise.d.ts +0 -68
  175. package/types/app-data/src/implementation/range.d.ts +0 -8
  176. package/types/app-data/src/implementation/schema.d.ts +0 -18
  177. package/types/app-data/src/implementation/sqlite.d.ts +0 -11
  178. package/types/app-data/src/index.d.ts +0 -4
  179. package/types/apps/src/contracts/storage.d.ts +0 -68
  180. package/types/apps/src/implementation/storage.d.ts +0 -15
@@ -1,48 +1,20 @@
1
+ import {
2
+ fromPromise
3
+ } from "./chunk-W6XCQAXP.js";
1
4
  import {
2
5
  HostedTool,
3
6
  RouterKey,
4
7
  RouterMeta,
5
8
  reservedRouterKeys
6
- } from "./chunk-WLE7WX2U.js";
9
+ } from "./chunk-NG56RPCA.js";
7
10
  import {
8
- decoderOf
9
- } from "./chunk-5T57N25Q.js";
11
+ decoderOf,
12
+ schemaArgument
13
+ } from "./chunk-KGCTYL2S.js";
10
14
  import {
11
15
  Effect_exports,
12
16
  Schema_exports
13
- } from "./chunk-CDL5PM2Q.js";
14
-
15
- // src/implementation/authoring.ts
16
- var NativeCallback = /* @__PURE__ */ Symbol("apps.NativeCallback");
17
- var fromPromise = (callback) => (...args) => {
18
- if (NativeCallback in callback) {
19
- const native = callback[NativeCallback];
20
- return native(...args);
21
- }
22
- return Effect_exports.tryPromise({ try: () => callback(...args), catch: (error) => error });
23
- };
24
- var toPromise = (operation, signal) => {
25
- const native = (...args) => Effect_exports.suspend(() => {
26
- if (signal === void 0) return operation(...args);
27
- if (signal.aborted) return Effect_exports.interrupt;
28
- const cancelled = Effect_exports.callback((resume) => {
29
- if (signal.aborted) {
30
- resume(Effect_exports.interrupt);
31
- return;
32
- }
33
- const abort = () => resume(Effect_exports.interrupt);
34
- signal.addEventListener("abort", abort, { once: true });
35
- return Effect_exports.sync(() => signal.removeEventListener("abort", abort));
36
- });
37
- return Effect_exports.raceFirst(
38
- cancelled,
39
- Effect_exports.suspend(() => operation(...args))
40
- );
41
- });
42
- return Object.assign((...args) => Effect_exports.runPromise(native(...args)), {
43
- [NativeCallback]: native
44
- });
45
- };
17
+ } from "./chunk-IFJU5SYQ.js";
46
18
 
47
19
  // src/implementation/operations.ts
48
20
  var NativeOperation = /* @__PURE__ */ Symbol("apps.Operation");
@@ -64,28 +36,30 @@ var operationOptions = (options) => {
64
36
  ...options._meta === void 0 ? {} : { _meta: options._meta },
65
37
  input: decoderOf(options.input),
66
38
  ...approval === void 0 ? {} : {
67
- approval: (context) => Effect_exports.tryPromise({ try: async () => approval(context), catch: (error) => error })
39
+ approval: (context) => fromPromise(async () => approval(context), "approval")()
68
40
  }
69
41
  };
70
42
  };
43
+ var approvedOperation = (operation, approval) => {
44
+ const copy = Object.defineProperties({}, Object.getOwnPropertyDescriptors(operation));
45
+ return Object.defineProperty(copy, "approval", {
46
+ enumerable: true,
47
+ value: (context) => fromPromise(async () => approval(context), "approval")()
48
+ });
49
+ };
71
50
  var withApproval = (operation, approval) => ({
72
51
  ...operation,
73
- [NativeOperation]: {
74
- ...operation[NativeOperation],
75
- approval: (context) => Effect_exports.tryPromise({ try: async () => approval(context), catch: (error) => error })
76
- }
52
+ [NativeOperation]: approvedOperation(operation[NativeOperation], approval)
77
53
  });
54
+ var toolAnnotations = (operation) => nativeOperation(operation)?.annotations;
78
55
  var make = (kind, options, run) => operationDeclaration({
79
- ...operationOptions(options),
56
+ ...operationOptions({ ...options, input: schemaArgument(options.input, `The ${kind} input`) }),
80
57
  kind,
81
58
  // The host always validates JSON serialization, even without a stronger output declaration.
82
- ...options.output === void 0 ? {} : { output: decoderOf(options.output) },
83
- run: (context, input) => Effect_exports.tryPromise({
84
- // SAFETY: defineApp checks the handler context against its requirements.
85
- // The host validates account bindings and creates the matching storage facade.
86
- try: () => run(context, input),
87
- catch: (error) => error
88
- })
59
+ ...options.output === void 0 ? {} : { output: decoderOf(schemaArgument(options.output, `The ${kind} output`)) },
60
+ // SAFETY: defineApp checks the handler context against its requirements.
61
+ // The host validates account bindings and creates the matching storage facade.
62
+ run: (context, input) => fromPromise(run, "handler")(context, input)
89
63
  });
90
64
  var query = (options, run) => make("query", options, run);
91
65
  var mutation = (options, run) => make("mutation", options, run);
@@ -133,14 +107,14 @@ var dynamicRouter = (source) => {
133
107
  return routerDeclaration({
134
108
  kind: "dynamic",
135
109
  ...meta === void 0 ? {} : {
136
- meta: () => fromPromise(async () => meta())().pipe(
110
+ meta: () => fromPromise(async () => meta(), "router")().pipe(
137
111
  Effect_exports.flatMap((options) => Schema_exports.decodeUnknownEffect(RouterMeta)(options))
138
112
  )
139
113
  },
140
- list: () => fromPromise(async () => source.list())().pipe(
114
+ list: () => fromPromise(async () => source.list(), "router")().pipe(
141
115
  Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(HostedTool)))
142
116
  ),
143
- resolve: (name) => fromPromise(async () => source.resolve(name))().pipe(
117
+ resolve: (name) => fromPromise(async () => source.resolve(name), "router")().pipe(
144
118
  Effect_exports.map((value) => {
145
119
  if (value === void 0) return void 0;
146
120
  const operation = nativeOperation(value);
@@ -189,13 +163,50 @@ var declaredOperations = (root, path = "") => Object.entries(root?.children ?? {
189
163
  return [];
190
164
  }
191
165
  });
166
+ var withApprovals = (source, policy) => {
167
+ const native = nativeRouter(source);
168
+ if (native === void 0) throw new Error("withApprovals expects a router");
169
+ const operation = (node, name) => {
170
+ const approval = policy(operationDeclaration(node), name);
171
+ return approval === void 0 ? node : approvedOperation(node, approval);
172
+ };
173
+ const child = (node, name) => {
174
+ switch (node.kind) {
175
+ case "query":
176
+ case "mutation":
177
+ return operation(node, name);
178
+ case "router":
179
+ case "dynamic":
180
+ return walk(node, name);
181
+ }
182
+ };
183
+ const walk = (node, path) => node.kind === "dynamic" ? {
184
+ ...node,
185
+ resolve: (name) => node.resolve(name).pipe(
186
+ Effect_exports.flatMap(
187
+ (resolved) => resolved === void 0 ? Effect_exports.succeed(void 0) : Effect_exports.try({
188
+ try: () => operation(resolved, joinPath(path, name)),
189
+ catch: (error) => error
190
+ })
191
+ )
192
+ )
193
+ } : {
194
+ ...node,
195
+ children: Object.fromEntries(
196
+ Object.entries(node.children).map(([key, value]) => [
197
+ key,
198
+ child(value, joinPath(path, key))
199
+ ])
200
+ )
201
+ };
202
+ return routerDeclaration(walk(native, ""));
203
+ };
192
204
 
193
205
  export {
194
- fromPromise,
195
- toPromise,
196
206
  operationDeclaration,
197
207
  nativeOperation,
198
208
  withApproval,
209
+ toolAnnotations,
199
210
  query,
200
211
  mutation,
201
212
  routerDeclaration,
@@ -205,5 +216,6 @@ export {
205
216
  dynamicRouter,
206
217
  joinPath,
207
218
  locate,
208
- declaredOperations
219
+ declaredOperations,
220
+ withApprovals
209
221
  };
@@ -4,7 +4,7 @@ import {
4
4
  fromWeb,
5
5
  layerMergedContext,
6
6
  make2 as make
7
- } from "./chunk-UK573G7W.js";
7
+ } from "./chunk-EOPQ727L.js";
8
8
  import {
9
9
  Reference,
10
10
  Service,
@@ -13,16 +13,16 @@ import {
13
13
  getOrUndefined2 as getOrUndefined,
14
14
  map3 as map,
15
15
  merge3 as merge,
16
- remove3 as remove,
16
+ remove2 as remove,
17
17
  succeed4 as succeed,
18
18
  toReadableStreamEffect,
19
19
  tryPromise
20
- } from "./chunk-CDL5PM2Q.js";
20
+ } from "./chunk-IFJU5SYQ.js";
21
21
  import {
22
22
  __export
23
23
  } from "./chunk-CZ7CSFO4.js";
24
24
 
25
- // ../../node_modules/.bun/effect@https+++pkg.pr.new+Effect-TS+effect+effect@c7d1ffff31a3e2ae0b0b+a654a55b752bdb24/node_modules/effect/dist/unstable/http/FetchHttpClient.js
25
+ // ../../node_modules/.bun/effect@4.0.1/node_modules/effect/dist/http/FetchHttpClient.js
26
26
  var FetchHttpClient_exports = {};
27
27
  __export(FetchHttpClient_exports, {
28
28
  Fetch: () => Fetch,
@@ -0,0 +1,334 @@
1
+ import {
2
+ appInvocationFetch
3
+ } from "./chunk-I6Q7ZPKJ.js";
4
+ import {
5
+ fromPromise,
6
+ method,
7
+ toPromise
8
+ } from "./chunk-W6XCQAXP.js";
9
+ import {
10
+ CacheAcquired,
11
+ CacheEntry,
12
+ CacheError,
13
+ cacheLimits
14
+ } from "./chunk-Q4IZAUIF.js";
15
+ import {
16
+ decoderOf
17
+ } from "./chunk-KGCTYL2S.js";
18
+ import {
19
+ captureTelemetry,
20
+ owned,
21
+ ownedBy
22
+ } from "./chunk-QWQM3CLH.js";
23
+ import {
24
+ Clock_exports,
25
+ Duration_exports,
26
+ Effect_exports,
27
+ Exit_exports,
28
+ Schema_exports
29
+ } from "./chunk-IFJU5SYQ.js";
30
+
31
+ // ../app-cache/src/index.ts
32
+ var canonical = (value) => {
33
+ if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
34
+ if (value !== null && typeof value === "object")
35
+ return `{${Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
36
+ return JSON.stringify(value);
37
+ };
38
+ var cacheKey = (key) => Effect_exports.gen(function* () {
39
+ const parsed = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Json)(key).pipe(
40
+ Effect_exports.mapError(() => new CacheError({ reason: "invalid" }))
41
+ );
42
+ const bytes = new TextEncoder().encode(canonical(parsed));
43
+ if (bytes.byteLength > cacheLimits.keyBytes)
44
+ return yield* new CacheError({ reason: "capacity", limit: "keyBytes" });
45
+ const hash = yield* Effect_exports.tryPromise({
46
+ try: () => crypto.subtle.digest("SHA-256", bytes),
47
+ catch: () => new CacheError({ reason: "invalid" })
48
+ });
49
+ return [...new Uint8Array(hash)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
50
+ });
51
+ var makeCache = (host, background, scope = "shared", deadline, leaseWait = (effect) => effect) => {
52
+ const transport = (command) => host(command).pipe(
53
+ Effect_exports.withSpan("app.cache.command", {
54
+ attributes: { "cache.operation": command.operation }
55
+ })
56
+ );
57
+ const keyOf = (key) => cacheKey([scope, key]);
58
+ const readKeys = (keys) => transport({ operation: "read", keys }).pipe(
59
+ Effect_exports.flatMap(Schema_exports.decodeUnknownEffect(Schema_exports.Array(Schema_exports.NullOr(CacheEntry)))),
60
+ Effect_exports.mapError(() => new CacheError({ reason: "storage" }))
61
+ );
62
+ const durations = (freshFor, staleFor = 0) => Effect_exports.try({
63
+ try: () => ({
64
+ fresh: Duration_exports.toMillis(Duration_exports.fromInputUnsafe(freshFor)),
65
+ stale: Duration_exports.toMillis(Duration_exports.fromInputUnsafe(staleFor))
66
+ }),
67
+ catch: () => new CacheError({ reason: "invalid" })
68
+ }).pipe(
69
+ Effect_exports.flatMap(
70
+ ({ fresh, stale }) => ![fresh, stale].every((value) => Number.isFinite(value) && value >= 0) ? Effect_exports.fail(new CacheError({ reason: "invalid" })) : (
71
+ // The cache keeps nothing past its retention: a longer lifetime loses staleness first.
72
+ Effect_exports.succeed({
73
+ fresh: Math.min(fresh, cacheLimits.retentionMs),
74
+ stale: Math.max(0, Math.min(stale, cacheLimits.retentionMs - fresh))
75
+ })
76
+ )
77
+ )
78
+ );
79
+ const get = (options, refresh, also = () => []) => Effect_exports.gen(function* () {
80
+ const key = yield* keyOf(options.key);
81
+ const extra = also(key);
82
+ const reads = extra.length === 0 ? void 0 : yield* Effect_exports.forEach(extra, keyOf);
83
+ const withReads = (value, entries) => ({
84
+ value,
85
+ key,
86
+ reads: entries
87
+ });
88
+ const loaded = (value) => ({ value, key, reads: void 0 });
89
+ const { fresh, stale } = yield* durations(options.freshFor, options.staleFor);
90
+ const decode = (value) => Schema_exports.decodeUnknownEffect(options.schema)(value);
91
+ const load = (lease) => Effect_exports.gen(function* () {
92
+ const value = yield* options.load.pipe(Effect_exports.flatMap(decode));
93
+ const json = yield* Schema_exports.decodeUnknownEffect(Schema_exports.Json)(value).pipe(
94
+ Effect_exports.mapError(() => new CacheError({ reason: "invalid" }))
95
+ );
96
+ const now = yield* Clock_exports.currentTimeMillis;
97
+ const published = yield* transport({
98
+ operation: "publish",
99
+ key,
100
+ lease,
101
+ entry: {
102
+ value: json,
103
+ version: crypto.randomUUID(),
104
+ freshUntil: now + fresh,
105
+ staleUntil: now + fresh + stale
106
+ }
107
+ }).pipe(Effect_exports.withSpan("app.cache.publish"));
108
+ if (published !== true) return yield* new CacheError({ reason: "unavailable" });
109
+ return value;
110
+ }).pipe(
111
+ Effect_exports.withSpan("app.cache.load"),
112
+ Effect_exports.timeout(cacheLimits.loadTimeoutMs),
113
+ // Publishing clears the lease in the same transaction. Only an unpublished load releases it.
114
+ Effect_exports.onExit(
115
+ (exit) => Exit_exports.isSuccess(exit) ? Effect_exports.void : transport({ operation: "release", key, lease }).pipe(
116
+ Effect_exports.catch(() => Effect_exports.void)
117
+ )
118
+ )
119
+ );
120
+ const waitUntil = Math.min(
121
+ (yield* Clock_exports.currentTimeMillis) + cacheLimits.waitMs,
122
+ deadline ?? Number.POSITIVE_INFINITY
123
+ );
124
+ let initialVersion;
125
+ const attempt = Effect_exports.gen(function* () {
126
+ const acquired = yield* transport({
127
+ operation: "acquire",
128
+ key,
129
+ refresh,
130
+ ...initialVersion === void 0 ? {} : { version: initialVersion },
131
+ ...reads === void 0 ? {} : { reads }
132
+ }).pipe(
133
+ Effect_exports.flatMap(
134
+ (reply) => Schema_exports.decodeUnknownEffect(CacheAcquired)(reply).pipe(
135
+ Effect_exports.mapError(() => new CacheError({ reason: "storage" }))
136
+ )
137
+ )
138
+ );
139
+ const { entry, lease } = acquired;
140
+ const together = acquired.reads?.length === reads?.length ? acquired.reads : void 0;
141
+ const now = yield* Clock_exports.currentTimeMillis;
142
+ if (initialVersion === void 0) initialVersion = entry?.version ?? null;
143
+ const refreshed = refresh && entry !== null && entry.version !== initialVersion;
144
+ if (entry !== null && (refreshed || !refresh && lease === null && now < entry.freshUntil))
145
+ return { next: "fresh", entry, together };
146
+ const kept = !refresh && entry !== null && now < entry.staleUntil;
147
+ if (kept && options.stale !== "revalidate")
148
+ return { next: "stale", entry, lease, together };
149
+ if (lease !== null) return { next: "load", lease, kept };
150
+ if (now >= waitUntil) return { next: "local" };
151
+ return { next: "wait" };
152
+ });
153
+ let decided = yield* attempt;
154
+ if (decided.next === "wait")
155
+ decided = yield* Effect_exports.gen(function* () {
156
+ while (true) {
157
+ yield* Effect_exports.sleep("100 millis");
158
+ const next = yield* attempt;
159
+ if (next.next !== "wait") return next;
160
+ }
161
+ }).pipe(leaseWait);
162
+ switch (decided.next) {
163
+ case "fresh":
164
+ yield* Effect_exports.annotateCurrentSpan("cache.result", "fresh");
165
+ return withReads(yield* decode(decided.entry.value), decided.together);
166
+ case "stale":
167
+ yield* Effect_exports.annotateCurrentSpan("cache.result", "stale");
168
+ if (decided.lease !== null) yield* background(load(decided.lease).pipe(Effect_exports.asVoid));
169
+ return withReads(yield* decode(decided.entry.value), decided.together);
170
+ case "load":
171
+ yield* Effect_exports.annotateCurrentSpan("cache.result", decided.kept ? "revalidated" : "miss");
172
+ return loaded(yield* load(decided.lease));
173
+ case "local":
174
+ yield* Effect_exports.annotateCurrentSpan("cache.result", "local");
175
+ return loaded(
176
+ yield* options.load.pipe(
177
+ Effect_exports.flatMap(decode),
178
+ Effect_exports.timeout(cacheLimits.loadTimeoutMs),
179
+ Effect_exports.withSpan("app.cache.load", { attributes: { "cache.load.leased": false } })
180
+ )
181
+ );
182
+ }
183
+ }).pipe(Effect_exports.withSpan("app.cache.get"));
184
+ return {
185
+ /** Read arbitrary retained JSON entries without initiating a refresh. Missing and null are distinct. */
186
+ read: (keys) => Effect_exports.forEach(keys, keyOf).pipe(Effect_exports.flatMap(readKeys)),
187
+ /** Publish bounded immutable parts before publishing the manifest that references them. */
188
+ write: (entries, retention) => Effect_exports.gen(function* () {
189
+ const { fresh } = yield* durations(retention);
190
+ const now = yield* Clock_exports.currentTimeMillis;
191
+ const values = yield* Effect_exports.forEach(
192
+ entries,
193
+ ({ key, value }) => Effect_exports.gen(function* () {
194
+ return {
195
+ key: yield* keyOf(key),
196
+ entry: {
197
+ value,
198
+ version: crypto.randomUUID(),
199
+ freshUntil: now + fresh,
200
+ staleUntil: now + fresh
201
+ }
202
+ };
203
+ })
204
+ );
205
+ yield* transport({ operation: "write", entries: values });
206
+ }),
207
+ /** Revoke retained data and any loader's right to publish its in-flight result. */
208
+ invalidate: (key) => keyOf(key).pipe(
209
+ Effect_exports.flatMap((key2) => transport({ operation: "invalidate", key: key2 })),
210
+ Effect_exports.asVoid
211
+ ),
212
+ /**
213
+ * Read fresh data, refresh stale data in the background (or first, with `stale: "revalidate"`),
214
+ * or wait for the lease owner.
215
+ */
216
+ get: (options) => get(options, false).pipe(Effect_exports.map(({ value }) => value)),
217
+ /**
218
+ * `get`, also reading the keys of this scope that `keys` names in the same round trip. `keys`
219
+ * gets the entry's store key, which is unique to this scope and key, so a caller can remember
220
+ * what it read under it. `reads` holds their entries, undecoded and in order, when the value
221
+ * was read from the store; it is undefined when the value was loaded or the store did not read
222
+ * them, and the caller then reads what it still needs.
223
+ */
224
+ getWith: (options, keys) => get(options, false, keys),
225
+ /** Force one awaited refresh without removing the retained value. Concurrent refreshes share a load. */
226
+ revalidate: (options) => get(options, true).pipe(Effect_exports.map(({ value }) => value))
227
+ };
228
+ };
229
+
230
+ // src/implementation/cache.ts
231
+ var getWithReads = /* @__PURE__ */ Symbol("executor.cache.getWithReads");
232
+ var unavailableCache = {
233
+ transport: () => Effect_exports.fail(new CacheError({ reason: "unavailable" })),
234
+ background: () => Effect_exports.die(new Error("Cache background runner is unavailable"))
235
+ };
236
+ var authorCache = (host, accounts, signal, telemetry, deadline) => {
237
+ const scoped = (scope, callerSignal = signal, services = telemetry) => {
238
+ const cache = makeCache(
239
+ host.transport,
240
+ // A refresh handed to the background runs beside the caller, which does not wait on it.
241
+ (task) => host.background(task.pipe(owned("background", "app.cache.refresh"))),
242
+ scope,
243
+ deadline,
244
+ // Waiting on another caller's load is waiting, not Executor's work.
245
+ (wait) => wait.pipe(Effect_exports.withSpan("app.cache.lease.wait", ownedBy("lease")))
246
+ );
247
+ const getOptions = (options) => ({
248
+ key: options.key,
249
+ schema: decoderOf(options.schema),
250
+ freshFor: options.freshFor,
251
+ ...options.staleFor === void 0 ? {} : { staleFor: options.staleFor },
252
+ ...options.stale === void 0 ? {} : { stale: options.stale },
253
+ load: Effect_exports.acquireUseRelease(
254
+ Effect_exports.sync(() => new AbortController()),
255
+ (controller) => Effect_exports.all([appInvocationFetch(controller.signal), captureTelemetry]).pipe(
256
+ Effect_exports.flatMap(
257
+ ([fetch, loading]) => fromPromise(
258
+ method(options, "load"),
259
+ "loader"
260
+ )({
261
+ fetch,
262
+ signal: controller.signal,
263
+ cache: scoped(scope, controller.signal, loading.context)
264
+ })
265
+ )
266
+ ),
267
+ (controller) => Effect_exports.sync(() => controller.abort())
268
+ )
269
+ });
270
+ const load = (read, given) => cache[read](getOptions(given));
271
+ const decodeEntries = (entries, schema) => Effect_exports.forEach(
272
+ entries,
273
+ (entry) => entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value)
274
+ );
275
+ const service = (method2, operation) => toPromise(
276
+ (...args) => operation(...args).pipe(
277
+ owned("executor", "app.cache.call", { attributes: { "cache.method": method2 } })
278
+ ),
279
+ callerSignal,
280
+ services
281
+ );
282
+ const authored = {
283
+ get: service("get", (options) => load("get", options)),
284
+ revalidate: service(
285
+ "revalidate",
286
+ (options) => load("revalidate", options)
287
+ ),
288
+ read: service(
289
+ "read",
290
+ (key, schema) => cache.read([key]).pipe(
291
+ Effect_exports.flatMap((entries) => {
292
+ const entry = entries[0];
293
+ return entry === void 0 || entry === null ? Effect_exports.succeed(void 0) : Schema_exports.decodeUnknownEffect(decoderOf(schema))(entry.value);
294
+ })
295
+ )
296
+ ),
297
+ readMany: service(
298
+ "readMany",
299
+ (keys, schema) => cache.read(keys).pipe(Effect_exports.flatMap((entries) => decodeEntries(entries, schema)))
300
+ ),
301
+ write: service("write", cache.write),
302
+ invalidate: service("invalidate", cache.invalidate),
303
+ forAccount: (account) => {
304
+ const bound = Object.values(accounts).flatMap((value) => Array.isArray(value) ? value : [value]).find((value) => value.id === account.id);
305
+ if (bound === void 0) throw new CacheError({ reason: "invalid" });
306
+ return scoped(
307
+ { account: bound.id, method: bound.method, generation: bound.generation },
308
+ callerSignal,
309
+ services
310
+ );
311
+ }
312
+ };
313
+ return Object.defineProperty(authored, getWithReads, {
314
+ value: service(
315
+ "get",
316
+ (given, keys) => cache.getWith(getOptions(given), keys).pipe(
317
+ Effect_exports.map(({ value, key, reads }) => ({
318
+ value,
319
+ key,
320
+ reads: reads?.map((entry) => entry === null ? void 0 : entry.value)
321
+ }))
322
+ )
323
+ )
324
+ });
325
+ };
326
+ return scoped("shared");
327
+ };
328
+
329
+ export {
330
+ cacheKey,
331
+ getWithReads,
332
+ unavailableCache,
333
+ authorCache
334
+ };