@topik/core 0.1.0-alpha.3 → 0.1.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.d.mts +419 -17
  2. package/dist/index.mjs +2900 -346
  3. package/package.json +9 -10
package/dist/index.d.mts CHANGED
@@ -1,6 +1,13 @@
1
1
  import { z } from "zod";
2
- import { Asset, Guide, Wiki, WikiPage } from "@topik/schema";
3
-
2
+ import { TopikContentDiagnostic, TopikGeneratedAssetName } from "@topik/content-schema";
3
+ import { CoursePage } from "@topik/schema/course-page/v1";
4
+ import { Guide } from "@topik/schema/guide/v1";
5
+ import { WikiPage } from "@topik/schema/wiki-page/v1";
6
+ import { Asset } from "@topik/schema/asset/v1";
7
+ import { Course } from "@topik/schema/course/v1";
8
+ import { CourseModule } from "@topik/schema/course-module/v1";
9
+ import { Person } from "@topik/schema/person/v1";
10
+ import { Wiki, WikiDropdownNavNode, WikiExternalDropdownNavNode, WikiExternalTabNavNode, WikiInternalDropdownNavNode, WikiInternalTabNavNode, WikiNavContainerNode, WikiNavNode, WikiNavigation, WikiPageNavNode, WikiTabNavNode } from "@topik/schema/wiki/v1";
4
11
  //#region src/config/collection.d.ts
