@opetope/runtime 0.1.1 → 0.2.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.
- package/CHANGELOG.md +20 -0
- package/README.md +19 -9
- package/README.ru.md +21 -9
- package/dist/feature-authoring-types.d.ts +6 -10
- package/dist/feature-authoring.js +1 -1
- package/dist/feature-authoring.js.map +1 -1
- package/dist/feature-body.d.ts +1 -1
- package/dist/feature-body.js.map +1 -1
- package/dist/feature-contribution.d.ts +5 -3
- package/dist/feature-contribution.js +1 -1
- package/dist/feature-contribution.js.map +1 -1
- package/dist/feature-definition-api.d.ts +1 -1
- package/dist/feature-generation.js +1 -1
- package/dist/feature-generation.js.map +1 -1
- package/dist/feature-lazy-generation.d.ts +1 -1
- package/dist/feature-lazy-generation.js +1 -1
- package/dist/feature-lazy-generation.js.map +1 -1
- package/dist/feature-own-values.d.ts +10 -0
- package/dist/feature-own-values.js +2 -0
- package/dist/feature-own-values.js.map +1 -0
- package/dist/feature-port-binding.d.ts +2 -1
- package/dist/feature-port-binding.js +1 -1
- package/dist/feature-port-binding.js.map +1 -1
- package/dist/feature-port.d.ts +13 -23
- package/dist/feature-port.js +1 -1
- package/dist/feature-port.js.map +1 -1
- package/dist/public-module-types.d.ts +1 -1
- package/dist/public-module.d.ts +1 -1
- package/docs/agent-guide.md +11 -4
- package/docs/agent-guide.ru.md +11 -4
- package/docs/cookbook.md +9 -7
- package/docs/cookbook.ru.md +9 -7
- package/docs/decisions.md +14 -0
- package/docs/how-it-works.md +20 -5
- package/docs/how-it-works.ru.md +19 -5
- package/docs/spec.md +31 -17
- package/docs/spec.ru.md +32 -18
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @opetope/runtime
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2d41c56: Give `provides` only its declaration builders and let nested callbacks select the current instance's live values:
|
|
8
|
+
|
|
9
|
+
- The outer `provides` receives exactly `{ port, register, slot, pipe }`, with no `own`.
|
|
10
|
+
- `port(Port, ({ own }) => own.model.call)` or `port(Port, ({ own }) => own.call)` selects an authentic Call during instance preparation, before readiness and contribution publication. Its callback receives only `{ own }`.
|
|
11
|
+
- `register` factories receive `{ own, imports }`.
|
|
12
|
+
- `slot` factories receive `{ own, imports, model }` for per-mount UI models.
|
|
13
|
+
- `when` predicates and `pipe.fold` handlers receive `{ own, imports, read }`.
|
|
14
|
+
|
|
15
|
+
This is a breaking authoring API change. Remove `own` from the outer `provides` context. Replace both `port(Port, ref)` and `port(Port, { from, select })` with a selector of the ready value, such as `port(Port, ({ own }) => own.order.submit)`. Port targets remain known at declaration; selecting the Call waits for the concrete instance.
|
|
16
|
+
|
|
17
|
+
Contribution contexts no longer expose `exports` or `instance`, and `register` no longer exposes `model`. Replace `context.exports.submit` with the source value, such as `context.own.order.submit`; remove exports needed only for internal composition. Replace instance-based binding with the ready value from `own`. Private model calls can be registered without adding them to the feature's public API. There are no compatibility aliases.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- @opetope/core@0.2.0
|
|
22
|
+
|
|
3
23
|
## 0.1.1
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -98,9 +98,10 @@ its own context created (D139). The refs of `model()` take no part in the loweri
|
|
|
98
98
|
cannot be used in `within`. A contribution component reads the models of its feature through `useModel` inside the
|
|
99
99
|
contribution mount, which binds them automatically. A single field goes outward through
|
|
100
100
|
`exports: ({ own }) => ({ x: own.model.field })`. A model call can also provide a port:
|
|
101
|
-
`port(SubmitPort, {
|
|
102
|
-
|
|
103
|
-
through a dependency call.
|
|
101
|
+
`port(SubmitPort, ({ own }) => own.order.submit)`. The selector receives only `{ own }` and runs once during instance
|
|
102
|
+
preparation, before readiness and publication; the selected authentic `Call` is fenced by the provider's lifetime
|
|
103
|
+
even if it passes through a dependency call. Use `port(SubmitPort, ({ own }) => own.submit)` for a call declared
|
|
104
|
+
directly in `own`. Both forms select ready Calls; direct refs and `{ from, select }` descriptors are not accepted (D255).
|
|
104
105
|
|
|
105
106
|
`target` is a selector `(source) => Readable<T | null | undefined>` in both feature and model APIs.
|
|
106
107
|
TypeScript infers the payload of the returned `Readable`, whose shape is checked before opening; a scalar
|
|
@@ -112,8 +113,8 @@ Both APIs publish one atomic snapshot `idle | opening | ready | refreshing | err
|
|
|
112
113
|
work; demand is set by a separate `retain()` lease. Retention by default merges the StrictMode
|
|
113
114
|
release/reacquire into one microtask and aborts unfinished work after the last lease. An explicit
|
|
114
115
|
`scoped({ capacity })` holds the materialization until retirement and bounds the sticky
|
|
115
|
-
cache.
|
|
116
|
-
|
|
116
|
+
cache. A nested contribution factory reads the instance-bound resource as `own.x` and can pass it to the UI;
|
|
117
|
+
the React `useResource` holds one lease per mounted consumer.
|
|
117
118
|
|
|
118
119
|
There are exactly two policy factories, and both have a production pilot: `scoped({ capacity })` for retention and
|
|
119
120
|
`latest()` for stream and event backpressure. The former `drop`, `sample` and `queue` are removed together with their branches:
|
|
@@ -207,7 +208,7 @@ explicit `key` keeps the current generation. `keyed` holds an independent child
|
|
|
207
208
|
unique `string | number` key. A repeated key rejects the whole new snapshot before any change to the children that are
|
|
208
209
|
already active. Retire fences the children synchronously and waits for their physical drain.
|
|
209
210
|
|
|
210
|
-
The `provides` section declares both ports and contributions: `port`
|
|
211
|
+
The `provides` section declares both ports and contributions: `port` selects an owned Call for a `Port`, while `slot`, `pipe` and
|
|
211
212
|
`register` declare a contribution by the kind of its target:
|
|
212
213
|
|
|
213
214
|
```ts
|
|
@@ -223,16 +224,25 @@ const titleFeature = defineFeature({
|
|
|
223
224
|
});
|
|
224
225
|
```
|
|
225
226
|
|
|
226
|
-
The outer factory
|
|
227
|
-
|
|
227
|
+
The outer factory receives only `{ port, register, slot, pipe }`, runs synchronously at `defineFeature`, and records
|
|
228
|
+
targets, ids and priorities for the application compiler before an instance opens. A `port` selector runs later,
|
|
229
|
+
with the instance's `{ own }`, during preparation. The second argument of `pipe(...)` is a `{ fold }` descriptor:
|
|
228
230
|
the runtime binds it to the concrete instance after the critical barrier and calls the handler only on a fold (D223).
|
|
229
|
-
`slot` and `register` take either a value factory
|
|
231
|
+
`slot` and `register` take either a value factory for the concrete instance, which also runs only after
|
|
230
232
|
that barrier, or a ready contribution value. An exact plain record must
|
|
231
233
|
return every receipt exactly once; the id of an entry is derived as `featureId.key`. The whole batch goes through
|
|
232
234
|
preflight and is published atomically. The start of retirement removes the entries synchronously before the async cleanup, including
|
|
233
235
|
a reentrant retirement from a target listener; a failed opening or an error in the value factory leaves no partially
|
|
234
236
|
published contributions.
|
|
235
237
|
|
|
238
|
+
The `register` value factory receives `{ own, imports }`; `slot` receives `{ own, imports, model }`, where `model`
|
|
239
|
+
declares a UI model created for each mount. `when` predicates and `pipe.fold` handlers receive `{ own, imports, read }`.
|
|
240
|
+
Their `own` contains the live models, calls and resources of that instance (D255). For example,
|
|
241
|
+
`register(target, ({ own }) => ({ key: 'submit', value: own.order.submit }))` registers a private model call without
|
|
242
|
+
exporting it. These contexts have no `exports` or `instance` field; `register` also has no `model` builder.
|
|
243
|
+
The outer `provides` has no `own`; each nested callback receives its own context of ready values. Model calls keep
|
|
244
|
+
their existing lifetime and owned state is read-only outside its model.
|
|
245
|
+
|
|
236
246
|
The feature API is declared by the `exports: ({ own }) => ({ … })` section: the contract is created from the feature
|
|
237
247
|
definition under the id `<feature>.exports`, and a consumer imports the definition itself — `imports: { provider: providerFeature }`.
|
|
238
248
|
Assigned missing/extra keys and incompatible `Call` signatures are rejected at compile time. Host-only values
|
package/README.ru.md
CHANGED
|
@@ -98,9 +98,11 @@ lookup: requires.lookup }, create)` передаёт readonly-запись ра
|
|
|
98
98
|
нельзя использовать в `within`. Компонент вклада читает модели своей фичи через `useModel` внутри монтирования
|
|
99
99
|
вклада, которое связывает их автоматически. Отдельное поле уходит наружу через
|
|
100
100
|
`exports: ({ own }) => ({ x: own.model.field })`. Вызов модели также может предоставлять порт:
|
|
101
|
-
`port(SubmitPort, {
|
|
102
|
-
|
|
103
|
-
передан из зависимости. Для объявленного
|
|
101
|
+
`port(SubmitPort, ({ own }) => own.order.submit)`. Селектор получает только `{ own }` и вызывается один раз при
|
|
102
|
+
подготовке экземпляра, до readiness и публикации; выбранный подлинный `Call` ограничен временем жизни провайдера,
|
|
103
|
+
даже когда он напрямую передан из зависимости. Для вызова, объявленного прямо в `own`, используется
|
|
104
|
+
`port(SubmitPort, ({ own }) => own.submit)`. Обе формы выбирают готовые Calls; прямые refs и дескрипторы
|
|
105
|
+
`{ from, select }` не принимаются (D255).
|
|
104
106
|
|
|
105
107
|
`target` — селектор `(source) => Readable<T | null | undefined>` и у фичи, и у модели.
|
|
106
108
|
TypeScript выводит payload возвращённого `Readable`, форма которого проверяется перед открытием;
|
|
@@ -112,8 +114,8 @@ TypeScript выводит payload возвращённого `Readable`, фор
|
|
|
112
114
|
работу; спрос задаёт отдельный lease `retain()`. Удержание по умолчанию объединяет StrictMode
|
|
113
115
|
release/reacquire в одну микрозадачу и abort-ит незавершённую работу после последнего lease. Явный
|
|
114
116
|
`scoped({ capacity })` удерживает materialization до retirement и ограничивает sticky
|
|
115
|
-
кэша.
|
|
116
|
-
|
|
117
|
+
кэша. Вложенная фабрика вклада получает привязанный к экземпляру ресурс как `own.x` и может передать его в UI;
|
|
118
|
+
React `useResource` держит один lease на смонтированного потребителя.
|
|
117
119
|
|
|
118
120
|
Фабрик политик ровно две, и обе с production-пилотом: `scoped({ capacity })` для удержания и `latest()` для
|
|
119
121
|
backpressure стрима и события. Прежние `drop`, `sample` и `queue` удалены вместе с их ветками: назвать их из авторского
|
|
@@ -206,7 +208,7 @@ own: ({ imports, scope }) => ({
|
|
|
206
208
|
уникальный `string | number` key. Повтор ключа отклоняет весь новый snapshot до любых изменений уже
|
|
207
209
|
активных детей. Retire синхронно фенсит детей и ждёт их физический дренаж.
|
|
208
210
|
|
|
209
|
-
Секция `provides` объявляет и порты, и вклады: `port`
|
|
211
|
+
Секция `provides` объявляет и порты, и вклады: `port` выбирает владеемый Call для `Port`, `slot`, `pipe` и
|
|
210
212
|
`register` объявляют вклад по виду цели:
|
|
211
213
|
|
|
212
214
|
```ts
|
|
@@ -222,16 +224,26 @@ const titleFeature = defineFeature({
|
|
|
222
224
|
});
|
|
223
225
|
```
|
|
224
226
|
|
|
225
|
-
Внешняя factory
|
|
226
|
-
|
|
227
|
+
Внешняя factory получает только `{ port, register, slot, pipe }`, синхронно выполняется при `defineFeature` и
|
|
228
|
+
записывает target/id/priority для компилятора приложения до открытия экземпляра. Селектор `port` выполняется
|
|
229
|
+
позже, с `{ own }` конкретного экземпляра, при его подготовке. Второй аргумент `pipe(...)` — дескриптор `{ fold }`: рантайм
|
|
227
230
|
связывает его с конкретным экземпляром после critical barrier и вызывает обработчик только на свёртке (D223).
|
|
228
|
-
`slot` и `register` принимают либо value factory
|
|
231
|
+
`slot` и `register` принимают либо value factory конкретного экземпляра, которая тоже выполняется только
|
|
229
232
|
после этого барьера, либо готовое значение вклада. Exact plain record обязан
|
|
230
233
|
вернуть каждый receipt ровно один раз; id записи выводится как `featureId.key`. Весь batch проходит
|
|
231
234
|
preflight и публикуется атомарно. Начало retirement синхронно удаляет записи до async cleanup, включая
|
|
232
235
|
reentrant retirement из target listener; failed opening или ошибка value factory не оставляют частично
|
|
233
236
|
опубликованных вкладов.
|
|
234
237
|
|
|
238
|
+
Value factory `register` получает `{ own, imports }`, а `slot` — `{ own, imports, model }`, где `model` объявляет
|
|
239
|
+
UI-модель, создаваемую на каждое монтирование. Предикаты `when` и обработчики `pipe.fold` получают `{ own, imports, read }`.
|
|
240
|
+
Их `own` содержит готовые модели, вызовы и ресурсы конкретного экземпляра (D255). Например,
|
|
241
|
+
`register(target, ({ own }) => ({ key: 'submit', value: own.order.submit }))` регистрирует вызов внутренней модели
|
|
242
|
+
без его экспорта. В этих контекстах нет полей `exports` и `instance`; у `register` также нет построителя `model`.
|
|
243
|
+
У внешней `provides` нет `own`; каждый вложенный колбэк получает собственный контекст готовых значений.
|
|
244
|
+
Вызовы модели сохраняют своё время жизни, а owned state за пределами модели доступен
|
|
245
|
+
только для чтения.
|
|
246
|
+
|
|
235
247
|
Feature API объявляется секцией `exports: ({ own }) => ({ … })`: contract создаётся из определения
|
|
236
248
|
фичи под id `<feature>.exports`, а consumer импортирует само определение — `imports: { provider: providerFeature }`.
|
|
237
249
|
Assigned missing/extra keys и несовместимые `Call` signatures отклоняются compile-time. Host-only значения
|
|
@@ -6,7 +6,6 @@ import type { FeatureAttachBuilder, FeatureCallsBuilder, FeatureImportRef, Featu
|
|
|
6
6
|
import type { FeatureCallBuilder, FeatureCallLaneBuilder, FeatureExposureMode, FeatureImportedAttachmentRef } from './feature-call-types.js';
|
|
7
7
|
import type { FeatureContract, FeatureContractIdentity, FeatureImportRecord, FeatureImportValues } from './feature-contract.js';
|
|
8
8
|
import type { FeatureContributionDescriptor } from './feature-contribution.js';
|
|
9
|
-
import type { ContributionModelBuilder } from './feature-contribution-model.js';
|
|
10
9
|
import type { FeatureResourceRef, FeatureStreamRef } from './feature-materialization-types.js';
|
|
11
10
|
import type { FeatureDataDescriptor, FeatureModelBuilder, FeatureModelRef } from './feature-model.js';
|
|
12
11
|
import type { FeatureRequiredCalls, PortProviderDescriptor, PortRequirementRecord, RequiredPortValues } from './feature-port.js';
|
|
@@ -15,7 +14,7 @@ import type { FeatureResourceBuilder } from './feature-resource.js';
|
|
|
15
14
|
import type { FeatureScopeBuilder } from './feature-scope-types.js';
|
|
16
15
|
import type { FeatureStreamBuilder } from './feature-stream.js';
|
|
17
16
|
import type { FeatureTimers } from './feature-timers.js';
|
|
18
|
-
import type { ModuleAttachmentRefIdentity, ModuleCallRef,
|
|
17
|
+
import type { ModuleAttachmentRefIdentity, ModuleCallRef, ModuleRuntimeRefIdentity, ModuleScopeRef } from './public-module.js';
|
|
19
18
|
declare const featureBrand: unique symbol;
|
|
20
19
|
type FeatureLifecycleRef<Source, Id extends string, Imports extends FeatureImportRecord, Mode extends FeatureExposureMode> = FeatureImportedAttachmentRef<Source, Id, FeatureImportValues<Imports>, Mode>;
|
|
21
20
|
type FeatureEffectRunContext<Source, Value> = {
|
|
@@ -144,18 +143,15 @@ type FeatureRead = <Value>(source: Readable<Value>) => Value;
|
|
|
144
143
|
* is the materialized form `exports` already uses — a model field is a `Readable`, not the ref the declaration
|
|
145
144
|
* context carries — because a calculation reads values and never constructs a node (D220).
|
|
146
145
|
*/
|
|
147
|
-
type FeatureEvaluationContext<Id extends string, Imports extends FeatureImportRecord, Runtime extends FeatureOwnRecord<Id
|
|
148
|
-
readonly exports: Exports;
|
|
146
|
+
type FeatureEvaluationContext<Id extends string, Imports extends FeatureImportRecord, Runtime extends FeatureOwnRecord<Id>> = {
|
|
149
147
|
readonly imports: FeatureImportValues<Imports>;
|
|
150
148
|
readonly own: FeatureOwnValues<Id, Runtime>;
|
|
151
149
|
readonly read: FeatureRead;
|
|
152
150
|
};
|
|
153
|
-
|
|
154
|
-
|
|
151
|
+
/** Contribution factories select live values; the outer `provides` carries only declaration builders (D255). */
|
|
152
|
+
type FeatureOpenContext<Id extends string, Imports extends FeatureImportRecord, Runtime extends FeatureOwnRecord<Id>> = {
|
|
155
153
|
readonly imports: FeatureImportValues<Imports>;
|
|
156
|
-
readonly
|
|
157
|
-
readonly model: ContributionModelBuilder;
|
|
158
|
-
readonly own: Runtime;
|
|
154
|
+
readonly own: FeatureOwnValues<Id, Runtime>;
|
|
159
155
|
};
|
|
160
156
|
type FeatureRecord = {
|
|
161
157
|
readonly contributions: readonly FeatureContributionDescriptor[];
|
|
@@ -193,4 +189,4 @@ type FeatureExportDeclarationSnapshot = {
|
|
|
193
189
|
readonly own: unknown;
|
|
194
190
|
}) => unknown;
|
|
195
191
|
};
|
|
196
|
-
export type { AnyFeature, AttachmentLowering, AttachmentProjection, AttachmentRecipe, Feature, FeatureAttachBuilder, FeatureCallBuilder, FeatureCallOperation, FeatureConditionsOf, FeatureEffectBuilder, FeatureEvaluationContext, FeatureEventBuilder, FeatureExportDeclarationSnapshot, FeatureExportRecord, FeatureExportsFactory, FeatureExportsOf, FeatureExposureMode, FeatureIdOf, FeatureImportRecord, FeatureImportRef, FeatureImportsOf, FeatureImportValues, FeatureLifecycleRef, FeatureOpenContext, FeatureOwnBuilder, FeatureOwnRecord, FeatureRecord, FeatureRequirementsOf, };
|
|
192
|
+
export type { AnyFeature, AttachmentLowering, AttachmentProjection, AttachmentRecipe, Feature, FeatureAttachBuilder, FeatureCallBuilder, FeatureCallOperation, FeatureConditionsOf, FeatureEffectBuilder, FeatureEvaluationContext, FeatureEventBuilder, FeatureExportDeclarationSnapshot, FeatureExportRecord, FeatureExportsFactory, FeatureExportsOf, FeatureExposureMode, FeatureIdOf, FeatureImportRecord, FeatureImportRef, FeatureImportsOf, FeatureImportValues, FeatureLifecycleRef, FeatureOpenContext, FeatureOwnBuilder, FeatureOwnRecord, FeatureOwnValues, FeatureRecord, FeatureRequirementsOf, };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{declarationId as
|
|
1
|
+
import{declarationId as $}from"@opetope/core";import{snapshotFeatureConditions as O}from"./condition.js";import{preloadFeatureBody as I,featureBody as M,requireFeatureBody as k}from"./feature-body.js";import{defineFeatureContract as q}from"./feature-contract.js";import{isFeatureContributionDeclaration as z,snapshotFeatureContributions as L,createFeatureContributionBuilders as G}from"./feature-contribution.js";import{snapshotFeatureOptions as H,requireString as W,snapshotFeatureExportDeclaration as x,optionalFunction as b,snapshotFeatureImports as j,snapshotFeatureRequirements as K,registerFeatureRecord as g,requireFeatureRecord as A}from"./feature-definition-support.js";import{isFeature as we}from"./feature-definition-support.js";import{snapshotDeclaredProvided as J,registerLazyFeature as N,assertBodyMatchesHeader as Q}from"./feature-lazy.js";import{lowerFeatureOwn as E}from"./feature-own-lowering.js";import{createPortBuilder as U,snapshotPortProviders as V}from"./feature-port.js";import{dataEntries as y,assertPlainRecord as X}from"./feature-record.js";import{defineModule as Y}from"./public-module-definition.js";const P=Y;function Z(r){if((typeof r!="object"||r===null)&&typeof r!="function")return!1;let e=r;for(;e!==null;){const t=Object.getOwnPropertyDescriptor(e,"then");if(t!==void 0)return"value"in t&&typeof t.value=="function";e=Object.getPrototypeOf(e)}return!1}function D(r,e){const t=G();if(e===void 0)return Object.freeze({contributions:Object.freeze([]),providers:Object.freeze([])});const i=e({pipe:t.pipe,port:U(),register:t.register,slot:t.slot});if(Z(i))throw Promise.resolve(i).catch(()=>{}),new TypeError("defineFeature provides must return synchronously.");X(i,"defineFeature provides result");const u=y(i,"defineFeature provides result"),s=u.filter(([,n])=>z(t,n)),c=u.filter(([,n])=>!z(t,n));return Object.freeze({contributions:L(r,t,s),providers:V(c)})}const v=new WeakMap;function _(r,e){const t=b(e.own,"defineFeature own")??(()=>({})),i=x(e.exports),u=b(e.provides,"defineFeature provides");let s;const c=P({id:r.id,runtime:F=>(s=E(F,{build:t,id:r.id,importKeys:r.importKeys,imports:r.imports,requirementKeys:r.requirementKeys}),s.loweredRuntime)});if(s===void 0)throw new TypeError("defineFeature own did not produce a public record.");const{dataDescriptors:n,importScopeKey:p,publicRuntime:f,requirementScopeKey:d}=s,m=f,{contributions:o,providers:a}=D(r.id,u);return{own:m,record:{contributions:o,dataDescriptors:n,exports:i.from,importKeys:r.importKeys,importScopeKey:p,module:c,providers:a,requirementKeys:r.requirementKeys,requirementScopeKey:d}}}function ee(r,e){for(const o of["exports","own"])if(r[o]!==void 0)throw new TypeError(`defineFeature ${e} declares body and ${o}: the implementation belongs to the body.`);if(typeof r.provides=="function")throw new TypeError(`defineFeature ${e} declares body and a provides factory: the header declares targets only.`);const t=r.body;if(typeof t!="function")throw new TypeError("defineFeature body must be a loader function.");const i=j(r.imports),u=K(r.requires),s=Object.freeze(y(i,"defineFeature imports").map(([o])=>o)),c=Object.freeze(y(u,"defineFeature requires").map(([o])=>o)),n=J(e,r.provides),p=q(`${e}.exports`);let f=Object.freeze({});const d=Object.freeze({exports:p,id:$(e),imports:i,get own(){return f},requires:u,when:O(r.when)}),m={id:e,importKeys:s,imports:i,requirementKeys:c};return g(d,{contributions:n.contributions,dataDescriptors:Object.freeze([]),exports:()=>({}),importKeys:s,importScopeKey:void 0,module:Object.freeze({}),providers:n.providers.map(o=>Object.freeze({...o,target:void 0})),requirementKeys:c,requirementScopeKey:void 0}),N(d,{load:()=>Promise.resolve(t()).then(o=>k(e,o)),materialize:o=>{const a=_(m,o);return Q(e,n,a.record),f=Object.freeze(a.own),a.record}}),v.set(p,d),d}function re(r){const e=H(r),t=W(e.id,"defineFeature id");if(e.body!==void 0)return ee(e,t);const i=x(e.exports),u=b(e.own,"defineFeature own")??(()=>({})),s=i.from,c=b(e.provides,"defineFeature provides"),n=j(e.imports),p=K(e.requires),f=y(p,"defineFeature requires"),d=Object.freeze(y(n,"defineFeature imports").map(([l])=>l)),m=Object.freeze(f.map(([l])=>l));let o;const a=P({id:t,runtime:l=>(o=E(l,{build:u,id:t,importKeys:d,imports:n,requirementKeys:m}),o.loweredRuntime)});if(o===void 0)throw new TypeError("defineFeature own did not produce a public record.");const{dataDescriptors:F,importScopeKey:C,publicRuntime:B,requirementScopeKey:R}=o,{contributions:S,providers:T}=D(t,c),h=q(`${t}.exports`),w=Object.freeze({exports:h,id:a.id,imports:n,own:B,requires:p,when:O(e.when)});return g(w,{contributions:S,dataDescriptors:F,exports:s,importKeys:d,importScopeKey:C,module:a,providers:T,requirementKeys:m,requirementScopeKey:R}),v.set(h,w),w}function te(r){return v.get(r)}const oe=Object.assign(re,{body:M,preload:I});function ne(r){return A(r).contributions}export{oe as defineFeature,te as getFeatureByExportContract,ne as getFeatureContributionDescriptors,we as isFeature};
|
|
2
2
|
//# sourceMappingURL=feature-authoring.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-authoring.js","sources":["../src/feature-authoring.ts"],"sourcesContent":["import { declarationId } from '@opetope/core';\n\nimport { snapshotFeatureConditions } from './condition';\nimport type { Condition } from './condition';\nimport type {\n AnyFeature,\n Feature,\n FeatureEvaluationContext,\n FeatureExportRecord,\n FeatureImportRecord,\n FeatureOpenContext,\n FeatureOwnBuilder,\n FeatureOwnRecord,\n FeatureRecord,\n} from './feature-authoring-types';\nimport { featureBody, preloadFeatureBody, requireFeatureBody } from './feature-body';\nimport type { LoadedFeatureBody } from './feature-body';\nimport { defineFeatureContract } from './feature-contract';\nimport {\n createFeatureContributionBuilders,\n isFeatureContributionDeclaration,\n snapshotFeatureContributions,\n} from './feature-contribution';\nimport type { FeatureContributionDescriptor } from './feature-contribution';\nimport type { DefineFeature, FeatureInput } from './feature-definition-api';\nimport {\n isFeature,\n optionalFunction,\n registerFeatureRecord,\n requireFeatureRecord,\n requireString,\n snapshotFeatureExportDeclaration,\n snapshotFeatureImports,\n snapshotFeatureOptions,\n snapshotFeatureRequirements,\n} from './feature-definition-support';\nimport { assertBodyMatchesHeader, registerLazyFeature, snapshotDeclaredProvided } from './feature-lazy';\nimport { lowerFeatureOwn } from './feature-own-lowering';\nimport type { FeatureOwnLoweringResult } from './feature-own-lowering';\nimport { createPortBuilder, snapshotPortProviders } from './feature-port';\nimport type { FeatureProvidedRecord, FeatureProvidesFactory, PortRequirementRecord } from './feature-port';\nimport { assertPlainRecord, dataEntries } from './feature-record';\nimport type { ExactKeys } from './feature-record';\nimport { defineModule } from './public-module';\nimport type { ModuleDefinition, ModuleRuntimeBuilder, ModuleRuntimeRecord } from './public-module';\n\ntype DefineGeneratedModule = <Id extends string, Runtime extends ModuleRuntimeRecord<Id>>(options: {\n readonly id: Id;\n readonly runtime: (builder: ModuleRuntimeBuilder<Id>) => Runtime;\n}) => ModuleDefinition<Id, Runtime>;\n\n// The public defineModule guard rejects union author records. Feature lowering has already applied\n// the same guard before it appends collision-free private refs to one concrete `own` record.\nconst defineGeneratedModule = defineModule as DefineGeneratedModule;\n\nfunction hasDataThen(value: unknown): boolean {\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n\n let source: object | null = value;\n\n while (source !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(source, 'then');\n\n if (descriptor !== undefined) return 'value' in descriptor && typeof descriptor.value === 'function';\n\n source = Object.getPrototypeOf(source) as object | null;\n }\n\n return false;\n}\n\n/** `provides` returns ports and contributions in one record; each entry is split by the builder that made it. */\nfunction buildFeatureProvided<\n Id extends string,\n Context,\n Evaluation,\n Runtime extends FeatureOwnRecord<Id>,\n Provided extends FeatureProvidedRecord<Id>,\n>(\n featureId: string,\n build: FeatureProvidesFactory<Id, Context, Evaluation, Runtime, Provided> | undefined,\n own: Runtime,\n runtimeValues: ReadonlySet<object>,\n): Readonly<{\n contributions: readonly FeatureContributionDescriptor[];\n providers: FeatureRecord['providers'];\n}> {\n const builders = createFeatureContributionBuilders<Context, Evaluation>();\n\n if (build === undefined) return Object.freeze({ contributions: Object.freeze([]), providers: Object.freeze([]) });\n\n const value = build({\n own,\n pipe: builders.pipe,\n port: createPortBuilder<Id>(),\n register: builders.register,\n slot: builders.slot,\n });\n\n if (hasDataThen(value)) {\n void Promise.resolve(value).catch(() => undefined);\n\n throw new TypeError('defineFeature provides must return synchronously.');\n }\n\n assertPlainRecord(value, 'defineFeature provides result');\n const entries = dataEntries(value, 'defineFeature provides result');\n const contributionEntries = entries.filter(([, entry]) => isFeatureContributionDeclaration(builders as never, entry));\n const providerEntries = entries.filter(([, entry]) => !isFeatureContributionDeclaration(builders as never, entry));\n\n return Object.freeze({\n contributions: snapshotFeatureContributions(featureId, builders, contributionEntries),\n providers: snapshotPortProviders(runtimeValues, providerEntries),\n });\n}\n\nconst featuresByExportContract = new WeakMap<object, AnyFeature>();\n\ntype FeatureHeader = {\n readonly exportsContract: object;\n readonly id: string;\n readonly importKeys: readonly string[];\n readonly imports: FeatureImportRecord;\n readonly requirementKeys: readonly string[];\n readonly requirements: PortRequirementRecord;\n};\n\n/**\n * The heavy half of a feature: lowering `own`, running `provides` and selecting `exports`. An eager feature runs it\n * at declaration; a lazy one runs the very same code once its body has loaded (D186).\n */\nfunction materializeFeatureImplementation(\n header: FeatureHeader,\n body: LoadedFeatureBody,\n): { readonly own: Readonly<Record<string, unknown>>; readonly record: FeatureRecord } {\n const build =\n optionalFunction<(builder: never) => Readonly<Record<string, unknown>>>(body.own, 'defineFeature own') ??\n (() => ({}));\n const exportDeclaration = snapshotFeatureExportDeclaration(body.exports);\n const buildProvides = optionalFunction<FeatureProvidesFactory<string, never, never, never, never>>(\n body.provides,\n 'defineFeature provides',\n );\n let lowering: FeatureOwnLoweringResult<string, never> | undefined;\n const module = defineGeneratedModule({\n id: header.id,\n runtime: low => {\n lowering = lowerFeatureOwn(low as never, {\n build: build as never,\n id: header.id,\n importKeys: header.importKeys,\n imports: header.imports,\n requirementKeys: header.requirementKeys,\n }) as FeatureOwnLoweringResult<string, never>;\n\n return lowering.loweredRuntime;\n },\n });\n\n if (lowering === undefined) throw new TypeError('defineFeature own did not produce a public record.');\n\n const { dataDescriptors, importScopeKey, publicRuntime, requirementScopeKey } = lowering;\n const own = publicRuntime as unknown as Readonly<Record<string, unknown>>;\n const runtimeValues = new Set<object>(\n Object.values(own).filter((value): value is object => typeof value === 'object'),\n );\n const { contributions, providers } = buildFeatureProvided(\n header.id,\n buildProvides as never,\n publicRuntime,\n runtimeValues,\n );\n\n return {\n own,\n record: {\n contributions,\n dataDescriptors,\n exports: exportDeclaration.from,\n importKeys: header.importKeys,\n importScopeKey,\n module,\n providers,\n requirementKeys: header.requirementKeys,\n requirementScopeKey,\n },\n };\n}\n\n/**\n * D186: a header opens nothing by itself. It registers the identity, the edges and the declared border, and keeps\n * the loader; the body is materialized once, on the first open, and every later open reuses the same code.\n */\nfunction defineLazyFeature(source: Readonly<Record<string, unknown>>, id: string): AnyFeature {\n for (const key of ['exports', 'own'] as const) {\n if (source[key] !== undefined) {\n throw new TypeError(`defineFeature ${id} declares body and ${key}: the implementation belongs to the body.`);\n }\n }\n\n if (typeof source['provides'] === 'function') {\n throw new TypeError(`defineFeature ${id} declares body and a provides factory: the header declares targets only.`);\n }\n\n const load = source['body'];\n\n if (typeof load !== 'function') throw new TypeError('defineFeature body must be a loader function.');\n\n const imports = snapshotFeatureImports(source['imports'] as FeatureImportRecord | undefined);\n const requirements = snapshotFeatureRequirements(source['requires'] as PortRequirementRecord | undefined);\n const importKeys = Object.freeze(dataEntries(imports, 'defineFeature imports').map(([key]) => key));\n const requirementKeys = Object.freeze(dataEntries(requirements, 'defineFeature requires').map(([key]) => key));\n const declared = snapshotDeclaredProvided(id, source['provides']);\n const exportsContract = defineFeatureContract<{}>(`${id}.exports`);\n // The refs of `own` are minted by the body, so the header reads them through the record it materializes later.\n let materializedOwn: Readonly<Record<string, unknown>> = Object.freeze({});\n const feature = Object.freeze({\n exports: exportsContract,\n id: declarationId(id),\n imports,\n get own(): Readonly<Record<string, unknown>> {\n return materializedOwn;\n },\n requires: requirements,\n when: snapshotFeatureConditions(source['when']),\n }) as unknown as AnyFeature;\n const header: FeatureHeader = { exportsContract, id, importKeys, imports, requirementKeys, requirements };\n\n registerFeatureRecord(feature, {\n contributions: declared.contributions,\n dataDescriptors: Object.freeze([]),\n exports: () => ({}),\n importKeys,\n importScopeKey: undefined,\n module: Object.freeze({}),\n providers: declared.providers.map(entry => Object.freeze({ ...entry, target: undefined })) as never,\n requirementKeys,\n requirementScopeKey: undefined,\n });\n registerLazyFeature(feature, {\n load: () => Promise.resolve((load as () => PromiseLike<unknown>)()).then(value => requireFeatureBody(id, value)),\n materialize: (body: LoadedFeatureBody) => {\n const materialized = materializeFeatureImplementation(header, body);\n assertBodyMatchesHeader(id, declared, materialized.record);\n materializedOwn = Object.freeze(materialized.own);\n\n return materialized.record;\n },\n });\n featuresByExportContract.set(exportsContract, feature);\n\n return feature;\n}\n\nfunction defineFeatureImplementation<\n const Id extends string,\n const Imports extends FeatureImportRecord,\n const Runtime extends FeatureOwnRecord<Id>,\n const Exports extends FeatureExportRecord,\n const Requires extends PortRequirementRecord = {},\n const Provided extends FeatureProvidedRecord<Id> = FeatureProvidedRecord<Id>,\n When extends readonly Condition[] = readonly Condition[],\n const Keys extends PropertyKey = keyof FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>,\n>(\n options: ExactKeys<Keys, FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>> &\n FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>,\n): Feature<Id, Imports, Runtime, Exports, Requires, When> {\n const source = snapshotFeatureOptions(options);\n const id = requireString<Id>(source['id'], 'defineFeature id');\n\n if (source['body'] !== undefined) {\n return defineLazyFeature(source, id) as unknown as Feature<Id, Imports, Runtime, Exports, Requires, When>;\n }\n\n const exportDeclaration = snapshotFeatureExportDeclaration(source['exports']);\n const build =\n optionalFunction<(builder: FeatureOwnBuilder<Id, Imports, Requires>) => Runtime>(\n source['own'],\n 'defineFeature own',\n ) ?? ((() => ({})) as unknown as (builder: FeatureOwnBuilder<Id, Imports, Requires>) => Runtime);\n const selectExports = exportDeclaration.from;\n const buildProvides = optionalFunction<\n FeatureProvidesFactory<\n Id,\n FeatureOpenContext<Id, Imports, Runtime, Exports>,\n FeatureEvaluationContext<Id, Imports, Runtime, Exports>,\n Runtime,\n Provided\n >\n >(source['provides'], 'defineFeature provides');\n\n const imports = snapshotFeatureImports(source['imports'] as Imports);\n const requirements = snapshotFeatureRequirements(source['requires'] as Requires | undefined);\n const requirementEntries = dataEntries(requirements, 'defineFeature requires');\n const importKeys = Object.freeze(dataEntries(imports, 'defineFeature imports').map(([key]) => key));\n const requirementKeys = Object.freeze(requirementEntries.map(([key]) => key));\n let lowering: FeatureOwnLoweringResult<Id, Runtime> | undefined;\n const module = defineGeneratedModule({\n id,\n runtime: low => {\n lowering = lowerFeatureOwn(low, {\n build,\n id,\n importKeys,\n imports,\n requirementKeys,\n });\n\n return lowering.loweredRuntime;\n },\n });\n\n if (lowering === undefined) throw new TypeError('defineFeature own did not produce a public record.');\n\n const { dataDescriptors, importScopeKey, publicRuntime, requirementScopeKey } = lowering;\n\n const runtimeValues = new Set(Object.values(publicRuntime));\n const { contributions, providers } = buildFeatureProvided<\n Id,\n FeatureOpenContext<Id, Imports, Runtime, Exports>,\n FeatureEvaluationContext<Id, Imports, Runtime, Exports>,\n Runtime,\n Provided\n >(id, buildProvides, publicRuntime, runtimeValues);\n\n const exportsContract = defineFeatureContract<{}>(`${id}.exports`);\n const feature = Object.freeze({\n exports: exportsContract,\n id: module.id,\n imports,\n own: publicRuntime,\n requires: requirements,\n when: snapshotFeatureConditions(source['when']),\n }) as unknown as Feature<Id, Imports, Runtime, Exports, Requires, When>;\n registerFeatureRecord(feature, {\n contributions,\n dataDescriptors,\n exports: selectExports,\n importKeys,\n importScopeKey,\n module,\n providers,\n requirementKeys,\n requirementScopeKey,\n });\n featuresByExportContract.set(exportsContract, feature);\n\n return feature;\n}\n\n/** `imports` stores the contract, so the application world resolves a feature edge back to the feature (D68). */\nfunction getFeatureByExportContract(contract: object): AnyFeature | undefined {\n return featuresByExportContract.get(contract);\n}\n\n// D186: one word, two forms — the eager triple and the lazy header, so the overload set is the public type.\n// D207: `defineFeature.body` writes the implementation of a header; a member costs no new word of the vocabulary.\nconst defineFeature = Object.assign(defineFeatureImplementation as unknown as DefineFeature, {\n body: featureBody,\n preload: preloadFeatureBody,\n});\n\nfunction getFeatureModule<\n const Id extends string,\n const Imports extends FeatureImportRecord,\n const Runtime extends FeatureOwnRecord<Id>,\n const Exports extends FeatureExportRecord,\n>(feature: Feature<Id, Imports, Runtime, Exports>): ModuleDefinition<Id> {\n return requireFeatureRecord(feature).module as ModuleDefinition<Id>;\n}\n\nfunction getFeatureContributionDescriptors(feature: AnyFeature): FeatureRecord['contributions'] {\n return requireFeatureRecord(feature).contributions;\n}\n\nexport { defineFeature, getFeatureByExportContract, getFeatureContributionDescriptors, getFeatureModule, isFeature };\nexport type {\n AnyFeature,\n Feature,\n FeatureConditionsOf,\n FeatureExportRecord,\n FeatureExportsOf,\n FeatureIdOf,\n FeatureImportRecord,\n FeatureImportsOf,\n FeatureImportValues,\n FeatureOwnRecord,\n FeatureRequirementsOf,\n} from './feature-authoring-types';\n"],"names":["defineGeneratedModule","defineModule","hasDataThen","value","source","descriptor","buildFeatureProvided","featureId","build","own","runtimeValues","builders","createFeatureContributionBuilders","createPortBuilder","assertPlainRecord","entries","dataEntries","contributionEntries","entry","isFeatureContributionDeclaration","providerEntries","snapshotFeatureContributions","snapshotPortProviders","featuresByExportContract","materializeFeatureImplementation","header","body","optionalFunction","exportDeclaration","snapshotFeatureExportDeclaration","buildProvides","lowering","module","low","lowerFeatureOwn","dataDescriptors","importScopeKey","publicRuntime","requirementScopeKey","contributions","providers","defineLazyFeature","id","key","load","imports","snapshotFeatureImports","requirements","snapshotFeatureRequirements","importKeys","requirementKeys","declared","snapshotDeclaredProvided","exportsContract","defineFeatureContract","materializedOwn","feature","declarationId","snapshotFeatureConditions","registerFeatureRecord","registerLazyFeature","requireFeatureBody","materialized","assertBodyMatchesHeader","defineFeatureImplementation","options","snapshotFeatureOptions","requireString","selectExports","requirementEntries","getFeatureByExportContract","contract","defineFeature","featureBody","preloadFeatureBody","getFeatureContributionDescriptors","requireFeatureRecord"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"feature-authoring.js","sources":["../src/feature-authoring.ts"],"sourcesContent":["import { declarationId } from '@opetope/core';\n\nimport { snapshotFeatureConditions } from './condition';\nimport type { Condition } from './condition';\nimport type {\n AnyFeature,\n Feature,\n FeatureEvaluationContext,\n FeatureExportRecord,\n FeatureImportRecord,\n FeatureOpenContext,\n FeatureOwnBuilder,\n FeatureOwnRecord,\n FeatureRecord,\n} from './feature-authoring-types';\nimport { featureBody, preloadFeatureBody, requireFeatureBody } from './feature-body';\nimport type { LoadedFeatureBody } from './feature-body';\nimport { defineFeatureContract } from './feature-contract';\nimport {\n createFeatureContributionBuilders,\n isFeatureContributionDeclaration,\n snapshotFeatureContributions,\n} from './feature-contribution';\nimport type { FeatureContributionDescriptor } from './feature-contribution';\nimport type { DefineFeature, FeatureInput } from './feature-definition-api';\nimport {\n isFeature,\n optionalFunction,\n registerFeatureRecord,\n requireFeatureRecord,\n requireString,\n snapshotFeatureExportDeclaration,\n snapshotFeatureImports,\n snapshotFeatureOptions,\n snapshotFeatureRequirements,\n} from './feature-definition-support';\nimport { assertBodyMatchesHeader, registerLazyFeature, snapshotDeclaredProvided } from './feature-lazy';\nimport { lowerFeatureOwn } from './feature-own-lowering';\nimport type { FeatureOwnLoweringResult } from './feature-own-lowering';\nimport { createPortBuilder, snapshotPortProviders } from './feature-port';\nimport type { FeatureProvidedRecord, FeatureProvidesFactory, PortRequirementRecord } from './feature-port';\nimport { assertPlainRecord, dataEntries } from './feature-record';\nimport type { ExactKeys } from './feature-record';\nimport { defineModule } from './public-module';\nimport type { ModuleDefinition, ModuleRuntimeBuilder, ModuleRuntimeRecord } from './public-module';\n\ntype DefineGeneratedModule = <Id extends string, Runtime extends ModuleRuntimeRecord<Id>>(options: {\n readonly id: Id;\n readonly runtime: (builder: ModuleRuntimeBuilder<Id>) => Runtime;\n}) => ModuleDefinition<Id, Runtime>;\n\n// The public defineModule guard rejects union author records. Feature lowering has already applied\n// the same guard before it appends collision-free private refs to one concrete `own` record.\nconst defineGeneratedModule = defineModule as DefineGeneratedModule;\n\nfunction hasDataThen(value: unknown): boolean {\n if ((typeof value !== 'object' || value === null) && typeof value !== 'function') return false;\n\n let source: object | null = value;\n\n while (source !== null) {\n const descriptor = Object.getOwnPropertyDescriptor(source, 'then');\n\n if (descriptor !== undefined) return 'value' in descriptor && typeof descriptor.value === 'function';\n\n source = Object.getPrototypeOf(source) as object | null;\n }\n\n return false;\n}\n\n/** `provides` returns ports and contributions in one record; each entry is split by the builder that made it. */\nfunction buildFeatureProvided<\n Id extends string,\n Context,\n Evaluation,\n Runtime extends FeatureOwnRecord<Id>,\n Provided extends FeatureProvidedRecord<Id>,\n>(\n featureId: string,\n build: FeatureProvidesFactory<Id, Context, Evaluation, Runtime, Provided> | undefined,\n): Readonly<{\n contributions: readonly FeatureContributionDescriptor[];\n providers: FeatureRecord['providers'];\n}> {\n const builders = createFeatureContributionBuilders<Context, Evaluation>();\n\n if (build === undefined) return Object.freeze({ contributions: Object.freeze([]), providers: Object.freeze([]) });\n\n const value = build({\n pipe: builders.pipe,\n port: createPortBuilder(),\n register: builders.register,\n slot: builders.slot,\n });\n\n if (hasDataThen(value)) {\n void Promise.resolve(value).catch(() => undefined);\n\n throw new TypeError('defineFeature provides must return synchronously.');\n }\n\n assertPlainRecord(value, 'defineFeature provides result');\n const entries = dataEntries(value, 'defineFeature provides result');\n const contributionEntries = entries.filter(([, entry]) => isFeatureContributionDeclaration(builders as never, entry));\n const providerEntries = entries.filter(([, entry]) => !isFeatureContributionDeclaration(builders as never, entry));\n\n return Object.freeze({\n contributions: snapshotFeatureContributions(featureId, builders, contributionEntries),\n providers: snapshotPortProviders(providerEntries),\n });\n}\n\nconst featuresByExportContract = new WeakMap<object, AnyFeature>();\n\ntype FeatureHeader = {\n readonly exportsContract: object;\n readonly id: string;\n readonly importKeys: readonly string[];\n readonly imports: FeatureImportRecord;\n readonly requirementKeys: readonly string[];\n readonly requirements: PortRequirementRecord;\n};\n\n/**\n * The heavy half of a feature: lowering `own`, running `provides` and selecting `exports`. An eager feature runs it\n * at declaration; a lazy one runs the very same code once its body has loaded (D186).\n */\nfunction materializeFeatureImplementation(\n header: FeatureHeader,\n body: LoadedFeatureBody,\n): { readonly own: Readonly<Record<string, unknown>>; readonly record: FeatureRecord } {\n const build =\n optionalFunction<(builder: never) => Readonly<Record<string, unknown>>>(body.own, 'defineFeature own') ??\n (() => ({}));\n const exportDeclaration = snapshotFeatureExportDeclaration(body.exports);\n const buildProvides = optionalFunction<FeatureProvidesFactory<string, never, never, never, never>>(\n body.provides,\n 'defineFeature provides',\n );\n let lowering: FeatureOwnLoweringResult<string, never> | undefined;\n const module = defineGeneratedModule({\n id: header.id,\n runtime: low => {\n lowering = lowerFeatureOwn(low as never, {\n build: build as never,\n id: header.id,\n importKeys: header.importKeys,\n imports: header.imports,\n requirementKeys: header.requirementKeys,\n }) as FeatureOwnLoweringResult<string, never>;\n\n return lowering.loweredRuntime;\n },\n });\n\n if (lowering === undefined) throw new TypeError('defineFeature own did not produce a public record.');\n\n const { dataDescriptors, importScopeKey, publicRuntime, requirementScopeKey } = lowering;\n const own = publicRuntime as unknown as Readonly<Record<string, unknown>>;\n const { contributions, providers } = buildFeatureProvided(header.id, buildProvides as never);\n\n return {\n own,\n record: {\n contributions,\n dataDescriptors,\n exports: exportDeclaration.from,\n importKeys: header.importKeys,\n importScopeKey,\n module,\n providers,\n requirementKeys: header.requirementKeys,\n requirementScopeKey,\n },\n };\n}\n\n/**\n * D186: a header opens nothing by itself. It registers the identity, the edges and the declared border, and keeps\n * the loader; the body is materialized once, on the first open, and every later open reuses the same code.\n */\nfunction defineLazyFeature(source: Readonly<Record<string, unknown>>, id: string): AnyFeature {\n for (const key of ['exports', 'own'] as const) {\n if (source[key] !== undefined) {\n throw new TypeError(`defineFeature ${id} declares body and ${key}: the implementation belongs to the body.`);\n }\n }\n\n if (typeof source['provides'] === 'function') {\n throw new TypeError(`defineFeature ${id} declares body and a provides factory: the header declares targets only.`);\n }\n\n const load = source['body'];\n\n if (typeof load !== 'function') throw new TypeError('defineFeature body must be a loader function.');\n\n const imports = snapshotFeatureImports(source['imports'] as FeatureImportRecord | undefined);\n const requirements = snapshotFeatureRequirements(source['requires'] as PortRequirementRecord | undefined);\n const importKeys = Object.freeze(dataEntries(imports, 'defineFeature imports').map(([key]) => key));\n const requirementKeys = Object.freeze(dataEntries(requirements, 'defineFeature requires').map(([key]) => key));\n const declared = snapshotDeclaredProvided(id, source['provides']);\n const exportsContract = defineFeatureContract<{}>(`${id}.exports`);\n // The refs of `own` are minted by the body, so the header reads them through the record it materializes later.\n let materializedOwn: Readonly<Record<string, unknown>> = Object.freeze({});\n const feature = Object.freeze({\n exports: exportsContract,\n id: declarationId(id),\n imports,\n get own(): Readonly<Record<string, unknown>> {\n return materializedOwn;\n },\n requires: requirements,\n when: snapshotFeatureConditions(source['when']),\n }) as unknown as AnyFeature;\n const header: FeatureHeader = { exportsContract, id, importKeys, imports, requirementKeys, requirements };\n\n registerFeatureRecord(feature, {\n contributions: declared.contributions,\n dataDescriptors: Object.freeze([]),\n exports: () => ({}),\n importKeys,\n importScopeKey: undefined,\n module: Object.freeze({}),\n providers: declared.providers.map(entry => Object.freeze({ ...entry, target: undefined })) as never,\n requirementKeys,\n requirementScopeKey: undefined,\n });\n registerLazyFeature(feature, {\n load: () => Promise.resolve((load as () => PromiseLike<unknown>)()).then(value => requireFeatureBody(id, value)),\n materialize: (body: LoadedFeatureBody) => {\n const materialized = materializeFeatureImplementation(header, body);\n assertBodyMatchesHeader(id, declared, materialized.record);\n materializedOwn = Object.freeze(materialized.own);\n\n return materialized.record;\n },\n });\n featuresByExportContract.set(exportsContract, feature);\n\n return feature;\n}\n\nfunction defineFeatureImplementation<\n const Id extends string,\n const Imports extends FeatureImportRecord,\n const Runtime extends FeatureOwnRecord<Id>,\n const Exports extends FeatureExportRecord,\n const Requires extends PortRequirementRecord = {},\n const Provided extends FeatureProvidedRecord<Id> = FeatureProvidedRecord<Id>,\n When extends readonly Condition[] = readonly Condition[],\n const Keys extends PropertyKey = keyof FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>,\n>(\n options: ExactKeys<Keys, FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>> &\n FeatureInput<Id, Imports, Requires, Runtime, Exports, Provided, When>,\n): Feature<Id, Imports, Runtime, Exports, Requires, When> {\n const source = snapshotFeatureOptions(options);\n const id = requireString<Id>(source['id'], 'defineFeature id');\n\n if (source['body'] !== undefined) {\n return defineLazyFeature(source, id) as unknown as Feature<Id, Imports, Runtime, Exports, Requires, When>;\n }\n\n const exportDeclaration = snapshotFeatureExportDeclaration(source['exports']);\n const build =\n optionalFunction<(builder: FeatureOwnBuilder<Id, Imports, Requires>) => Runtime>(\n source['own'],\n 'defineFeature own',\n ) ?? ((() => ({})) as unknown as (builder: FeatureOwnBuilder<Id, Imports, Requires>) => Runtime);\n const selectExports = exportDeclaration.from;\n const buildProvides = optionalFunction<\n FeatureProvidesFactory<\n Id,\n FeatureOpenContext<Id, Imports, Runtime>,\n FeatureEvaluationContext<Id, Imports, Runtime>,\n Runtime,\n Provided\n >\n >(source['provides'], 'defineFeature provides');\n\n const imports = snapshotFeatureImports(source['imports'] as Imports);\n const requirements = snapshotFeatureRequirements(source['requires'] as Requires | undefined);\n const requirementEntries = dataEntries(requirements, 'defineFeature requires');\n const importKeys = Object.freeze(dataEntries(imports, 'defineFeature imports').map(([key]) => key));\n const requirementKeys = Object.freeze(requirementEntries.map(([key]) => key));\n let lowering: FeatureOwnLoweringResult<Id, Runtime> | undefined;\n const module = defineGeneratedModule({\n id,\n runtime: low => {\n lowering = lowerFeatureOwn(low, {\n build,\n id,\n importKeys,\n imports,\n requirementKeys,\n });\n\n return lowering.loweredRuntime;\n },\n });\n\n if (lowering === undefined) throw new TypeError('defineFeature own did not produce a public record.');\n\n const { dataDescriptors, importScopeKey, publicRuntime, requirementScopeKey } = lowering;\n\n const { contributions, providers } = buildFeatureProvided<\n Id,\n FeatureOpenContext<Id, Imports, Runtime>,\n FeatureEvaluationContext<Id, Imports, Runtime>,\n Runtime,\n Provided\n >(id, buildProvides);\n\n const exportsContract = defineFeatureContract<{}>(`${id}.exports`);\n const feature = Object.freeze({\n exports: exportsContract,\n id: module.id,\n imports,\n own: publicRuntime,\n requires: requirements,\n when: snapshotFeatureConditions(source['when']),\n }) as unknown as Feature<Id, Imports, Runtime, Exports, Requires, When>;\n registerFeatureRecord(feature, {\n contributions,\n dataDescriptors,\n exports: selectExports,\n importKeys,\n importScopeKey,\n module,\n providers,\n requirementKeys,\n requirementScopeKey,\n });\n featuresByExportContract.set(exportsContract, feature);\n\n return feature;\n}\n\n/** `imports` stores the contract, so the application world resolves a feature edge back to the feature (D68). */\nfunction getFeatureByExportContract(contract: object): AnyFeature | undefined {\n return featuresByExportContract.get(contract);\n}\n\n// D186: one word, two forms — the eager triple and the lazy header, so the overload set is the public type.\n// D207: `defineFeature.body` writes the implementation of a header; a member costs no new word of the vocabulary.\nconst defineFeature = Object.assign(defineFeatureImplementation as unknown as DefineFeature, {\n body: featureBody,\n preload: preloadFeatureBody,\n});\n\nfunction getFeatureModule<\n const Id extends string,\n const Imports extends FeatureImportRecord,\n const Runtime extends FeatureOwnRecord<Id>,\n const Exports extends FeatureExportRecord,\n>(feature: Feature<Id, Imports, Runtime, Exports>): ModuleDefinition<Id> {\n return requireFeatureRecord(feature).module as ModuleDefinition<Id>;\n}\n\nfunction getFeatureContributionDescriptors(feature: AnyFeature): FeatureRecord['contributions'] {\n return requireFeatureRecord(feature).contributions;\n}\n\nexport { defineFeature, getFeatureByExportContract, getFeatureContributionDescriptors, getFeatureModule, isFeature };\nexport type {\n AnyFeature,\n Feature,\n FeatureConditionsOf,\n FeatureExportRecord,\n FeatureExportsOf,\n FeatureIdOf,\n FeatureImportRecord,\n FeatureImportsOf,\n FeatureImportValues,\n FeatureOwnRecord,\n FeatureRequirementsOf,\n} from './feature-authoring-types';\n"],"names":["defineGeneratedModule","defineModule","hasDataThen","value","source","descriptor","buildFeatureProvided","featureId","build","builders","createFeatureContributionBuilders","createPortBuilder","assertPlainRecord","entries","dataEntries","contributionEntries","entry","isFeatureContributionDeclaration","providerEntries","snapshotFeatureContributions","snapshotPortProviders","featuresByExportContract","materializeFeatureImplementation","header","body","optionalFunction","exportDeclaration","snapshotFeatureExportDeclaration","buildProvides","lowering","module","low","lowerFeatureOwn","dataDescriptors","importScopeKey","publicRuntime","requirementScopeKey","own","contributions","providers","defineLazyFeature","id","key","load","imports","snapshotFeatureImports","requirements","snapshotFeatureRequirements","importKeys","requirementKeys","declared","snapshotDeclaredProvided","exportsContract","defineFeatureContract","materializedOwn","feature","declarationId","snapshotFeatureConditions","registerFeatureRecord","registerLazyFeature","requireFeatureBody","materialized","assertBodyMatchesHeader","defineFeatureImplementation","options","snapshotFeatureOptions","requireString","selectExports","requirementEntries","getFeatureByExportContract","contract","defineFeature","featureBody","preloadFeatureBody","getFeatureContributionDescriptors","requireFeatureRecord"],"mappings":"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"}
|
package/dist/feature-body.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ interface FeatureBody<Exports extends FeatureExportRecord = FeatureExportRecord>
|
|
|
22
22
|
type FeatureBodyInput<Id extends string, Imports extends FeatureImportRecord, Requires extends PortRequirementRecord, Own extends FeatureOwnRecord<Id>, Exports extends FeatureExportRecord, Provided extends FeatureProvidedRecord<Id>> = {
|
|
23
23
|
readonly exports?: FeatureExportsFactory<Id, Own, Exports>;
|
|
24
24
|
readonly own?: ExactNonUnionRuntime<Own> & ((builder: FeatureOwnBuilder<Id, Imports, NoInfer<Requires>>) => Own);
|
|
25
|
-
readonly provides?: FeatureProvidesFactory<Id, FeatureOpenContext<Id, Imports, Own
|
|
25
|
+
readonly provides?: FeatureProvidesFactory<Id, FeatureOpenContext<Id, Imports, Own>, FeatureEvaluationContext<Id, Imports, Own>, Own, Provided>;
|
|
26
26
|
};
|
|
27
27
|
type FeatureImportRecordOf<Header> = Header extends Feature<infer _Id, infer Imports, infer _Own, infer _Exports, infer _Requires, infer _When> ? Imports : never;
|
|
28
28
|
type FeatureExportRecordOf<Header> = Header extends Feature<infer _Id, infer _Imports, infer _Own, infer Exports, infer _Requires, infer _When> ? Exports : never;
|
package/dist/feature-body.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-body.js","sources":["../src/feature-body.ts"],"sourcesContent":["import type { Condition } from './condition';\nimport type {\n Feature,\n FeatureEvaluationContext,\n FeatureExportRecord,\n FeatureExportsFactory,\n FeatureOpenContext,\n FeatureOwnBuilder,\n FeatureOwnRecord,\n} from './feature-authoring-types';\nimport type { FeatureImportRecord } from './feature-contract';\nimport { isFeature } from './feature-definition-support';\nimport { getLazyFeature, loadFeatureBody } from './feature-lazy';\nimport type { FeatureProvidedRecord, FeatureProvidesFactory, PortRequirementRecord } from './feature-port';\nimport type { ExactNonUnionRuntime } from './public-module';\n\n/**\n * D186: the header of a feature and its body are two files. The header is the identity every consumer imports; the\n * body is the implementation the loader brings in later. `FeatureBody<Exports>` is the narrow view the header names\n * in the return type of its loader — it carries the export contract and nothing else, so the header never depends on\n * the body module and the two types cannot form a cycle.\n */\ninterface FeatureBody<Exports extends FeatureExportRecord = FeatureExportRecord> {\n readonly exports?: (context: never) => Exports;\n readonly own?: unknown;\n readonly provides?: unknown;\n}\n\n/**\n * The body as its own file writes it: `own`, `exports` and `provides` of the declared header, with the builders typed\n * from the header's id, imports and requirements. The record is plain data — the header already owns the identity,\n * so a body needs no second authentic declaration.\n */\ntype FeatureBodyInput<\n Id extends string,\n Imports extends FeatureImportRecord,\n Requires extends PortRequirementRecord,\n Own extends FeatureOwnRecord<Id>,\n Exports extends FeatureExportRecord,\n Provided extends FeatureProvidedRecord<Id>,\n> = {\n readonly exports?: FeatureExportsFactory<Id, Own, Exports>;\n readonly own?: ExactNonUnionRuntime<Own> & ((builder: FeatureOwnBuilder<Id, Imports, NoInfer<Requires>>) => Own);\n readonly provides?: FeatureProvidesFactory<\n Id,\n FeatureOpenContext<Id, Imports, Own
|
|
1
|
+
{"version":3,"file":"feature-body.js","sources":["../src/feature-body.ts"],"sourcesContent":["import type { Condition } from './condition';\nimport type {\n Feature,\n FeatureEvaluationContext,\n FeatureExportRecord,\n FeatureExportsFactory,\n FeatureOpenContext,\n FeatureOwnBuilder,\n FeatureOwnRecord,\n} from './feature-authoring-types';\nimport type { FeatureImportRecord } from './feature-contract';\nimport { isFeature } from './feature-definition-support';\nimport { getLazyFeature, loadFeatureBody } from './feature-lazy';\nimport type { FeatureProvidedRecord, FeatureProvidesFactory, PortRequirementRecord } from './feature-port';\nimport type { ExactNonUnionRuntime } from './public-module';\n\n/**\n * D186: the header of a feature and its body are two files. The header is the identity every consumer imports; the\n * body is the implementation the loader brings in later. `FeatureBody<Exports>` is the narrow view the header names\n * in the return type of its loader — it carries the export contract and nothing else, so the header never depends on\n * the body module and the two types cannot form a cycle.\n */\ninterface FeatureBody<Exports extends FeatureExportRecord = FeatureExportRecord> {\n readonly exports?: (context: never) => Exports;\n readonly own?: unknown;\n readonly provides?: unknown;\n}\n\n/**\n * The body as its own file writes it: `own`, `exports` and `provides` of the declared header, with the builders typed\n * from the header's id, imports and requirements. The record is plain data — the header already owns the identity,\n * so a body needs no second authentic declaration.\n */\ntype FeatureBodyInput<\n Id extends string,\n Imports extends FeatureImportRecord,\n Requires extends PortRequirementRecord,\n Own extends FeatureOwnRecord<Id>,\n Exports extends FeatureExportRecord,\n Provided extends FeatureProvidedRecord<Id>,\n> = {\n readonly exports?: FeatureExportsFactory<Id, Own, Exports>;\n readonly own?: ExactNonUnionRuntime<Own> & ((builder: FeatureOwnBuilder<Id, Imports, NoInfer<Requires>>) => Own);\n readonly provides?: FeatureProvidesFactory<\n Id,\n FeatureOpenContext<Id, Imports, Own>,\n FeatureEvaluationContext<Id, Imports, Own>,\n Own,\n Provided\n >;\n};\n\ntype FeatureImportRecordOf<Header> =\n Header extends Feature<infer _Id, infer Imports, infer _Own, infer _Exports, infer _Requires, infer _When>\n ? Imports\n : never;\ntype FeatureExportRecordOf<Header> =\n Header extends Feature<infer _Id, infer _Imports, infer _Own, infer Exports, infer _Requires, infer _When>\n ? Exports\n : never;\ntype FeatureRequirementRecordOf<Header> =\n Header extends Feature<infer _Id, infer _Imports, infer _Own, infer _Exports, infer Requires, infer _When>\n ? Requires\n : never;\ntype FeatureHeaderIdOf<Header> =\n Header extends Feature<infer Id, infer _Imports, infer _Own, infer _Exports, infer _Requires, infer _When>\n ? Id\n : never;\n\n/** What the body file annotates itself with: everything the header already fixed, and the own record it invents. */\ntype FeatureBodyOf<\n Header,\n Own extends FeatureOwnRecord<FeatureHeaderIdOf<Header>> = FeatureOwnRecord<FeatureHeaderIdOf<Header>>,\n Provided extends FeatureProvidedRecord<FeatureHeaderIdOf<Header>> = FeatureProvidedRecord<FeatureHeaderIdOf<Header>>,\n> = FeatureBodyInput<\n FeatureHeaderIdOf<Header>,\n FeatureImportRecordOf<Header>,\n FeatureRequirementRecordOf<Header>,\n Own,\n FeatureExportRecordOf<Header>,\n Provided\n>;\n\ntype LoadedFeatureBody = {\n readonly exports?: unknown;\n readonly own?: unknown;\n readonly provides?: unknown;\n};\n\nconst bodyKeys = new Set(['exports', 'own', 'provides']);\n\nfunction assertPlainBodyRecord(featureId: string, value: unknown): asserts value is object {\n if (typeof value !== 'object' || value === null) {\n throw new TypeError(`Feature ${featureId} body must be a record of own, exports and provides.`);\n }\n\n const prototype: unknown = Object.getPrototypeOf(value);\n\n if (prototype !== Object.prototype && prototype !== null) {\n throw new TypeError(`Feature ${featureId} body must be a plain object record.`);\n }\n}\n\n/** The loader is foreign code, so what it returns is checked before anything of the feature is materialized. */\nfunction requireFeatureBody(featureId: string, value: unknown): LoadedFeatureBody {\n assertPlainBodyRecord(featureId, value);\n\n for (const key of Reflect.ownKeys(value)) {\n if (typeof key !== 'string' || !bodyKeys.has(key)) {\n throw new TypeError(`Feature ${featureId} body contains unknown field ${String(key)}.`);\n }\n }\n\n return value;\n}\n\n/**\n * D207: the body is written through `defineFeature.body`, a member of the word that already names a feature. A\n * function is what lets TypeScript infer `own` for `exports` and `provides`, exactly as the eager form does, and a\n * member spends no new word on the author's vocabulary. It mints no identity — the header already is the feature.\n */\nfunction featureBody<\n Id extends string,\n Imports extends FeatureImportRecord,\n Exports extends FeatureExportRecord,\n Requires extends PortRequirementRecord,\n Own extends FeatureOwnRecord<Id> = {},\n Provided extends FeatureProvidedRecord<Id> = {},\n>(\n header: Feature<Id, Imports, FeatureOwnRecord<Id>, Exports, Requires, readonly Condition[]>,\n body: FeatureBodyInput<Id, Imports, Requires, Own, Exports, Provided>,\n): FeatureBody<Exports> {\n if (!isFeature(header)) throw new TypeError('featureBody takes the feature its header declared.');\n\n return requireFeatureBody(header.id, body) as FeatureBody<Exports>;\n}\n\n/**\n * D186 asked for a way to fetch the code without opening anything: a host that knows a feature is about to be\n * needed — a hovered entry point, an idle callback — warms its chunk here. It opens no instance, holds no lease and\n * publishes no state; a failure is the caller's to observe, and the next open tries the loader again.\n */\nfunction preloadFeatureBody(header: unknown): Promise<void> {\n if (!isFeature(header)) throw new TypeError('defineFeature.preload takes a feature declaration.');\n\n if (getLazyFeature(header) === undefined) return Promise.resolve();\n\n return loadFeatureBody(header).then(() => undefined);\n}\n\nexport { featureBody, preloadFeatureBody, requireFeatureBody };\nexport type { FeatureBody, FeatureBodyOf, LoadedFeatureBody };\n"],"names":["bodyKeys","assertPlainBodyRecord","featureId","value","prototype","requireFeatureBody","key","featureBody","header","body","isFeature","preloadFeatureBody","getLazyFeature","loadFeatureBody"],"mappings":"oIAyFA,MAAMA,EAAW,IAAI,IAAI,CAAC,UAAW,MAAO,UAAU,CAAC,EAEvD,SAASC,EAAsBC,EAAmBC,EAAc,CAC9D,GAAI,OAAOA,GAAU,UAAYA,IAAU,KACzC,MAAM,IAAI,UAAU,WAAWD,CAAS,sDAAsD,EAGhG,MAAME,EAAqB,OAAO,eAAeD,CAAK,EAEtD,GAAIC,IAAc,OAAO,WAAaA,IAAc,KAClD,MAAM,IAAI,UAAU,WAAWF,CAAS,sCAAsC,CAElF,CAGA,SAASG,EAAmBH,EAAmBC,EAAc,CAC3DF,EAAsBC,EAAWC,CAAK,EAEtC,UAAWG,KAAO,QAAQ,QAAQH,CAAK,EACrC,GAAI,OAAOG,GAAQ,UAAY,CAACN,EAAS,IAAIM,CAAG,EAC9C,MAAM,IAAI,UAAU,WAAWJ,CAAS,gCAAgC,OAAOI,CAAG,CAAC,GAAG,EAI1F,OAAOH,CACT,CAOA,SAASI,EAQPC,EACAC,EAAqE,CAErE,GAAI,CAACC,EAAUF,CAAM,EAAG,MAAM,IAAI,UAAU,oDAAoD,EAEhG,OAAOH,EAAmBG,EAAO,GAAIC,CAAI,CAC3C,CAOA,SAASE,EAAmBH,EAAe,CACzC,GAAI,CAACE,EAAUF,CAAM,EAAG,MAAM,IAAI,UAAU,oDAAoD,EAEhG,OAAII,EAAeJ,CAAM,IAAM,OAAkB,QAAQ,QAAO,EAEzDK,EAAgBL,CAAM,EAAE,KAAK,IAAA,EAAe,CACrD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeclarationId, Readable } from '@opetope/core';
|
|
2
2
|
import type { ContributionPublication, ContributionPublicationInput, ContributionTarget, PipeHandler } from '@opetope/core/internal';
|
|
3
|
-
import type { ContributionModelDeclaration, ContributionModelProps } from './feature-contribution-model.js';
|
|
3
|
+
import type { ContributionModelBuilder, ContributionModelDeclaration, ContributionModelProps } from './feature-contribution-model.js';
|
|
4
4
|
import type { ExactInput } from './feature-record.js';
|
|
5
5
|
declare const featureContributionBrand: unique symbol;
|
|
6
6
|
interface FeatureContribution {
|
|
@@ -70,7 +70,9 @@ type CheckedContribution<Spec, Value> = ExactContributionProps<Spec, Value> exte
|
|
|
70
70
|
* inference circular and TypeScript would fall back to the constraint.
|
|
71
71
|
*/
|
|
72
72
|
interface FeatureSlotBuilder<Context, Evaluation> {
|
|
73
|
-
<Value extends object, const Spec extends NoInfer<Value>, const Options extends FeatureContributionOptions<Evaluation>>(target: ContributionTarget<Value>, contribution: (context: Context
|
|
73
|
+
<Value extends object, const Spec extends NoInfer<Value>, const Options extends FeatureContributionOptions<Evaluation>>(target: ContributionTarget<Value>, contribution: (context: Context & {
|
|
74
|
+
readonly model: ContributionModelBuilder;
|
|
75
|
+
}) => Spec, options?: ExactInput<Options, FeatureContributionOptions<Evaluation>>): CheckedContribution<Spec, Value>;
|
|
74
76
|
<Value extends object, const Spec extends NoInfer<Value>, const Options extends FeatureContributionOptions<Evaluation>>(target: ContributionTarget<Value>, contribution: Spec, options?: ExactInput<Options, FeatureContributionOptions<Evaluation>>): CheckedContribution<Spec, Value>;
|
|
75
77
|
}
|
|
76
78
|
/**
|
|
@@ -90,7 +92,6 @@ interface FeatureContributionDescriptor {
|
|
|
90
92
|
}
|
|
91
93
|
/** The live values of one instance, read by every reactive calculation that instance declared (D220). */
|
|
92
94
|
type FeatureEvaluationValues = Readonly<{
|
|
93
|
-
exports: unknown;
|
|
94
95
|
imports: unknown;
|
|
95
96
|
own: unknown;
|
|
96
97
|
}>;
|
|
@@ -104,6 +105,7 @@ type SnapshotContributionOptions = {
|
|
|
104
105
|
type FeaturePipeFold = (value: unknown, meta: unknown, context: unknown) => unknown;
|
|
105
106
|
type PendingFeatureContribution = SnapshotContributionOptions & {
|
|
106
107
|
readonly fold: FeaturePipeFold | undefined;
|
|
108
|
+
readonly slot: boolean;
|
|
107
109
|
readonly target: ContributionPublicationInput['target'];
|
|
108
110
|
readonly value: FeatureContributionValueFactory<unknown, unknown>;
|
|
109
111
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{declarationId as
|
|
1
|
+
import{declarationId as F,computed as E}from"@opetope/core";import{isContributionTarget as g,publishContributions as T}from"@opetope/core/internal";import{contributionModel as j}from"./feature-contribution-model.js";import{assertPlainRecord as a,dataEntries as d,assertExactDataKeys as C}from"./feature-record.js";const b=new WeakMap,y=new WeakMap,w=new WeakMap,h=new WeakSet,O=new Set(["priority","when"]);function x(e){if(e===void 0)return 0;if(typeof e!="number"||!Number.isFinite(e))throw new TypeError("Feature contribution priority must be a finite number.");return e}function z(e,t){if(t===void 0)throw new TypeError("Feature contribution when predicate has no instance to read.");return E({read:r=>{const n=e({...t,read:r});if(typeof n!="boolean")throw new TypeError("Feature contribution when predicate must return a boolean.");return n}})}function S(e){if(e===void 0)return;if(typeof e=="function"){const r=e;return n=>z(r,n)}if(typeof e!="object"||e===null||typeof e.getSnapshot!="function"||typeof e.subscribe!="function")throw new TypeError("Feature contribution when must be a readable or a predicate of the instance.");const t=e;return()=>t}function k(e){if(e===void 0)return{priority:0,when:void 0};a(e,"Feature contribution options");const t=d(e,"Feature contribution options");if(t.some(([n])=>!O.has(n)))throw new TypeError("Feature contribution options accept only priority and when.");const r=Object.fromEntries(t);return{priority:x(r.priority),when:S(r.when)}}function M(e){if(typeof e=="function"||typeof e!="object"||e===null)throw new TypeError("Feature pipe expects a descriptor: pipe(target, { fold: (value, meta, context) => next }).");a(e,"Feature pipe descriptor");const t=d(e,"Feature pipe descriptor");C(e,t,["fold"],"Feature pipe descriptor");const r=e.fold;if(typeof r!="function")throw new TypeError("Feature pipe fold must be a function.");return r}function P(){const e=new WeakMap,t=new Set,r=(n,o,i,s)=>{if(!g(n))throw new TypeError(`Feature ${s} target is not authentic.`);const u=s==="pipe"?M(o):void 0,c=typeof o=="function"?o:()=>o,f=Object.freeze({});return t.add(f),e.set(f,{...k(i),fold:u,slot:s==="slot"&&typeof o=="function",target:n,value:c}),f};return Object.freeze({declarations:e,declared:t,pipe:(n,o,i)=>r(n,o,i,"pipe"),register:(n,o,i)=>r(n,o,i,"register"),slot:((n,o,i)=>r(n,o,i,"slot"))})}function V(e,t){return typeof t=="object"&&t!==null&&e.declarations.has(t)}function W(e,t){b.set(e,t.value),t.slot&&h.add(e),t.when!==void 0&&y.set(e,t.when),t.fold!==void 0&&w.set(e,t.fold)}function $(e,t,r){const n=new Set,o=r.map(([i,s])=>{const u=typeof s=="object"&&s!==null?t.declarations.get(s):void 0;if(u===void 0)throw new TypeError(`Feature contribution ${i} is not authentic.`);if(n.has(s))throw new TypeError("Every feature contribution must be returned under exactly one key.");n.add(s);const c=Object.freeze({id:F(`${e}.${i}`),priority:u.priority,target:u.target});return W(c,u),c});if(n.size!==t.declared.size)throw new TypeError("Every feature contribution must be returned under exactly one key.");return Object.freeze(o)}function D(e,t){if(t===void 0)throw new TypeError("Feature pipe fold has no instance to read.");const r=[],n=Object.freeze({...t,read:o=>{const i=r[r.length-1];return i===void 0?o.getSnapshot():i(o)}});return(o,i,s)=>{r.push(s.read);try{return e(o,i,n)}finally{r.pop()}}}function K(e,t,r,n,o){let i;const s=e.map(u=>{const c=b.get(u);if(c===void 0)throw new TypeError(`Feature contribution ${u.id} is not authentic.`);const f=w.get(u),l=h.has(u)?i??(i=Object.freeze({...t,model:j})):t,m=f===void 0?c(l):D(f,o),p=y.get(u);return{id:u.id,...n===void 0?{}:{owner:n},priority:u.priority,target:u.target,value:m,when:p==null?void 0:p(o)}});return T(s,r)}export{P as createFeatureContributionBuilders,K as createFeatureContributionPublication,V as isFeatureContributionDeclaration,$ as snapshotFeatureContributions};
|
|
2
2
|
//# sourceMappingURL=feature-contribution.js.map
|