@opetope/runtime 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.
Files changed (314) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +345 -0
  4. package/README.ru.md +344 -0
  5. package/dist/application-compiler-edges.d.ts +3 -0
  6. package/dist/application-compiler-edges.js +2 -0
  7. package/dist/application-compiler-edges.js.map +1 -0
  8. package/dist/application-compiler-graph.d.ts +8 -0
  9. package/dist/application-compiler-graph.js +2 -0
  10. package/dist/application-compiler-graph.js.map +1 -0
  11. package/dist/application-compiler.d.ts +116 -0
  12. package/dist/application-compiler.js +2 -0
  13. package/dist/application-compiler.js.map +1 -0
  14. package/dist/application-conditions.d.ts +18 -0
  15. package/dist/application-conditions.js +2 -0
  16. package/dist/application-conditions.js.map +1 -0
  17. package/dist/application-definition.d.ts +30 -0
  18. package/dist/application-definition.js +2 -0
  19. package/dist/application-definition.js.map +1 -0
  20. package/dist/application-error.d.ts +10 -0
  21. package/dist/application-error.js +2 -0
  22. package/dist/application-error.js.map +1 -0
  23. package/dist/application-execution.d.ts +43 -0
  24. package/dist/application-execution.js +2 -0
  25. package/dist/application-execution.js.map +1 -0
  26. package/dist/application-feature-bindings.d.ts +11 -0
  27. package/dist/application-feature-bindings.js +2 -0
  28. package/dist/application-feature-bindings.js.map +1 -0
  29. package/dist/application-feature-instance.d.ts +5 -0
  30. package/dist/application-feature-instance.js +2 -0
  31. package/dist/application-feature-instance.js.map +1 -0
  32. package/dist/application-group-order.d.ts +29 -0
  33. package/dist/application-group-order.js +2 -0
  34. package/dist/application-group-order.js.map +1 -0
  35. package/dist/application-instance-retirement.d.ts +36 -0
  36. package/dist/application-instance-retirement.js +2 -0
  37. package/dist/application-instance-retirement.js.map +1 -0
  38. package/dist/application-open-options.d.ts +29 -0
  39. package/dist/application-open-options.js +2 -0
  40. package/dist/application-open-options.js.map +1 -0
  41. package/dist/application-port-compiler.d.ts +28 -0
  42. package/dist/application-port-compiler.js +2 -0
  43. package/dist/application-port-compiler.js.map +1 -0
  44. package/dist/attachment-call-declaration.d.ts +43 -0
  45. package/dist/attachment-call-declaration.js +2 -0
  46. package/dist/attachment-call-declaration.js.map +1 -0
  47. package/dist/attachment-declaration.d.ts +68 -0
  48. package/dist/attachment-declaration.js +2 -0
  49. package/dist/attachment-declaration.js.map +1 -0
  50. package/dist/attachment-execution.d.ts +9 -0
  51. package/dist/attachment-execution.js +2 -0
  52. package/dist/attachment-execution.js.map +1 -0
  53. package/dist/attachment-retirement-scheduler.d.ts +14 -0
  54. package/dist/attachment-retirement-scheduler.js +2 -0
  55. package/dist/attachment-retirement-scheduler.js.map +1 -0
  56. package/dist/call-option-snapshot.d.ts +20 -0
  57. package/dist/call-option-snapshot.js +2 -0
  58. package/dist/call-option-snapshot.js.map +1 -0
  59. package/dist/compile-call-target-bindings.d.ts +14 -0
  60. package/dist/compile-call-target-bindings.js +2 -0
  61. package/dist/compile-call-target-bindings.js.map +1 -0
  62. package/dist/compile-module-template.d.ts +38 -0
  63. package/dist/compile-module-template.js +2 -0
  64. package/dist/compile-module-template.js.map +1 -0
  65. package/dist/condition-group-execution.d.ts +44 -0
  66. package/dist/condition-group-execution.js +2 -0
  67. package/dist/condition-group-execution.js.map +1 -0
  68. package/dist/condition-override.d.ts +28 -0
  69. package/dist/condition-override.js +2 -0
  70. package/dist/condition-override.js.map +1 -0
  71. package/dist/condition-source.d.ts +10 -0
  72. package/dist/condition-source.js +2 -0
  73. package/dist/condition-source.js.map +1 -0
  74. package/dist/condition-types.d.ts +14 -0
  75. package/dist/condition.d.ts +28 -0
  76. package/dist/condition.js +2 -0
  77. package/dist/condition.js.map +1 -0
  78. package/dist/control-registry.d.ts +56 -0
  79. package/dist/control-registry.js +2 -0
  80. package/dist/control-registry.js.map +1 -0
  81. package/dist/dynamic-scope-child.d.ts +23 -0
  82. package/dist/dynamic-scope-child.js +2 -0
  83. package/dist/dynamic-scope-child.js.map +1 -0
  84. package/dist/dynamic-scope-controller.d.ts +16 -0
  85. package/dist/dynamic-scope-controller.js +2 -0
  86. package/dist/dynamic-scope-controller.js.map +1 -0
  87. package/dist/feature-attachment-authoring-types.d.ts +51 -0
  88. package/dist/feature-attachment-lowering.d.ts +18 -0
  89. package/dist/feature-attachment-lowering.js +2 -0
  90. package/dist/feature-attachment-lowering.js.map +1 -0
  91. package/dist/feature-attachment.d.ts +45 -0
  92. package/dist/feature-attachment.js +2 -0
  93. package/dist/feature-attachment.js.map +1 -0
  94. package/dist/feature-authoring-types.d.ts +196 -0
  95. package/dist/feature-authoring.d.ts +15 -0
  96. package/dist/feature-authoring.js +2 -0
  97. package/dist/feature-authoring.js.map +1 -0
  98. package/dist/feature-body.d.ts +53 -0
  99. package/dist/feature-body.js +2 -0
  100. package/dist/feature-body.js.map +1 -0
  101. package/dist/feature-call-authority.d.ts +8 -0
  102. package/dist/feature-call-authority.js +2 -0
  103. package/dist/feature-call-authority.js.map +1 -0
  104. package/dist/feature-call-types.d.ts +39 -0
  105. package/dist/feature-call.d.ts +18 -0
  106. package/dist/feature-call.js +2 -0
  107. package/dist/feature-call.js.map +1 -0
  108. package/dist/feature-calls.d.ts +6 -0
  109. package/dist/feature-calls.js +2 -0
  110. package/dist/feature-calls.js.map +1 -0
  111. package/dist/feature-contract.d.ts +70 -0
  112. package/dist/feature-contract.js +2 -0
  113. package/dist/feature-contract.js.map +1 -0
  114. package/dist/feature-contribution-model.d.ts +38 -0
  115. package/dist/feature-contribution-model.js +2 -0
  116. package/dist/feature-contribution-model.js.map +1 -0
  117. package/dist/feature-contribution.d.ts +126 -0
  118. package/dist/feature-contribution.js +2 -0
  119. package/dist/feature-contribution.js.map +1 -0
  120. package/dist/feature-definition-api.d.ts +53 -0
  121. package/dist/feature-definition-support.d.ts +21 -0
  122. package/dist/feature-definition-support.js +2 -0
  123. package/dist/feature-definition-support.js.map +1 -0
  124. package/dist/feature-effect.d.ts +26 -0
  125. package/dist/feature-effect.js +2 -0
  126. package/dist/feature-effect.js.map +1 -0
  127. package/dist/feature-event.d.ts +32 -0
  128. package/dist/feature-event.js +2 -0
  129. package/dist/feature-event.js.map +1 -0
  130. package/dist/feature-generation.d.ts +34 -0
  131. package/dist/feature-generation.js +2 -0
  132. package/dist/feature-generation.js.map +1 -0
  133. package/dist/feature-lazy-generation.d.ts +6 -0
  134. package/dist/feature-lazy-generation.js +2 -0
  135. package/dist/feature-lazy-generation.js.map +1 -0
  136. package/dist/feature-lazy.d.ts +44 -0
  137. package/dist/feature-lazy.js +2 -0
  138. package/dist/feature-lazy.js.map +1 -0
  139. package/dist/feature-materialization-binding.d.ts +31 -0
  140. package/dist/feature-materialization-binding.js +2 -0
  141. package/dist/feature-materialization-binding.js.map +1 -0
  142. package/dist/feature-materialization-types.d.ts +45 -0
  143. package/dist/feature-model-dependencies.d.ts +23 -0
  144. package/dist/feature-model-dependencies.js +2 -0
  145. package/dist/feature-model-dependencies.js.map +1 -0
  146. package/dist/feature-model.d.ts +60 -0
  147. package/dist/feature-model.js +2 -0
  148. package/dist/feature-model.js.map +1 -0
  149. package/dist/feature-optional.d.ts +15 -0
  150. package/dist/feature-optional.js +2 -0
  151. package/dist/feature-optional.js.map +1 -0
  152. package/dist/feature-own-lowering.d.ts +22 -0
  153. package/dist/feature-own-lowering.js +2 -0
  154. package/dist/feature-own-lowering.js.map +1 -0
  155. package/dist/feature-port-binding.d.ts +6 -0
  156. package/dist/feature-port-binding.js +2 -0
  157. package/dist/feature-port-binding.js.map +1 -0
  158. package/dist/feature-port.d.ts +66 -0
  159. package/dist/feature-port.js +2 -0
  160. package/dist/feature-port.js.map +1 -0
  161. package/dist/feature-record.d.ts +6 -0
  162. package/dist/feature-record.js +2 -0
  163. package/dist/feature-record.js.map +1 -0
  164. package/dist/feature-resource.d.ts +29 -0
  165. package/dist/feature-resource.js +2 -0
  166. package/dist/feature-resource.js.map +1 -0
  167. package/dist/feature-scope-types.d.ts +35 -0
  168. package/dist/feature-scope.d.ts +29 -0
  169. package/dist/feature-scope.js +2 -0
  170. package/dist/feature-scope.js.map +1 -0
  171. package/dist/feature-stream.d.ts +37 -0
  172. package/dist/feature-stream.js +2 -0
  173. package/dist/feature-stream.js.map +1 -0
  174. package/dist/feature-timers.d.ts +14 -0
  175. package/dist/feature-timers.js +2 -0
  176. package/dist/feature-timers.js.map +1 -0
  177. package/dist/index.d.ts +19 -0
  178. package/dist/index.js +2 -0
  179. package/dist/index.js.map +1 -0
  180. package/dist/inspection-activity-protocol.d.ts +63 -0
  181. package/dist/inspection-activity.d.ts +54 -0
  182. package/dist/inspection-activity.js +2 -0
  183. package/dist/inspection-activity.js.map +1 -0
  184. package/dist/inspection-diff.d.ts +10 -0
  185. package/dist/inspection-diff.js +2 -0
  186. package/dist/inspection-diff.js.map +1 -0
  187. package/dist/inspection-module-activity.d.ts +4 -0
  188. package/dist/inspection-module-activity.js +2 -0
  189. package/dist/inspection-module-activity.js.map +1 -0
  190. package/dist/inspection-observer.d.ts +38 -0
  191. package/dist/inspection-observer.js +2 -0
  192. package/dist/inspection-observer.js.map +1 -0
  193. package/dist/inspection-plan.d.ts +33 -0
  194. package/dist/inspection-plan.js +2 -0
  195. package/dist/inspection-plan.js.map +1 -0
  196. package/dist/inspection-protocol.d.ts +333 -0
  197. package/dist/inspection-protocol.js +2 -0
  198. package/dist/inspection-protocol.js.map +1 -0
  199. package/dist/inspection-registry.d.ts +41 -0
  200. package/dist/inspection-registry.js +2 -0
  201. package/dist/inspection-registry.js.map +1 -0
  202. package/dist/inspection-session.d.ts +92 -0
  203. package/dist/inspection-session.js +2 -0
  204. package/dist/inspection-session.js.map +1 -0
  205. package/dist/inspection-snapshot.d.ts +4 -0
  206. package/dist/inspection-snapshot.js +2 -0
  207. package/dist/inspection-snapshot.js.map +1 -0
  208. package/dist/inspection-state.d.ts +91 -0
  209. package/dist/inspection-state.js +2 -0
  210. package/dist/inspection-state.js.map +1 -0
  211. package/dist/instance-demand.d.ts +31 -0
  212. package/dist/instance-demand.js +2 -0
  213. package/dist/instance-demand.js.map +1 -0
  214. package/dist/internal.d.ts +41 -0
  215. package/dist/internal.js +2 -0
  216. package/dist/internal.js.map +1 -0
  217. package/dist/keyed-scope-controller.d.ts +11 -0
  218. package/dist/keyed-scope-controller.js +2 -0
  219. package/dist/keyed-scope-controller.js.map +1 -0
  220. package/dist/model-kernel.d.ts +18 -0
  221. package/dist/model-kernel.js +2 -0
  222. package/dist/model-kernel.js.map +1 -0
  223. package/dist/module-call-context.d.ts +7 -0
  224. package/dist/module-call-context.js +2 -0
  225. package/dist/module-call-context.js.map +1 -0
  226. package/dist/module-call-runtime.d.ts +21 -0
  227. package/dist/module-call-runtime.js +2 -0
  228. package/dist/module-call-runtime.js.map +1 -0
  229. package/dist/module-generation.d.ts +57 -0
  230. package/dist/module-generation.js +2 -0
  231. package/dist/module-generation.js.map +1 -0
  232. package/dist/module-instance-types.d.ts +156 -0
  233. package/dist/module-instance.d.ts +19 -0
  234. package/dist/module-instance.js +2 -0
  235. package/dist/module-instance.js.map +1 -0
  236. package/dist/module-runtime-identity.d.ts +4 -0
  237. package/dist/module-runtime-identity.js +2 -0
  238. package/dist/module-runtime-identity.js.map +1 -0
  239. package/dist/module-scope-open.d.ts +4 -0
  240. package/dist/module-scope-open.js +2 -0
  241. package/dist/module-scope-open.js.map +1 -0
  242. package/dist/module-scope-retirement.d.ts +3 -0
  243. package/dist/module-scope-retirement.js +2 -0
  244. package/dist/module-scope-retirement.js.map +1 -0
  245. package/dist/module-template-ir.d.ts +59 -0
  246. package/dist/owner-generation-retirement.d.ts +6 -0
  247. package/dist/owner-generation-retirement.js +2 -0
  248. package/dist/owner-generation-retirement.js.map +1 -0
  249. package/dist/owner-generation-state.d.ts +123 -0
  250. package/dist/owner-generation-state.js +2 -0
  251. package/dist/owner-generation-state.js.map +1 -0
  252. package/dist/owner-generation.d.ts +16 -0
  253. package/dist/owner-generation.js +2 -0
  254. package/dist/owner-generation.js.map +1 -0
  255. package/dist/public-module-definition.d.ts +9 -0
  256. package/dist/public-module-definition.js +2 -0
  257. package/dist/public-module-definition.js.map +1 -0
  258. package/dist/public-module-instance.d.ts +6 -0
  259. package/dist/public-module-instance.js +2 -0
  260. package/dist/public-module-instance.js.map +1 -0
  261. package/dist/public-module-retirement-diagnostics.d.ts +5 -0
  262. package/dist/public-module-retirement-diagnostics.js +2 -0
  263. package/dist/public-module-retirement-diagnostics.js.map +1 -0
  264. package/dist/public-module-retirement.d.ts +3 -0
  265. package/dist/public-module-retirement.js +2 -0
  266. package/dist/public-module-retirement.js.map +1 -0
  267. package/dist/public-module-scope.d.ts +5 -0
  268. package/dist/public-module-scope.js +2 -0
  269. package/dist/public-module-scope.js.map +1 -0
  270. package/dist/public-module-state.d.ts +28 -0
  271. package/dist/public-module-state.js +2 -0
  272. package/dist/public-module-state.js.map +1 -0
  273. package/dist/public-module-types.d.ts +295 -0
  274. package/dist/public-module.d.ts +4 -0
  275. package/dist/resource-cache.d.ts +12 -0
  276. package/dist/resource-cache.js +2 -0
  277. package/dist/resource-cache.js.map +1 -0
  278. package/dist/resource-controller.d.ts +29 -0
  279. package/dist/resource-controller.js +2 -0
  280. package/dist/resource-controller.js.map +1 -0
  281. package/dist/resource-policy.d.ts +16 -0
  282. package/dist/resource-policy.js +2 -0
  283. package/dist/resource-policy.js.map +1 -0
  284. package/dist/resource-snapshot.d.ts +12 -0
  285. package/dist/resource-snapshot.js +2 -0
  286. package/dist/resource-snapshot.js.map +1 -0
  287. package/dist/resource-types.d.ts +3 -0
  288. package/dist/runtime-error-reporting.d.ts +4 -0
  289. package/dist/runtime-error-reporting.js +2 -0
  290. package/dist/runtime-error-reporting.js.map +1 -0
  291. package/dist/stream-backpressure.d.ts +18 -0
  292. package/dist/stream-backpressure.js +2 -0
  293. package/dist/stream-backpressure.js.map +1 -0
  294. package/dist/stream-cleanup.d.ts +17 -0
  295. package/dist/stream-cleanup.js +2 -0
  296. package/dist/stream-cleanup.js.map +1 -0
  297. package/dist/stream-controller-types.d.ts +51 -0
  298. package/dist/stream-controller.d.ts +5 -0
  299. package/dist/stream-controller.js +2 -0
  300. package/dist/stream-controller.js.map +1 -0
  301. package/docs/agent-guide.md +214 -0
  302. package/docs/agent-guide.ru.md +208 -0
  303. package/docs/cookbook.md +734 -0
  304. package/docs/cookbook.ru.md +729 -0
  305. package/docs/decisions.md +1437 -0
  306. package/docs/devtools.md +423 -0
  307. package/docs/devtools.ru.md +419 -0
  308. package/docs/how-it-works.md +521 -0
  309. package/docs/how-it-works.ru.md +495 -0
  310. package/docs/releases.md +78 -0
  311. package/docs/releases.ru.md +78 -0
  312. package/docs/spec.md +874 -0
  313. package/docs/spec.ru.md +884 -0
  314. package/package.json +72 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-scope.js","sources":["../src/feature-scope.ts"],"sourcesContent":["import type { Readable } from '@opetope/core';\nimport type { Awaitable } from '@opetope/core/internal';\nimport { isReadable } from '@opetope/core/internal';\n\nimport { createDynamicScopeChild } from './dynamic-scope-child';\nimport { closedSelection, createDynamicScopeController, dynamicScopeSelection } from './dynamic-scope-controller';\nimport { createFeatureStatefulAttachment, getFeatureAttachmentReporter } from './feature-attachment';\nimport type { FeatureStatefulAttachmentHandle } from './feature-attachment';\nimport type { FeatureAttachBuilder, FeatureImportRecord, FeatureImportRef } from './feature-authoring-types';\nimport { assertPlainRecord, dataEntries } from './feature-record';\nimport type { FeatureScopeBuilder, FeatureScopeKey } from './feature-scope-types';\nimport type { FeatureTimers } from './feature-timers';\nimport { createKeyedScopeController } from './keyed-scope-controller';\nimport type { ErrorReporter } from './public-module';\nimport { reportRuntimeFailure } from './runtime-error-reporting';\n\ntype Disposer = () => Awaitable<void>;\n\ntype ScopeOpen = (\n value: unknown,\n context: { readonly signal: AbortSignal; readonly timers: FeatureTimers },\n) => Awaitable<Disposer | void>;\n\ntype WhileScopeOptions = {\n readonly from: object;\n readonly open: ScopeOpen;\n readonly when: ((value: unknown) => boolean) | undefined;\n};\n\ntype SwitchScopeOptions = {\n readonly from: object;\n readonly key: ((value: unknown) => FeatureScopeKey) | undefined;\n readonly open: ScopeOpen;\n};\n\ntype KeyedScopeOptions = {\n readonly from: object;\n readonly key: (value: unknown) => FeatureScopeKey;\n readonly open: ScopeOpen;\n};\n\ninterface ReactiveScopeController {\n readonly dispose: () => Promise<void>;\n readonly fence: () => void;\n readonly invalidateProjection?: () => void;\n readonly project: (snapshot: unknown) => unknown;\n readonly update: (snapshot: unknown) => Promise<void>;\n}\n\nfunction withScopeProjection<Value>(\n controller: {\n readonly dispose: () => Promise<void>;\n readonly fence: () => void;\n readonly invalidateProjection?: () => void;\n readonly update: (selection: Value) => Promise<void>;\n },\n project: (snapshot: unknown) => Value,\n): ReactiveScopeController {\n return {\n dispose: controller.dispose,\n fence: controller.fence,\n ...(controller.invalidateProjection === undefined ? {} : { invalidateProjection: controller.invalidateProjection }),\n project,\n update: selection => controller.update(selection as Value),\n };\n}\n\ninterface ReactiveScopeState {\n readonly close: () => Promise<void>;\n readonly fence: () => void;\n readonly open: () => Promise<void>;\n}\n\ntype FeatureStatefulAttachBuilder<Id extends string> = (\n source: FeatureImportRef<unknown, Id, 'adapter-method'>,\n options: FeatureStatefulAttachmentHandle<unknown>,\n) => object;\n\nconst whileScopeOptionKeys = new Set(['from', 'open', 'when']);\nconst switchScopeOptionKeys = new Set(['from', 'key', 'open']);\nconst keyedScopeOptionKeys = new Set(['from', 'key', 'open']);\n\nfunction requiredFunction<Callable>(value: unknown, label: string): Callable {\n if (typeof value !== 'function') throw new TypeError(`${label} must be a function.`);\n\n return value as Callable;\n}\n\nfunction optionalFunction<Callable>(value: unknown, label: string): Callable | undefined {\n if (value === undefined) return undefined;\n\n return requiredFunction<Callable>(value, label);\n}\n\nfunction snapshotScopeOptions(\n value: unknown,\n label: string,\n allowed: ReadonlySet<string>,\n required: readonly string[],\n): Readonly<Record<string, unknown>> {\n assertPlainRecord(value, label);\n const entries = dataEntries(value, label);\n const keys = new Set(entries.map(([key]) => key));\n\n for (const key of keys) {\n if (!allowed.has(key)) throw new TypeError(`Unknown ${label} option ${key}.`);\n }\n\n for (const key of required) {\n if (!keys.has(key)) throw new TypeError(`${label} requires own ${key}.`);\n }\n\n const snapshot = Object.freeze(Object.fromEntries(entries));\n\n if (typeof snapshot['from'] !== 'object' || snapshot['from'] === null) {\n throw new TypeError(`${label} from must be an import from this definition.`);\n }\n\n return snapshot;\n}\n\nfunction snapshotWhileScopeOptions(value: unknown): WhileScopeOptions {\n const snapshot = snapshotScopeOptions(value, 'Feature while scope', whileScopeOptionKeys, ['from', 'open']);\n\n return Object.freeze({\n from: snapshot['from'] as object,\n open: requiredFunction<ScopeOpen>(snapshot['open'], 'Feature while scope open'),\n when: optionalFunction<NonNullable<WhileScopeOptions['when']>>(snapshot['when'], 'Feature while scope when'),\n });\n}\n\nfunction snapshotSwitchScopeOptions(value: unknown): SwitchScopeOptions {\n const snapshot = snapshotScopeOptions(value, 'Feature switch scope', switchScopeOptionKeys, ['from', 'open']);\n\n return Object.freeze({\n from: snapshot['from'] as object,\n key: optionalFunction<NonNullable<SwitchScopeOptions['key']>>(snapshot['key'], 'Feature switch scope key'),\n open: requiredFunction<ScopeOpen>(snapshot['open'], 'Feature switch scope open'),\n });\n}\n\nfunction snapshotKeyedScopeOptions(value: unknown): KeyedScopeOptions {\n const snapshot = snapshotScopeOptions(value, 'Feature keyed scope', keyedScopeOptionKeys, ['from', 'key', 'open']);\n\n return Object.freeze({\n from: snapshot['from'] as object,\n key: requiredFunction<KeyedScopeOptions['key']>(snapshot['key'], 'Feature keyed scope key'),\n open: requiredFunction<ScopeOpen>(snapshot['open'], 'Feature keyed scope open'),\n });\n}\n\nfunction assertReadable(value: unknown): asserts value is Readable<unknown> {\n if (!isReadable(value)) throw new TypeError('Feature dynamic scope from must resolve to a Readable.');\n}\n\nfunction validateScopeKey(value: unknown, label: string): FeatureScopeKey {\n if (typeof value !== 'string' && typeof value !== 'number') {\n throw new TypeError(`${label} must return a string or number.`);\n }\n\n return value;\n}\n\nfunction createReactiveScopeState(\n source: unknown,\n ownerSignal: AbortSignal,\n controller: ReactiveScopeController,\n reporter: ErrorReporter | undefined,\n): ReactiveScopeState {\n assertReadable(source);\n let active = true;\n let revision = 0;\n let release: (() => void) | undefined;\n const report = (error: unknown): void => reportRuntimeFailure(error, reporter);\n const update = (): Promise<void> => {\n const current = ++revision;\n controller.invalidateProjection?.();\n\n try {\n const snapshot = source.getSnapshot();\n\n if (!active || current !== revision) return Promise.resolve();\n\n const selection = controller.project(snapshot);\n\n if (!active || current !== revision) return Promise.resolve();\n\n return controller.update(selection);\n } catch (error) {\n return Promise.reject(error);\n }\n };\n const observe = (): void => {\n if (!active) return;\n\n void update().catch(report);\n };\n const fenceLogical = (): void => {\n if (!active) return;\n\n active = false;\n revision += 1;\n ownerSignal.removeEventListener('abort', fenceLogical);\n controller.fence();\n };\n const releaseSource = (): void => {\n if (release === undefined) return;\n\n release();\n release = undefined;\n };\n\n return Object.freeze({\n async close(): Promise<void> {\n fenceLogical();\n let failure: unknown;\n\n try {\n releaseSource();\n } catch (error) {\n failure = error;\n }\n\n try {\n await controller.dispose();\n } catch (error) {\n if (failure === undefined) failure = error;\n else report(error);\n }\n\n if (failure !== undefined) return Promise.reject(failure);\n },\n fence: fenceLogical,\n async open(): Promise<void> {\n try {\n const subscribed: unknown = source.subscribe(observe);\n\n if (typeof subscribed !== 'function') {\n throw new TypeError('Readable subscribe must return an unsubscribe function.');\n }\n\n release = subscribed as () => void;\n ownerSignal.addEventListener('abort', fenceLogical, { once: true });\n\n if (ownerSignal.aborted) fenceLogical();\n\n if (!active) return;\n\n await update();\n } catch (error) {\n fenceLogical();\n throw error;\n }\n },\n });\n}\n\ntype ReactiveScopeNode = {\n readonly createController: (reporter: ErrorReporter | undefined) => ReactiveScopeController;\n readonly from: object;\n};\n\ntype ReactiveScopeKind = 'keyed' | 'switch' | 'while';\n\n/**\n * One node description for both owners: `own` binds it to an attachment, a model opens it directly against its own\n * signal (D73). The dynamic child module and the controller semantics stay single-sourced.\n */\nfunction createReactiveScopeNode(kind: ReactiveScopeKind, id: string, value: unknown): ReactiveScopeNode {\n if (kind === 'while') {\n const options = snapshotWhileScopeOptions(value);\n const child = createDynamicScopeChild(id, options.open);\n\n return {\n createController: reporter => {\n const controller = createDynamicScopeController(child, reporter);\n\n return withScopeProjection(controller, snapshot =>\n (options.when?.(snapshot) ?? Boolean(snapshot)) ? dynamicScopeSelection(snapshot, 'active') : closedSelection,\n );\n },\n from: options.from,\n };\n }\n\n if (kind === 'switch') {\n const options = snapshotSwitchScopeOptions(value);\n const child = createDynamicScopeChild(id, options.open);\n\n return {\n createController: reporter => {\n const controller = createDynamicScopeController(child, reporter);\n\n return withScopeProjection(controller, snapshot => {\n if (snapshot === null || snapshot === undefined) return closedSelection;\n\n const key =\n options.key === undefined ? snapshot : validateScopeKey(options.key(snapshot), 'Feature switch scope key');\n\n return dynamicScopeSelection(snapshot, key);\n });\n },\n from: options.from,\n };\n }\n\n const options = snapshotKeyedScopeOptions(value);\n const child = createDynamicScopeChild(id, options.open);\n\n return {\n createController: reporter => {\n const controller = createKeyedScopeController(\n child,\n item => validateScopeKey(options.key(item), 'Feature keyed scope key'),\n reporter,\n );\n\n return withScopeProjection(controller, snapshot => snapshot as readonly unknown[]);\n },\n from: options.from,\n };\n}\n\nfunction createFeatureScopeBuilder<Id extends string, Imports extends FeatureImportRecord>(\n featureId: Id,\n attach: FeatureAttachBuilder<Id, Imports>,\n): FeatureScopeBuilder<Id, Imports> {\n let ordinal = 0;\n const attachStateful = attach as unknown as FeatureStatefulAttachBuilder<Id>;\n const bind = (kind: ReactiveScopeKind, value: unknown): object => {\n ordinal += 1;\n const node = createReactiveScopeNode(kind, `${featureId}.scope.${String(ordinal)}`, value);\n\n return attachStateful(\n node.from as FeatureImportRef<unknown, Id, 'adapter-method'>,\n createFeatureStatefulAttachment<unknown, ReactiveScopeState>({\n close: state => state.close(),\n create: context => {\n const reporter = getFeatureAttachmentReporter(context);\n\n return createReactiveScopeState(context.source, context.signal, node.createController(reporter), reporter);\n },\n open: state => state.open(),\n }),\n );\n };\n\n return Object.freeze({\n keyed: (value: unknown) => bind('keyed', value),\n switch: (value: unknown) => bind('switch', value),\n while: (value: unknown) => bind('while', value),\n }) as FeatureScopeBuilder<Id, Imports>;\n}\n\nexport { createFeatureScopeBuilder, createReactiveScopeNode, createReactiveScopeState };\nexport type { ReactiveScopeKind };\n"],"names":["withScopeProjection","controller","project","selection","whileScopeOptionKeys","switchScopeOptionKeys","keyedScopeOptionKeys","requiredFunction","value","label","optionalFunction","snapshotScopeOptions","allowed","required","assertPlainRecord","entries","dataEntries","keys","key","snapshot","snapshotWhileScopeOptions","snapshotSwitchScopeOptions","snapshotKeyedScopeOptions","assertReadable","isReadable","validateScopeKey","createReactiveScopeState","source","ownerSignal","reporter","active","revision","release","report","error","reportRuntimeFailure","update","current","_a","observe","fenceLogical","releaseSource","failure","subscribed","createReactiveScopeNode","kind","id","options","child","createDynamicScopeChild","createDynamicScopeController","dynamicScopeSelection","closedSelection","createKeyedScopeController","item","createFeatureScopeBuilder","featureId","attach","ordinal","attachStateful","bind","node","createFeatureStatefulAttachment","state","context","getFeatureAttachmentReporter"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Readable } from '@opetope/core';