5
12
  declare const collectionConfigSchema: z.ZodObject<{
6
13
  id: z.ZodString;
@@ -11,25 +18,49 @@ type CollectionConfig = z.infer<typeof collectionConfigSchema>;
11
18
  declare function parseCollectionConfig(raw: unknown): CollectionConfig;
12
19
  //#endregion
13
20
  //#region src/config/wiki.d.ts
14
- type WikiNavNode = string | {
15
- group: string;
21
+ type WikiPageNavNode$1 = {
22
+ type: "page";
23
+ slug: string;
24
+ icon?: string;
25
+ hidden?: boolean;
26
+ };
27
+ type WikiGroupNavNode = {
28
+ type: "group";
29
+ title: string;
16
30
  slug?: string;
17
31
  icon?: string;
18
- children: WikiNavNode[];
19
- } | {
20
- tab: string;
32
+ expanded?: boolean;
33
+ hidden?: boolean;
34
+ children: WikiNavNode$1[];
35
+ };
36
+ type WikiInternalSwitcherNavNode = {
37
+ type: "tab" | "dropdown";
38
+ title: string;
21
39
  slug?: string;
22
40
  icon?: string;
23
- children: WikiNavNode[];
24
- } | {
41
+ hidden?: boolean;
42
+ children: WikiNavNode$1[];
43
+ };
44
+ type WikiExternalSwitcherNavNode = {
45
+ type: "tab" | "dropdown";
46
+ title: string;
25
47
  href: string;
48
+ icon?: string;
49
+ hidden?: boolean;
50
+ };
51
+ type WikiLinkNavNode = {
52
+ type: "link";
26
53
  title: string;
54
+ href: string;
27
55
  icon?: string;
56
+ hidden?: boolean;
28
57
  };
58
+ type WikiNavNode$1 = string | WikiPageNavNode$1 | WikiGroupNavNode | WikiInternalSwitcherNavNode | WikiExternalSwitcherNavNode | WikiLinkNavNode;
29
59
  declare const wikiConfigSchema: z.ZodObject<{
30
60
  id: z.ZodString;
31
61
  title: z.ZodString;
32
- navigation: z.ZodOptional<z.ZodArray<z.ZodType<WikiNavNode, unknown, z.core.$ZodTypeInternals<WikiNavNode, unknown>>>>;
62
+ description: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNull]>>;
63
+ navigation: z.ZodOptional<z.ZodArray<z.ZodType<WikiNavNode$1, unknown, z.core.$ZodTypeInternals<WikiNavNode$1, unknown>>>>;
33
64
  theme: z.ZodOptional<z.ZodObject<{
34
65
  colors: z.ZodOptional<z.ZodObject<{
35
66
  primary: z.ZodString;
@@ -49,34 +80,294 @@ type WikiConfig = z.infer<typeof wikiConfigSchema>;
49
80
  declare function parseWikiConfig(raw: unknown): WikiConfig;
50
81
  //#endregion
51
82
  //#region src/resource.d.ts
52
- type Resource = Asset | Guide | Wiki | WikiPage;
83
+ type Resource = Asset | Course | CourseModule | CoursePage | Guide | Person | Wiki | WikiPage;
84
+ /** Resources accepted as compiler input. `Asset` exists only in compiler output. */
85
+ type SourceResource = Exclude<Resource, Asset>;
53
86
  type ResourceType = Resource["type"];
54
87
  //#endregion
88
+ //#region src/assets/constants.d.ts
89
+ declare const ASSET_API_VERSION: "v1";
90
+ declare const ASSET_TYPE: "Asset";
91
+ declare const ASSET_SCHEMA_ID: "https://topik.dev/schemas/asset/v1.json";
92
+ declare const TOPIK_JSON_VERSION: "topik-json-v1";
93
+ declare const TOPIK_PATH_VERSION: "topik-path-v1";
94
+ declare const TOPIK_ASSET_REFERENCE_VERSION: "topik-asset-reference-v1";
95
+ declare const TOPIK_MATERIALIZATION_VERSION: "topik-materialization-v1";
96
+ declare const TOPIK_ASSET_NAME_VERSION: "topik-asset-name-v1";
97
+ declare const TOPIK_BLOB_OUTPUT_PREFIX: "blobs";
98
+ declare const TOPIK_PATH_V1_DESCRIPTOR: {
99
+ readonly collisionNormalization: "toNFKC_Casefold";
100
+ readonly id: "topik-path-v1";
101
+ readonly localReferenceEncoding: "rfc3986-utf8-upper-v1";
102
+ readonly maxComponentUtf8Bytes: 255;
103
+ readonly maxComponents: 64;
104
+ readonly maxRepositoryPathUtf8Bytes: 768;
105
+ readonly normalizationSensitiveExclusion: "unicode-17-new-marks";
106
+ readonly storageNormalization: "NFC";
107
+ readonly unicodeVersion: "17.0.0";
108
+ };
109
+ declare const TOPIK_ASSET_LIMITS: {
110
+ readonly maxDescriptorBytes: 1048576;
111
+ readonly maxAssetBytes: 268435456;
112
+ readonly maxAssets: 10000;
113
+ readonly maxJsonDepth: 8;
114
+ readonly maxComponentUtf8Bytes: 255;
115
+ readonly maxComponents: 64;
116
+ readonly maxRepositoryPathUtf8Bytes: 768;
117
+ };
118
+ //#endregion
119
+ //#region src/assets/diagnostics.d.ts
120
+ declare const TOPIK_ASSET_DIAGNOSTIC_IDS: readonly ["TOPIK_ASSET_UNSUPPORTED_VERSION", "TOPIK_ASSET_DUPLICATE_MEMBER", "TOPIK_ASSET_SCHEMA_INVALID", "TOPIK_ASSET_NON_CANONICAL", "TOPIK_ASSET_NAME_INVALID", "TOPIK_ASSET_NAME_COLLISION", "TOPIK_ASSET_SOURCE_NAMESPACE_REQUIRED", "TOPIK_ASSET_SOURCE_NAMESPACE_INVALID", "TOPIK_ASSET_PATH_INVALID", "TOPIK_ASSET_PATH_COLLISION", "TOPIK_ASSET_REFERENCE_AMBIGUOUS", "TOPIK_ASSET_REFERENCE_MALFORMED", "TOPIK_ASSET_REFERENCE_MISSING", "TOPIK_ASSET_FILE_MISSING", "TOPIK_ASSET_DIGEST_MISMATCH", "TOPIK_ASSET_SIZE_MISMATCH", "TOPIK_ASSET_MEDIA_TYPE_MISMATCH", "TOPIK_ASSET_FILE_TYPE_UNSUPPORTED", "TOPIK_ASSET_ACTIVE_CONTENT_UNSUPPORTED", "TOPIK_ASSET_REFERENCE_ACCESSIBILITY_INVALID", "TOPIK_EXTERNAL_REFERENCE_UNSAFE", "TOPIK_ASSET_INVENTORY_INCOMPLETE", "TOPIK_ASSET_VERSION_INCOMPARABLE"];
121
+ declare const TOPIK_ASSET_DEFAULT_CORRELATION_ID: "cor_00000000000000000000000000";
122
+ declare const TOPIK_ASSET_CORRELATION_ID_PATTERN: RegExp;
123
+ type TopikAssetCorrelationId = `cor_${string}`;
124
+ type TopikAssetDiagnosticId = (typeof TOPIK_ASSET_DIAGNOSTIC_IDS)[number];
125
+ type TopikAssetPathDiagnosticReason = "invalid_utf8" | "capability_invalid" | "unicode_version_unsupported" | "not_nfc" | "absolute" | "separator_alias" | "dot_segment" | "percent_noncanonical" | "forbidden_character" | "reserved_name" | "too_long" | "casefold_collision";
126
+ type TopikAssetRecoveryCategory = "upgrade-reader" | "repair-source" | "restore-file" | "verify-bytes" | "preserve-read-only";
127
+ interface TopikAssetDiagnosticLocation {
128
+ jsonPointer?: string;
129
+ contentPosition?: string;
130
+ path?: string;
131
+ key?: string;
132
+ commit?: string;
133
+ }
134
+ interface TopikAssetDiagnostic {
135
+ id: TopikAssetDiagnosticId;
136
+ /** Safe opaque operation correlation; callers may replace the deterministic default. */
137
+ correlationId: TopikAssetCorrelationId;
138
+ severity: "error";
139
+ consequence: "block-resource" | "block-identity-and-writes" | "block-mutation";
140
+ descriptorVersion: string;
141
+ location: TopikAssetDiagnosticLocation;
142
+ recovery: TopikAssetRecoveryCategory;
143
+ reason?: TopikAssetPathDiagnosticReason;
144
+ /** Human wording is intentionally not a stable compatibility surface. */
145
+ message: string;
146
+ }
147
+ type TopikAssetResult<T> = {
148
+ ok: true;
149
+ value: T;
150
+ diagnostics: readonly [];
151
+ source?: Uint8Array;
152
+ } | {
153
+ ok: false;
154
+ value?: T;
155
+ diagnostics: readonly TopikAssetDiagnostic[];
156
+ /** Exact caller bytes are non-loggable evidence; never copy them into diagnostics/telemetry. */
157
+ source?: Uint8Array;
158
+ };
159
+ declare function correlateTopikAssetResult<T>(result: TopikAssetResult<T>, correlationId: TopikAssetCorrelationId): TopikAssetResult<T>;
160
+ //#endregion
161
+ //#region src/assets/asset.d.ts
162
+ interface ParsedAsset {
163
+ asset: Asset;
164
+ canonicalBytes: Uint8Array;
165
+ }
166
+ /** Compiler-generated name used by automatic Asset compilation. */
167
+ type GeneratedAssetName = TopikGeneratedAssetName;
168
+ declare const assetBlobUriBrand: unique symbol;
169
+ /** Opaque compiler output path for one SHA-256-addressed Asset blob. */
170
+ type AssetBlobUri = string & {
171
+ readonly [assetBlobUriBrand]: "AssetBlobUri";
172
+ };
173
+ declare function isAssetBlobUri(value: unknown): value is AssetBlobUri;
174
+ declare function parseAssetBlobUri(value: string): AssetBlobUri;
175
+ declare function parseGeneratedAssetName(value: string): GeneratedAssetName;
176
+ /** Asset descriptor emitted by the compiler with a materialized payload. */
177
+ interface CompiledAsset extends Asset {
178
+ name: GeneratedAssetName;
179
+ spec: {
180
+ uri: AssetBlobUri;
181
+ integrity: `sha256:${string}`;
182
+ size: number;
183
+ mediaType: string;
184
+ };
185
+ }
186
+ declare function parseAsset(input: string | Uint8Array): TopikAssetResult<ParsedAsset>;
187
+ declare function validateAssetValue(value: unknown): TopikAssetResult<Asset>;
188
+ /** Serialize one Asset to deterministic UTF-8 canonical JSON and prove its round trip. */
189
+ declare function serializeAsset(value: unknown): TopikAssetResult<Uint8Array>;
190
+ /** Admit a compiler-materialized blob path; Asset resources may use other URI forms. */
191
+ declare function validateAssetBlobUri(value: string): TopikAssetResult<{
192
+ uri: AssetBlobUri;
193
+ }>;
194
+ declare function isGeneratedAssetName(value: unknown): value is GeneratedAssetName;
195
+ declare function validateStableSourceNamespace(value: string): TopikAssetResult<string>;
196
+ interface GenerateAutomaticAssetNameOptions {
197
+ stableSourceNamespace: string;
198
+ normalizedPath: string;
199
+ }
200
+ declare function generateAutomaticAssetName(options: GenerateAutomaticAssetNameOptions): TopikAssetResult<GeneratedAssetName>;
201
+ declare function topikAssetNameDescriptor(): {
202
+ id: typeof TOPIK_ASSET_NAME_VERSION;
203
+ };
204
+ //#endregion
205
+ //#region src/assets/identity.d.ts
206
+ interface TopikAssetReferenceMappingV1 {
207
+ resource: string;
208
+ position: string;
209
+ slot: string;
210
+ name: string;
211
+ }
212
+ interface TopikAssetSemanticRecordV1 {
213
+ descriptor: "topik-asset-semantic-v1";
214
+ assetNames: readonly string[];
215
+ references: readonly TopikAssetReferenceMappingV1[];
216
+ }
217
+ interface TopikMaterializationResourceV1 {
218
+ resource: string;
219
+ path: string;
220
+ size: number;
221
+ sha256: string;
222
+ }
223
+ interface TopikMaterializationPayloadV1 {
224
+ path: string;
225
+ size: number;
226
+ sha256: string;
227
+ assetNames: readonly string[];
228
+ }
229
+ interface TopikMaterializationRecordV1 {
230
+ descriptor: "topik-materialization-v1";
231
+ resources: readonly TopikMaterializationResourceV1[];
232
+ payloads: readonly TopikMaterializationPayloadV1[];
233
+ }
234
+ interface TopikMaterializationResourceInput {
235
+ resource: {
236
+ type: string;
237
+ name: string;
238
+ };
239
+ bytes: Uint8Array;
240
+ }
241
+ interface TopikMaterializationPayloadInput {
242
+ path: string;
243
+ bytes: Uint8Array;
244
+ assetNames: readonly string[];
245
+ }
246
+ declare function createTopikAssetSemanticRecord(assets: readonly Asset[], references: readonly TopikAssetReferenceMappingV1[]): TopikAssetSemanticRecordV1;
247
+ declare function createTopikMaterializationRecord(resources: readonly TopikMaterializationResourceInput[], payloads: readonly TopikMaterializationPayloadInput[]): TopikMaterializationRecordV1;
248
+ declare function validateTopikMaterializationRecord(record: unknown, resources: readonly Resource[], semantic: unknown): TopikAssetResult<TopikMaterializationRecordV1>;
249
+ declare function digestTopikAssetSemanticRecord(record: TopikAssetSemanticRecordV1): string;
250
+ declare function digestTopikMaterializationRecord(record: TopikMaterializationRecordV1): string;
251
+ declare function compareTopikAssetIdentities(left: {
252
+ semantic: TopikAssetSemanticRecordV1;
253
+ materialization: TopikMaterializationRecordV1;
254
+ }, right: {
255
+ semantic: TopikAssetSemanticRecordV1;
256
+ materialization: TopikMaterializationRecordV1;
257
+ }): TopikAssetResult<{
258
+ semanticEqual: boolean;
259
+ exactEqual: boolean;
260
+ }>;
261
+ //#endregion
262
+ //#region src/compile/assets.d.ts
263
+ type ContentBearingResource = CoursePage | Guide | WikiPage;
264
+ interface AssetCompilationOptions {
265
+ /** Required only when supported local references are discovered automatically. */
266
+ sourceNamespace?: string;
267
+ }
268
+ interface CompileAssetResourcesInput extends AssetCompilationOptions {
269
+ rootDir: string;
270
+ resources: readonly SourceResource[];
271
+ /** Compilation-root-relative source paths keyed by `Type/name`. */
272
+ sourcePathsByResource: Readonly<Record<string, string>>;
273
+ /** Other consumed compiler inputs that cannot be owned as Asset bytes. */
274
+ protectedSourcePaths?: readonly string[];
275
+ }
276
+ interface AssetPayload {
277
+ path: AssetBlobUri;
278
+ integrity: `sha256:${string}`;
279
+ mediaType: string;
280
+ size: number;
281
+ bytes: Uint8Array;
282
+ assetNames: readonly string[];
283
+ }
284
+ interface AssetCompilationResult {
285
+ resources: CompiledResource[];
286
+ payloads: AssetPayload[];
287
+ semantic: TopikAssetSemanticRecordV1;
288
+ materialization: TopikMaterializationRecordV1;
289
+ }
290
+ type CompiledResource = SourceResource | CompiledAsset;
291
+ declare class AssetCompilationError extends Error {
292
+ readonly diagnostics: readonly TopikAssetDiagnostic[];
293
+ constructor(message: string, diagnostics?: readonly TopikAssetDiagnostic[]);
294
+ }
295
+ /** Discover and resolve one compilation-wide Asset set and deduplicated payload inventory. */
296
+ declare function compileAssetResources(input: CompileAssetResourcesInput): Promise<AssetCompilationResult>;
297
+ //#endregion
55
298
  //#region src/compile/shared.d.ts
56
299
  interface CompileResult {
57
- resources: Resource[];
300
+ diagnostics: TopikContentDiagnostic[];
301
+ resources: CompiledResource[];
302
+ payloads: AssetPayload[];
303
+ semantic: TopikAssetSemanticRecordV1;
304
+ materialization: TopikMaterializationRecordV1;
305
+ }
306
+ type LinkValidationPolicy = "error" | "warning" | "off";
307
+ interface CompileValidationOptions {
308
+ /** How unresolved wiki page links and same-page guide fragments are handled. */
309
+ links?: LinkValidationPolicy;
58
310
  }
311
+ declare class CompileError extends Error {
312
+ readonly diagnostics: TopikContentDiagnostic[];
313
+ constructor(diagnostics: TopikContentDiagnostic[]);
314
+ }
315
+ declare function isErrorDiagnostic(diagnostic: TopikContentDiagnostic): boolean;
316
+ //#endregion
317
+ //#region src/compile/guide.d.ts
318
+ interface CompileGuidesOptions {
319
+ dir: string;
320
+ validation?: CompileValidationOptions;
321
+ assets?: AssetCompilationOptions;
322
+ }
323
+ declare function compileGuides(options: CompileGuidesOptions): Promise<CompileResult>;
59
324
  //#endregion
60
325
  //#region src/compile/wiki.d.ts
61
326
  interface CompileWikiOptions {
62
327
  dir: string;
328
+ validation?: CompileValidationOptions;
329
+ assets?: AssetCompilationOptions;
63
330
  }
64
331
  declare function compileWiki(options: CompileWikiOptions): Promise<CompileResult>;
332
+ declare function pagePathToName(wikiId: string, pagePath: string): string;
65
333
  //#endregion
66
- //#region src/compile/guide.d.ts
67
- interface CompileGuidesOptions {
68
- dir: string;
334
+ //#region src/compile/public-errors.d.ts
335
+ declare const PUBLIC_COMPILE_ERROR_MESSAGES: {
336
+ readonly "config-access-failed": "Configuration file could not be accessed.";
337
+ readonly "config-invalid": "Configuration is invalid.";
338
+ readonly "config-not-found": "Required configuration file was not found.";
339
+ readonly "config-parse-failed": "Configuration file could not be parsed.";
340
+ readonly "config-read-failed": "Configuration file could not be read safely.";
341
+ readonly "file-not-regular": "Compilation input must be a regular file.";
342
+ readonly "file-outside-compilation-root": "Compilation input resolves outside the source root.";
343
+ readonly "frontmatter-invalid": "Document frontmatter is invalid.";
344
+ readonly "reference-list-invalid": "Document resource references are invalid.";
345
+ readonly "wiki-page-not-found": "A configured Wiki page file was not found.";
346
+ };
347
+ type PublicCompileErrorId = keyof typeof PUBLIC_COMPILE_ERROR_MESSAGES;
348
+ declare function publicCompileErrorMessage(id: unknown): string | undefined;
349
+ /** Public compiler failure with fixed wording, stable ID, and optional safe relative location. */
350
+ declare class PublicCompileError extends Error {
351
+ readonly id: PublicCompileErrorId;
352
+ readonly location?: string;
353
+ constructor(id: PublicCompileErrorId, location?: string);
69
354
  }
70
- declare function compileGuides(options: CompileGuidesOptions): Promise<CompileResult>;
71
355
  //#endregion
72
356
  //#region src/compile/index.d.ts
73
357
  interface CompileOptions {
74
358
  dir: string;
359
+ validation?: CompileValidationOptions;
360
+ assets?: AssetCompilationOptions;
75
361
  }
76
362
  declare function compile(options: CompileOptions): Promise<CompileResult>;
363
+ interface LintResult {
364
+ diagnostics: CompileResult["diagnostics"];
365
+ }
366
+ declare function lint(options: CompileOptions): Promise<LintResult>;
77
367
  //#endregion
78
368
  //#region src/validate.d.ts
79
369
  interface ValidationError {
370
+ id?: "resource-invalid" | "resource-unsupported-type" | "resource-unsupported-version" | TopikAssetDiagnosticId;
80
371
  resource: string;
81
372
  path: string;
82
373
  message: string;
@@ -88,16 +379,63 @@ interface ValidationResult {
88
379
  /** Validate the resources produced by `compile` and the CLI export. */
89
380
  declare function validateResources(resources: readonly unknown[]): ValidationResult;
90
381
  //#endregion
382
+ //#region src/wiki-navigation.d.ts
383
+ type ResolvedWikiPage = {
384
+ /** The compiled WikiPage resource name. */
385
+ page: string;
386
+ /** The page navigation node from the Wiki resource. */
387
+ node: WikiPageNavNode;
388
+ /** Public path without a leading slash. */
389
+ route: string;
390
+ /** Logical Markdown source path without an extension. */
391
+ sourcePath: string;
392
+ /** Internal navigation containers from outermost to innermost. */
393
+ ancestors: readonly WikiNavContainerNode[];
394
+ };
395
+ type ResolvedWikiNavigation = {
396
+ pages: readonly ResolvedWikiPage[];
397
+ pageByName: ReadonlyMap<string, ResolvedWikiPage>;
398
+ pageByRoute: ReadonlyMap<string, ResolvedWikiPage>;
399
+ };
400
+ type ResolvedWikiContentLink = {
401
+ page: ResolvedWikiPage;
402
+ route: string;
403
+ hash: string;
404
+ };
405
+ /** Returns true for tab, dropdown, and group nodes containing navigation children. */
406
+ declare function hasWikiNavChildren(node: WikiNavNode): node is WikiNavContainerNode;
407
+ declare function isInternalWikiTab(node: WikiNavNode): node is WikiInternalTabNavNode;
408
+ declare function isExternalWikiTab(node: WikiNavNode): node is WikiExternalTabNavNode;
409
+ declare function isInternalWikiDropdown(node: WikiNavNode): node is WikiInternalDropdownNavNode;
410
+ declare function isExternalWikiDropdown(node: WikiNavNode): node is WikiExternalDropdownNavNode;
411
+ /** Resolves page routes, source paths, and navigation ancestry from a compiled Wiki tree. */
412
+ declare function resolveWikiNavigation(navigation: WikiNavigation | readonly WikiNavNode[]): ResolvedWikiNavigation;
413
+ /** Finds the first page node in navigation order, ignoring external destinations. */
414
+ declare function findFirstWikiPage(navigation: WikiNavigation | readonly WikiNavNode[]): WikiPageNavNode | null;
415
+ /** Returns the internal containers owning a page, or an empty array for an unknown page. */
416
+ declare function findWikiPageAncestors(resolved: ResolvedWikiNavigation, pageName: string): readonly WikiNavContainerNode[];
417
+ /** Resolves an internal Markdown link against the logical source path of its current page. */
418
+ declare function resolveWikiContentHref(href: string, currentPageName: string, resolved: ResolvedWikiNavigation): ResolvedWikiContentLink | null;
419
+ declare function joinWikiPath(prefix: string, slug?: string): string;
420
+ type InternalWikiTab = WikiInternalTabNavNode;
421
+ type ExternalWikiTab = WikiExternalTabNavNode;
422
+ type InternalWikiDropdown = WikiInternalDropdownNavNode;
423
+ type ExternalWikiDropdown = WikiExternalDropdownNavNode;
424
+ type WikiSwitcherNode = WikiTabNavNode | WikiDropdownNavNode;
425
+ //#endregion
91
426
  //#region src/watch.d.ts
92
427
  interface WatchOptions {
93
428
  dir: string;
94
429
  signal?: AbortSignal;
430
+ assets?: AssetCompilationOptions;
95
431
  }
96
432
  type UpdateListener = (key: string, resource: Resource) => void;
97
433
  type ErrorListener = (error: Error) => void;
98
434
  interface Watcher {
99
435
  /** Current compiled resources, keyed by `Type/name`. */
100
436
  resources: Map<string, Resource>;
437
+ /** Current deduplicated local payloads, keyed by compilation-relative output path. */
438
+ payloads: Map<string, AssetPayload>;
101
439
  on(event: "update", listener: UpdateListener): this;
102
440
  on(event: "error", listener: ErrorListener): this;
103
441
  off(event: "update", listener: UpdateListener): this;
@@ -106,4 +444,68 @@ interface Watcher {
106
444
  }
107
445
  declare function watch(options: WatchOptions): Promise<Watcher>;
108
446
  //#endregion
109
- export { type CollectionConfig, type CompileGuidesOptions, type CompileOptions, type CompileResult, type CompileWikiOptions, type Resource, type ResourceType, type ValidationError, type ValidationResult, type WatchOptions, type Watcher, type WikiConfig, compile, compileGuides, compileWiki, parseCollectionConfig, parseWikiConfig, validateResources, watch };
447
+ //#region src/assets/path.d.ts
448
+ interface ValidateTopikPathOptions {
449
+ bindingRoot?: string;
450
+ capabilities?: {
451
+ maxComponentUtf8Bytes?: number;
452
+ maxComponents?: number;
453
+ maxRepositoryPathUtf8Bytes?: number;
454
+ };
455
+ }
456
+ interface ValidTopikPath {
457
+ path: string;
458
+ collisionKey: string;
459
+ utf8Bytes: number;
460
+ }
461
+ declare function validateTopikPath(input: string | Uint8Array, options?: ValidateTopikPathOptions): TopikAssetResult<ValidTopikPath>;
462
+ declare function computeTopikPathCollisionKey(path: string, options?: ValidateTopikPathOptions): TopikAssetResult<string>;
463
+ declare function validateTopikPathSet(paths: readonly string[], options?: ValidateTopikPathOptions): TopikAssetResult<Map<string, string>>;
464
+ /** Unicode 17 NFKC casefold for topik-path-v1-admitted input. */
465
+ declare function toNfkcCasefold(value: string): string;
466
+ //#endregion
467
+ //#region src/assets/json.d.ts
468
+ declare class TopikJsonSyntaxError extends SyntaxError {
469
+ readonly offset: number;
470
+ readonly duplicatePointer?: string | undefined;
471
+ constructor(message: string, offset: number, duplicatePointer?: string | undefined);
472
+ }
473
+ declare function parseStrictTopikJson(source: string, maxDepth?: number): unknown;
474
+ /** RFC 8785 scalar/member rules with Topik's two-space layout and final LF. */
475
+ declare function serializeTopikJson(value: unknown): string;
476
+ declare function topikJsonDescriptor(): {
477
+ id: typeof TOPIK_JSON_VERSION;
478
+ };
479
+ //#endregion
480
+ //#region src/assets/files.d.ts
481
+ type PortableAssetFileType = "regular" | "symlink" | "hardlink" | "gitlink" | "device" | "fifo" | "socket" | "special" | "sparse" | "archive-link";
482
+ interface PortableAssetFileDescriptor {
483
+ path: string;
484
+ type: PortableAssetFileType;
485
+ source?: "git" | "archive" | "filesystem";
486
+ /** Git mode (`100644`) or archive mode (`0644`). */
487
+ mode: string;
488
+ bytes?: Uint8Array;
489
+ linkCount?: number;
490
+ hasAlternateDataStream?: boolean;
491
+ contentFilter?: string;
492
+ workingTreeEncoding?: string;
493
+ }
494
+ declare function validatePortableAssetFile(file: PortableAssetFileDescriptor): TopikAssetResult<PortableAssetFileDescriptor>;
495
+ declare function validatePortableAssetTree(files: readonly PortableAssetFileDescriptor[]): TopikAssetResult<readonly PortableAssetFileDescriptor[]>;
496
+ interface ReadPortableAssetFileOptions {
497
+ root: string;
498
+ path: string;
499
+ }
500
+ /** Filesystem reader using no-follow traversal and stable same-handle identity checks. */
501
+ declare function readPortableAssetFile(options: ReadPortableAssetFileOptions): Promise<TopikAssetResult<PortableAssetFileDescriptor>>;
502
+ declare function looksLikeGitLfsPointer(bytes: Uint8Array): boolean;
503
+ //#endregion
504
+ //#region src/assets/media.d.ts
505
+ declare const TOPIK_UNRESOLVED_ACTIVE_CONTENT_TYPE: "application/x-topik-active-content";
506
+ /** Sniff exact bytes conservatively. Unknown safe bytes remain opaque downloads. */
507
+ declare function sniffPortableMediaType(bytes: Uint8Array): string;
508
+ declare function isTopikActiveMediaType(mediaType: string): boolean;
509
+ declare function isInlineMediaCompatible(mediaType: string, role: string): boolean;
510
+ //#endregion
511
+ export { ASSET_API_VERSION, ASSET_SCHEMA_ID, ASSET_TYPE, type AssetBlobUri, AssetCompilationError, type AssetCompilationOptions, type AssetCompilationResult, type AssetPayload, type CollectionConfig, type CompileAssetResourcesInput, CompileError, type CompileGuidesOptions, type CompileOptions, type CompileResult, type CompileValidationOptions, type CompileWikiOptions, type CompiledAsset, type CompiledResource, type ContentBearingResource, type ExternalWikiDropdown, type ExternalWikiTab, type GenerateAutomaticAssetNameOptions, type GeneratedAssetName, type InternalWikiDropdown, type InternalWikiTab, type LinkValidationPolicy, type LintResult, type ParsedAsset, type PortableAssetFileDescriptor, type PortableAssetFileType, PublicCompileError, type PublicCompileErrorId, type ReadPortableAssetFileOptions, type ResolvedWikiContentLink, type ResolvedWikiNavigation, type ResolvedWikiPage, type Resource, type ResourceType, type SourceResource, TOPIK_ASSET_CORRELATION_ID_PATTERN, TOPIK_ASSET_DEFAULT_CORRELATION_ID, TOPIK_ASSET_DIAGNOSTIC_IDS, TOPIK_ASSET_LIMITS, TOPIK_ASSET_NAME_VERSION, TOPIK_ASSET_REFERENCE_VERSION, TOPIK_BLOB_OUTPUT_PREFIX, TOPIK_JSON_VERSION, TOPIK_MATERIALIZATION_VERSION, TOPIK_PATH_V1_DESCRIPTOR, TOPIK_PATH_VERSION, TOPIK_UNRESOLVED_ACTIVE_CONTENT_TYPE, type TopikAssetCorrelationId, type TopikAssetDiagnostic, type TopikAssetDiagnosticId, type TopikAssetDiagnosticLocation, type TopikAssetPathDiagnosticReason, type TopikAssetRecoveryCategory, type TopikAssetReferenceMappingV1, type TopikAssetResult, type TopikAssetSemanticRecordV1, TopikJsonSyntaxError, type TopikMaterializationPayloadInput, type TopikMaterializationPayloadV1, type TopikMaterializationRecordV1, type TopikMaterializationResourceInput, type TopikMaterializationResourceV1, type ValidTopikPath, type ValidateTopikPathOptions, type ValidationError, type ValidationResult, type WatchOptions, type Watcher, type WikiConfig, type WikiSwitcherNode, compareTopikAssetIdentities, compile, compileAssetResources, compileGuides, compileWiki, computeTopikPathCollisionKey, correlateTopikAssetResult, createTopikAssetSemanticRecord, createTopikMaterializationRecord, digestTopikAssetSemanticRecord, digestTopikMaterializationRecord, findFirstWikiPage, findWikiPageAncestors, generateAutomaticAssetName, hasWikiNavChildren, isAssetBlobUri, isErrorDiagnostic, isExternalWikiDropdown, isExternalWikiTab, isGeneratedAssetName, isInlineMediaCompatible, isInternalWikiDropdown, isInternalWikiTab, isTopikActiveMediaType, joinWikiPath, lint, looksLikeGitLfsPointer, pagePathToName, parseAsset, parseAssetBlobUri, parseCollectionConfig, parseGeneratedAssetName, parseStrictTopikJson, parseWikiConfig, publicCompileErrorMessage, readPortableAssetFile, resolveWikiContentHref, resolveWikiNavigation, serializeAsset, serializeTopikJson, sniffPortableMediaType, toNfkcCasefold, topikAssetNameDescriptor, topikJsonDescriptor, validateAssetBlobUri, validateAssetValue, validatePortableAssetFile, validatePortableAssetTree, validateResources, validateStableSourceNamespace, validateTopikMaterializationRecord, validateTopikPath, validateTopikPathSet, watch };