@c4a/context 0.6.0-beta.4 → 0.6.0-beta.6

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/index.js CHANGED
@@ -7016,6 +7016,23 @@ var assertDocumentEvidenceSectionMetadata = (section, options, field = "document
7016
7016
  assertHasSourceRefs(section, field);
7017
7017
  };
7018
7018
  // src/phases.ts
7019
+ var NO_ENTRY_DETECTED = "NO_ENTRY_DETECTED";
7020
+
7021
+ class ExtractTsConfigurationError extends TypeError {
7022
+ code = NO_ENTRY_DETECTED;
7023
+ constructor(message) {
7024
+ super(message);
7025
+ this.name = "ExtractTsConfigurationError";
7026
+ }
7027
+ }
7028
+ function normalizeExtractEntry(value) {
7029
+ const slashPath = value.trim().replace(/\\/gu, "/");
7030
+ const segments = slashPath.replace(/^\.\//u, "").split("/");
7031
+ if (slashPath.length === 0 || slashPath.startsWith("/") || /^[A-Za-z]:\//u.test(slashPath) || segments.some((segment) => segment.length === 0 || segment === "." || segment === "..")) {
7032
+ throw new TypeError(`extractTs entries must be source-relative file paths: ${value}`);
7033
+ }
7034
+ return segments.join("/");
7035
+ }
7019
7036
  var getSourceType = (sourceDefinition) => {
7020
7037
  if (sourceDefinition.kind === "source.collection" || sourceDefinition.kind === "source.ref") {
7021
7038
  if (!("type" in sourceDefinition)) {
@@ -7197,6 +7214,14 @@ var extractTs = (definition) => {
7197
7214
  throw new TypeError(`extractTs collection must be codegraph: ${definition.collection}`);
7198
7215
  }
7199
7216
  const sourceId = sourceDefinition.kind === "source.collection" ? sourceDefinition.type : sourceDefinition.name;
7217
+ const mode = definition.mode ?? "exports";
7218
+ if (mode === "scan" && definition.entries !== undefined) {
7219
+ throw new TypeError("extractTs entries cannot be combined with mode: scan; scan mode uses every file matched by include");
7220
+ }
7221
+ if (definition.entries !== undefined && definition.entries.length === 0) {
7222
+ throw new ExtractTsConfigurationError("extractTs entries must contain at least one source-relative file path");
7223
+ }
7224
+ const entries = definition.entries === undefined ? undefined : [...new Set(definition.entries.map(normalizeExtractEntry))];
7200
7225
  const phase = {
7201
7226
  kind: "phase.extract.ts",
7202
7227
  id: `extract:${sourceId}:${definition.collection}`,
@@ -7213,7 +7238,9 @@ var extractTs = (definition) => {
7213
7238
  source: sourceDefinition,
7214
7239
  collection: definition.collection,
7215
7240
  include: definition.include ?? ["src/**/*.{ts,tsx}"],
7216
- exportedOnly: definition.exportedOnly ?? true,
7241
+ mode,
7242
+ ...entries !== undefined ? { entries } : {},
7243
+ exportedOnly: definition.exportedOnly ?? mode === "exports",
7217
7244
  out: {
7218
7245
  kind: "codegraph-entities",
7219
7246
  candidateFile: "unapproved/entities.jsonl",
@@ -11332,12 +11359,24 @@ var DEFAULT_FILE_SOURCES_REGISTRY_PATH = "sources/file/index.yaml";
11332
11359
  var DEFAULT_LARK_SOURCES_REGISTRY_PATH = "sources/lark/index.yaml";
11333
11360
  var SOURCE_TYPES = ["repo", "file", "lark"];
11334
11361
  var SOURCE_NAME_PATTERN = /^[a-z0-9][a-z0-9._-]*$/u;
11362
+ var REPO_DATE_NAMESPACE_PATTERN = /^\d{8}$/u;
11335
11363
  function assertSourceType(value, field) {
11336
11364
  if (!SOURCE_TYPES.includes(value)) {
11337
11365
  throw new TypeError(`${field} must be one of ${SOURCE_TYPES.join(", ")}: ${value}`);
11338
11366
  }
11339
11367
  }
11340
- function source(name, options) {
11368
+ function source(name, options, moduleOptions) {
11369
+ if (typeof options === "string") {
11370
+ const moduleName = options;
11371
+ const type2 = moduleOptions?.type ?? "repo";
11372
+ assertSourceType(type2, "source type");
11373
+ return {
11374
+ kind: "source.ref",
11375
+ type: type2,
11376
+ name: `${name}/${moduleName}`,
11377
+ materializedAt: type2 === "repo" ? `sources/repo/${name}/${moduleName}` : `sources/${type2}/${name}`
11378
+ };
11379
+ }
11341
11380
  const type = options?.type;
11342
11381
  if (type === undefined) {
11343
11382
  return {
@@ -11354,7 +11393,7 @@ function source(name, options) {
11354
11393
  materializedAt: `sources/${type}/${name}`
11355
11394
  };
11356
11395
  }
11357
- var repoSourceRegistryEntrySchema = exports_external.object({
11396
+ var repoSourceModuleSchema = exports_external.object({
11358
11397
  id: exports_external.string().min(1).optional(),
11359
11398
  name: exports_external.string().min(1),
11360
11399
  local: exports_external.string().min(1).optional(),
@@ -11365,6 +11404,10 @@ var repoSourceRegistryEntrySchema = exports_external.object({
11365
11404
  ref: exports_external.string().min(1)
11366
11405
  }).strict().optional()
11367
11406
  }).strict();
11407
+ var repoSourceRegistryEntrySchema = exports_external.object({
11408
+ name: exports_external.string().min(1),
11409
+ modules: exports_external.array(repoSourceModuleSchema).min(1)
11410
+ }).strict();
11368
11411
  var sourceSnapshotSchema = exports_external.object({
11369
11412
  manifest: exports_external.string().min(1)
11370
11413
  }).strict();
@@ -11376,6 +11419,10 @@ var fileSourceRegistryEntrySchema = exports_external.object({
11376
11419
  materializedAt: exports_external.string().min(1).optional(),
11377
11420
  snapshot: sourceSnapshotSchema.optional()
11378
11421
  }).strict();
11422
+ var fileSourceBatchSchema = exports_external.object({
11423
+ name: exports_external.string().min(1),
11424
+ modules: exports_external.array(fileSourceRegistryEntrySchema).min(1)
11425
+ }).strict();
11379
11426
  var larkSourceRegistryEntrySchema = exports_external.object({
11380
11427
  id: exports_external.string().min(1).optional(),
11381
11428
  name: exports_external.string().min(1),
@@ -11386,14 +11433,18 @@ var larkSourceRegistryEntrySchema = exports_external.object({
11386
11433
  title: exports_external.string().min(1).optional(),
11387
11434
  snapshot: sourceSnapshotSchema.optional()
11388
11435
  }).strict();
11436
+ var larkSourceBatchSchema = exports_external.object({
11437
+ name: exports_external.string().min(1),
11438
+ modules: exports_external.array(larkSourceRegistryEntrySchema).min(1)
11439
+ }).strict();
11389
11440
  var repoSourcesRegistrySchema = exports_external.object({
11390
11441
  sources: exports_external.array(repoSourceRegistryEntrySchema).default([])
11391
11442
  }).strict();
11392
11443
  var fileSourcesRegistrySchema = exports_external.object({
11393
- sources: exports_external.array(fileSourceRegistryEntrySchema).default([])
11444
+ sources: exports_external.array(exports_external.union([fileSourceRegistryEntrySchema, fileSourceBatchSchema])).default([])
11394
11445
  }).strict();
11395
11446
  var larkSourcesRegistrySchema = exports_external.object({
11396
- sources: exports_external.array(larkSourceRegistryEntrySchema).default([])
11447
+ sources: exports_external.array(exports_external.union([larkSourceRegistryEntrySchema, larkSourceBatchSchema])).default([])
11397
11448
  }).strict();
11398
11449
  var formatRegistryIssues = (issues) => issues.map((issue) => {
11399
11450
  const path = issue.path.length > 0 ? issue.path.join(".") : "<root>";
@@ -11405,6 +11456,20 @@ var assertSourceName = (sourceType, name, registryPath) => {
11405
11456
  throw new TypeError(`${sourceType} source name must be a lowercase path-safe slug in ${registryPath}: ${name}`);
11406
11457
  }
11407
11458
  };
11459
+ var assertDateSourceNamespace = (sourceType, name, registryPath) => {
11460
+ if (!REPO_DATE_NAMESPACE_PATTERN.test(name)) {
11461
+ throw new TypeError(`${sourceType} source batch must be a valid YYYYMMDD date in ${registryPath}: ${name}`);
11462
+ }
11463
+ const year = Number(name.slice(0, 4));
11464
+ const month = Number(name.slice(4, 6));
11465
+ const day = Number(name.slice(6, 8));
11466
+ const date = new Date(0);
11467
+ date.setUTCHours(0, 0, 0, 0);
11468
+ date.setUTCFullYear(year, month - 1, day);
11469
+ if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {
11470
+ throw new TypeError(`${sourceType} source batch must be a valid YYYYMMDD date in ${registryPath}: ${name}`);
11471
+ }
11472
+ };
11408
11473
  var assertRegistryRelativePath = (sourceType, name, field, value, registryPath) => {
11409
11474
  if (value.length === 0 || value.includes("\x00") || isAbsoluteRegistryPath(value)) {
11410
11475
  throw new TypeError(`${sourceType} source "${name}" in ${registryPath} has invalid ${field}; use a committed relative path`);
@@ -11424,7 +11489,9 @@ var assertWorkspaceRelativePath = (sourceType, name, field, value, registryPath)
11424
11489
  var assertDocumentSourcePath = (sourceType, name, field, value, registryPath, options = {}) => {
11425
11490
  assertWorkspaceRelativePath(sourceType, name, field, value, registryPath);
11426
11491
  const normalized = value.replaceAll("\\", "/");
11427
- const base = `sources/${sourceType}/${name}`;
11492
+ const [namespace, module, ...rest] = name.split("/");
11493
+ const batchName = module !== undefined && rest.length === 0 && REPO_DATE_NAMESPACE_PATTERN.test(namespace ?? "") ? namespace : name;
11494
+ const base = `sources/${sourceType}/${batchName}`;
11428
11495
  if (normalized === base && options.allowBase === true)
11429
11496
  return;
11430
11497
  if (!normalized.startsWith(`${base}/`)) {
@@ -11440,40 +11507,55 @@ var parseRepoSourcesRegistry = (input, registryPath, absolutePath) => {
11440
11507
  throw new TypeError(`Invalid repo sources registry ${registryPath}: ${formatRegistryIssues(parsed.error.issues)}`);
11441
11508
  }
11442
11509
  const seenSourceKeys = new Set;
11443
- const repos = parsed.data.sources.map((entry) => {
11444
- assertSourceName("repo", entry.name, registryPath);
11445
- const id = entry.id ?? entry.name;
11446
- for (const key of new Set([entry.name, id])) {
11447
- if (seenSourceKeys.has(key)) {
11448
- throw new TypeError(`Duplicate repo source identifier "${key}" in ${registryPath}`);
11449
- }
11450
- seenSourceKeys.add(key);
11451
- }
11452
- const remote = entry.git?.remote;
11453
- const ref = entry.git?.ref;
11454
- if (!remote) {
11455
- throw new TypeError(`Repo source "${entry.name}" in ${registryPath} is missing remote`);
11456
- }
11457
- if (!ref) {
11458
- throw new TypeError(`Repo source "${entry.name}" in ${registryPath} is missing ref`);
11459
- }
11460
- const materializedAt = entry.materializedAt ?? `sources/repo/${entry.name}`;
11461
- assertWorkspaceRelativePath("repo", entry.name, "materializedAt", materializedAt, registryPath);
11462
- const normalized = {
11463
- id,
11464
- name: entry.name,
11465
- materializedAt,
11466
- remote,
11467
- ref
11468
- };
11469
- if (entry.local) {
11470
- normalized.local = entry.local;
11471
- }
11472
- if (entry.subpath) {
11473
- assertWorkspaceRelativePath("repo", entry.name, "subpath", entry.subpath, registryPath);
11474
- normalized.subpath = entry.subpath;
11475
- }
11476
- return normalized;
11510
+ const moduleNamespaces = new Map;
11511
+ const repos = parsed.data.sources.flatMap((namespaceEntry) => {
11512
+ assertDateSourceNamespace("repo", namespaceEntry.name, registryPath);
11513
+ const namespace = namespaceEntry.name;
11514
+ return namespaceEntry.modules.map((entry) => {
11515
+ assertSourceName("repo", entry.name, registryPath);
11516
+ if (entry.id !== undefined)
11517
+ assertSourceName("repo", entry.id, registryPath);
11518
+ const existingNamespace = moduleNamespaces.get(entry.name);
11519
+ if (existingNamespace !== undefined && existingNamespace !== namespace) {
11520
+ throw new TypeError(`Duplicate repo module ${JSON.stringify(entry.name)} across date batches ${existingNamespace} and ${namespace} in ${registryPath}; repo module names are project-wide codegraph identities`);
11521
+ }
11522
+ moduleNamespaces.set(entry.name, namespace);
11523
+ const name = `${namespace}/${entry.name}`;
11524
+ const id = `${namespace}/${entry.id ?? entry.name}`;
11525
+ for (const key of new Set([name, id])) {
11526
+ if (seenSourceKeys.has(key)) {
11527
+ throw new TypeError(`Duplicate repo source identifier "${key}" in ${registryPath}`);
11528
+ }
11529
+ seenSourceKeys.add(key);
11530
+ }
11531
+ const remote = entry.git?.remote;
11532
+ const ref = entry.git?.ref;
11533
+ if (!remote) {
11534
+ throw new TypeError(`Repo source "${name}" in ${registryPath} is missing remote`);
11535
+ }
11536
+ if (!ref) {
11537
+ throw new TypeError(`Repo source "${name}" in ${registryPath} is missing ref`);
11538
+ }
11539
+ const materializedAt = entry.materializedAt ?? `sources/repo/${namespace}/${entry.name}`;
11540
+ assertWorkspaceRelativePath("repo", name, "materializedAt", materializedAt, registryPath);
11541
+ const normalized = {
11542
+ id,
11543
+ name,
11544
+ namespace,
11545
+ module: entry.name,
11546
+ materializedAt,
11547
+ remote,
11548
+ ref
11549
+ };
11550
+ if (entry.local) {
11551
+ normalized.local = entry.local;
11552
+ }
11553
+ if (entry.subpath) {
11554
+ assertWorkspaceRelativePath("repo", name, "subpath", entry.subpath, registryPath);
11555
+ normalized.subpath = entry.subpath;
11556
+ }
11557
+ return normalized;
11558
+ });
11477
11559
  });
11478
11560
  return {
11479
11561
  kind: "sources.registry.repo",
@@ -11488,34 +11570,43 @@ var parseFileSourcesRegistry = (input, registryPath) => {
11488
11570
  throw new TypeError(`Invalid file sources registry ${registryPath}: ${formatRegistryIssues(parsed.error.issues)}`);
11489
11571
  }
11490
11572
  const seenSourceKeys = new Set;
11491
- return parsed.data.sources.map((entry) => {
11492
- assertSourceName("file", entry.name, registryPath);
11493
- if (entry.local !== undefined) {
11494
- assertRegistryRelativePath("file", entry.name, "local", entry.local, registryPath);
11495
- }
11496
- const materializedAt = entry.materializedAt ?? `sources/file/${entry.name}`;
11497
- assertDocumentSourcePath("file", entry.name, "materializedAt", materializedAt, registryPath, { allowBase: true });
11498
- for (const [index, include] of (entry.include ?? []).entries()) {
11499
- assertDocumentIncludePath("file", entry.name, `include[${index}]`, include, registryPath);
11500
- }
11501
- if (entry.snapshot !== undefined) {
11502
- assertDocumentSourcePath("file", entry.name, "snapshot.manifest", entry.snapshot.manifest, registryPath);
11503
- }
11504
- const id = entry.id ?? entry.name;
11505
- for (const key of new Set([entry.name, id])) {
11506
- if (seenSourceKeys.has(key)) {
11507
- throw new TypeError(`Duplicate file source identifier "${key}" in ${registryPath}`);
11573
+ return parsed.data.sources.flatMap((sourceEntry) => {
11574
+ const namespace = "modules" in sourceEntry ? sourceEntry.name : undefined;
11575
+ if (namespace !== undefined)
11576
+ assertDateSourceNamespace("file", namespace, registryPath);
11577
+ const entries = "modules" in sourceEntry ? sourceEntry.modules : [sourceEntry];
11578
+ return entries.map((entry) => {
11579
+ assertSourceName("file", entry.name, registryPath);
11580
+ const name = namespace === undefined ? entry.name : `${namespace}/${entry.name}`;
11581
+ if (entry.local !== undefined) {
11582
+ assertRegistryRelativePath("file", name, "local", entry.local, registryPath);
11583
+ }
11584
+ const materializedAt = entry.materializedAt ?? `sources/file/${namespace ?? name}`;
11585
+ assertDocumentSourcePath("file", name, "materializedAt", materializedAt, registryPath, { allowBase: true });
11586
+ for (const [index, include] of (entry.include ?? []).entries()) {
11587
+ assertDocumentIncludePath("file", name, `include[${index}]`, include, registryPath);
11588
+ }
11589
+ const snapshot = entry.snapshot ?? (namespace !== undefined ? { manifest: `sources/file/${namespace}/manifest.json` } : undefined);
11590
+ if (snapshot !== undefined) {
11591
+ assertDocumentSourcePath("file", name, "snapshot.manifest", snapshot.manifest, registryPath);
11592
+ }
11593
+ const id = namespace === undefined ? entry.id ?? entry.name : `${namespace}/${entry.id ?? entry.name}`;
11594
+ for (const key of new Set([name, id])) {
11595
+ if (seenSourceKeys.has(key)) {
11596
+ throw new TypeError(`Duplicate file source identifier "${key}" in ${registryPath}`);
11597
+ }
11598
+ seenSourceKeys.add(key);
11508
11599
  }
11509
- seenSourceKeys.add(key);
11510
- }
11511
- return {
11512
- id,
11513
- name: entry.name,
11514
- materializedAt,
11515
- ...entry.local !== undefined ? { local: entry.local } : {},
11516
- ...entry.include !== undefined ? { include: entry.include } : {},
11517
- ...entry.snapshot !== undefined ? { snapshot: entry.snapshot } : {}
11518
- };
11600
+ return {
11601
+ id,
11602
+ name,
11603
+ ...namespace !== undefined ? { namespace, module: entry.name } : {},
11604
+ materializedAt,
11605
+ ...entry.local !== undefined ? { local: entry.local } : {},
11606
+ ...entry.include !== undefined ? { include: entry.include } : {},
11607
+ ...snapshot !== undefined ? { snapshot } : {}
11608
+ };
11609
+ });
11519
11610
  });
11520
11611
  };
11521
11612
  var parseLarkSourcesRegistry = (input, registryPath) => {
@@ -11524,38 +11615,47 @@ var parseLarkSourcesRegistry = (input, registryPath) => {
11524
11615
  throw new TypeError(`Invalid lark sources registry ${registryPath}: ${formatRegistryIssues(parsed.error.issues)}`);
11525
11616
  }
11526
11617
  const seenSourceKeys = new Set;
11527
- return parsed.data.sources.map((entry) => {
11528
- assertSourceName("lark", entry.name, registryPath);
11529
- const identityCount = [
11530
- entry.url !== undefined,
11531
- entry.docToken !== undefined,
11532
- entry.wikiToken !== undefined
11533
- ].filter(Boolean).length;
11534
- if (identityCount !== 1) {
11535
- throw new TypeError(`Lark source "${entry.name}" in ${registryPath} must declare exactly one of url, docToken, or wikiToken`);
11536
- }
11537
- const materializedAt = entry.materializedAt ?? `sources/lark/${entry.name}`;
11538
- assertDocumentSourcePath("lark", entry.name, "materializedAt", materializedAt, registryPath, { allowBase: true });
11539
- if (entry.snapshot !== undefined) {
11540
- assertDocumentSourcePath("lark", entry.name, "snapshot.manifest", entry.snapshot.manifest, registryPath);
11541
- }
11542
- const id = entry.id ?? entry.name;
11543
- for (const key of new Set([entry.name, id])) {
11544
- if (seenSourceKeys.has(key)) {
11545
- throw new TypeError(`Duplicate lark source identifier "${key}" in ${registryPath}`);
11546
- }
11547
- seenSourceKeys.add(key);
11548
- }
11549
- return {
11550
- id,
11551
- name: entry.name,
11552
- materializedAt,
11553
- ...entry.url !== undefined ? { url: entry.url } : {},
11554
- ...entry.docToken !== undefined ? { docToken: entry.docToken } : {},
11555
- ...entry.wikiToken !== undefined ? { wikiToken: entry.wikiToken } : {},
11556
- ...entry.title !== undefined ? { title: entry.title } : {},
11557
- ...entry.snapshot !== undefined ? { snapshot: entry.snapshot } : {}
11558
- };
11618
+ return parsed.data.sources.flatMap((sourceEntry) => {
11619
+ const namespace = "modules" in sourceEntry ? sourceEntry.name : undefined;
11620
+ if (namespace !== undefined)
11621
+ assertDateSourceNamespace("lark", namespace, registryPath);
11622
+ const entries = "modules" in sourceEntry ? sourceEntry.modules : [sourceEntry];
11623
+ return entries.map((entry) => {
11624
+ assertSourceName("lark", entry.name, registryPath);
11625
+ const name = namespace === undefined ? entry.name : `${namespace}/${entry.name}`;
11626
+ const identityCount = [
11627
+ entry.url !== undefined,
11628
+ entry.docToken !== undefined,
11629
+ entry.wikiToken !== undefined
11630
+ ].filter(Boolean).length;
11631
+ if (identityCount !== 1) {
11632
+ throw new TypeError(`Lark source "${name}" in ${registryPath} must declare exactly one of url, docToken, or wikiToken`);
11633
+ }
11634
+ const materializedAt = entry.materializedAt ?? `sources/lark/${namespace ?? name}`;
11635
+ assertDocumentSourcePath("lark", name, "materializedAt", materializedAt, registryPath, { allowBase: true });
11636
+ const snapshot = entry.snapshot ?? (namespace !== undefined ? { manifest: `sources/lark/${namespace}/manifest.json` } : undefined);
11637
+ if (snapshot !== undefined) {
11638
+ assertDocumentSourcePath("lark", name, "snapshot.manifest", snapshot.manifest, registryPath);
11639
+ }
11640
+ const id = namespace === undefined ? entry.id ?? entry.name : `${namespace}/${entry.id ?? entry.name}`;
11641
+ for (const key of new Set([name, id])) {
11642
+ if (seenSourceKeys.has(key)) {
11643
+ throw new TypeError(`Duplicate lark source identifier "${key}" in ${registryPath}`);
11644
+ }
11645
+ seenSourceKeys.add(key);
11646
+ }
11647
+ return {
11648
+ id,
11649
+ name,
11650
+ ...namespace !== undefined ? { namespace, module: entry.name } : {},
11651
+ materializedAt,
11652
+ ...entry.url !== undefined ? { url: entry.url } : {},
11653
+ ...entry.docToken !== undefined ? { docToken: entry.docToken } : {},
11654
+ ...entry.wikiToken !== undefined ? { wikiToken: entry.wikiToken } : {},
11655
+ ...entry.title !== undefined ? { title: entry.title } : {},
11656
+ ...snapshot !== undefined ? { snapshot } : {}
11657
+ };
11658
+ });
11559
11659
  });
11560
11660
  };
11561
11661
  var readYamlIfPresent = async (absolutePath, emptyValue) => {
@@ -11632,6 +11732,8 @@ var resolveSourceReference = (reference, registry) => {
11632
11732
  kind: "source.repo",
11633
11733
  id: entry.id,
11634
11734
  name: entry.name,
11735
+ namespace: entry.namespace,
11736
+ module: entry.module,
11635
11737
  materializedAt: entry.materializedAt,
11636
11738
  git: {
11637
11739
  remote: entry.remote,
@@ -11656,10 +11758,23 @@ var allSources = (type) => {
11656
11758
  };
11657
11759
 
11658
11760
  // src/index.ts
11659
- var defineProject = (project) => ({
11660
- kind: "context.project",
11661
- project
11662
- });
11761
+ function assertUniquePhaseIds(phases) {
11762
+ const firstById = new Map;
11763
+ for (const [index, phase] of phases.entries()) {
11764
+ const first = firstById.get(phase.id);
11765
+ if (first !== undefined) {
11766
+ throw new TypeError(`Duplicate Context phase id ${JSON.stringify(phase.id)}: phases[${first.index}] (${first.kind}) conflicts with phases[${index}] (${phase.kind}). Every phase id must be unique.`);
11767
+ }
11768
+ firstById.set(phase.id, { index, kind: phase.kind });
11769
+ }
11770
+ }
11771
+ var defineProject = (project) => {
11772
+ assertUniquePhaseIds(project.phases);
11773
+ return {
11774
+ kind: "context.project",
11775
+ project
11776
+ };
11777
+ };
11663
11778
  var normalizeTemplate = (template, builtInVars) => {
11664
11779
  const assertTemplatePath = (templatePath) => {
11665
11780
  if (!isSafeProjectRelativePath(templatePath)) {
@@ -11797,8 +11912,10 @@ export {
11797
11912
  alignProse,
11798
11913
  TOP_LEVEL_NAMESPACES,
11799
11914
  OKF_ROOTS,
11915
+ NO_ENTRY_DETECTED,
11800
11916
  MAINLINE_COLLECTIONS,
11801
11917
  KNOWLEDGE_COLLECTIONS,
11918
+ ExtractTsConfigurationError,
11802
11919
  DOC_MAINLINE_COLLECTIONS,
11803
11920
  DOCUMENT_STRUCTURE_SCHEMA_VERSION,
11804
11921
  DOCUMENT_SECTION_CONTENT_MODES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/context",
3
- "version": "0.6.0-beta.4",
3
+ "version": "0.6.0-beta.6",
4
4
  "type": "module",
5
5
  "dependencies": {
6
6
  "yaml": "^2.5.1",
package/phases.d.ts CHANGED
@@ -60,6 +60,8 @@ export type ExtractTsPhaseDefinition = {
60
60
  source: RepoProjectSourceDefinition;
61
61
  collection: "codegraph";
62
62
  include: readonly string[];
63
+ mode: "exports" | "scan";
64
+ entries?: readonly string[];
63
65
  exportedOnly: boolean;
64
66
  transform?: MarkdownTransform | readonly MarkdownTransform[];
65
67
  out: {
@@ -69,6 +71,11 @@ export type ExtractTsPhaseDefinition = {
69
71
  initialStatus: "draft";
70
72
  };
71
73
  };
74
+ export declare const NO_ENTRY_DETECTED: "NO_ENTRY_DETECTED";
75
+ export declare class ExtractTsConfigurationError extends TypeError {
76
+ readonly code: "NO_ENTRY_DETECTED";
77
+ constructor(message: string);
78
+ }
72
79
  export type CaptureFilePhaseDefinition = {
73
80
  kind: "phase.capture.file";
74
81
  id: string;
@@ -153,6 +160,8 @@ export declare const extractTs: (definition: {
153
160
  source: RepoProjectSourceDefinition;
154
161
  collection: "codegraph";
155
162
  include?: readonly string[];
163
+ mode?: "exports" | "scan";
164
+ entries?: readonly string[];
156
165
  exportedOnly?: boolean;
157
166
  transform?: MarkdownTransform | readonly MarkdownTransform[];
158
167
  }) => ExtractTsPhaseDefinition;
package/sources.d.ts CHANGED
@@ -7,6 +7,8 @@ export type RepoSourceDefinition = {
7
7
  kind: "source.repo";
8
8
  id: string;
9
9
  name: string;
10
+ namespace: string;
11
+ module: string;
10
12
  local?: string;
11
13
  subpath?: string;
12
14
  materializedAt: string;
@@ -19,6 +21,8 @@ export type FileSourceDefinition = {
19
21
  kind: "source.file";
20
22
  id: string;
21
23
  name: string;
24
+ namespace?: string;
25
+ module?: string;
22
26
  local?: string;
23
27
  materializedAt: string;
24
28
  include?: readonly string[];
@@ -30,6 +34,8 @@ export type LarkSourceDefinition = {
30
34
  kind: "source.lark";
31
35
  id: string;
32
36
  name: string;
37
+ namespace?: string;
38
+ module?: string;
33
39
  materializedAt: string;
34
40
  url?: string;
35
41
  docToken?: string;
@@ -62,6 +68,8 @@ export type SourceCollectionReference<TType extends SourceType = SourceType> = {
62
68
  export type RepoSourceRegistryEntry = {
63
69
  id: string;
64
70
  name: string;
71
+ namespace: string;
72
+ module: string;
65
73
  local?: string;
66
74
  subpath?: string;
67
75
  materializedAt: string;
@@ -71,6 +79,8 @@ export type RepoSourceRegistryEntry = {
71
79
  export type FileSourceRegistryEntry = {
72
80
  id: string;
73
81
  name: string;
82
+ namespace?: string;
83
+ module?: string;
74
84
  local?: string;
75
85
  materializedAt: string;
76
86
  include?: readonly string[];
@@ -81,6 +91,8 @@ export type FileSourceRegistryEntry = {
81
91
  export type LarkSourceRegistryEntry = {
82
92
  id: string;
83
93
  name: string;
94
+ namespace?: string;
95
+ module?: string;
84
96
  materializedAt: string;
85
97
  url?: string;
86
98
  docToken?: string;
@@ -124,6 +136,16 @@ export type DocumentSourceDefinition = FileSourceDefinition | LarkSourceDefiniti
124
136
  export type RepoProjectSourceDefinition = RepoSourceDefinition | RepoSourceReference | SourceCollectionReference<"repo">;
125
137
  export type ProjectSourceDefinition = SourceDefinition | SourceCollectionReference;
126
138
  export declare function source(name: string): RegistrySourceReference;
139
+ export declare function source(namespace: string, module: string): RepoSourceReference;
140
+ export declare function source(namespace: string, module: string, options: {
141
+ type: "repo";
142
+ }): RepoSourceReference;
143
+ export declare function source(namespace: string, module: string, options: {
144
+ type: "file";
145
+ }): FileSourceReference;
146
+ export declare function source(namespace: string, module: string, options: {
147
+ type: "lark";
148
+ }): LarkSourceReference;
127
149
  export declare function source(name: string, options: {
128
150
  type: "repo";
129
151
  }): RepoSourceReference;