2
+ import type { FeatureAttachBuilder, FeatureImportRecord, FeatureImportRef } from './feature-authoring-types.js';
3
+ import type { FeatureExposureMode } from './feature-call-types.js';
4
+ import type { FeatureMaterializationTarget, FeatureStreamOptions as FeatureStreamOptionsInput, FeatureStreamRef } from './feature-materialization-types.js';
5
+ import type { ExactKeys } from './feature-record.js';
6
+ import type { ResourceRequestKey, ResourceRetention, ResourceRetry, StreamBackpressure } from './resource-types.js';
7
+ type FeatureStreamOptions = {
8
+ readonly backpressure: StreamBackpressure;
9
+ readonly connect: (target: unknown, context: {
10
+ readonly emit: (data: unknown) => void;
11
+ readonly signal: AbortSignal;
12
+ readonly source: unknown;
13
+ }) => unknown;
14
+ readonly consume: ((context: {
15
+ readonly data: unknown;
16
+ readonly signal: AbortSignal;
17
+ readonly source: unknown;
18
+ readonly target: unknown;
19
+ }) => unknown) | undefined;
20
+ readonly from: object;
21
+ readonly key: (target: unknown) => ResourceRequestKey;
22
+ readonly retention: ResourceRetention;
23
+ readonly retry: ResourceRetry | undefined;
24
+ readonly target: (source: unknown) => Readable<unknown | null>;
25
+ };
26
+ type FeatureStreamData<Source> = Source extends {
27
+ readonly connect: (...arguments_: infer Arguments) => unknown;
28
+ } ? Arguments extends readonly [unknown, (data: infer Data) => unknown, ...unknown[]] ? Data : never : never;
29
+ /**
30
+ * `from` and `target` are positional so TypeScript resolves `Source` and then `Target` before it contextually types
31
+ * the option callbacks. Key order inside the options object is therefore irrelevant.
32
+ */
33
+ type FeatureStreamBuilder<Id extends string> = <Source, Target, Key extends ResourceRequestKey, Mode extends FeatureExposureMode, const Keys extends PropertyKey = keyof FeatureStreamOptionsInput<Source, Target, FeatureStreamData<Source>, Key>>(from: FeatureImportRef<Source, Id, Mode>, target: FeatureMaterializationTarget<NoInfer<Source>, Target>, options: ExactKeys<Keys, FeatureStreamOptionsInput<NoInfer<Source>, NoInfer<Target>, FeatureStreamData<NoInfer<Source>>, Key>> & FeatureStreamOptionsInput<NoInfer<Source>, NoInfer<Target>, FeatureStreamData<NoInfer<Source>>, Key>) => FeatureStreamRef<FeatureStreamData<Source>, Key, Id>;
34
+ declare function snapshotFeatureStreamOptions(source: unknown, select: unknown, value: unknown): FeatureStreamOptions;
35
+ declare function createFeatureStreamBuilder<Id extends string, Imports extends FeatureImportRecord>(attach: FeatureAttachBuilder<Id, Imports>): FeatureStreamBuilder<Id>;
36
+ export { createFeatureStreamBuilder, snapshotFeatureStreamOptions };
37
+ export type { FeatureStreamBuilder };
@@ -0,0 +1,2 @@
1
+ import{getFeatureAttachmentReporter as h}from"./feature-attachment.js";import{openingMaterializationGenerationAllocator as g,attachOpeningMaterialization as w,registerFeatureMaterialization as F}from"./feature-materialization-binding.js";import{assertPlainRecord as b,dataEntries as S}from"./feature-record.js";import{selectTargetReadable as E,requireTargetSelector as T,requireRequestKey as R}from"./feature-resource.js";import{snapshotResourceRetry as q,snapshotResourceRetention as z,snapshotStreamBackpressure as O}from"./resource-policy.js";import{createStreamController as K}from"./stream-controller.js";const M=new Set(["backpressure","connect","consume","key","retention","retry"]);function $(e){for(const r of e)if(!M.has(r))throw new TypeError(`Unknown feature stream option ${r}.`);for(const r of["backpressure","connect","key"])if(!e.has(r))throw new TypeError(`Feature stream requires own ${r}.`)}function y(e,r){if(typeof e!="function")throw new TypeError(`Feature stream ${r} must be a function.`);return e}function j(e){if(e!==void 0){if(typeof e!="function")throw new TypeError("Feature stream consume must be a function.");return e}}function d(e,r,n){b(n,"Feature stream options");const m=S(n,"Feature stream options"),t=new Set(m.map(([f])=>f));if($(t),typeof e!="object"||e===null)throw new TypeError("Feature stream from must be an import from this definition.");const a=y(n.connect,"connect"),c=j(n.consume),u=y(n.key,"key"),o=T(r,"Feature stream target");return Object.freeze({backpressure:O(n.backpressure),connect:a,consume:c,from:e,key:u,retention:z(n.retention),retry:q(n.retry),target:o})}function A(e){return((r,n,m)=>{const t=d(r,n,m),a={},c=()=>{if(a.token===void 0)throw new TypeError("Feature stream is not registered.");return a.token},u=e(t.from,{open:o=>{const f=E(t.target,o.source,"Feature stream target"),p=h(o),i=K({allocateGeneration:g(c()),backpressure:t.backpressure,connect:(s,l)=>t.connect(s,l),key:s=>R(t.key(s)),retention:t.retention,source:o.source,target:f,...t.consume===void 0?{}:{consume:s=>t.consume(s)},...p===void 0?{}:{reporter:p},...t.retry===void 0?{}:{retry:t.retry}});o.signal.addEventListener("abort",i.fence,{once:!0}),o.signal.aborted&&i.fence();const k=w(c(),i);return async()=>{o.signal.removeEventListener("abort",i.fence);let s=!1;try{await i.close(),s=!0}finally{k(s)}}}});return a.token=F(u,"stream"),u})}export{A as createFeatureStreamBuilder,d as snapshotFeatureStreamOptions};
2
+ //# sourceMappingURL=feature-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-stream.js","sources":["../src/feature-stream.ts"],"sourcesContent":["import type { Readable } from '@opetope/core';\n\nimport type { LifetimeAttachmentRefIdentity } from './attachment-declaration';\nimport { getFeatureAttachmentReporter } from './feature-attachment';\nimport type { FeatureAttachBuilder, FeatureImportRecord, FeatureImportRef } from './feature-authoring-types';\nimport type { FeatureExposureMode } from './feature-call-types';\nimport {\n attachOpeningMaterialization,\n openingMaterializationGenerationAllocator,\n registerFeatureMaterialization,\n} from './feature-materialization-binding';\nimport type {\n FeatureMaterializationTarget,\n FeatureStreamOptions as FeatureStreamOptionsInput,\n FeatureStreamRef,\n} from './feature-materialization-types';\nimport { assertPlainRecord, dataEntries } from './feature-record';\nimport type { ExactKeys } from './feature-record';\nimport { requireRequestKey, requireTargetSelector, selectTargetReadable } from './feature-resource';\nimport { snapshotResourceRetention, snapshotResourceRetry, snapshotStreamBackpressure } from './resource-policy';\nimport type { ResourceRequestKey, ResourceRetention, ResourceRetry, StreamBackpressure } from './resource-types';\nimport { createStreamController } from './stream-controller';\n\ntype FeatureStreamOptions = {\n readonly backpressure: StreamBackpressure;\n readonly connect: (\n target: unknown,\n context: { readonly emit: (data: unknown) => void; readonly signal: AbortSignal; readonly source: unknown },\n ) => unknown;\n readonly consume:\n | ((context: {\n readonly data: unknown;\n readonly signal: AbortSignal;\n readonly source: unknown;\n readonly target: unknown;\n }) => unknown)\n | undefined;\n readonly from: object;\n readonly key: (target: unknown) => ResourceRequestKey;\n readonly retention: ResourceRetention;\n readonly retry: ResourceRetry | undefined;\n readonly target: (source: unknown) => Readable<unknown | null>;\n};\n\ntype FeatureStreamData<Source> = Source extends { readonly connect: (...arguments_: infer Arguments) => unknown }\n ? Arguments extends readonly [unknown, (data: infer Data) => unknown, ...unknown[]]\n ? Data\n : never\n : never;\n/**\n * `from` and `target` are positional so TypeScript resolves `Source` and then `Target` before it contextually types\n * the option callbacks. Key order inside the options object is therefore irrelevant.\n */\ntype FeatureStreamBuilder<Id extends string> = <\n Source,\n Target,\n Key extends ResourceRequestKey,\n // D187: every exposure mode may feed a resource or a stream; only `calls` cares which one it is.\n Mode extends FeatureExposureMode,\n const Keys extends PropertyKey = keyof FeatureStreamOptionsInput<Source, Target, FeatureStreamData<Source>, Key>,\n>(\n from: FeatureImportRef<Source, Id, Mode>,\n target: FeatureMaterializationTarget<NoInfer<Source>, Target>,\n options: ExactKeys<\n Keys,\n FeatureStreamOptionsInput<NoInfer<Source>, NoInfer<Target>, FeatureStreamData<NoInfer<Source>>, Key>\n > &\n FeatureStreamOptionsInput<NoInfer<Source>, NoInfer<Target>, FeatureStreamData<NoInfer<Source>>, Key>,\n) => FeatureStreamRef<FeatureStreamData<Source>, Key, Id>;\n\nconst streamOptionKeys = new Set(['backpressure', 'connect', 'consume', 'key', 'retention', 'retry']);\n\nfunction assertFeatureStreamKeys(keys: ReadonlySet<string>): void {\n for (const key of keys) {\n if (!streamOptionKeys.has(key)) throw new TypeError(`Unknown feature stream option ${key}.`);\n }\n\n for (const key of ['backpressure', 'connect', 'key'] as const) {\n if (!keys.has(key)) throw new TypeError(`Feature stream requires own ${key}.`);\n }\n}\n\nfunction requireStreamFunction(value: unknown, key: string): (...arguments_: never[]) => unknown {\n if (typeof value !== 'function') throw new TypeError(`Feature stream ${key} must be a function.`);\n\n return value as (...arguments_: never[]) => unknown;\n}\n\nfunction optionalStreamFunction(value: unknown): FeatureStreamOptions['consume'] {\n if (value === undefined) return undefined;\n\n if (typeof value !== 'function') throw new TypeError('Feature stream consume must be a function.');\n\n return value as FeatureStreamOptions['consume'];\n}\n\nfunction snapshotFeatureStreamOptions(source: unknown, select: unknown, value: unknown): FeatureStreamOptions {\n assertPlainRecord(value, 'Feature stream options');\n const entries = dataEntries(value, 'Feature stream options');\n const keys = new Set(entries.map(([key]) => key));\n assertFeatureStreamKeys(keys);\n\n if (typeof source !== 'object' || source === null) {\n throw new TypeError('Feature stream from must be an import from this definition.');\n }\n\n const connect = requireStreamFunction(value['connect'], 'connect');\n const consume = optionalStreamFunction(value['consume']);\n const key = requireStreamFunction(value['key'], 'key');\n const target = requireTargetSelector(select, 'Feature stream target');\n\n return Object.freeze({\n backpressure: snapshotStreamBackpressure(value['backpressure']),\n connect: connect as FeatureStreamOptions['connect'],\n consume,\n from: source,\n key: key as FeatureStreamOptions['key'],\n retention: snapshotResourceRetention(value['retention']),\n retry: snapshotResourceRetry(value['retry']),\n target: target as FeatureStreamOptions['target'],\n });\n}\n\nfunction createFeatureStreamBuilder<Id extends string, Imports extends FeatureImportRecord>(\n attach: FeatureAttachBuilder<Id, Imports>,\n): FeatureStreamBuilder<Id> {\n return ((source: unknown, select: unknown, value: unknown) => {\n const options = snapshotFeatureStreamOptions(source, select, value);\n const registration: { token?: ReturnType<typeof registerFeatureMaterialization> } = {};\n const requireToken = (): ReturnType<typeof registerFeatureMaterialization> => {\n if (registration.token === undefined) throw new TypeError('Feature stream is not registered.');\n\n return registration.token;\n };\n const attachment = attach(options.from as FeatureImportRef<unknown, Id, 'adapter-method'>, {\n open: context => {\n const target = selectTargetReadable(options.target, context.source, 'Feature stream target');\n const reporter = getFeatureAttachmentReporter(context);\n const controller = createStreamController({\n allocateGeneration: openingMaterializationGenerationAllocator(requireToken()),\n backpressure: options.backpressure,\n connect: (selected, connectContext) => options.connect(selected, connectContext) as never,\n key: selected => requireRequestKey(options.key(selected)),\n retention: options.retention,\n source: context.source,\n target,\n ...(options.consume === undefined\n ? {}\n : {\n consume: (consumeContext: Parameters<NonNullable<typeof options.consume>>[0]) =>\n options.consume!(consumeContext) as never,\n }),\n ...(reporter === undefined ? {} : { reporter }),\n ...(options.retry === undefined ? {} : { retry: options.retry }),\n });\n context.signal.addEventListener('abort', controller.fence, { once: true });\n\n if (context.signal.aborted) controller.fence();\n\n const detach = attachOpeningMaterialization(requireToken(), controller);\n\n return async () => {\n context.signal.removeEventListener('abort', controller.fence);\n let physicallyClosed = false;\n try {\n await controller.close();\n physicallyClosed = true;\n } finally {\n detach(physicallyClosed);\n }\n };\n },\n });\n registration.token = registerFeatureMaterialization(\n attachment as unknown as LifetimeAttachmentRefIdentity,\n 'stream',\n );\n\n return attachment;\n }) as unknown as FeatureStreamBuilder<Id>;\n}\n\nexport { createFeatureStreamBuilder, snapshotFeatureStreamOptions };\nexport type { FeatureStreamBuilder };\n"],"names":["streamOptionKeys","assertFeatureStreamKeys","keys","key","requireStreamFunction","value","optionalStreamFunction","snapshotFeatureStreamOptions","source","select","assertPlainRecord","entries","dataEntries","connect","consume","target","requireTargetSelector","snapshotStreamBackpressure","snapshotResourceRetention","snapshotResourceRetry","createFeatureStreamBuilder","attach","options","registration","requireToken","attachment","context","selectTargetReadable","reporter","getFeatureAttachmentReporter","controller","createStreamController","openingMaterializationGenerationAllocator","selected","connectContext","requireRequestKey","consumeContext","detach","attachOpeningMaterialization","physicallyClosed","registerFeatureMaterialization"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { RuntimeErrorReporter } from './runtime-error-reporting.js';
2
+ type FeatureTimerCallback = (signal: AbortSignal) => unknown;
3
+ type FeatureTimerCancellation = () => void;
4
+ interface FeatureTimers {
5
+ readonly delay: (milliseconds: number, callback: FeatureTimerCallback) => FeatureTimerCancellation;
6
+ readonly interval: (milliseconds: number, callback: FeatureTimerCallback) => FeatureTimerCancellation;
7
+ }
8
+ interface TimerRegistry {
9
+ readonly close: () => void;
10
+ readonly timers: FeatureTimers;
11
+ }
12
+ declare function createTimerRegistry(signal: AbortSignal, reporter?: RuntimeErrorReporter): TimerRegistry;
13
+ export { createTimerRegistry };
14
+ export type { FeatureTimers };
@@ -0,0 +1,2 @@
1
+ import{throwIfSignalAborted as p,reportDetachedError as T}from"@opetope/core/internal";import{reportRuntimeFailure as b}from"./runtime-error-reporting.js";function w(i,d){let f=!0,t;const l=d===void 0?T:e=>b(e,d),a=()=>{if(!f||(f=!1,t===void 0))return;i.removeEventListener("abort",a);const e=t;t=void 0;for(const r of e)r()},s=(e,r)=>{if(!f)throw new TypeError("Timer is unavailable after retire.");if(p(i),!Number.isFinite(e)||e<0)throw new TypeError("Timer duration must be finite and >= 0.");if(typeof r!="function")throw new TypeError("Timer callback must be a function.")},m=e=>{t===void 0&&(t=new Set,i.addEventListener("abort",a,{once:!0})),t.add(e)},c=e=>{t==null||t.delete(e),(t==null?void 0:t.size)===0&&(t=void 0,i.removeEventListener("abort",a))},v=e=>{if(f)try{const r=e(i);r!==void 0&&Promise.resolve(r).catch(l)}catch(r){l(r)}};return{close:a,timers:Object.freeze({delay:(e,r)=>{s(e,r);let o=!0,u;const n=()=>{o&&(o=!1,clearTimeout(u),c(n))};return u=setTimeout(()=>{o&&(o=!1,c(n),v(r))},e),m(n),n},interval:(e,r)=>{s(e,r);let o=!0,u;const n=()=>{o&&(o=!1,clearInterval(u),c(n))};return u=setInterval(()=>v(r),e),m(n),n}})}}export{w as createTimerRegistry};
2
+ //# sourceMappingURL=feature-timers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-timers.js","sources":["../src/feature-timers.ts"],"sourcesContent":["import { reportDetachedError, throwIfSignalAborted } from '@opetope/core/internal';\n\nimport { reportRuntimeFailure } from './runtime-error-reporting';\nimport type { RuntimeErrorReporter } from './runtime-error-reporting';\n\ntype FeatureTimerCallback = (signal: AbortSignal) => unknown;\ntype FeatureTimerCancellation = () => void;\n\ninterface FeatureTimers {\n readonly delay: (milliseconds: number, callback: FeatureTimerCallback) => FeatureTimerCancellation;\n readonly interval: (milliseconds: number, callback: FeatureTimerCallback) => FeatureTimerCancellation;\n}\n\ninterface TimerRegistry {\n readonly close: () => void;\n readonly timers: FeatureTimers;\n}\n\nfunction createTimerRegistry(signal: AbortSignal, reporter?: RuntimeErrorReporter): TimerRegistry {\n let active = true;\n let timers: Set<FeatureTimerCancellation> | undefined;\n const reportFailure =\n reporter === undefined ? reportDetachedError : (error: unknown): void => reportRuntimeFailure(error, reporter);\n const close = (): void => {\n if (!active) return;\n\n active = false;\n\n if (timers === undefined) return;\n\n signal.removeEventListener('abort', close);\n\n const enrolled = timers;\n timers = undefined;\n\n for (const cancel of enrolled) cancel();\n };\n const requireTimer = (milliseconds: number, callback: FeatureTimerCallback): void => {\n if (!active) throw new TypeError('Timer is unavailable after retire.');\n\n throwIfSignalAborted(signal);\n\n if (!Number.isFinite(milliseconds) || milliseconds < 0) {\n throw new TypeError('Timer duration must be finite and >= 0.');\n }\n\n if (typeof callback !== 'function') throw new TypeError('Timer callback must be a function.');\n };\n const enroll = (cancel: FeatureTimerCancellation): void => {\n if (timers === undefined) {\n timers = new Set();\n signal.addEventListener('abort', close, { once: true });\n }\n\n timers.add(cancel);\n };\n const release = (cancel: FeatureTimerCancellation): void => {\n timers?.delete(cancel);\n\n if (timers?.size !== 0) return;\n\n timers = undefined;\n signal.removeEventListener('abort', close);\n };\n const invoke = (callback: FeatureTimerCallback): void => {\n if (!active) return;\n\n try {\n const result = callback(signal);\n\n if (result !== undefined) void Promise.resolve(result).catch(reportFailure);\n } catch (error) {\n reportFailure(error);\n }\n };\n const delay = (milliseconds: number, callback: FeatureTimerCallback): FeatureTimerCancellation => {\n requireTimer(milliseconds, callback);\n\n let pending = true;\n // oxlint-disable-next-line prefer-const -- cancellation and timeout callbacks share the eventual handle.\n let timer: ReturnType<typeof setTimeout>;\n const cancel = (): void => {\n if (!pending) return;\n\n pending = false;\n clearTimeout(timer);\n release(cancel);\n };\n timer = setTimeout(() => {\n if (!pending) return;\n\n pending = false;\n release(cancel);\n invoke(callback);\n }, milliseconds);\n\n enroll(cancel);\n\n return cancel;\n };\n const interval = (milliseconds: number, callback: FeatureTimerCallback): FeatureTimerCancellation => {\n requireTimer(milliseconds, callback);\n\n let pending = true;\n // oxlint-disable-next-line prefer-const -- cancellation closes over the interval handle assigned below.\n let timer: ReturnType<typeof setInterval>;\n const cancel = (): void => {\n if (!pending) return;\n\n pending = false;\n clearInterval(timer);\n release(cancel);\n };\n timer = setInterval(() => invoke(callback), milliseconds);\n\n enroll(cancel);\n\n return cancel;\n };\n\n return { close, timers: Object.freeze({ delay, interval }) };\n}\n\nexport { createTimerRegistry };\nexport type { FeatureTimers };\n"],"names":["createTimerRegistry","signal","reporter","active","timers","reportFailure","reportDetachedError","error","reportRuntimeFailure","close","enrolled","cancel","requireTimer","milliseconds","callback","throwIfSignalAborted","enroll","release","invoke","result","pending","timer"],"mappings":"2JAkBA,SAASA,EAAoBC,EAAqBC,EAA+B,CAC/E,IAAIC,EAAS,GACTC,EACJ,MAAMC,EACJH,IAAa,OAAYI,EAAuBC,GAAyBC,EAAqBD,EAAOL,CAAQ,EACzGO,EAAQ,IAAW,CAKvB,GAJI,CAACN,IAELA,EAAS,GAELC,IAAW,QAAW,OAE1BH,EAAO,oBAAoB,QAASQ,CAAK,EAEzC,MAAMC,EAAWN,EACjBA,EAAS,OAET,UAAWO,KAAUD,EAAUC,EAAM,CACvC,EACMC,EAAe,CAACC,EAAsBC,IAAwC,CAClF,GAAI,CAACX,EAAQ,MAAM,IAAI,UAAU,oCAAoC,EAIrE,GAFAY,EAAqBd,CAAM,EAEvB,CAAC,OAAO,SAASY,CAAY,GAAKA,EAAe,EACnD,MAAM,IAAI,UAAU,yCAAyC,EAG/D,GAAI,OAAOC,GAAa,WAAY,MAAM,IAAI,UAAU,oCAAoC,CAC9F,EACME,EAAUL,GAA0C,CACpDP,IAAW,SACbA,EAAS,IAAI,IACbH,EAAO,iBAAiB,QAASQ,EAAO,CAAE,KAAM,GAAM,GAGxDL,EAAO,IAAIO,CAAM,CACnB,EACMM,EAAWN,GAA0C,CACzDP,GAAA,MAAAA,EAAQ,OAAOO,IAEXP,GAAA,YAAAA,EAAQ,QAAS,IAErBA,EAAS,OACTH,EAAO,oBAAoB,QAASQ,CAAK,EAC3C,EACMS,EAAUJ,GAAwC,CACtD,GAAKX,EAEL,GAAI,CACF,MAAMgB,EAASL,EAASb,CAAM,EAE1BkB,IAAW,QAAgB,QAAQ,QAAQA,CAAM,EAAE,MAAMd,CAAa,CAC5E,OAASE,EAAO,CACdF,EAAcE,CAAK,CACrB,CACF,EA8CA,MAAO,CAAE,MAAAE,EAAO,OAAQ,OAAO,OAAO,CAAE,MA7C1B,CAACI,EAAsBC,IAA4D,CAC/FF,EAAaC,EAAcC,CAAQ,EAEnC,IAAIM,EAAU,GAEVC,EACJ,MAAMV,EAAS,IAAW,CACnBS,IAELA,EAAU,GACV,aAAaC,CAAK,EAClBJ,EAAQN,CAAM,EAChB,EACA,OAAAU,EAAQ,WAAW,IAAK,CACjBD,IAELA,EAAU,GACVH,EAAQN,CAAM,EACdO,EAAOJ,CAAQ,EACjB,EAAGD,CAAY,EAEfG,EAAOL,CAAM,EAENA,CACT,EAqB+C,SApB9B,CAACE,EAAsBC,IAA4D,CAClGF,EAAaC,EAAcC,CAAQ,EAEnC,IAAIM,EAAU,GAEVC,EACJ,MAAMV,EAAS,IAAW,CACnBS,IAELA,EAAU,GACV,cAAcC,CAAK,EACnBJ,EAAQN,CAAM,EAChB,EACA,OAAAU,EAAQ,YAAY,IAAMH,EAAOJ,CAAQ,EAAGD,CAAY,EAExDG,EAAOL,CAAM,EAENA,CACT,CAEuD,CAAE,CAAC,CAC5D"}
@@ -0,0 +1,19 @@
1
+ export { defineApplication } from './application-definition.js';
2
+ export type { Application } from './application-definition.js';
3
+ export { ApplicationError, bind, openApplication } from './application-execution.js';
4
+ export type { ApplicationExecution, ApplicationImportBinding } from './application-execution.js';
5
+ export { defineCondition } from './condition.js';
6
+ export type { Condition } from './condition.js';
7
+ export { defineFeature } from './feature-authoring.js';
8
+ export type { Feature } from './feature-authoring.js';
9
+ export type { FeatureBody, FeatureBodyOf } from './feature-body.js';
10
+ export { defineHostContract, onDemand } from './feature-contract.js';
11
+ export type { HostContract } from './feature-contract.js';
12
+ export { openFeature } from './feature-generation.js';
13
+ export { optional } from './feature-optional.js';
14
+ export type { FeatureInstance } from './module-generation.js';
15
+ export type { CleanupFailurePolicy, ErrorReporter } from './public-module.js';
16
+ export { latest, scoped } from './resource-policy.js';
17
+ export type { LatestBackpressure, Resource, ResourceSnapshot, ScopedRetention } from './resource-types.js';
18
+ export { FeatureError } from '@opetope/core';
19
+ export type { Call, Readable } from '@opetope/core';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import{defineApplication as e}from"./application-definition.js";import{openApplication as p}from"./application-execution.js";import{defineCondition as f}from"./condition.js";import{defineFeature as m}from"./feature-authoring.js";import{defineHostContract as a,onDemand as d}from"./feature-contract.js";import{openFeature as l}from"./feature-generation.js";import{optional as u}from"./feature-optional.js";import{latest as F,scoped as C}from"./resource-policy.js";import{FeatureError as b}from"@opetope/core";import{ApplicationError as H}from"./application-error.js";import{bind as h}from"./application-open-options.js";export{H as ApplicationError,b as FeatureError,h as bind,e as defineApplication,f as defineCondition,m as defineFeature,a as defineHostContract,F as latest,d as onDemand,p as openApplication,l as openFeature,u as optional,C as scoped};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,63 @@
1
+ /** D206: bounded, data-only facts from the existing inspection port; never product inputs, values or error objects. */
2
+ type ActivityOwner = Readonly<{
3
+ feature: string;
4
+ generation: number;
5
+ instance: string;
6
+ }>;
7
+ type FeatureActivity = ActivityOwner & Readonly<{
8
+ body: 'eager' | 'loaded' | 'loading' | 'not-loaded' | 'unknown';
9
+ demandCount: 'unknown';
10
+ id: string;
11
+ phase: 'draining' | 'failed' | 'fenced' | 'opening' | 'quarantined' | 'ready';
12
+ }>;
13
+ type CallActivity = Readonly<{
14
+ callId: string;
15
+ declaration: string;
16
+ id: string;
17
+ lane: Readonly<{
18
+ blockedBy: readonly string[] | 'unknown';
19
+ declaration: string;
20
+ id: string;
21
+ }> | null;
22
+ owner: ActivityOwner;
23
+ pendingWaiters: number;
24
+ state: 'draining' | 'queued' | 'running';
25
+ }>;
26
+ type ResourceLoadActivity = Readonly<{
27
+ attempt: number;
28
+ generation: number;
29
+ id: string;
30
+ state: 'draining' | 'running' | 'scheduled';
31
+ }>;
32
+ type ResourceActivity = Readonly<{
33
+ generation: number;
34
+ id: string;
35
+ kind: 'resource' | 'stream';
36
+ loads: readonly ResourceLoadActivity[] | 'unknown';
37
+ owner: ActivityOwner;
38
+ retainers: 'unknown' | number;
39
+ retention: 'observer' | 'scope' | 'unknown';
40
+ state: 'error' | 'fenced' | 'idle' | 'opening' | 'ready' | 'refreshing';
41
+ }>;
42
+ type RuntimeActivitySnapshot = Readonly<{
43
+ calls: readonly CallActivity[];
44
+ /** Shared bound for feature, call, resource and nested load records. */
45
+ capacity: number;
46
+ /** True only after application close completes its physical drain successfully. */
47
+ closed: boolean;
48
+ coverage: Readonly<{
49
+ calls: 'feature-and-owned-model';
50
+ hostDemand: 'unknown';
51
+ resources: 'registered-resource-controllers';
52
+ streams: 'state-only';
53
+ uiModels: 'unknown';
54
+ }>;
55
+ executionId: string;
56
+ features: readonly FeatureActivity[];
57
+ /** Session close keeps a final data snapshot; it cannot establish subsequent ownership or liveness. */
58
+ freshness: 'live' | 'stale';
59
+ resources: readonly ResourceActivity[];
60
+ schemaRevision: 'opetope.runtime-activity/1';
61
+ truncated: boolean;
62
+ }>;
63
+ export type { ActivityOwner, CallActivity, FeatureActivity, ResourceActivity, ResourceLoadActivity, RuntimeActivitySnapshot, };
@@ -0,0 +1,54 @@
1
+ import type { CallExecutor, CallObservationSlot } from '@opetope/core/internal';
2
+ import type { ActivityOwner, FeatureActivity, ResourceActivity, ResourceLoadActivity, RuntimeActivitySnapshot } from './inspection-activity-protocol.js';
3
+ import type { ObservationSlot } from './inspection-observer.js';
4
+ import type { Resource, ResourceRequestKey } from './resource-types.js';
5
+ type ResourceInspection = Readonly<{
6
+ generation: number;
7
+ loads: readonly ResourceLoadActivity[];
8
+ retainers: number;
9
+ retention: 'observer' | 'scope';
10
+ state: ResourceActivity['state'];
11
+ truncated: boolean;
12
+ }>;
13
+ type InspectableResource = Resource<unknown, ResourceRequestKey> & {
14
+ readonly inspect?: (capacity: number) => ResourceInspection;
15
+ readonly inspectionState?: () => ResourceActivity['state'];
16
+ readonly observe?: (slot: CallObservationSlot) => void;
17
+ };
18
+ /** D206: one passive ownership record per real application opening, shared with the existing observer slot. */
19
+ declare class FeatureActivityOwner implements CallObservationSlot {
20
+ readonly slot: ObservationSlot;
21
+ readonly calls: Set<CallExecutor<unknown, unknown>>;
22
+ readonly id: string;
23
+ readonly identity: ActivityOwner;
24
+ phase: FeatureActivity['phase'];
25
+ readonly resources: Map<object, Readonly<{
26
+ id: string;
27
+ kind: "resource" | "stream";
28
+ resource: InspectableResource;
29
+ }>>;
30
+ get changed(): (() => void) | undefined;
31
+ private bodySource;
32
+ private resourceOrdinal;
33
+ constructor(executionId: string, featureId: string, generation: number, slot: ObservationSlot, body: () => FeatureActivity['body']);
34
+ body(): FeatureActivity['body'];
35
+ clear(): void;
36
+ registerCall(executor: CallExecutor<unknown, unknown>): void;
37
+ registerResource(kind: 'resource' | 'stream', resource: InspectableResource): void;
38
+ releaseCall(executor: CallExecutor<unknown, unknown>): void;
39
+ releaseResource(resource: object): void;
40
+ }
41
+ declare class ApplicationActivity {
42
+ private readonly observation;
43
+ readonly executionId: string;
44
+ readonly owners: Map<number, FeatureActivityOwner>;
45
+ private closed;
46
+ private readonly generations;
47
+ constructor(observation: ObservationSlot);
48
+ close(): void;
49
+ open(featureIndex: number, featureId: string, body: () => FeatureActivity['body']): FeatureActivityOwner;
50
+ retire(featureIndex: number, owner?: FeatureActivityOwner | undefined): void;
51
+ snapshot(capacity: number): RuntimeActivitySnapshot;
52
+ }
53
+ export { ApplicationActivity, FeatureActivityOwner };
54
+ export type { ResourceInspection };
@@ -0,0 +1,2 @@
1
+ import{nodeIds as d,encodeIdPart as u}from"./inspection-plan.js";const f=Object.freeze({calls:"feature-and-owned-model",hostDemand:"unknown",resources:"registered-resource-controllers",streams:"state-only",uiModels:"unknown"});let b=0;class h{slot;calls=new Set;id;identity;phase="opening";resources=new Map;get changed(){var e;return(e=this.slot.observer)==null?void 0:e.activityChanged}bodySource;resourceOrdinal=0;constructor(e,t,s,i,n){this.slot=i,this.identity=Object.freeze({feature:d.feature(t),generation:s,instance:d.instance(t)}),this.id=`${e}:${u(t)}:${String(s)}`,this.bodySource=n}body(){var e;return((e=this.bodySource)==null?void 0:e.call(this))??"unknown"}clear(){this.calls.clear(),this.resources.clear(),this.bodySource=void 0}registerCall(e){this.calls.add(e)}registerResource(e,t){var s,i;this.resources.has(t)||(this.resources.set(t,{id:`${this.id}:resource:${String(++this.resourceOrdinal)}`,kind:e,resource:t}),(s=t.observe)==null||s.call(t,this),(i=this.changed)==null||i.call(this))}releaseCall(e){var t;this.calls.delete(e),(t=this.changed)==null||t.call(this)}releaseResource(e){var t;this.resources.delete(e),(t=this.changed)==null||t.call(this)}}class g{executionId;capacity;calls=[];features=[];remaining;resources=[];truncated=!1;constructor(e,t){this.executionId=e,this.capacity=t,this.remaining=t}add(e){if(!this.take())return!1;this.features.push(Object.freeze({...e.identity,body:e.body(),demandCount:"unknown",id:e.id,phase:e.phase}));for(const t of e.calls)if(this.addCalls(e,t),this.truncated)return!1;for(const t of e.resources.values())if(this.addResource(e,t),this.truncated)return!1;return!0}finish(e){const t=new Set(this.calls.map(s=>s.id));for(const[s,i]of this.calls.entries())i.lane!==null&&i.lane.blockedBy!=="unknown"&&i.lane.blockedBy.some(n=>!t.has(n))&&(this.calls[s]=Object.freeze({...i,lane:Object.freeze({...i.lane,blockedBy:"unknown"})}));return Object.freeze({calls:Object.freeze(this.calls),capacity:this.capacity,closed:e,coverage:f,executionId:this.executionId,features:Object.freeze(this.features),freshness:"live",resources:Object.freeze(this.resources),schemaRevision:"opetope.runtime-activity/1",truncated:this.truncated})}addCalls(e,t){const s=t.inspect(this.remaining);this.truncated||(this.truncated=s.truncated);for(const i of s.calls){this.remaining-=1;const n=i.lane;this.calls.push(Object.freeze({...i,id:this.callId(i.id),lane:n===null?null:Object.freeze({blockedBy:n.blockedBy==="unknown"?"unknown":Object.freeze(n.blockedBy===null?[]:[this.callId(n.blockedBy)]),declaration:n.declaration,id:`${this.executionId}:lane:${String(n.id)}`}),owner:e.identity}))}}addResource(e,t){var n,a,o,c;if(!this.take())return;const s=(a=(n=t.resource).inspect)==null?void 0:a.call(n,this.remaining);if(s!==void 0){this.truncated||(this.truncated=s.truncated),this.remaining-=s.loads.length,this.resources.push(Object.freeze({generation:s.generation,id:t.id,kind:t.kind,loads:Object.freeze(s.loads.map(l=>Object.freeze({...l,id:`${t.id}:load:${l.id}`}))),owner:e.identity,retainers:s.retainers,retention:s.retention,state:s.state}));return}const i=t.resource.getSnapshot();this.resources.push(Object.freeze({generation:i.generation,id:t.id,kind:t.kind,loads:"unknown",owner:e.identity,retainers:"unknown",retention:"unknown",state:((c=(o=t.resource).inspectionState)==null?void 0:c.call(o))??i.status}))}callId(e){return`${this.executionId}:call:${String(e)}`}take(){return this.remaining>0?(this.remaining-=1,!0):(this.truncated=!0,!1)}}class y{observation;executionId=`execution-${String(++b)}`;owners=new Map;closed=!1;generations=[];constructor(e){this.observation=e}close(){var e;this.closed=!0,(e=this.observation.observer)==null||e.activityChanged()}open(e,t,s){const i=(this.generations[e]??0)+1;this.generations[e]=i;const n=new h(this.executionId,t,i,this.observation,s);return this.owners.set(e,n),n}retire(e,t=this.owners.get(e)){t!==void 0&&(t.clear(),this.owners.get(e)===t&&this.owners.delete(e))}snapshot(e){const t=new g(this.executionId,e);for(const s of this.owners.values())if(!t.add(s))break;return t.finish(this.closed)}}export{y as ApplicationActivity,h as FeatureActivityOwner};
2
+ //# sourceMappingURL=inspection-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-activity.js","sources":["../src/inspection-activity.ts"],"sourcesContent":["import type { CallExecutor, CallObservationSlot } from '@opetope/core/internal';\n\nimport type {\n ActivityOwner,\n CallActivity,\n FeatureActivity,\n ResourceActivity,\n ResourceLoadActivity,\n RuntimeActivitySnapshot,\n} from './inspection-activity-protocol';\nimport type { ObservationSlot } from './inspection-observer';\nimport { encodeIdPart, nodeIds } from './inspection-plan';\nimport type { Resource, ResourceRequestKey } from './resource-types';\n\ntype ResourceInspection = Readonly<{\n generation: number;\n loads: readonly ResourceLoadActivity[];\n retainers: number;\n retention: 'observer' | 'scope';\n state: ResourceActivity['state'];\n truncated: boolean;\n}>;\n\ntype InspectableResource = Resource<unknown, ResourceRequestKey> & {\n readonly inspect?: (capacity: number) => ResourceInspection;\n readonly inspectionState?: () => ResourceActivity['state'];\n readonly observe?: (slot: CallObservationSlot) => void;\n};\n\ntype ResourceSource = Readonly<{ id: string; kind: 'resource' | 'stream'; resource: InspectableResource }>;\n\nconst activityCoverage = Object.freeze({\n calls: 'feature-and-owned-model' as const,\n hostDemand: 'unknown' as const,\n resources: 'registered-resource-controllers' as const,\n streams: 'state-only' as const,\n uiModels: 'unknown' as const,\n});\nlet nextApplicationIdentity = 0;\n\n/** D206: one passive ownership record per real application opening, shared with the existing observer slot. */\nclass FeatureActivityOwner implements CallObservationSlot {\n readonly calls = new Set<CallExecutor<unknown, unknown>>();\n readonly id: string;\n readonly identity: ActivityOwner;\n phase: FeatureActivity['phase'] = 'opening';\n readonly resources = new Map<object, ResourceSource>();\n get changed(): (() => void) | undefined {\n return this.slot.observer?.activityChanged;\n }\n private bodySource: (() => FeatureActivity['body']) | undefined;\n\n private resourceOrdinal = 0;\n\n constructor(\n executionId: string,\n featureId: string,\n generation: number,\n readonly slot: ObservationSlot,\n body: () => FeatureActivity['body'],\n ) {\n this.identity = Object.freeze({\n feature: nodeIds.feature(featureId),\n generation,\n instance: nodeIds.instance(featureId),\n });\n this.id = `${executionId}:${encodeIdPart(featureId)}:${String(generation)}`;\n this.bodySource = body;\n }\n\n body(): FeatureActivity['body'] {\n return this.bodySource?.() ?? 'unknown';\n }\n\n clear(): void {\n this.calls.clear();\n this.resources.clear();\n this.bodySource = undefined;\n }\n\n registerCall(executor: CallExecutor<unknown, unknown>): void {\n // Both creators register an idle executor; its first admission publishes the first observable activity.\n this.calls.add(executor);\n }\n\n registerResource(kind: 'resource' | 'stream', resource: InspectableResource): void {\n if (this.resources.has(resource)) return;\n\n this.resources.set(resource, { id: `${this.id}:resource:${String(++this.resourceOrdinal)}`, kind, resource });\n resource.observe?.(this);\n this.changed?.();\n }\n\n releaseCall(executor: CallExecutor<unknown, unknown>): void {\n this.calls.delete(executor);\n this.changed?.();\n }\n\n releaseResource(resource: object): void {\n this.resources.delete(resource);\n this.changed?.();\n }\n}\n\n/** The snapshot cap includes nested load records, so a single resource cannot bypass the session bound. */\nclass ActivitySnapshotBuilder {\n private readonly calls: CallActivity[] = [];\n private readonly features: FeatureActivity[] = [];\n private remaining: number;\n private readonly resources: ResourceActivity[] = [];\n private truncated = false;\n\n constructor(\n private readonly executionId: string,\n private readonly capacity: number,\n ) {\n this.remaining = capacity;\n }\n\n add(owner: FeatureActivityOwner): boolean {\n if (!this.take()) return false;\n\n this.features.push(\n Object.freeze({\n ...owner.identity,\n body: owner.body(),\n demandCount: 'unknown',\n id: owner.id,\n phase: owner.phase,\n }),\n );\n for (const executor of owner.calls) {\n this.addCalls(owner, executor);\n\n if (this.truncated) return false;\n }\n for (const source of owner.resources.values()) {\n this.addResource(owner, source);\n\n if (this.truncated) return false;\n }\n\n return true;\n }\n\n finish(closed: boolean): RuntimeActivitySnapshot {\n const knownCalls = new Set(this.calls.map(call => call.id));\n for (const [index, call] of this.calls.entries()) {\n if (\n call.lane !== null &&\n call.lane.blockedBy !== 'unknown' &&\n call.lane.blockedBy.some(id => !knownCalls.has(id))\n ) {\n this.calls[index] = Object.freeze({ ...call, lane: Object.freeze({ ...call.lane, blockedBy: 'unknown' }) });\n }\n }\n\n return Object.freeze({\n calls: Object.freeze(this.calls),\n capacity: this.capacity,\n closed,\n coverage: activityCoverage,\n executionId: this.executionId,\n features: Object.freeze(this.features),\n freshness: 'live',\n resources: Object.freeze(this.resources),\n schemaRevision: 'opetope.runtime-activity/1',\n truncated: this.truncated,\n });\n }\n\n private addCalls(owner: FeatureActivityOwner, executor: CallExecutor<unknown, unknown>): void {\n const facts = executor.inspect(this.remaining);\n this.truncated ||= facts.truncated;\n for (const fact of facts.calls) {\n this.remaining -= 1;\n const lane = fact.lane;\n this.calls.push(\n Object.freeze({\n ...fact,\n id: this.callId(fact.id),\n lane:\n lane === null\n ? null\n : Object.freeze({\n blockedBy:\n lane.blockedBy === 'unknown'\n ? 'unknown'\n : Object.freeze(lane.blockedBy === null ? [] : [this.callId(lane.blockedBy)]),\n declaration: lane.declaration,\n id: `${this.executionId}:lane:${String(lane.id)}`,\n }),\n owner: owner.identity,\n }),\n );\n }\n }\n\n private addResource(owner: FeatureActivityOwner, source: ResourceSource): void {\n if (!this.take()) return;\n\n const fact = source.resource.inspect?.(this.remaining);\n\n if (fact !== undefined) {\n this.truncated ||= fact.truncated;\n this.remaining -= fact.loads.length;\n this.resources.push(\n Object.freeze({\n generation: fact.generation,\n id: source.id,\n kind: source.kind,\n loads: Object.freeze(fact.loads.map(load => Object.freeze({ ...load, id: `${source.id}:load:${load.id}` }))),\n owner: owner.identity,\n retainers: fact.retainers,\n retention: fact.retention,\n state: fact.state,\n }),\n );\n\n return;\n }\n\n const snapshot = source.resource.getSnapshot();\n this.resources.push(\n Object.freeze({\n generation: snapshot.generation,\n id: source.id,\n kind: source.kind,\n loads: 'unknown',\n owner: owner.identity,\n retainers: 'unknown',\n retention: 'unknown',\n state: source.resource.inspectionState?.() ?? snapshot.status,\n }),\n );\n }\n\n private callId(identity: number): string {\n return `${this.executionId}:call:${String(identity)}`;\n }\n\n private take(): boolean {\n if (this.remaining > 0) {\n this.remaining -= 1;\n\n return true;\n }\n\n this.truncated = true;\n\n return false;\n }\n}\n\nclass ApplicationActivity {\n readonly executionId = `execution-${String(++nextApplicationIdentity)}`;\n readonly owners = new Map<number, FeatureActivityOwner>();\n private closed = false;\n private readonly generations: number[] = [];\n\n constructor(private readonly observation: ObservationSlot) {}\n\n close(): void {\n this.closed = true;\n this.observation.observer?.activityChanged();\n }\n\n open(featureIndex: number, featureId: string, body: () => FeatureActivity['body']): FeatureActivityOwner {\n const generation = (this.generations[featureIndex] ?? 0) + 1;\n this.generations[featureIndex] = generation;\n const owner = new FeatureActivityOwner(this.executionId, featureId, generation, this.observation, body);\n this.owners.set(featureIndex, owner);\n\n return owner;\n }\n\n retire(featureIndex: number, owner = this.owners.get(featureIndex)): void {\n if (owner === undefined) return;\n\n owner.clear();\n\n if (this.owners.get(featureIndex) === owner) this.owners.delete(featureIndex);\n }\n\n snapshot(capacity: number): RuntimeActivitySnapshot {\n const builder = new ActivitySnapshotBuilder(this.executionId, capacity);\n for (const owner of this.owners.values()) {\n if (!builder.add(owner)) break;\n }\n\n return builder.finish(this.closed);\n }\n}\n\nexport { ApplicationActivity, FeatureActivityOwner };\nexport type { ResourceInspection };\n"],"names":["activityCoverage","nextApplicationIdentity","FeatureActivityOwner","_a","executionId","featureId","generation","slot","body","nodeIds","encodeIdPart","executor","kind","resource","_b","ActivitySnapshotBuilder","capacity","owner","source","closed","knownCalls","call","index","id","facts","fact","lane","load","snapshot","_d","_c","identity","ApplicationActivity","observation","featureIndex","builder"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Structural comparison of two protocol records, which is what decides whether a commit carries a node at all.
3
+ * `JSON.stringify` on both sides of every node and edge made an observed commit cost a serialization of the whole
4
+ * derived graph; the protocol is data-only (`docs/devtools.md` §6), so a walk over plain objects, arrays and primitives decides it
5
+ * Without allocating a string.
6
+ */
7
+ type Comparison = (left: unknown, right: unknown) => boolean;
8
+ /** One walk, three shapes: a primitive compares by identity, an array by position, a record by its data fields. */
9
+ declare const sameRecord: Comparison;
10
+ export { sameRecord };
@@ -0,0 +1,2 @@
1
+ function a(e){return typeof e=="object"&&e!==null}function i(e){return Object.entries(e).filter(([,r])=>r!==void 0).map(([r])=>r)}function o(e,r,n){return!Array.isArray(n)||r.length!==n.length?!1:r.every((s,t)=>e(s,n[t]))}function c(e,r,n){const s=i(r);return s.length!==i(n).length?!1:s.every(t=>e(r[t],n[t]))}const u=(e,r)=>e===r?!0:!a(e)||!a(r)?!1:Array.isArray(e)?o(u,e,r):Array.isArray(r)?!1:c(u,e,r);export{u as sameRecord};
2
+ //# sourceMappingURL=inspection-diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-diff.js","sources":["../src/inspection-diff.ts"],"sourcesContent":["/**\n * Structural comparison of two protocol records, which is what decides whether a commit carries a node at all.\n * `JSON.stringify` on both sides of every node and edge made an observed commit cost a serialization of the whole\n * derived graph; the protocol is data-only (`docs/devtools.md` §6), so a walk over plain objects, arrays and primitives decides it\n * Without allocating a string.\n */\n\ntype Comparison = (left: unknown, right: unknown) => boolean;\n\nfunction isRecord(value: unknown): value is object {\n return typeof value === 'object' && value !== null;\n}\n\nfunction dataKeys(value: object): readonly string[] {\n return Object.entries(value)\n .filter(([, entry]) => entry !== undefined)\n .map(([key]) => key);\n}\n\nfunction sameList(same: Comparison, left: readonly unknown[], right: unknown): boolean {\n if (!Array.isArray(right) || left.length !== right.length) return false;\n\n return left.every((entry, index) => same(entry, right[index]));\n}\n\nfunction sameFields(same: Comparison, left: object, right: object): boolean {\n const keys = dataKeys(left);\n\n if (keys.length !== dataKeys(right).length) return false;\n\n return keys.every(key => same((left as Record<string, unknown>)[key], (right as Record<string, unknown>)[key]));\n}\n\n/** One walk, three shapes: a primitive compares by identity, an array by position, a record by its data fields. */\nconst sameRecord: Comparison = (left, right) => {\n if (left === right) return true;\n\n if (!isRecord(left) || !isRecord(right)) return false;\n\n if (Array.isArray(left)) return sameList(sameRecord, left, right);\n\n return Array.isArray(right) ? false : sameFields(sameRecord, left, right);\n};\n\nexport { sameRecord };\n"],"names":["isRecord","value","dataKeys","entry","key","sameList","same","left","right","index","sameFields","keys","sameRecord"],"mappings":"AASA,SAASA,EAASC,EAAc,CAC9B,OAAO,OAAOA,GAAU,UAAYA,IAAU,IAChD,CAEA,SAASC,EAASD,EAAa,CAC7B,OAAO,OAAO,QAAQA,CAAK,EACxB,OAAO,CAAC,CAAA,CAAGE,CAAK,IAAMA,IAAU,MAAS,EACzC,IAAI,CAAC,CAACC,CAAG,IAAMA,CAAG,CACvB,CAEA,SAASC,EAASC,EAAkBC,EAA0BC,EAAc,CAC1E,MAAI,CAAC,MAAM,QAAQA,CAAK,GAAKD,EAAK,SAAWC,EAAM,OAAe,GAE3DD,EAAK,MAAM,CAACJ,EAAOM,IAAUH,EAAKH,EAAOK,EAAMC,CAAK,CAAC,CAAC,CAC/D,CAEA,SAASC,EAAWJ,EAAkBC,EAAcC,EAAa,CAC/D,MAAMG,EAAOT,EAASK,CAAI,EAE1B,OAAII,EAAK,SAAWT,EAASM,CAAK,EAAE,OAAe,GAE5CG,EAAK,MAAMP,GAAOE,EAAMC,EAAiCH,CAAG,EAAII,EAAkCJ,CAAG,CAAC,CAAC,CAChH,CAGA,MAAMQ,EAAyB,CAACL,EAAMC,IAChCD,IAASC,EAAc,GAEvB,CAACR,EAASO,CAAI,GAAK,CAACP,EAASQ,CAAK,EAAU,GAE5C,MAAM,QAAQD,CAAI,EAAUF,EAASO,EAAYL,EAAMC,CAAK,EAEzD,MAAM,QAAQA,CAAK,EAAI,GAAQE,EAAWE,EAAYL,EAAMC,CAAK"}
@@ -0,0 +1,4 @@
1
+ import type { FeatureActivityOwner } from './inspection-activity.js';
2
+ /** Ownership follows the existing local instance record before any model or attachment starts. */
3
+ declare function registerModuleActivity(instance: object, owner: FeatureActivityOwner): void;
4
+ export { registerModuleActivity };
@@ -0,0 +1,2 @@
1
+ import{requireActiveLocal as r,requireModuleInstance as c}from"./public-module-state.js";function a(o,e){const i=r(c(o));i.callRegistry.activity=e;for(const t of i.materializationBindings)t==null||t.observe(e)}export{a as registerModuleActivity};
2
+ //# sourceMappingURL=inspection-module-activity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-module-activity.js","sources":["../src/inspection-module-activity.ts"],"sourcesContent":["import type { FeatureActivityOwner } from './inspection-activity';\nimport { requireActiveLocal, requireModuleInstance } from './public-module-state';\n\n/** Ownership follows the existing local instance record before any model or attachment starts. */\nfunction registerModuleActivity(instance: object, owner: FeatureActivityOwner): void {\n const local = requireActiveLocal(requireModuleInstance(instance));\n local.callRegistry.activity = owner;\n for (const binding of local.materializationBindings) binding?.observe(owner);\n}\n\nexport { registerModuleActivity };\n"],"names":["registerModuleActivity","instance","owner","local","requireActiveLocal","requireModuleInstance","binding"],"mappings":"yFAIA,SAASA,EAAuBC,EAAkBC,EAA2B,CAC3E,MAAMC,EAAQC,EAAmBC,EAAsBJ,CAAQ,CAAC,EAChEE,EAAM,aAAa,SAAWD,EAC9B,UAAWI,KAAWH,EAAM,wBAAyBG,GAAA,MAAAA,EAAS,QAAQJ,EACxE"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The seam the lifecycle calls when someone is watching. Without a session the slot holds `undefined`, so an
3
+ * unobserved application reads the empty slot and allocates no per-operation observation record (`docs/devtools.md` §3.2).
4
+ */
5
+ import type { ConditionGroupState, DiagnosticConditionId, DiagnosticNodeId, DiagnosticPhase } from './inspection-protocol.js';
6
+ interface ApplicationObserver {
7
+ readonly activityChanged: () => void;
8
+ /** The conjunction of a group's conditions was republished; the truth of each one is pulled, not pushed. */
9
+ readonly conditionsChanged: (groupId: string) => void;
10
+ /** A target republished its live entries, so a `when` moved a contribution between published and withheld (D167). */
11
+ readonly contributionsChanged: (targetId: string) => void;
12
+ /**
13
+ * A control command was accepted and is about to change the graph: the frame the change publishes carries this
14
+ * cause instead of its own, so «what I did» and «what happened» read as one line of the timeline (D176).
15
+ */
16
+ readonly controlAttributed: (node: DiagnosticNodeId, condition: DiagnosticConditionId | undefined) => void;
17
+ /** The frame a control command is visible in; the port reports it back to the caller as `applied.sequence`. */
18
+ readonly currentSequence: () => number;
19
+ readonly groupState: (groupId: string, state: ConditionGroupState) => void;
20
+ readonly instanceFailed: (featureIndex: number, error: unknown, phase: DiagnosticPhase) => void;
21
+ readonly instanceOpening: (featureIndex: number) => void;
22
+ readonly instanceReady: (featureIndex: number) => void;
23
+ readonly instanceRetired: (featureIndex: number) => void;
24
+ readonly instanceRetiring: (featureIndex: number) => void;
25
+ }
26
+ /**
27
+ * A holder, not a value: a session may attach long after the application opened, and the lifecycle keeps the slot.
28
+ * `closeSession` is how the application takes the session down with itself, so closing an application never leaves a
29
+ * Live ring, live readables and a registry entry behind (D167).
30
+ */
31
+ type ObservationSlot = {
32
+ closeSession: (() => void) | undefined;
33
+ completed: boolean;
34
+ observer: ApplicationObserver | undefined;
35
+ };
36
+ declare function createObservationSlot(): ObservationSlot;
37
+ export { createObservationSlot };
38
+ export type { ApplicationObserver, ObservationSlot };
@@ -0,0 +1,2 @@
1
+ function e(){return{closeSession:void 0,completed:!1,observer:void 0}}export{e as createObservationSlot};
2
+ //# sourceMappingURL=inspection-observer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-observer.js","sources":["../src/inspection-observer.ts"],"sourcesContent":["/**\n * The seam the lifecycle calls when someone is watching. Without a session the slot holds `undefined`, so an\n * unobserved application reads the empty slot and allocates no per-operation observation record (`docs/devtools.md` §3.2).\n */\n\nimport type {\n ConditionGroupState,\n DiagnosticConditionId,\n DiagnosticNodeId,\n DiagnosticPhase,\n} from './inspection-protocol';\n\ninterface ApplicationObserver {\n readonly activityChanged: () => void;\n /** The conjunction of a group's conditions was republished; the truth of each one is pulled, not pushed. */\n readonly conditionsChanged: (groupId: string) => void;\n /** A target republished its live entries, so a `when` moved a contribution between published and withheld (D167). */\n readonly contributionsChanged: (targetId: string) => void;\n /**\n * A control command was accepted and is about to change the graph: the frame the change publishes carries this\n * cause instead of its own, so «what I did» and «what happened» read as one line of the timeline (D176).\n */\n readonly controlAttributed: (node: DiagnosticNodeId, condition: DiagnosticConditionId | undefined) => void;\n /** The frame a control command is visible in; the port reports it back to the caller as `applied.sequence`. */\n readonly currentSequence: () => number;\n readonly groupState: (groupId: string, state: ConditionGroupState) => void;\n readonly instanceFailed: (featureIndex: number, error: unknown, phase: DiagnosticPhase) => void;\n readonly instanceOpening: (featureIndex: number) => void;\n readonly instanceReady: (featureIndex: number) => void;\n readonly instanceRetired: (featureIndex: number) => void;\n readonly instanceRetiring: (featureIndex: number) => void;\n}\n\n/**\n * A holder, not a value: a session may attach long after the application opened, and the lifecycle keeps the slot.\n * `closeSession` is how the application takes the session down with itself, so closing an application never leaves a\n * Live ring, live readables and a registry entry behind (D167).\n */\ntype ObservationSlot = {\n closeSession: (() => void) | undefined;\n completed: boolean;\n observer: ApplicationObserver | undefined;\n};\n\nfunction createObservationSlot(): ObservationSlot {\n return { closeSession: undefined, completed: false, observer: undefined };\n}\n\nexport { createObservationSlot };\nexport type { ApplicationObserver, ObservationSlot };\n"],"names":["createObservationSlot"],"mappings":"AA4CA,SAASA,GAAqB,CAC5B,MAAO,CAAE,aAAc,OAAW,UAAW,GAAO,SAAU,MAAS,CACzE"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The immutable half of the observation port: the compiled topology, projected node by node from
3
+ * `CompiledApplicationPlanIR` (`docs/devtools.md` §4).
4
+ *
5
+ * Everything here is derived once per session and never changes: a plan replacement opens a new session instead of
6
+ * mutating this (§4.1). Ids are the declaration ids with a kind prefix, so a port and the feature that provides it
7
+ * cannot collide, and characters the consumer's id grammar rejects are escaped instead of folded (D200).
8
+ */
9
+ import type { CompiledApplicationPlanIR } from './application-compiler.js';
10
+ import type { ApplicationPlanSnapshot, DiagnosticConditionId, DiagnosticNodeId } from './inspection-protocol.js';
11
+ /** One pass, no `String.prototype.replaceAll`: Chrome 82 is the browser floor, and that floor is a contract. */
12
+ declare function encodeIdPart(value: string): string;
13
+ declare const nodeIds: {
14
+ readonly absentProvider: (contractId: string) => DiagnosticNodeId;
15
+ readonly application: (applicationId: string) => DiagnosticNodeId;
16
+ readonly condition: (conditionId: string) => DiagnosticNodeId;
17
+ readonly contribution: (contributionId: string) => DiagnosticNodeId;
18
+ readonly feature: (featureId: string) => DiagnosticNodeId;
19
+ readonly group: (groupId: string) => DiagnosticNodeId;
20
+ readonly hostContract: (contractId: string) => DiagnosticNodeId;
21
+ readonly instance: (featureId: string) => DiagnosticNodeId;
22
+ readonly port: (portId: string) => DiagnosticNodeId;
23
+ readonly target: (targetId: string) => DiagnosticNodeId;
24
+ };
25
+ /**
26
+ * The atom a control command addresses. It is the same encoding every other diagnostic id uses, so a declaration id
27
+ * that admits `/` or `:` reaches the consumer's grammar intact; the readable original stays in the node label (D200).
28
+ */
29
+ declare function conditionAtomId(conditionId: string): DiagnosticConditionId;
30
+ /** The ends of an edge are themselves composed ids, so they are escaped again before `:` joins the three parts. */
31
+ declare function diagnosticEdgeId(kind: string, from: DiagnosticNodeId, to: DiagnosticNodeId): string;
32
+ declare function projectApplicationPlan(plan: CompiledApplicationPlanIR, applicationId: string): ApplicationPlanSnapshot;
33
+ export { conditionAtomId, diagnosticEdgeId, encodeIdPart, nodeIds, projectApplicationPlan };
@@ -0,0 +1,2 @@
1
+ import{requireConditionRecord as b}from"./condition.js";const I=new Map([["/","_s"],[":","_c"],["_","__"],["|","_p"]]);function d(t){let r="";for(const o of t){const i=I.get(o);if(i!==void 0){r+=i;continue}r+=/[A-Za-z0-9.-]/u.test(o)?o:`_u${(o.codePointAt(0)??0).toString(16)}_`}return r}const n={absentProvider:t=>`absent:${d(t)}`,application:t=>`application:${d(t)}`,condition:t=>`condition:${d(t)}`,contribution:t=>`contribution:${d(t)}`,feature:t=>d(t),group:t=>`group:${d(t)}`,hostContract:t=>`host:${d(t)}`,instance:t=>`instance:${d(t)}`,port:t=>`port:${d(t)}`,target:t=>`target:${d(t)}`};function s(t){return d(t)}function u(t,r,o){return`${t}:${d(r)}:${d(o)}`}function c(t,r,o){return Object.freeze({from:r,id:u(t,r,o),kind:t,to:o})}function f(t,r,o){return Object.freeze({from:r,id:u(t,r,o),kind:t,pending:!1,to:o})}function a(t,r,o){return Object.freeze({from:r,id:u(t,r,o),kind:t,lookup:"missing",to:o})}function p(t,r){return t.kind==="group"?n.group(t.groupId):r}function l(t){return t.kind==="feature"?n.feature(t.featureId):t.kind==="absent"?n.absentProvider(t.contractId):n.hostContract(t.contractId)}function m(t){if(t.kind==="provides-port")return c("provides-port",n.feature(t.featureId),n.port(t.portId));const r=n.feature(t.consumerFeatureId),o=n.port(t.portId);return t.kind==="absent-port"?a("absent-port",o,r):f("requires-port",o,r)}function g(t){const r=n.feature(t.consumerFeatureId),o=l(t.provider);return t.kind==="hard-import"?f("hard-import",o,r):t.kind==="on-demand-import"?c("on-demand-import",o,r):a(t.kind,o,r)}function k(t,r){return t.kind==="owns"?c("owns",p(t.owner,r),n.feature(t.featureId)):t.kind==="condition-control"?c("condition-control",n.condition(t.conditionId),n.group(t.groupId)):t.kind==="contributes-to"?c("contributes-to",n.contribution(t.contributionId),n.target(t.targetId)):t.kind==="absent-port"||t.kind==="provides-port"||t.kind==="requires-port"?m(t):g(t)}function h(t,r){const o=new Set(t.requirements.filter(e=>e.optional&&e.provider!==void 0).map(e=>`${e.consumerFeatureId}:${e.portId}`)),i=[];for(const e of t.edges){if(e.kind==="requires-port"&&o.has(`${e.consumerFeatureId}:${e.portId}`)){i.push(a("optional-port",n.port(e.portId),n.feature(e.consumerFeatureId)));continue}i.push(k(e,r))}for(const e of t.contributions)i.push(c("owns",n.feature(e.contributorFeatureId),n.contribution(e.contributionId)));return Object.freeze(i)}function v(t){const r=new Map;for(const o of t.groups)for(const i of o.conditions){const e=b(i);r.set(i.id,{conditionId:s(i.id),id:n.condition(i.id),kind:"condition",label:i.id,source:e.from===void 0?"host":n.feature(e.from.id)})}return Object.freeze([...r.values()])}function $(t){return Object.freeze(t.groups.map(r=>({conditions:Object.freeze(r.conditions.map(o=>s(o.id))),id:n.group(r.groupId),kind:"condition-group",label:`when ${r.conditions.map(o=>o.id).join(" & ")}`,order:Object.freeze(r.activationOrder.map(o=>{var i;return n.feature(((i=t.features[o])==null?void 0:i.featureId)??String(o))}))})))}function j(t){const r=new Map;for(const o of t.providers)r.set(o.portId,{id:n.port(o.portId),kind:"port",label:o.portId,provider:n.feature(o.featureId)});for(const o of t.requirements)r.has(o.portId)||r.set(o.portId,{id:n.port(o.portId),kind:"port",label:o.portId});return Object.freeze([...r.values()])}function w(t){const r=new Map;for(const o of t.imports)o.provider.kind==="application-input"&&r.set(o.contractId,{demand:o.demand,id:n.hostContract(o.contractId),kind:"host-contract",label:o.contractId,optional:o.optional});return Object.freeze([...r.values()])}function z(t){const r=new Map;for(const o of t.imports)o.provider.kind==="absent"&&r.set(o.contractId,{id:n.absentProvider(o.contractId),kind:"absent-provider",label:o.contractId});return Object.freeze([...r.values()])}function O(t){const r=new Map;for(const o of t.contributions)r.set(o.targetId,{id:n.target(o.targetId),kind:"contribution-target",label:o.targetId});return Object.freeze([...r.values()])}function P(t){return Object.freeze(t.contributions.map(r=>({contributor:n.feature(r.contributorFeatureId),id:n.contribution(r.contributionId),kind:"contribution",label:r.contributionId,priority:r.priority,target:n.target(r.targetId)})))}function N(t,r){return Object.freeze(t.features.map(o=>({id:n.feature(o.featureId),kind:"feature",label:o.featureId,owner:p(o.owner,r)})))}function E(t,r){const o=n.application(r);return Object.freeze({absentProviders:z(t),application:{features:t.features.length,groups:t.groups.length,id:o,kind:"application",label:r},conditions:v(t),contributions:P(t),edges:h(t,o),features:N(t,o),groups:$(t),hostContracts:w(t),ports:j(t),targets:O(t)})}export{s as conditionAtomId,u as diagnosticEdgeId,d as encodeIdPart,n as nodeIds,E as projectApplicationPlan};
2
+ //# sourceMappingURL=inspection-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspection-plan.js","sources":["../src/inspection-plan.ts"],"sourcesContent":["/**\n * The immutable half of the observation port: the compiled topology, projected node by node from\n * `CompiledApplicationPlanIR` (`docs/devtools.md` §4).\n *\n * Everything here is derived once per session and never changes: a plan replacement opens a new session instead of\n * mutating this (§4.1). Ids are the declaration ids with a kind prefix, so a port and the feature that provides it\n * cannot collide, and characters the consumer's id grammar rejects are escaped instead of folded (D200).\n */\n\nimport type { DeclarationId } from '@opetope/core';\n\nimport type {\n ApplicationImportProviderIR,\n ApplicationLifetimeOwnerIR,\n ApplicationTopologyEdgeIR,\n CompiledApplicationPlanIR,\n} from './application-compiler';\nimport { requireConditionRecord } from './condition';\nimport type {\n AbsentProviderPlanNode,\n ApplicationPlanSnapshot,\n ConditionGroupPlanNode,\n ConditionPlanNode,\n ContributionPlanNode,\n ContributionTargetPlanNode,\n DiagnosticConditionId,\n DiagnosticEdge,\n DiagnosticNodeId,\n FeaturePlanNode,\n HostContractPlanNode,\n PortPlanNode,\n} from './inspection-protocol';\n\n/**\n * D200: one diagnostic id names one thing. Declaration ids admit `/` and `:`, group keys join condition ids with\n * `|`, and the consumer's grammar accepts none of the first and reads the second as a separator, so every part is\n * escaped with `_` before it is composed. A valid declaration id never carries `_`, and the escape is reversible,\n * so distinct parts stay distinct: `probe.inspect/a` and `probe.inspect-a` are two nodes, not one.\n */\nconst idEscapes = new Map<string, string>([\n ['/', '_s'],\n [':', '_c'],\n ['_', '__'],\n ['|', '_p'],\n]);\n\n/** One pass, no `String.prototype.replaceAll`: Chrome 82 is the browser floor, and that floor is a contract. */\nfunction encodeIdPart(value: string): string {\n let encoded = '';\n\n for (const character of value) {\n const escape = idEscapes.get(character);\n\n if (escape !== undefined) {\n encoded += escape;\n continue;\n }\n\n // Anything else the grammar rejects keeps its code point, so an unexpected id stays readable and still unique.\n encoded += /[A-Za-z0-9.-]/u.test(character) ? character : `_u${(character.codePointAt(0) ?? 0).toString(16)}_`;\n }\n\n return encoded;\n}\n\nconst nodeIds = {\n absentProvider: (contractId: string): DiagnosticNodeId => `absent:${encodeIdPart(contractId)}`,\n application: (applicationId: string): DiagnosticNodeId => `application:${encodeIdPart(applicationId)}`,\n condition: (conditionId: string): DiagnosticNodeId => `condition:${encodeIdPart(conditionId)}`,\n contribution: (contributionId: string): DiagnosticNodeId => `contribution:${encodeIdPart(contributionId)}`,\n feature: (featureId: string): DiagnosticNodeId => encodeIdPart(featureId),\n group: (groupId: string): DiagnosticNodeId => `group:${encodeIdPart(groupId)}`,\n hostContract: (contractId: string): DiagnosticNodeId => `host:${encodeIdPart(contractId)}`,\n instance: (featureId: string): DiagnosticNodeId => `instance:${encodeIdPart(featureId)}`,\n port: (portId: string): DiagnosticNodeId => `port:${encodeIdPart(portId)}`,\n target: (targetId: string): DiagnosticNodeId => `target:${encodeIdPart(targetId)}`,\n} as const;\n\n/**\n * The atom a control command addresses. It is the same encoding every other diagnostic id uses, so a declaration id\n * that admits `/` or `:` reaches the consumer's grammar intact; the readable original stays in the node label (D200).\n */\nfunction conditionAtomId(conditionId: string): DiagnosticConditionId {\n return encodeIdPart(conditionId);\n}\n\n/** The ends of an edge are themselves composed ids, so they are escaped again before `:` joins the three parts. */\nfunction diagnosticEdgeId(kind: string, from: DiagnosticNodeId, to: DiagnosticNodeId): string {\n return `${kind}:${encodeIdPart(from)}:${encodeIdPart(to)}`;\n}\n\n/** A structural edge names a relation the compiler decided; nothing reports on it later. */\nfunction structuralEdge(\n kind: 'condition-control' | 'contributes-to' | 'on-demand-import' | 'owns' | 'provides-port',\n from: DiagnosticNodeId,\n to: DiagnosticNodeId,\n): DiagnosticEdge {\n return Object.freeze({ from, id: diagnosticEdgeId(kind, from, to), kind, to });\n}\n\n/** A hard edge is the only kind an activation waits on; a declaration itself never waits, so the plan reads false. */\nfunction hardEdge(kind: 'hard-import' | 'requires-port', from: DiagnosticNodeId, to: DiagnosticNodeId): DiagnosticEdge {\n return Object.freeze({ from, id: diagnosticEdgeId(kind, from, to), kind, pending: false, to });\n}\n\n/** A weak edge carries the `Lookup` its consumer reads; before any instance opens that is `missing` (D105). */\nfunction weakEdge(\n kind: 'absent-import' | 'absent-port' | 'optional-import' | 'optional-port',\n from: DiagnosticNodeId,\n to: DiagnosticNodeId,\n): DiagnosticEdge {\n return Object.freeze({ from, id: diagnosticEdgeId(kind, from, to), kind, lookup: 'missing', to });\n}\n\nfunction ownerNodeId(owner: ApplicationLifetimeOwnerIR, applicationId: DiagnosticNodeId): DiagnosticNodeId {\n return owner.kind === 'group' ? nodeIds.group(owner.groupId) : applicationId;\n}\n\nfunction importProviderNodeId(provider: ApplicationImportProviderIR): DiagnosticNodeId {\n if (provider.kind === 'feature') return nodeIds.feature(provider.featureId);\n\n return provider.kind === 'absent'\n ? nodeIds.absentProvider(provider.contractId)\n : nodeIds.hostContract(provider.contractId);\n}\n\n/** T14: the port is a node of its own, so the IR edge that names both features becomes provider → port → consumer. */\nfunction portPlanEdge(\n edge: Extract<ApplicationTopologyEdgeIR, { kind: 'absent-port' | 'provides-port' | 'requires-port' }>,\n): DiagnosticEdge {\n if (edge.kind === 'provides-port') {\n return structuralEdge('provides-port', nodeIds.feature(edge.featureId), nodeIds.port(edge.portId));\n }\n\n const consumer = nodeIds.feature(edge.consumerFeatureId);\n const port = nodeIds.port(edge.portId);\n\n return edge.kind === 'absent-port'\n ? weakEdge('absent-port', port, consumer)\n : hardEdge('requires-port', port, consumer);\n}\n\nfunction importPlanEdge(\n edge: Extract<\n ApplicationTopologyEdgeIR,\n { kind: 'absent-import' | 'hard-import' | 'on-demand-import' | 'optional-import' }\n >,\n): DiagnosticEdge {\n const consumer = nodeIds.feature(edge.consumerFeatureId);\n const provider = importProviderNodeId(edge.provider);\n\n if (edge.kind === 'hard-import') return hardEdge('hard-import', provider, consumer);\n\n if (edge.kind === 'on-demand-import') return structuralEdge('on-demand-import', provider, consumer);\n\n return weakEdge(edge.kind, provider, consumer);\n}\n\nfunction planEdge(edge: ApplicationTopologyEdgeIR, applicationId: DiagnosticNodeId): DiagnosticEdge {\n if (edge.kind === 'owns') {\n return structuralEdge('owns', ownerNodeId(edge.owner, applicationId), nodeIds.feature(edge.featureId));\n }\n\n if (edge.kind === 'condition-control') {\n return structuralEdge('condition-control', nodeIds.condition(edge.conditionId), nodeIds.group(edge.groupId));\n }\n\n if (edge.kind === 'contributes-to') {\n return structuralEdge('contributes-to', nodeIds.contribution(edge.contributionId), nodeIds.target(edge.targetId));\n }\n\n if (edge.kind === 'absent-port' || edge.kind === 'provides-port' || edge.kind === 'requires-port') {\n return portPlanEdge(edge);\n }\n\n return importPlanEdge(edge);\n}\n\n/**\n * T13: the IR keeps one `requires-port` edge for a hard and a weak requirement, so the weak half is split out here\n * by `CompiledApplicationRequirementIR.optional`. T16: a contribution is a node, so the single IR edge becomes\n * ownership plus `contributes-to`.\n */\nfunction planEdges(plan: CompiledApplicationPlanIR, applicationId: DiagnosticNodeId): readonly DiagnosticEdge[] {\n const weakRequirements = new Set(\n plan.requirements\n .filter(requirement => requirement.optional && requirement.provider !== undefined)\n .map(requirement => `${requirement.consumerFeatureId}:${requirement.portId}`),\n );\n const edges: DiagnosticEdge[] = [];\n\n for (const edge of plan.edges) {\n if (edge.kind === 'requires-port' && weakRequirements.has(`${edge.consumerFeatureId}:${edge.portId}`)) {\n edges.push(weakEdge('optional-port', nodeIds.port(edge.portId), nodeIds.feature(edge.consumerFeatureId)));\n\n continue;\n }\n\n edges.push(planEdge(edge, applicationId));\n }\n\n for (const contribution of plan.contributions) {\n edges.push(\n structuralEdge(\n 'owns',\n nodeIds.feature(contribution.contributorFeatureId),\n nodeIds.contribution(contribution.contributionId),\n ),\n );\n }\n\n return Object.freeze(edges);\n}\n\nfunction conditionNodes(plan: CompiledApplicationPlanIR): readonly ConditionPlanNode[] {\n const nodes = new Map<DeclarationId, ConditionPlanNode>();\n\n for (const group of plan.groups) {\n for (const condition of group.conditions) {\n const record = requireConditionRecord(condition);\n\n nodes.set(condition.id, {\n conditionId: conditionAtomId(condition.id),\n id: nodeIds.condition(condition.id),\n kind: 'condition',\n label: condition.id,\n source: record.from === undefined ? 'host' : nodeIds.feature(record.from.id),\n });\n }\n }\n\n return Object.freeze([...nodes.values()]);\n}\n\nfunction groupNodes(plan: CompiledApplicationPlanIR): readonly ConditionGroupPlanNode[] {\n return Object.freeze(\n plan.groups.map(group => ({\n conditions: Object.freeze(group.conditions.map(condition => conditionAtomId(condition.id))),\n id: nodeIds.group(group.groupId),\n kind: 'condition-group' as const,\n label: `when ${group.conditions.map(condition => condition.id as string).join(' & ')}`,\n order: Object.freeze(\n group.activationOrder.map(index => nodeIds.feature(plan.features[index]?.featureId ?? String(index))),\n ),\n })),\n );\n}\n\nfunction portNodes(plan: CompiledApplicationPlanIR): readonly PortPlanNode[] {\n const nodes = new Map<string, PortPlanNode>();\n\n for (const provider of plan.providers) {\n nodes.set(provider.portId, {\n id: nodeIds.port(provider.portId),\n kind: 'port',\n label: provider.portId,\n provider: nodeIds.feature(provider.featureId),\n });\n }\n\n for (const requirement of plan.requirements) {\n if (nodes.has(requirement.portId)) continue;\n\n nodes.set(requirement.portId, { id: nodeIds.port(requirement.portId), kind: 'port', label: requirement.portId });\n }\n\n return Object.freeze([...nodes.values()]);\n}\n\nfunction hostContractNodes(plan: CompiledApplicationPlanIR): readonly HostContractPlanNode[] {\n const nodes = new Map<string, HostContractPlanNode>();\n\n for (const binding of plan.imports) {\n if (binding.provider.kind !== 'application-input') continue;\n\n nodes.set(binding.contractId, {\n demand: binding.demand,\n id: nodeIds.hostContract(binding.contractId),\n kind: 'host-contract',\n label: binding.contractId,\n optional: binding.optional,\n });\n }\n\n return Object.freeze([...nodes.values()]);\n}\n\nfunction absentProviderNodes(plan: CompiledApplicationPlanIR): readonly AbsentProviderPlanNode[] {\n const nodes = new Map<string, AbsentProviderPlanNode>();\n\n for (const binding of plan.imports) {\n if (binding.provider.kind !== 'absent') continue;\n\n nodes.set(binding.contractId, {\n id: nodeIds.absentProvider(binding.contractId),\n kind: 'absent-provider',\n label: binding.contractId,\n });\n }\n\n return Object.freeze([...nodes.values()]);\n}\n\nfunction targetNodes(plan: CompiledApplicationPlanIR): readonly ContributionTargetPlanNode[] {\n const nodes = new Map<string, ContributionTargetPlanNode>();\n\n for (const contribution of plan.contributions) {\n nodes.set(contribution.targetId, {\n id: nodeIds.target(contribution.targetId),\n kind: 'contribution-target',\n label: contribution.targetId,\n });\n }\n\n return Object.freeze([...nodes.values()]);\n}\n\nfunction contributionNodes(plan: CompiledApplicationPlanIR): readonly ContributionPlanNode[] {\n return Object.freeze(\n plan.contributions.map(contribution => ({\n contributor: nodeIds.feature(contribution.contributorFeatureId),\n id: nodeIds.contribution(contribution.contributionId),\n kind: 'contribution' as const,\n label: contribution.contributionId,\n priority: contribution.priority,\n target: nodeIds.target(contribution.targetId),\n })),\n );\n}\n\nfunction featureNodes(plan: CompiledApplicationPlanIR, applicationId: DiagnosticNodeId): readonly FeaturePlanNode[] {\n return Object.freeze(\n plan.features.map(feature => ({\n id: nodeIds.feature(feature.featureId),\n kind: 'feature' as const,\n label: feature.featureId,\n owner: ownerNodeId(feature.owner, applicationId),\n })),\n );\n}\n\nfunction projectApplicationPlan(plan: CompiledApplicationPlanIR, applicationId: string): ApplicationPlanSnapshot {\n const id = nodeIds.application(applicationId);\n\n return Object.freeze({\n absentProviders: absentProviderNodes(plan),\n application: {\n features: plan.features.length,\n groups: plan.groups.length,\n id,\n kind: 'application' as const,\n label: applicationId,\n },\n conditions: conditionNodes(plan),\n contributions: contributionNodes(plan),\n edges: planEdges(plan, id),\n features: featureNodes(plan, id),\n groups: groupNodes(plan),\n hostContracts: hostContractNodes(plan),\n ports: portNodes(plan),\n targets: targetNodes(plan),\n });\n}\n\nexport { conditionAtomId, diagnosticEdgeId, encodeIdPart, nodeIds, projectApplicationPlan };\n"],"names":["idEscapes","encodeIdPart","value","encoded","character","escape","nodeIds","contractId","applicationId","conditionId","contributionId","featureId","groupId","portId","targetId","conditionAtomId","diagnosticEdgeId","kind","from","to","structuralEdge","hardEdge","weakEdge","ownerNodeId","owner","importProviderNodeId","provider","portPlanEdge","edge","consumer","port","importPlanEdge","planEdge","planEdges","plan","weakRequirements","requirement","edges","contribution","conditionNodes","nodes","group","condition","record","requireConditionRecord","groupNodes","index","_a","portNodes","hostContractNodes","binding","absentProviderNodes","targetNodes","contributionNodes","featureNodes","feature","projectApplicationPlan","id"],"mappings":"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"}