@fragmentsx/runtime-react 0.2.0-dev-20260902143145 → 0.2.0-dev-20260910122311
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/dist/index.d.ts +436 -11
- package/dist/index.es.js +4 -1
- package/package.json +5 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { ComponentType } from 'react';
|
|
2
2
|
import { Context } from 'react';
|
|
3
|
-
import { createFragmentsClient } from '
|
|
4
|
-
import { CreateFragmentsClientOptions } from '
|
|
3
|
+
import { createFragmentsClient } from '@fragmentsx/fragments-client';
|
|
4
|
+
import { CreateFragmentsClientOptions } from '@fragmentsx/fragments-client';
|
|
5
5
|
import { FC } from 'react';
|
|
6
|
-
import { FragmentsApiVersionError } from '
|
|
7
|
-
import { FragmentsAreaError } from '
|
|
8
|
-
import { FragmentsLoadError } from '
|
|
6
|
+
import { FragmentsApiVersionError } from '@fragmentsx/fragments-client';
|
|
7
|
+
import { FragmentsAreaError } from '@fragmentsx/fragments-client';
|
|
8
|
+
import { FragmentsLoadError } from '@fragmentsx/fragments-client';
|
|
9
9
|
import { GraphState } from '@graph-state/core';
|
|
10
|
-
import { JSX } from 'react/jsx-runtime';
|
|
11
10
|
import { ReactElement } from 'react';
|
|
12
11
|
import { ReactNode } from 'react';
|
|
13
12
|
|
|
@@ -60,12 +59,136 @@ export declare interface AreaProps {
|
|
|
60
59
|
};
|
|
61
60
|
}
|
|
62
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Тип поля `Array`. Вырожденный вердикт — `never[]`, когда `definition`
|
|
64
|
+
* отсутствует: элементы читать нельзя, и это ошибка компиляции, а не
|
|
65
|
+
* `unknown[]`/`any[]`, которые открыли бы всё.
|
|
66
|
+
*/
|
|
67
|
+
declare type ArrayFieldType<F extends SchemaFieldDescriptor, D extends number> = F extends {
|
|
68
|
+
definition: infer Def;
|
|
69
|
+
} ? Def extends SchemaFieldDescriptor ? D extends 0 ? ValueOfVariableType<"Array"> : FieldValueType<Def, PrevDepth<D>>[] : never[] : never[];
|
|
70
|
+
|
|
71
|
+
/** Тип-цель `satisfies` для литерала `schema` артефакта (SURF-06). */
|
|
72
|
+
export declare type ArtifactSchema = Readonly<Record<string, ArtifactSchemaField>>;
|
|
73
|
+
|
|
74
|
+
/** Дескриптор одного поля литерала `schema` на верхнем уровне вложенности (корень — `MAX_SCHEMA_DEPTH`). */
|
|
75
|
+
export declare type ArtifactSchemaField = ArtifactSchemaFieldAtDepth<typeof MAX_SCHEMA_DEPTH>;
|
|
76
|
+
|
|
77
|
+
declare type ArtifactSchemaFieldAtDepth<D extends number> = D extends 0 ? never : (ArtifactSchemaFieldCommon & {
|
|
78
|
+
readonly type: "String";
|
|
79
|
+
readonly defaultValue?: string;
|
|
80
|
+
readonly placeholder?: string;
|
|
81
|
+
readonly isTextarea?: boolean;
|
|
82
|
+
readonly isRich?: boolean;
|
|
83
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
84
|
+
readonly type: "Number";
|
|
85
|
+
readonly defaultValue?: number;
|
|
86
|
+
readonly min?: number;
|
|
87
|
+
readonly max?: number;
|
|
88
|
+
readonly step?: number;
|
|
89
|
+
readonly displayStepper?: boolean;
|
|
90
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
91
|
+
readonly type: "Boolean";
|
|
92
|
+
readonly defaultValue?: boolean;
|
|
93
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
94
|
+
readonly type: "Color";
|
|
95
|
+
readonly defaultValue?: string;
|
|
96
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
97
|
+
readonly type: "Image";
|
|
98
|
+
readonly defaultValue?: string | null;
|
|
99
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
100
|
+
readonly type: "Link";
|
|
101
|
+
readonly defaultValue?: string;
|
|
102
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
103
|
+
readonly type: "Enum";
|
|
104
|
+
readonly defaultValue?: string;
|
|
105
|
+
readonly cases?: ReadonlyArray<{
|
|
106
|
+
readonly id: string;
|
|
107
|
+
readonly name: string;
|
|
108
|
+
}>;
|
|
109
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
110
|
+
readonly type: "Object";
|
|
111
|
+
readonly defaultValue?: Record<string, unknown>;
|
|
112
|
+
readonly fields?: Record<string, ArtifactSchemaFieldAtDepth<PrevDepth<D>>>;
|
|
113
|
+
}) | (ArtifactSchemaFieldCommon & {
|
|
114
|
+
readonly type: "Array";
|
|
115
|
+
readonly defaultValue?: readonly unknown[];
|
|
116
|
+
readonly definition?: ArtifactSchemaFieldAtDepth<PrevDepth<D>>;
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Тип-цель литерала `schema` артефакта (Phase 100, план 100-01, SURF-06).
|
|
121
|
+
*
|
|
122
|
+
* Второе представление канона, а не переиспользование valibot-схем
|
|
123
|
+
* (`packages/fragment-compiler/src/gate/schemaLiteralSchemas.ts`) напрямую:
|
|
124
|
+
* прогон планирования показал, что `v.InferInput` не выдерживает рекурсию —
|
|
125
|
+
* `makeVariableLiteralSchema` объявлен с возвращаемым типом
|
|
126
|
+
* `v.BaseSchema<any, any, any>`, и `v.lazy(() => makeVariableLiteralSchema(...))`
|
|
127
|
+
* стирает форму вложенного уровня до `any` (см. `research/questions.md`,
|
|
128
|
+
* ветвь (б)). Переезд valibot-схем в `definition` цели не достигает — второе
|
|
129
|
+
* представление неизбежно, и оно обязано стоять там, откуда его видит
|
|
130
|
+
* артефакт (`@fragmentsx/runtime-react` реэкспортирует ТОЛЬКО типы, без
|
|
131
|
+
* зависимости от `fragment-compiler`).
|
|
132
|
+
*
|
|
133
|
+
* Девять вариантов буквально повторяют девять литеральных valibot-схем
|
|
134
|
+
* `schemaLiteralSchemas.ts` — согласие набора полей в обе стороны держит
|
|
135
|
+
* инвариант-тест `artifactSchemaInvariant.test.ts` (задача 3), а не
|
|
136
|
+
* компилятор: `InferInput` для этого не годится (см. выше).
|
|
137
|
+
*
|
|
138
|
+
* Зарезервированные типы словаря (`Event`, `Goal`, `ComponentInstance`,
|
|
139
|
+
* `Date`, `'fragment'`) в объединение НЕ входят — этим `ArtifactSchema`
|
|
140
|
+
* отличается от `SchemaFieldDescriptor` (`propsFromSchema.ts`), у которого
|
|
141
|
+
* `type: VariableType` принимает любой тип словаря. Ключи `RESERVED_SCHEMA_KEYS`
|
|
142
|
+
* (`__proto__`/`constructor`/`prototype`/`_id`/`_type`/`parent`/`$ref`) типом
|
|
143
|
+
* не выражаются и остаются структурным кодом `SCHEMA_RESERVED_KEY` в гейте —
|
|
144
|
+
* TypeScript не умеет запретить конкретные строковые ключи объекта общим
|
|
145
|
+
* механизмом без потери индексной сигнатуры.
|
|
146
|
+
*
|
|
147
|
+
* Предел вложенности приходит СНАРУЖИ через `typeof MAX_SCHEMA_DEPTH`, а
|
|
148
|
+
* отсчёт — та же таблица `PrevDepth`, что уже стоит в `propsFromSchema.ts`:
|
|
149
|
+
* второй копии литерала предела в этом файле нет. За пределом глубины
|
|
150
|
+
* вложенный дескриптор — `never`, а не `any` (T-100-01): схема четвёртого
|
|
151
|
+
* уровня обязана быть ошибкой компиляции, симметрично `v.never()` в
|
|
152
|
+
* `makeVariableLiteralSchema`.
|
|
153
|
+
*/
|
|
154
|
+
declare interface ArtifactSchemaFieldCommon {
|
|
155
|
+
readonly required?: boolean;
|
|
156
|
+
readonly editable?: boolean;
|
|
157
|
+
}
|
|
158
|
+
|
|
63
159
|
/**
|
|
64
160
|
* Browser-specific options — identical к CreateFragmentsClientOptions, но без `inject`.
|
|
65
161
|
* `inject` pre-populated через `injectStylesheet` из runtime-react автоматически.
|
|
66
162
|
*/
|
|
67
163
|
declare type BrowserClientOptions = Omit<CreateFragmentsClientOptions, "inject">;
|
|
68
164
|
|
|
165
|
+
/** Раскрывает кортеж/массив `cases` до union строковых литералов `id`. */
|
|
166
|
+
declare type CaseIds<Cases> = Cases extends ReadonlyArray<infer Case> ? Case extends {
|
|
167
|
+
readonly id: infer Id;
|
|
168
|
+
} ? Id extends string ? Id : never : never : never;
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Представление ПОТРЕБИТЕЛЯ (Phase 97, план 97-02, TYPES-04) — то, что видит
|
|
172
|
+
* вызывающий, конструирующий `props` для артефакта СНАРУЖИ (например, тест
|
|
173
|
+
* или превью). Отличается от `PropsFromSchema` РОВНО одним: значение по
|
|
174
|
+
* умолчанию на верхнем уровне обязательности НЕ создаёт (`ConsiderDefault =
|
|
175
|
+
* false`) — подставит его рантайм (`resolveVariantProps`), а не вызывающий.
|
|
176
|
+
*
|
|
177
|
+
* Внутри `Object.fields` правило ОДНО на оба представления — только
|
|
178
|
+
* `required: true` (D-97-05): в домене схемы артефакта вложенные дефолты не
|
|
179
|
+
* применяет никто (`resolveVariantProps` не рекурсирует в `descriptor.fields`
|
|
180
|
+
* — это свойство ИМЕННО этого домена, не общий факт кодовой базы: в домене
|
|
181
|
+
* уровневых переменных проекта, который читает `ProjectPropertyDescriptor` в
|
|
182
|
+
* `@fragmentsx/fragment-compiler`, рекурсивное применение дефолтов ЕСТЬ и
|
|
183
|
+
* работает в проде тремя копиями, см. `composeScopePropertyValue.ts`).
|
|
184
|
+
*
|
|
185
|
+
* ГРАНИЦА ПРИМЕНИМОСТИ (WR-03, Phase 97 review) — та же, что у
|
|
186
|
+
* `PropsFromSchema` (см. её докстринг): `S` обязан выводиться из ЛИТЕРАЛА,
|
|
187
|
+
* широкая аннотация переменной схемы до `typeof` схлопывает generic молча,
|
|
188
|
+
* без ошибки компиляции.
|
|
189
|
+
*/
|
|
190
|
+
export declare type ConsumerPropsFromSchema<S extends Record<string, SchemaFieldDescriptor>> = PropsShape<S, false, typeof MAX_SCHEMA_DEPTH>;
|
|
191
|
+
|
|
69
192
|
/**
|
|
70
193
|
* Создаёт FragmentsClient с pre-populated inject = injectStylesheet (BLOCKER-4-wiring bridge).
|
|
71
194
|
*
|
|
@@ -77,8 +200,71 @@ export declare function createBrowserClient(opts: BrowserClientOptions): ReturnT
|
|
|
77
200
|
/**
|
|
78
201
|
* Дефолтное значение, когда Provider не установлен (потребитель вне
|
|
79
202
|
* `FragmentRenderer`, например изолированный юнит-тест компонента).
|
|
203
|
+
*
|
|
204
|
+
* Литерал типизирован утверждением типа (Phase 97): пока `ProjectProperties`
|
|
205
|
+
* пуст, пустой объектный литерал ему соответствует и без утверждения; после
|
|
206
|
+
* расширения потребителем (`declare module` в его собственном файле) этот
|
|
207
|
+
* платформенный код по-прежнему обязан компилироваться БЕЗ расширения рядом
|
|
208
|
+
* — утверждение фиксирует эту границу, а не обходит проверку.
|
|
209
|
+
*/
|
|
210
|
+
export declare const defaultProjectProperties: ProjectProperties;
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Отсчёт глубины на уровне типов — конечная таблица декремента, а не
|
|
214
|
+
* повторный литерал предела: сам предел приходит СНАРУЖИ через `typeof
|
|
215
|
+
* MAX_SCHEMA_DEPTH` (канон `@fragmentsx/definition/constants`), таблица лишь
|
|
216
|
+
* реализует арифметику «минус один» для чисел вплоть до предела с запасом.
|
|
217
|
+
*
|
|
218
|
+
* Экспортирован (Phase 100, план 100-01) — `artifactSchema.ts` использует ТУ ЖЕ
|
|
219
|
+
* машинерию отсчёта, а не второй скопированный литерал предела: копия таблицы
|
|
220
|
+
* несла бы буквенный `3` вторым местом, которое проверка `grep` плана обязана
|
|
221
|
+
* не найти нигде, кроме строки с `MAX_SCHEMA_DEPTH`.
|
|
80
222
|
*/
|
|
81
|
-
|
|
223
|
+
declare type DepthCountdown = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Тип поля `Enum`. Вырожденный вердикт (Phase 97, T-97-02-03) — `never`,
|
|
227
|
+
* когда `cases` отсутствует ИЛИ пуст: у перечисления без вариантов нет ни
|
|
228
|
+
* одного допустимого значения, `never` делает чтение такого поля ошибкой
|
|
229
|
+
* компиляции вместо тихого `string` (базовое отображение таблицы).
|
|
230
|
+
*
|
|
231
|
+
* Проверка присутствия ключа идёт через `F extends { cases: infer Cases }`
|
|
232
|
+
* (сравнение по факту наличия свойства в конкретной инстанциации F), а НЕ
|
|
233
|
+
* через прямой индексированный доступ `F["cases"]` — последний в generic-
|
|
234
|
+
* контексте резолвится по ограничению (`SchemaFieldDescriptor`), а не по
|
|
235
|
+
* фактической форме F, и не отличил бы «cases нет» от «cases есть».
|
|
236
|
+
*/
|
|
237
|
+
declare type EnumFieldType<F extends SchemaFieldDescriptor> = F extends {
|
|
238
|
+
cases: infer Cases;
|
|
239
|
+
} ? Cases extends ReadonlyArray<{
|
|
240
|
+
readonly id: string;
|
|
241
|
+
}> ? Cases extends readonly [] ? never : CaseIds<Cases> : never : never;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Правило обязательности ВЕРХНЕГО уровня, параметризованное одним флагом
|
|
245
|
+
* `ConsiderDefault` — единственное различие между `PropsFromSchema`
|
|
246
|
+
* (`ConsiderDefault = true`, домен компонента) и `ConsumerPropsFromSchema`
|
|
247
|
+
* (`ConsiderDefault = false`, домен потребителя, подставляющего значение по
|
|
248
|
+
* умолчанию сам). Внутри `Object.fields` этот же обход вызывается с
|
|
249
|
+
* `ConsiderDefault = false` НЕЗАВИСИМО от верхнего представления — правило
|
|
250
|
+
* вложенного уровня одно на оба представления (D-97-05).
|
|
251
|
+
*
|
|
252
|
+
* `required: true` И `defaultValue` одновременно — поле обязательно
|
|
253
|
+
* (признаки не отменяют друг друга: `HasRequiredTrue` проверяется первым и
|
|
254
|
+
* коротким замыканием даёт `true`, не заглядывая в `ConsiderDefault`).
|
|
255
|
+
*/
|
|
256
|
+
declare type FieldRequired<F extends SchemaFieldDescriptor, ConsiderDefault extends boolean> = HasRequiredTrue<F> extends true ? true : ConsiderDefault extends true ? HasDefaultValueKey<F> : false;
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Тип ЗНАЧЕНИЯ одного поля на глубине обхода `D` — три сужения (Enum/Object/
|
|
260
|
+
* Array), остальные десять типов — прямая проекция таблицы
|
|
261
|
+
* `VARIABLE_TYPE_TO_TS`. `F["type"]` внутри условного типа резолвится ПО
|
|
262
|
+
* КОНКРЕТНОЙ инстанциации F (условный тип с голым параметром типа
|
|
263
|
+
* пере-вычисляется на каждой инстанциации) — в отличие от прямого
|
|
264
|
+
* индексированного доступа вне условного типа, который резолвился бы по
|
|
265
|
+
* ограничению.
|
|
266
|
+
*/
|
|
267
|
+
declare type FieldValueType<F extends SchemaFieldDescriptor, D extends number> = F["type"] extends "Enum" ? EnumFieldType<F> : F["type"] extends "Object" ? ObjectFieldType<F, D> : F["type"] extends "Array" ? ArrayFieldType<F, D> : ValueOfVariableType<F["type"]>;
|
|
82
268
|
|
|
83
269
|
export declare interface FragmentMetrics {
|
|
84
270
|
reachGoal: (info: ReachGoalInfo) => void;
|
|
@@ -132,11 +318,15 @@ export declare const FragmentsClientContext: Context<FragmentsClient | null>;
|
|
|
132
318
|
/**
|
|
133
319
|
* React-компонент-обёртка для установки FragmentsClient в Context. Эмиссия
|
|
134
320
|
* compiled-output её не вызывает — это app-level wiring entry point.
|
|
321
|
+
*
|
|
322
|
+
* Явная аннотация возврата (WR-01, Phase 97 review) — требуется страховкой
|
|
323
|
+
* барреля `sdk-surface.test.ts` («каждая поверхность несёт явную аннотацию
|
|
324
|
+
* возврата»), см. докстринг `getExplicitReturnTypeNode` там же.
|
|
135
325
|
*/
|
|
136
326
|
export declare function FragmentsClientProvider(props: {
|
|
137
327
|
value: FragmentsClient;
|
|
138
328
|
children: ReactNode;
|
|
139
|
-
}):
|
|
329
|
+
}): ReactElement;
|
|
140
330
|
|
|
141
331
|
export { FragmentsLoadError }
|
|
142
332
|
|
|
@@ -157,13 +347,21 @@ declare interface FragmentsProviderProps {
|
|
|
157
347
|
children: ReactNode;
|
|
158
348
|
}
|
|
159
349
|
|
|
160
|
-
export declare function FragmentStylesheet({ href, fragmentKey }: FragmentStylesheetProps):
|
|
350
|
+
export declare function FragmentStylesheet({ href, fragmentKey, }: FragmentStylesheetProps): ReactElement | null;
|
|
161
351
|
|
|
162
352
|
declare interface FragmentStylesheetProps {
|
|
163
353
|
href: string;
|
|
164
354
|
fragmentKey: string;
|
|
165
355
|
}
|
|
166
356
|
|
|
357
|
+
/** Присутствие КЛЮЧА `defaultValue`, а не истинность его значения (Phase 97, план 97-02): `defaultValue: 0`/`''`/`false`/`null` — присутствующие значения, `keyof F` включает ключ ровно тогда, когда он был указан в литерале поля. */
|
|
358
|
+
declare type HasDefaultValueKey<F> = "defaultValue" extends keyof F ? true : false;
|
|
359
|
+
|
|
360
|
+
/** Есть ли у поля флаг `required: true` — ЕДИНСТВЕННОЕ правило обязательности внутри `Object.fields` на любом уровне (D-97-05). */
|
|
361
|
+
declare type HasRequiredTrue<F> = F extends {
|
|
362
|
+
required: true;
|
|
363
|
+
} ? true : false;
|
|
364
|
+
|
|
167
365
|
/**
|
|
168
366
|
* Инжектирует `<link rel="stylesheet">` в `document.head` с ref-count dedup.
|
|
169
367
|
*
|
|
@@ -176,6 +374,13 @@ export declare const injectStylesheet: (href: string, key: string) => Stylesheet
|
|
|
176
374
|
|
|
177
375
|
export declare const InstanceIdContext: Context<string | null>;
|
|
178
376
|
|
|
377
|
+
/**
|
|
378
|
+
* Единственный литерал предела глубины вложенности Object/Array-переменных
|
|
379
|
+
* (D-71-12) — тем же значением пользуется гейт публикации (`fragment-compiler`
|
|
380
|
+
* ре-экспортирует эту константу вместо собственного литерала).
|
|
381
|
+
*/
|
|
382
|
+
declare const MAX_SCHEMA_DEPTH = 3;
|
|
383
|
+
|
|
179
384
|
/**
|
|
180
385
|
* React Context для инъекции cache-reader'а в дерево компонентов.
|
|
181
386
|
* Null default = «provider не установлен» (no-provider signal).
|
|
@@ -185,6 +390,19 @@ export declare const ModulesMapContext: Context<ModulesMapContextValue | null>;
|
|
|
185
390
|
/**
|
|
186
391
|
* Значение ModulesMapContext. Единственная fn — cache-reader (D-05).
|
|
187
392
|
*
|
|
393
|
+
* `read` возвращает `ComponentType` с широким параметром типа — ЗАПИСАННОЕ
|
|
394
|
+
* РЕШЕНИЕ (D-97-12), не недоделка. Тип чужого динамически загружаемого
|
|
395
|
+
* компонента статически неизвестен по построению: фрагмент грузится по
|
|
396
|
+
* числовому идентификатору в момент выполнения, и его форма не известна ни
|
|
397
|
+
* одному участнику сборки. Оба мыслимых сужения хуже неопределённости:
|
|
398
|
+
* параметр типа от вызывающего — то же утверждение типа, только отмытое и
|
|
399
|
+
* перенесённое на вызывающего, запрещено Г-03; сужение до пустого
|
|
400
|
+
* объектного параметра типа честно и бесполезно — артефакт всё равно не
|
|
401
|
+
* может употребить чужой компонент иначе, чем передав его в JSX. ЗАПРЕЩЕНО
|
|
402
|
+
* «чинить» эту сигнатуру утверждением типа или параметром типа от
|
|
403
|
+
* вызывающего — `sdk-surface.test.ts` требует этого маркера у сигнатуры и
|
|
404
|
+
* красит тест при его снятии.
|
|
405
|
+
*
|
|
188
406
|
* @param id - числовой идентификатор фрагмента
|
|
189
407
|
* @returns ComponentType (cache hit) | throws Promise (pending) | throws FragmentsLoadError (missing)
|
|
190
408
|
*/
|
|
@@ -212,7 +430,83 @@ declare interface ModulesMapProviderProps {
|
|
|
212
430
|
children: ReactNode;
|
|
213
431
|
}
|
|
214
432
|
|
|
215
|
-
|
|
433
|
+
/**
|
|
434
|
+
* Тип поля `Object`. Вырожденный вердикт — литеральный `{}` (пустой
|
|
435
|
+
* объектный тип БЕЗ индексной сигнатуры), когда `fields` отсутствует или
|
|
436
|
+
* пуст: `{}` даёт ошибку компиляции (TS2339) на обращении к произвольному
|
|
437
|
+
* ключу, а базовое отображение таблицы `Record<string, unknown>` этого не
|
|
438
|
+
* делает — оно как раз ДАЁТ доступ к любому ключу молча, и это ровно то,
|
|
439
|
+
* чего вырожденный дескриптор не должен разрешать.
|
|
440
|
+
*
|
|
441
|
+
* За пределом `MAX_SCHEMA_DEPTH` (D-глубина исчерпана) обход не идёт дальше:
|
|
442
|
+
* возвращается базовое отображение таблицы, а не `any`.
|
|
443
|
+
*/
|
|
444
|
+
declare type ObjectFieldType<F extends SchemaFieldDescriptor, D extends number> = F extends {
|
|
445
|
+
fields: infer Fields;
|
|
446
|
+
} ? Fields extends Record<string, SchemaFieldDescriptor> ? keyof Fields extends never ? {} : D extends 0 ? ValueOfVariableType<"Object"> : PropsShape<Fields, false, PrevDepth<D>> : {} : {};
|
|
447
|
+
|
|
448
|
+
declare type PrevDepth<D extends number> = D extends 0 ? never : DepthCountdown[D];
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Расширяемый интерфейс SDK (Phase 97, D-97-01) — единственная поверхность,
|
|
452
|
+
* которую расширяет сгенерированный `project.d.ts`. Объявлен пустым здесь
|
|
453
|
+
* же, а не в отдельном модуле типов: контекст и его дефолт ниже типизируются
|
|
454
|
+
* ИМ ЖЕ, и разводить объявление с его единственными потребителями незачем.
|
|
455
|
+
*/
|
|
456
|
+
export declare interface ProjectProperties {
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export declare const ProjectPropertiesContext: Context<ProjectProperties | null>;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Внутрикомпонентное представление типа `props` (Phase 97, план 97-02,
|
|
463
|
+
* TYPES-03) — то, что артефакт видит у СЕБЯ внутри компонента. Поле верхнего
|
|
464
|
+
* уровня обязательно при `required: true` ИЛИ при присутствии ключа
|
|
465
|
+
* `defaultValue` (`ConsiderDefault = true`): `resolveVariantProps`
|
|
466
|
+
* (`helpers/resolveVariantProps.ts:35,62`) идёт только по верхнеуровневым
|
|
467
|
+
* ключам и подставляет `defaultValue` буквально — внутри компонента такое
|
|
468
|
+
* поле гарантировано присутствует.
|
|
469
|
+
*
|
|
470
|
+
* `defaultValue: null` — присутствующее значение, поле обязательно так же,
|
|
471
|
+
* как и с любым другим значением (0/''/false); граница «присутствует» и
|
|
472
|
+
* «осмысленно» здесь расходится СОЗНАТЕЛЬНО: `resolveVariantProps` подставит
|
|
473
|
+
* буквально `null`, и внутри компонента поле будет — `null`, не отсутствовать.
|
|
474
|
+
*
|
|
475
|
+
* Схема без полей (`{}`) даёт тип без пригодных ключей — обращение к
|
|
476
|
+
* произвольному ключу такого `props` есть ошибка компиляции.
|
|
477
|
+
*
|
|
478
|
+
* ГРАНИЦА ПРИМЕНИМОСТИ (WR-03, Phase 97 review): `S` ОБЯЗАН выводиться из
|
|
479
|
+
* ЛИТЕРАЛА (`typeof schema` на буквальном объектном литерале, как в каждом
|
|
480
|
+
* примере `artifactExamples.ts`). Если потребитель аннотирует переменную
|
|
481
|
+
* схемы широким типом ДО `typeof` —
|
|
482
|
+
* `const schema: Record<string, SchemaFieldDescriptor> = {...}` — `S`
|
|
483
|
+
* инстанциируется как этот широкий тип, `keyof S` схлопывается до `string`,
|
|
484
|
+
* и КАЖДОЕ поле резолвится до целого `SchemaFieldDescriptor` вместо своего
|
|
485
|
+
* буквального поля: `HasDefaultValueKey`/`HasRequiredTrue`/`FieldValueType`
|
|
486
|
+
* дают бесполезный широкий результат ОДИНАКОВО для всех полей — БЕЗ единой
|
|
487
|
+
* ошибки компиляции (см. `propsFromSchema.test-d.ts`, кейс «широкая
|
|
488
|
+
* аннотация до typeof схлопывает generic»). Это известное ограничение
|
|
489
|
+
* TS-generic-утилит такого рода, а не дефект: штатный путь — необсуждённый
|
|
490
|
+
* литерал `schema` в TSX-исходнике — с ним не сталкивается.
|
|
491
|
+
*/
|
|
492
|
+
export declare type PropsFromSchema<S extends Record<string, SchemaFieldDescriptor>> = PropsShape<S, true, typeof MAX_SCHEMA_DEPTH>;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Один обход схемы, параметризованный правилом верхнего уровня
|
|
496
|
+
* (`ConsiderDefault`) — оба публичных представления (`PropsFromSchema`/
|
|
497
|
+
* `ConsumerPropsFromSchema`) производятся ИМ ЖЕ, а не двумя копиями (Г-07):
|
|
498
|
+
* разъехавшиеся копии обхода и есть тот второй контракт рядом со значением
|
|
499
|
+
* по умолчанию, который правило запрещает.
|
|
500
|
+
*
|
|
501
|
+
* Ключи разбиваются на обязательные/опциональные через `as`-переотображение
|
|
502
|
+
* мэппед-типа (стандартный приём разбиения ключей объекта по предикату) и
|
|
503
|
+
* пересекаются — обязательные без `?`, опциональные с `?`.
|
|
504
|
+
*/
|
|
505
|
+
declare type PropsShape<S extends Record<string, SchemaFieldDescriptor>, ConsiderDefault extends boolean, D extends number> = Simplify<{
|
|
506
|
+
[K in keyof S as FieldRequired<S[K], ConsiderDefault> extends true ? K : never]: FieldValueType<S[K], D>;
|
|
507
|
+
} & {
|
|
508
|
+
[K in keyof S as FieldRequired<S[K], ConsiderDefault> extends true ? never : K]?: FieldValueType<S[K], D>;
|
|
509
|
+
}>;
|
|
216
510
|
|
|
217
511
|
/**
|
|
218
512
|
* Payload для `reachGoal`. Phase 3 НЕ автоинъектит scope-поля
|
|
@@ -227,6 +521,38 @@ export declare interface ReachGoalInfo {
|
|
|
227
521
|
campaignId?: number;
|
|
228
522
|
}
|
|
229
523
|
|
|
524
|
+
/**
|
|
525
|
+
* Дескриптор ОДНОГО поля литерала `schema` артефакта (Phase 97, план 97-02,
|
|
526
|
+
* TYPES-03/04) — форма, которую `PropsFromSchema` видит в TSX-исходнике
|
|
527
|
+
* артефакта (домен схемы артефакта, не домен уровневых переменных проекта —
|
|
528
|
+
* см. `ProjectPropertyDescriptor` в `@fragmentsx/fragment-compiler`, форма та
|
|
529
|
+
* же, но домен другой, и объединять их не нужно: у гейта дескриптор — вход
|
|
530
|
+
* публичного контракта, здесь — форма литерала в исходнике артефакта).
|
|
531
|
+
*
|
|
532
|
+
* `readonly` на всех полях — этот тип используется ТОЛЬКО как параметр
|
|
533
|
+
* `extends` для generic-вывода (`PropsFromSchema<typeof schema>`), а не как
|
|
534
|
+
* тип значения, которое мутируется в рантайме.
|
|
535
|
+
*/
|
|
536
|
+
export declare interface SchemaFieldDescriptor {
|
|
537
|
+
readonly type: VariableType;
|
|
538
|
+
readonly required?: boolean;
|
|
539
|
+
readonly defaultValue?: unknown;
|
|
540
|
+
/** `Enum` — варианты значения; `PropsFromSchema` сужает до `cases[].id`. */
|
|
541
|
+
readonly cases?: ReadonlyArray<{
|
|
542
|
+
readonly id: string;
|
|
543
|
+
readonly name: string;
|
|
544
|
+
}>;
|
|
545
|
+
/** `Object` — вложенные поля; та же форма рекурсивно. */
|
|
546
|
+
readonly fields?: Record<string, SchemaFieldDescriptor>;
|
|
547
|
+
/** `Array` — дескриптор элемента; та же форма рекурсивно. */
|
|
548
|
+
readonly definition?: SchemaFieldDescriptor;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/** Разворачивает пересечение мэппед-типов в один плоский объектный тип для читаемых сообщений об ошибках компилятора. */
|
|
552
|
+
declare type Simplify<T> = {
|
|
553
|
+
[K in keyof T]: T[K];
|
|
554
|
+
} & {};
|
|
555
|
+
|
|
230
556
|
/**
|
|
231
557
|
* Ref-counted `<link rel="stylesheet">` injector для compiled fragment CSS delivery (Req #11).
|
|
232
558
|
*
|
|
@@ -385,6 +711,105 @@ export declare function useFragmentMetrics(): FragmentMetrics;
|
|
|
385
711
|
|
|
386
712
|
export declare function useFragmentStylesheet(href: string, key: string): void;
|
|
387
713
|
|
|
388
|
-
export declare function useProjectProperty(name:
|
|
714
|
+
export declare function useProjectProperty<K extends keyof ProjectProperties>(name: K): ProjectProperties[K];
|
|
715
|
+
|
|
716
|
+
/** Носитель типа поля-НЕ-Enum/Object/Array — читает `value`-проекцию таблицы `VARIABLE_TYPE_TO_TS` (носитель, значение не используется, только тип). */
|
|
717
|
+
declare type ValueOfVariableType<T extends VariableType> = (typeof VARIABLE_TYPE_TO_TS)[T]["value"];
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Таблица `VariableType → тип TS` (Phase 97, TYPES-02, D-97-03). Живёт в
|
|
721
|
+
* `packages/definition` — рядом с самим `VariableType` (`constants/index.ts`),
|
|
722
|
+
* а не в гейте и не в `runtime-react`: `PropsFromSchema` (план 97-02) обязан
|
|
723
|
+
* быть импортируем артефактом (`@fragmentsx/runtime-react`), а зависимость
|
|
724
|
+
* `runtime-react → fragment-compiler` недопустима бюджетом бандла (RUNTIME-05).
|
|
725
|
+
*
|
|
726
|
+
* НЕ сливать с двумя соседними реестрами `VariableType → valibot-схема`,
|
|
727
|
+
* живущими в другом домене (домен valibot-дефолтов и домен литеральности
|
|
728
|
+
* схемы артефакта соответственно) — три таблицы, три домена (D-97-03).
|
|
729
|
+
* Поимённо и с числом покрытия каждого соседнего реестра — см. докстринг
|
|
730
|
+
* `variableTypeToTs.test.ts`: это единственное место, где запрет на
|
|
731
|
+
* слияние виден тому, кто через полгода откроет три похожих объекта и
|
|
732
|
+
* решит их свести. Обе соседние таблицы разошлись между собой незамеченно
|
|
733
|
+
* именно потому, что ни одна не была исчерпывающей механически; эта
|
|
734
|
+
* таблица закрывает исчерпанность компилятором — предикатом полноты в
|
|
735
|
+
* конце файла, а не глазами.
|
|
736
|
+
*
|
|
737
|
+
* `Event`/`Goal`/`ComponentInstance` — `never`: у события и цели значения
|
|
738
|
+
* нет вовсе, а экземпляр компонента в артефакт не проецируется — `never`
|
|
739
|
+
* делает попытку прочитать такое свойство ошибкой компиляции вместо тихого
|
|
740
|
+
* `undefined` в рантайме.
|
|
741
|
+
*/
|
|
742
|
+
declare const VARIABLE_TYPE_TO_TS: {
|
|
743
|
+
String: {
|
|
744
|
+
ts: string;
|
|
745
|
+
value: string;
|
|
746
|
+
};
|
|
747
|
+
Link: {
|
|
748
|
+
ts: string;
|
|
749
|
+
value: string;
|
|
750
|
+
};
|
|
751
|
+
Color: {
|
|
752
|
+
ts: string;
|
|
753
|
+
value: string;
|
|
754
|
+
};
|
|
755
|
+
Image: {
|
|
756
|
+
ts: string;
|
|
757
|
+
value: string;
|
|
758
|
+
};
|
|
759
|
+
Date: {
|
|
760
|
+
ts: string;
|
|
761
|
+
value: string;
|
|
762
|
+
};
|
|
763
|
+
Number: {
|
|
764
|
+
ts: string;
|
|
765
|
+
value: number;
|
|
766
|
+
};
|
|
767
|
+
Boolean: {
|
|
768
|
+
ts: string;
|
|
769
|
+
value: boolean;
|
|
770
|
+
};
|
|
771
|
+
Enum: {
|
|
772
|
+
ts: string;
|
|
773
|
+
value: string;
|
|
774
|
+
};
|
|
775
|
+
Object: {
|
|
776
|
+
ts: string;
|
|
777
|
+
value: Record<string, unknown>;
|
|
778
|
+
};
|
|
779
|
+
Array: {
|
|
780
|
+
ts: string;
|
|
781
|
+
value: unknown[];
|
|
782
|
+
};
|
|
783
|
+
Event: {
|
|
784
|
+
ts: string;
|
|
785
|
+
value: never;
|
|
786
|
+
};
|
|
787
|
+
Goal: {
|
|
788
|
+
ts: string;
|
|
789
|
+
value: never;
|
|
790
|
+
};
|
|
791
|
+
ComponentInstance: {
|
|
792
|
+
ts: string;
|
|
793
|
+
value: never;
|
|
794
|
+
};
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
declare type VariableType = keyof typeof variableType;
|
|
798
|
+
|
|
799
|
+
declare const variableType: {
|
|
800
|
+
Image: "Image";
|
|
801
|
+
Link: "Link";
|
|
802
|
+
Event: "Event";
|
|
803
|
+
String: "String";
|
|
804
|
+
Boolean: "Boolean";
|
|
805
|
+
Array: "Array";
|
|
806
|
+
Color: "Color";
|
|
807
|
+
ComponentInstance: "ComponentInstance";
|
|
808
|
+
Date: "Date";
|
|
809
|
+
Enum: "Enum";
|
|
810
|
+
Number: "Number";
|
|
811
|
+
Object: "Object";
|
|
812
|
+
Goal: "Goal";
|
|
813
|
+
};
|
|
389
814
|
|
|
390
815
|
export { }
|
package/dist/index.es.js
CHANGED
|
@@ -118,7 +118,10 @@ function J(r, e) {
|
|
|
118
118
|
H(() => M(r, e), [r, e]);
|
|
119
119
|
}
|
|
120
120
|
const q = parseInt(k.split(".")[0], 10), Q = q >= 19;
|
|
121
|
-
function E({
|
|
121
|
+
function E({
|
|
122
|
+
href: r,
|
|
123
|
+
fragmentKey: e
|
|
124
|
+
}) {
|
|
122
125
|
return Q ? /* @__PURE__ */ l(
|
|
123
126
|
"link",
|
|
124
127
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fragmentsx/runtime-react",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.2.0-dev-
|
|
4
|
+
"version": "0.2.0-dev-20260910122311",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@graph-state/core": "^0.13.3",
|
|
35
|
-
"@fragmentsx/fragments-client": "0.2.0-dev-
|
|
35
|
+
"@fragmentsx/fragments-client": "0.2.0-dev-20260910122311"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@testing-library/jest-dom": "^6.6.3",
|
|
@@ -45,13 +45,14 @@
|
|
|
45
45
|
"typescript": "^5.5.4",
|
|
46
46
|
"vite": "^6.1.0",
|
|
47
47
|
"vite-plugin-dts": "^4.5.0",
|
|
48
|
-
"vitest": "^3.1.1"
|
|
48
|
+
"vitest": "^3.1.1",
|
|
49
|
+
"@fragmentsx/definition": "0.2.3"
|
|
49
50
|
},
|
|
50
51
|
"scripts": {
|
|
51
52
|
"clear": "rm -r -f ./dist",
|
|
52
53
|
"build": "vite build",
|
|
53
54
|
"dev": "vite build -w",
|
|
54
|
-
"test": "vitest run --config ./vitest.config.ts",
|
|
55
|
+
"test": "NODE_OPTIONS=--max-old-space-size=2048 vitest run --config ./vitest.config.ts",
|
|
55
56
|
"test:watch": "vitest --config ./vitest.config.ts",
|
|
56
57
|
"lint": "eslint . --ext .ts,.tsx --fix"
|
|
57
58
|
}
|