@sequenceholdings/pipeline-spec 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/authoring/per-table-ingestion.d.ts +74 -0
- package/dist/authoring/per-table-ingestion.d.ts.map +1 -0
- package/dist/authoring/per-table-ingestion.js +122 -0
- package/dist/authoring/per-table-ingestion.js.map +1 -0
- package/dist/authoring/yaml.d.ts +6 -0
- package/dist/authoring/yaml.d.ts.map +1 -0
- package/dist/authoring/yaml.js +15 -0
- package/dist/authoring/yaml.js.map +1 -0
- package/dist/binding-gaps.d.ts +21 -0
- package/dist/binding-gaps.d.ts.map +1 -0
- package/dist/binding-gaps.js +74 -0
- package/dist/binding-gaps.js.map +1 -0
- package/dist/bodies/ingestion.d.ts +359 -0
- package/dist/bodies/ingestion.d.ts.map +1 -0
- package/dist/bodies/ingestion.js +446 -0
- package/dist/bodies/ingestion.js.map +1 -0
- package/dist/bodies/serving.d.ts +316 -0
- package/dist/bodies/serving.d.ts.map +1 -0
- package/dist/bodies/serving.js +290 -0
- package/dist/bodies/serving.js.map +1 -0
- package/dist/bodies/transformation.d.ts +397 -0
- package/dist/bodies/transformation.d.ts.map +1 -0
- package/dist/bodies/transformation.js +278 -0
- package/dist/bodies/transformation.js.map +1 -0
- package/dist/catalog-binding.d.ts +15 -0
- package/dist/catalog-binding.d.ts.map +1 -0
- package/dist/catalog-binding.js +15 -0
- package/dist/catalog-binding.js.map +1 -0
- package/dist/columns.d.ts +177 -0
- package/dist/columns.d.ts.map +1 -0
- package/dist/columns.js +89 -0
- package/dist/columns.js.map +1 -0
- package/dist/compatibility.d.ts +25 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +108 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/constants.d.ts +95 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +105 -0
- package/dist/constants.js.map +1 -0
- package/dist/diff.d.ts +36 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +300 -0
- package/dist/diff.js.map +1 -0
- package/dist/documentation.d.ts +22 -0
- package/dist/documentation.d.ts.map +1 -0
- package/dist/documentation.js +43 -0
- package/dist/documentation.js.map +1 -0
- package/dist/envelope.d.ts +1241 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +163 -0
- package/dist/envelope.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +47 -0
- package/dist/errors.js.map +1 -0
- package/dist/graph-references.d.ts +34 -0
- package/dist/graph-references.d.ts.map +1 -0
- package/dist/graph-references.js +81 -0
- package/dist/graph-references.js.map +1 -0
- package/dist/graph.d.ts +112 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +546 -0
- package/dist/graph.js.map +1 -0
- package/dist/hash.d.ts +28 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +91 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/issues.d.ts +14 -0
- package/dist/issues.d.ts.map +1 -0
- package/dist/issues.js +27 -0
- package/dist/issues.js.map +1 -0
- package/dist/loader.d.ts +50 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +241 -0
- package/dist/loader.js.map +1 -0
- package/dist/migrations/contracts.d.ts +38 -0
- package/dist/migrations/contracts.d.ts.map +1 -0
- package/dist/migrations/contracts.js +175 -0
- package/dist/migrations/contracts.js.map +1 -0
- package/dist/migrations/manifest.d.ts +137 -0
- package/dist/migrations/manifest.d.ts.map +1 -0
- package/dist/migrations/manifest.js +137 -0
- package/dist/migrations/manifest.js.map +1 -0
- package/dist/operations.d.ts +214 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +275 -0
- package/dist/operations.js.map +1 -0
- package/dist/orm-satisfies.d.ts +132 -0
- package/dist/orm-satisfies.d.ts.map +1 -0
- package/dist/orm-satisfies.js +119 -0
- package/dist/orm-satisfies.js.map +1 -0
- package/dist/primitives.d.ts +11 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +20 -0
- package/dist/primitives.js.map +1 -0
- package/dist/resolve.d.ts +124 -0
- package/dist/resolve.d.ts.map +1 -0
- package/dist/resolve.js +194 -0
- package/dist/resolve.js.map +1 -0
- package/dist/secret-scan.d.ts +34 -0
- package/dist/secret-scan.d.ts.map +1 -0
- package/dist/secret-scan.js +98 -0
- package/dist/secret-scan.js.map +1 -0
- package/dist/serving-compatibility.d.ts +14 -0
- package/dist/serving-compatibility.d.ts.map +1 -0
- package/dist/serving-compatibility.js +19 -0
- package/dist/serving-compatibility.js.map +1 -0
- package/dist/snapshot-transport.d.ts +83 -0
- package/dist/snapshot-transport.d.ts.map +1 -0
- package/dist/snapshot-transport.js +42 -0
- package/dist/snapshot-transport.js.map +1 -0
- package/dist/suggestions.d.ts +3 -0
- package/dist/suggestions.d.ts.map +1 -0
- package/dist/suggestions.js +26 -0
- package/dist/suggestions.js.map +1 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +119 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage ids are kebab-case slugs — they become file basenames
|
|
3
|
+
* (`<stage>.stage.yml`), registry keys, and halves of logical asset ids
|
|
4
|
+
* (`<stage>.<asset>`), so the grammar is deliberately tight.
|
|
5
|
+
*/
|
|
6
|
+
export const STAGE_ID_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
|
|
7
|
+
/** Logical names such as feeds, assets, stages, and namespaces. */
|
|
8
|
+
export const IDENTIFIER_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
9
|
+
/** Physical column names may preserve source-system leading underscores. */
|
|
10
|
+
export const COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
|
|
11
|
+
export const MAX_IDENTIFIER_LENGTH = 63;
|
|
12
|
+
/** Transformation output assets live in the medallion layers or report lane. */
|
|
13
|
+
export const OUTPUT_ASSET_PATTERN = /^(silver|gold|report)\.[a-z][a-z0-9_]*$/;
|
|
14
|
+
/** Raw report passthrough assets are isolated from ontology silver/gold assets. */
|
|
15
|
+
export const REPORT_ASSET_PATTERN = /^report\.[a-z][a-z0-9_]*$/;
|
|
16
|
+
/** ORM-bound serving sources are restricted to the gold layer (mirrors the ORM's `SYNCED_SOURCE_PATTERN`). */
|
|
17
|
+
export const GOLD_ASSET_PATTERN = /^gold\.[a-z][a-z0-9_]*$/;
|
|
18
|
+
/** Serving views are exposed in the Lakebase `public` schema. */
|
|
19
|
+
export const PUBLIC_VIEW_PATTERN = /^public\.[a-z][a-z0-9_]*$/;
|
|
20
|
+
/** FIS compatibility relations are isolated to the dedicated reporting schema. */
|
|
21
|
+
export const REPORTING_TABLE_PATTERN = /^fis_reports\.[a-z][a-z0-9_]*$/;
|
|
22
|
+
/** `<schema>.<table>` reference for Lakebase CDF source tables (e.g. `manual.retail_customers`). */
|
|
23
|
+
export const QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/;
|
|
24
|
+
/**
|
|
25
|
+
* Symbolic registry references (credential families, alert channels, worker
|
|
26
|
+
* machines, source systems). Names only — the tight slug grammar is one of the
|
|
27
|
+
* two layers that keep literal secrets/URLs out of specs (the other is the
|
|
28
|
+
* credential scan in the envelope).
|
|
29
|
+
*/
|
|
30
|
+
export const SYMBOLIC_REF_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
31
|
+
/** Deploy-target slugs (environment names) — no path separators or dots. */
|
|
32
|
+
export const DEPLOY_TARGET_PATTERN = /^[a-z][a-z0-9_-]*$/;
|
|
33
|
+
/** ISO-8601 duration (`PT4H`, `P1D`, `PT30M`) — used by SLOs, freshness, and retention. */
|
|
34
|
+
export const ISO_DURATION_PATTERN = /^P(?!$)(\d+Y)?(\d+M)?(\d+W)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
|
|
35
|
+
/** 5–7 whitespace-separated cron fields; semantic validation belongs to the scheduler. */
|
|
36
|
+
export const CRON_PATTERN = /^\S+(\s+\S+){4,6}$/;
|
|
37
|
+
/** IANA timezone shape (`America/New_York`) or `UTC`. */
|
|
38
|
+
export const TIMEZONE_PATTERN = /^(UTC|[A-Za-z]+(?:\/[A-Za-z0-9_+-]+)+)$/;
|
|
39
|
+
/** Stage spec files: `<stage>.stage.yml` in the Pipeline repo root. */
|
|
40
|
+
export const STAGE_FILE_SUFFIXES = ['.stage.yml', '.stage.yaml'];
|
|
41
|
+
/** Named schema artifacts: `schemas/<name>.schema.yml` in the Pipeline repo. */
|
|
42
|
+
export const SCHEMA_FILE_SUFFIXES = ['.schema.yml', '.schema.yaml'];
|
|
43
|
+
/** Directory (relative to the Pipeline root) holding named schema artifacts. */
|
|
44
|
+
export const SCHEMAS_DIRECTORY = 'schemas';
|
|
45
|
+
/** Per-feed documentation sidecars, kept separate from typed schema contracts. */
|
|
46
|
+
export const DOCUMENTATION_FILE_SUFFIXES = ['.documentation.yml', '.documentation.yaml'];
|
|
47
|
+
export const DOCUMENTATION_DIRECTORY = 'documentation';
|
|
48
|
+
/**
|
|
49
|
+
* Platform-defined operation names. The platform owns these verbs (they get
|
|
50
|
+
* platform semantics, ledgers, and UI affordances) — author-declared
|
|
51
|
+
* operations may not shadow them.
|
|
52
|
+
*/
|
|
53
|
+
export const RESERVED_OPERATION_NAMES = new Set([
|
|
54
|
+
'backfill',
|
|
55
|
+
'replay',
|
|
56
|
+
'sample',
|
|
57
|
+
'live-source-run',
|
|
58
|
+
]);
|
|
59
|
+
/**
|
|
60
|
+
* Bronze envelope columns the materializer stamps onto every row —
|
|
61
|
+
* `stamp_envelope`'s `_ENVELOPE_COLUMN_NAMES` in
|
|
62
|
+
* `databricks/pipeline_runtime/materializer.py` is the single source of
|
|
63
|
+
* truth this is derived from (not guessed). A SOURCE column sharing one of
|
|
64
|
+
* these names is silently overwritten by `stamp_envelope` and permanently
|
|
65
|
+
* lost, so they're reserved for the only column-name-bearing fields an
|
|
66
|
+
* ingestion feed declares about its own source columns: `natural_key` and
|
|
67
|
+
* `cursor.column` (`refineFeed` in `bodies/ingestion.ts`).
|
|
68
|
+
*
|
|
69
|
+
* Deliberately NOT reserved on transformation `outputs`/CDF `columns`/
|
|
70
|
+
* serving `projection.columns` (`columnMapSchema` in `columns.ts`) — those
|
|
71
|
+
* are silver/gold/CDF-envelope business columns on a completely different
|
|
72
|
+
* write path the materializer never touches, and real specs legitimately
|
|
73
|
+
* use `ingested_at`/`source_system` there (see
|
|
74
|
+
* `fixtures/billing/billing-silver.stage.yml`,
|
|
75
|
+
* `fixtures/er/entity-resolution.stage.yml`).
|
|
76
|
+
*
|
|
77
|
+
* MUST match `RESERVED_ENVELOPE_COLUMNS` in
|
|
78
|
+
* `databricks/pipeline_runtime/materializer.py` byte-for-byte — Python
|
|
79
|
+
* can't import TS, only a shared naming convention (a parity test on each
|
|
80
|
+
* side pins the two lists literally equal).
|
|
81
|
+
*/
|
|
82
|
+
export const RESERVED_ENVELOPE_COLUMNS = new Set([
|
|
83
|
+
'batch_id',
|
|
84
|
+
'ingested_at',
|
|
85
|
+
'source_system',
|
|
86
|
+
'content_hash',
|
|
87
|
+
]);
|
|
88
|
+
/**
|
|
89
|
+
* Quarantine table name derivation: rows failing a `quarantine`-posture check
|
|
90
|
+
* land in a platform-derived sibling table. Defined here (M1) so the M6
|
|
91
|
+
* compiler and every doc derive the same name.
|
|
92
|
+
*/
|
|
93
|
+
export const QUARANTINE_SUFFIX = '__quarantine';
|
|
94
|
+
export const quarantineAssetName = (outputAsset) => `${outputAsset}${QUARANTINE_SUFFIX}`;
|
|
95
|
+
/** Domain-separation prefixes so spec and contract hashes can never collide. */
|
|
96
|
+
export const SPEC_HASH_DOMAIN = 'sequence-pipeline-spec\0';
|
|
97
|
+
export const CONTRACT_HASH_DOMAIN = 'sequence-pipeline-contract\0';
|
|
98
|
+
/**
|
|
99
|
+
* Per-file byte cap where the loader reads untrusted YAML into memory (same
|
|
100
|
+
* posture as the ORM loader) — a real failure mode, not a product limit.
|
|
101
|
+
*/
|
|
102
|
+
export const MAX_SPEC_FILE_BYTES = 1024 * 1024;
|
|
103
|
+
/** Stage files may embed full source dictionaries; stay within Git Service's blob cap. */
|
|
104
|
+
export const MAX_STAGE_SPEC_FILE_BYTES = 5 * 1024 * 1024;
|
|
105
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,+BAA+B,CAAA;AAE/D,mEAAmE;AACnE,MAAM,CAAC,MAAM,kBAAkB,GAAG,mBAAmB,CAAA;AAErD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,yBAAyB,GAAG,qBAAqB,CAAA;AAE9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAA;AAEvC,gFAAgF;AAChF,MAAM,CAAC,MAAM,oBAAoB,GAAG,yCAAyC,CAAA;AAE7E,mFAAmF;AACnF,MAAM,CAAC,MAAM,oBAAoB,GAAG,2BAA2B,CAAA;AAE/D,8GAA8G;AAC9G,MAAM,CAAC,MAAM,kBAAkB,GAAG,yBAAyB,CAAA;AAE3D,iEAAiE;AACjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,2BAA2B,CAAA;AAE9D,kFAAkF;AAClF,MAAM,CAAC,MAAM,uBAAuB,GAAG,gCAAgC,CAAA;AAEvE,oGAAoG;AACpG,MAAM,CAAC,MAAM,uBAAuB,GAAG,oCAAoC,CAAA;AAE3E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAA;AAExD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,oBAAoB,CAAA;AAEzD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,oBAAoB,GAC/B,qEAAqE,CAAA;AAEvE,0FAA0F;AAC1F,MAAM,CAAC,MAAM,YAAY,GAAG,oBAAoB,CAAA;AAEhD,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,yCAAyC,CAAA;AAEzE,uEAAuE;AACvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,YAAY,EAAE,aAAa,CAAU,CAAA;AAEzE,gFAAgF;AAChF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,aAAa,EAAE,cAAc,CAAU,CAAA;AAE5E,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAA;AAE1C,kFAAkF;AAClF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,oBAAoB,EAAE,qBAAqB,CAAU,CAAA;AACjG,MAAM,CAAC,MAAM,uBAAuB,GAAG,eAAe,CAAA;AAEtD;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAwB,IAAI,GAAG,CAAC;IACnE,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,iBAAiB;CAClB,CAAC,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAwB,IAAI,GAAG,CAAC;IACpE,UAAU;IACV,aAAa;IACb,eAAe;IACf,cAAc;CACf,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAA;AAE/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAU,EAAE,CAAC,GAAG,WAAW,GAAG,iBAAiB,EAAE,CAAA;AAExG,gFAAgF;AAChF,MAAM,CAAC,MAAM,gBAAgB,GAAG,0BAA0B,CAAA;AAC1D,MAAM,CAAC,MAAM,oBAAoB,GAAG,8BAA8B,CAAA;AAElE;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAAA;AAE9C,0FAA0F;AAC1F,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA"}
|
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { StageSpec } from './envelope.js';
|
|
2
|
+
/**
|
|
3
|
+
* Contract diffing between two versions of a stage spec — the primitive the
|
|
4
|
+
* `additive-only` compatibility default enforces. A change is ADDITIVE iff
|
|
5
|
+
* every consumer requirement satisfied by the old contract is still satisfied
|
|
6
|
+
* by the new one; anything else is BREAKING. Cosmetic fields (title,
|
|
7
|
+
* description, owners, runbook) are outside the contract surface entirely.
|
|
8
|
+
*/
|
|
9
|
+
export type ContractClassification = 'breaking' | 'additive' | 'none';
|
|
10
|
+
export declare const CONTRACT_CHANGE_CODES: readonly ["stage_type_changed", "output_added", "output_removed", "column_added", "column_removed", "type_changed", "nullability_loosened", "nullability_tightened", "domain_shrunk", "domain_expanded", "domain_constraint_added", "domain_constraint_removed", "key_changed", "write_pattern_changed", "write_scope_added", "write_scope_changed", "source_changed", "sync_mode_changed", "orm_binding_changed", "satisfies_changed", "primary_key_changed", "feed_added", "feed_removed", "feed_semantics_changed", "violation_posture_changed", "compatibility_mode_changed"];
|
|
11
|
+
export type ContractChangeCode = (typeof CONTRACT_CHANGE_CODES)[number];
|
|
12
|
+
export interface ContractChange {
|
|
13
|
+
readonly code: ContractChangeCode;
|
|
14
|
+
readonly column?: string;
|
|
15
|
+
readonly message: string;
|
|
16
|
+
}
|
|
17
|
+
export interface OutputContractDiff {
|
|
18
|
+
readonly classification: ContractClassification;
|
|
19
|
+
readonly changes: readonly ContractChange[];
|
|
20
|
+
}
|
|
21
|
+
export interface ContractDiff {
|
|
22
|
+
readonly classification: ContractClassification;
|
|
23
|
+
/** Spec-level (non-output) changes, e.g. a stage kind change. */
|
|
24
|
+
readonly changes: readonly ContractChange[];
|
|
25
|
+
/** Per-output classification, keyed by asset name. */
|
|
26
|
+
readonly outputs: Readonly<Record<string, OutputContractDiff>>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Classify the contract delta between two versions of a stage spec.
|
|
30
|
+
* Transformation outputs diff by asset name; serving projections by exposed
|
|
31
|
+
* view; non-column contract fields (serving source/sync_mode/orm_binding/
|
|
32
|
+
* primary_key, ingestion source identity + feed semantics) surface as
|
|
33
|
+
* spec-level `changes` — everything in `contractSurface` is diffable.
|
|
34
|
+
*/
|
|
35
|
+
export declare function diffContracts(oldSpec: StageSpec, newSpec: StageSpec): ContractDiff;
|
|
36
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C;;;;;;GAMG;AAEH,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAErE,eAAO,MAAM,qBAAqB,mjBA2BxB,CAAA;AAEV,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAUvE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAA;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;CAC5C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,EAAE,sBAAsB,CAAA;IAC/C,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;IAC3C,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAA;CAC/D;AAsMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,YAAY,CA8ElF"}
|
package/dist/diff.js
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { requireResolvedColumns } from './columns.js';
|
|
2
|
+
import { domainKey } from './compatibility.js';
|
|
3
|
+
import { feedContract, ingestionSourceIdentity } from './bodies/ingestion.js';
|
|
4
|
+
import { canonicalJson } from './hash.js';
|
|
5
|
+
export const CONTRACT_CHANGE_CODES = [
|
|
6
|
+
'stage_type_changed',
|
|
7
|
+
'output_added',
|
|
8
|
+
'output_removed',
|
|
9
|
+
'column_added',
|
|
10
|
+
'column_removed',
|
|
11
|
+
'type_changed',
|
|
12
|
+
'nullability_loosened',
|
|
13
|
+
'nullability_tightened',
|
|
14
|
+
'domain_shrunk',
|
|
15
|
+
'domain_expanded',
|
|
16
|
+
'domain_constraint_added',
|
|
17
|
+
'domain_constraint_removed',
|
|
18
|
+
'key_changed',
|
|
19
|
+
'write_pattern_changed',
|
|
20
|
+
'write_scope_added',
|
|
21
|
+
'write_scope_changed',
|
|
22
|
+
'source_changed',
|
|
23
|
+
'sync_mode_changed',
|
|
24
|
+
'orm_binding_changed',
|
|
25
|
+
'satisfies_changed',
|
|
26
|
+
'primary_key_changed',
|
|
27
|
+
'feed_added',
|
|
28
|
+
'feed_removed',
|
|
29
|
+
'feed_semantics_changed',
|
|
30
|
+
'violation_posture_changed',
|
|
31
|
+
'compatibility_mode_changed',
|
|
32
|
+
];
|
|
33
|
+
const ADDITIVE_CODES = new Set([
|
|
34
|
+
'output_added',
|
|
35
|
+
'column_added',
|
|
36
|
+
'nullability_tightened',
|
|
37
|
+
'feed_added',
|
|
38
|
+
'write_scope_added',
|
|
39
|
+
]);
|
|
40
|
+
function classify(changes) {
|
|
41
|
+
if (changes.length === 0)
|
|
42
|
+
return 'none';
|
|
43
|
+
return changes.every((change) => ADDITIVE_CODES.has(change.code)) ? 'additive' : 'breaking';
|
|
44
|
+
}
|
|
45
|
+
function diffColumnMaps(oldColumns, newColumns) {
|
|
46
|
+
const changes = [];
|
|
47
|
+
for (const [name, oldColumn] of Object.entries(oldColumns)) {
|
|
48
|
+
const newColumn = newColumns[name];
|
|
49
|
+
if (!newColumn) {
|
|
50
|
+
changes.push({ code: 'column_removed', column: name, message: `column '${name}' was removed` });
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (oldColumn.type !== newColumn.type) {
|
|
54
|
+
changes.push({
|
|
55
|
+
code: 'type_changed',
|
|
56
|
+
column: name,
|
|
57
|
+
message: `column '${name}' changed type '${oldColumn.type}' → '${newColumn.type}'`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (oldColumn.nullable !== newColumn.nullable) {
|
|
61
|
+
changes.push(newColumn.nullable
|
|
62
|
+
? {
|
|
63
|
+
code: 'nullability_loosened',
|
|
64
|
+
column: name,
|
|
65
|
+
message: `column '${name}' became nullable — consumers requiring non-null break`,
|
|
66
|
+
}
|
|
67
|
+
: { code: 'nullability_tightened', column: name, message: `column '${name}' became non-null` });
|
|
68
|
+
}
|
|
69
|
+
if (oldColumn.key !== newColumn.key) {
|
|
70
|
+
changes.push({ code: 'key_changed', column: name, message: `column '${name}' key participation changed` });
|
|
71
|
+
}
|
|
72
|
+
if (oldColumn.on_violation !== newColumn.on_violation) {
|
|
73
|
+
// Rows move between fail/quarantine/warn destinations — output
|
|
74
|
+
// semantics change for every consumer, so never additive.
|
|
75
|
+
changes.push({
|
|
76
|
+
code: 'violation_posture_changed',
|
|
77
|
+
column: name,
|
|
78
|
+
message: `column '${name}' on_violation changed '${oldColumn.on_violation}' → '${newColumn.on_violation}'`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const oldDomain = oldColumn.domain;
|
|
82
|
+
const newDomain = newColumn.domain;
|
|
83
|
+
if (oldDomain && !newDomain) {
|
|
84
|
+
changes.push({
|
|
85
|
+
code: 'domain_constraint_removed',
|
|
86
|
+
column: name,
|
|
87
|
+
message: `column '${name}' dropped its domain constraint — new values may appear`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else if (!oldDomain && newDomain) {
|
|
91
|
+
changes.push({
|
|
92
|
+
code: 'domain_constraint_added',
|
|
93
|
+
column: name,
|
|
94
|
+
message: `column '${name}' gained a domain constraint — previously legal values may vanish`,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else if (oldDomain && newDomain) {
|
|
98
|
+
const newKeys = new Set(newDomain.map(domainKey));
|
|
99
|
+
const removed = oldDomain.filter((value) => !newKeys.has(domainKey(value)));
|
|
100
|
+
const oldKeys = new Set(oldDomain.map(domainKey));
|
|
101
|
+
const added = newDomain.filter((value) => !oldKeys.has(domainKey(value)));
|
|
102
|
+
if (removed.length > 0) {
|
|
103
|
+
changes.push({
|
|
104
|
+
code: 'domain_shrunk',
|
|
105
|
+
column: name,
|
|
106
|
+
message: `column '${name}' domain shrank (removed: ${removed.map(String).join(', ')}) — consumers relying on those values break`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (added.length > 0) {
|
|
110
|
+
changes.push({
|
|
111
|
+
code: 'domain_expanded',
|
|
112
|
+
column: name,
|
|
113
|
+
message: `column '${name}' domain expanded (added: ${added.map(String).join(', ')}) — consumers with closed handling break`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const name of Object.keys(newColumns)) {
|
|
119
|
+
if (!(name in oldColumns)) {
|
|
120
|
+
changes.push({ code: 'column_added', column: name, message: `column '${name}' was added` });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return changes;
|
|
124
|
+
}
|
|
125
|
+
function contractsOf(spec) {
|
|
126
|
+
if (spec.type === 'transformation') {
|
|
127
|
+
const contracts = {};
|
|
128
|
+
for (const [asset, output] of Object.entries(spec.outputs)) {
|
|
129
|
+
contracts[asset] = {
|
|
130
|
+
columns: requireResolvedColumns(output.columns, `${spec.stage}: outputs.${asset}.columns`),
|
|
131
|
+
write_pattern: output.write_pattern,
|
|
132
|
+
...(output.write_scope ? { write_scope: output.write_scope } : {}),
|
|
133
|
+
on_type_violation: output.on_type_violation,
|
|
134
|
+
compatibility: output.compatibility,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return contracts;
|
|
138
|
+
}
|
|
139
|
+
if (spec.type === 'serving') {
|
|
140
|
+
return {
|
|
141
|
+
[spec.expose.view]: {
|
|
142
|
+
columns: requireResolvedColumns(spec.projection.columns, `${spec.stage}: projection.columns`),
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
return {};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Non-column contract fields — everything `contractSurface` covers beyond
|
|
150
|
+
* output/projection columns must be diffable here, or additive-only
|
|
151
|
+
* enforcement would miss breaking changes that DO churn `contract_hash`:
|
|
152
|
+
* serving source/sync_mode/orm_binding/primary_key, and ingestion source
|
|
153
|
+
* identity + feed batch semantics.
|
|
154
|
+
*/
|
|
155
|
+
function specLevelChanges(oldSpec, newSpec) {
|
|
156
|
+
const changes = [];
|
|
157
|
+
if (oldSpec.type === 'serving' && newSpec.type === 'serving') {
|
|
158
|
+
if (canonicalJson(oldSpec.source) !== canonicalJson(newSpec.source)) {
|
|
159
|
+
changes.push({
|
|
160
|
+
code: 'source_changed',
|
|
161
|
+
message: `serving source changed '${oldSpec.source.stage}.${oldSpec.source.output}' → '${newSpec.source.stage}.${newSpec.source.output}'`,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
if (oldSpec.sync_mode !== newSpec.sync_mode) {
|
|
165
|
+
changes.push({
|
|
166
|
+
code: 'sync_mode_changed',
|
|
167
|
+
message: `sync_mode changed '${oldSpec.sync_mode}' → '${newSpec.sync_mode}'`,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (canonicalJson(oldSpec.orm_binding ?? null) !== canonicalJson(newSpec.orm_binding ?? null)) {
|
|
171
|
+
changes.push({
|
|
172
|
+
code: 'orm_binding_changed',
|
|
173
|
+
message: 'orm_binding changed — the platform↔ORM join key is contract identity',
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
if (canonicalJson(oldSpec.satisfies ?? null) !== canonicalJson(newSpec.satisfies ?? null)) {
|
|
177
|
+
changes.push({
|
|
178
|
+
code: 'satisfies_changed',
|
|
179
|
+
message: 'satisfies changed — the ORM contract pin (namespace.table@hash) is contract identity',
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (canonicalJson(oldSpec.projection.primary_key) !== canonicalJson(newSpec.projection.primary_key)) {
|
|
183
|
+
changes.push({
|
|
184
|
+
code: 'primary_key_changed',
|
|
185
|
+
message: `primary_key changed [${oldSpec.projection.primary_key.join(', ')}] → [${newSpec.projection.primary_key.join(', ')}]`,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (oldSpec.type === 'ingestion' && newSpec.type === 'ingestion') {
|
|
190
|
+
const oldSource = ingestionSourceIdentity(oldSpec);
|
|
191
|
+
const newSource = ingestionSourceIdentity(newSpec);
|
|
192
|
+
if (oldSource !== newSource) {
|
|
193
|
+
changes.push({
|
|
194
|
+
code: 'source_changed',
|
|
195
|
+
message: `source identity changed '${oldSource}' → '${newSource}' — every derived bronze name moves`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
for (const [name, oldFeed] of Object.entries(oldSpec.feeds)) {
|
|
199
|
+
const newFeed = newSpec.feeds[name];
|
|
200
|
+
if (!newFeed) {
|
|
201
|
+
changes.push({ code: 'feed_removed', message: `feed '${name}' was removed` });
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
if (canonicalJson(feedContract(oldFeed)) !== canonicalJson(feedContract(newFeed))) {
|
|
205
|
+
changes.push({
|
|
206
|
+
code: 'feed_semantics_changed',
|
|
207
|
+
message: `feed '${name}' batch semantics changed (snapshot_mode/keys/cursor/format/pii/extraction)`,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const name of Object.keys(newSpec.feeds)) {
|
|
212
|
+
if (!(name in oldSpec.feeds)) {
|
|
213
|
+
changes.push({ code: 'feed_added', message: `feed '${name}' was added` });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return changes;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Classify the contract delta between two versions of a stage spec.
|
|
221
|
+
* Transformation outputs diff by asset name; serving projections by exposed
|
|
222
|
+
* view; non-column contract fields (serving source/sync_mode/orm_binding/
|
|
223
|
+
* primary_key, ingestion source identity + feed semantics) surface as
|
|
224
|
+
* spec-level `changes` — everything in `contractSurface` is diffable.
|
|
225
|
+
*/
|
|
226
|
+
export function diffContracts(oldSpec, newSpec) {
|
|
227
|
+
if (oldSpec.type !== newSpec.type) {
|
|
228
|
+
// A stage kind change is a lifecycle-breaking replacement even when the
|
|
229
|
+
// derived output maps happen to overlap (e.g. ingestion → transformation
|
|
230
|
+
// both derive empty/none) — never classifiable as additive.
|
|
231
|
+
return {
|
|
232
|
+
classification: 'breaking',
|
|
233
|
+
changes: [
|
|
234
|
+
{
|
|
235
|
+
code: 'stage_type_changed',
|
|
236
|
+
message: `stage kind changed '${oldSpec.type}' → '${newSpec.type}' — a replacement, not an evolution`,
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
outputs: {},
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
const oldContracts = contractsOf(oldSpec);
|
|
243
|
+
const newContracts = contractsOf(newSpec);
|
|
244
|
+
const outputs = {};
|
|
245
|
+
for (const [asset, oldContract] of Object.entries(oldContracts)) {
|
|
246
|
+
const newContract = newContracts[asset];
|
|
247
|
+
if (!newContract) {
|
|
248
|
+
outputs[asset] = {
|
|
249
|
+
classification: 'breaking',
|
|
250
|
+
changes: [{ code: 'output_removed', message: `output '${asset}' was removed` }],
|
|
251
|
+
};
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
const changes = diffColumnMaps(oldContract.columns, newContract.columns);
|
|
255
|
+
if (canonicalJson(oldContract.write_scope) !== canonicalJson(newContract.write_scope)) {
|
|
256
|
+
changes.push({
|
|
257
|
+
code: oldContract.write_scope ? 'write_scope_changed' : 'write_scope_added',
|
|
258
|
+
message: `output '${asset}' write scope changed ${canonicalJson(oldContract.write_scope) ?? 'unscoped'} → ${canonicalJson(newContract.write_scope) ?? 'unscoped'}`,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
// Non-column output posture fields — every one of them is hashed by
|
|
262
|
+
// contractSurface, so every one must be diffable (never silently `none`).
|
|
263
|
+
const postureFields = [
|
|
264
|
+
['write_pattern', 'write_pattern_changed'],
|
|
265
|
+
['on_type_violation', 'violation_posture_changed'],
|
|
266
|
+
['compatibility', 'compatibility_mode_changed'],
|
|
267
|
+
];
|
|
268
|
+
for (const [field, code] of postureFields) {
|
|
269
|
+
const oldValue = oldContract[field];
|
|
270
|
+
const newValue = newContract[field];
|
|
271
|
+
if (oldValue !== undefined && newValue !== undefined && oldValue !== newValue) {
|
|
272
|
+
changes.push({
|
|
273
|
+
code,
|
|
274
|
+
message: `output '${asset}' ${field} changed '${oldValue}' → '${newValue}'`,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
outputs[asset] = { classification: classify(changes), changes };
|
|
279
|
+
}
|
|
280
|
+
for (const asset of Object.keys(newContracts)) {
|
|
281
|
+
if (!(asset in oldContracts)) {
|
|
282
|
+
outputs[asset] = {
|
|
283
|
+
classification: 'additive',
|
|
284
|
+
changes: [{ code: 'output_added', message: `output '${asset}' was added` }],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const specChanges = specLevelChanges(oldSpec, newSpec);
|
|
289
|
+
const classifications = [
|
|
290
|
+
...Object.values(outputs).map((output) => output.classification),
|
|
291
|
+
classify(specChanges),
|
|
292
|
+
];
|
|
293
|
+
const overall = classifications.includes('breaking')
|
|
294
|
+
? 'breaking'
|
|
295
|
+
: classifications.includes('additive')
|
|
296
|
+
? 'additive'
|
|
297
|
+
: 'none';
|
|
298
|
+
return { classification: overall, changes: specChanges, outputs };
|
|
299
|
+
}
|
|
300
|
+
//# sourceMappingURL=diff.js.map
|
package/dist/diff.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { StageSpec } from './envelope.js';
|
|
3
|
+
export declare const columnDescriptionsSchema: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
4
|
+
/** Bronze column annotations do not declare or enforce types from the source. */
|
|
5
|
+
export declare const feedColumnsSchema: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
6
|
+
description: z.ZodString;
|
|
7
|
+
}, z.core.$strict>>;
|
|
8
|
+
/** Documentation is deliberately independent of enforced column/type contracts. */
|
|
9
|
+
export declare const feedDocumentationSchema: z.ZodObject<{
|
|
10
|
+
description: z.ZodOptional<z.ZodString>;
|
|
11
|
+
column_descriptions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
12
|
+
}, z.core.$strict>;
|
|
13
|
+
export type FeedDocumentation = z.infer<typeof feedDocumentationSchema>;
|
|
14
|
+
/** Resolve sidecars into the stage snapshot; explicitly authored metadata wins. */
|
|
15
|
+
export declare function resolveFeedDocumentation({ spec, file, documentation, }: {
|
|
16
|
+
spec: StageSpec;
|
|
17
|
+
file: string;
|
|
18
|
+
documentation: ReadonlyMap<string, FeedDocumentation>;
|
|
19
|
+
}): void;
|
|
20
|
+
/** Direct resolver callers must load documentation before creating immutable snapshots. */
|
|
21
|
+
export declare function assertFeedDocumentationResolved(spec: StageSpec): void;
|
|
22
|
+
//# sourceMappingURL=documentation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentation.d.ts","sourceRoot":"","sources":["../src/documentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9C,eAAO,MAAM,wBAAwB,uCAAiD,CAAA;AAEtF,iFAAiF;AACjF,eAAO,MAAM,iBAAiB;;mBAG7B,CAAA;AAED,mFAAmF;AACnF,eAAO,MAAM,uBAAuB;;;kBAGlC,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAEvE,mFAAmF;AACnF,wBAAgB,wBAAwB,CAAC,EACvC,IAAI,EACJ,IAAI,EACJ,aAAa,GACd,EAAE;IACD,IAAI,EAAE,SAAS,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CACtD,GAAG,IAAI,CAkBP;AAED,2FAA2F;AAC3F,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,CAWrE"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { MAX_IDENTIFIER_LENGTH } from './constants.js';
|
|
3
|
+
import { SpecDefinitionError } from './errors.js';
|
|
4
|
+
/** Literal physical names, including source-native characters such as '#'. */
|
|
5
|
+
const physicalColumnNameSchema = z.string().min(1).max(MAX_IDENTIFIER_LENGTH);
|
|
6
|
+
export const columnDescriptionsSchema = z.record(physicalColumnNameSchema, z.string());
|
|
7
|
+
/** Bronze column annotations do not declare or enforce types from the source. */
|
|
8
|
+
export const feedColumnsSchema = z.record(physicalColumnNameSchema, z.strictObject({ description: z.string() }));
|
|
9
|
+
/** Documentation is deliberately independent of enforced column/type contracts. */
|
|
10
|
+
export const feedDocumentationSchema = z.strictObject({
|
|
11
|
+
description: z.string().optional(),
|
|
12
|
+
column_descriptions: columnDescriptionsSchema.optional(),
|
|
13
|
+
});
|
|
14
|
+
/** Resolve sidecars into the stage snapshot; explicitly authored metadata wins. */
|
|
15
|
+
export function resolveFeedDocumentation({ spec, file, documentation, }) {
|
|
16
|
+
if (spec.type !== 'ingestion')
|
|
17
|
+
return;
|
|
18
|
+
for (const [name, feed] of Object.entries(spec.feeds)) {
|
|
19
|
+
if (feed.documentation_ref === undefined)
|
|
20
|
+
continue;
|
|
21
|
+
const docs = documentation.get(feed.documentation_ref);
|
|
22
|
+
if (!docs) {
|
|
23
|
+
throw new SpecDefinitionError(`documentation_ref '${feed.documentation_ref}' does not resolve — no documentation/${feed.documentation_ref}.documentation.yml in this Pipeline`, file, `feeds.${name}.documentation_ref`);
|
|
24
|
+
}
|
|
25
|
+
if (feed.description === undefined && docs.description !== undefined)
|
|
26
|
+
feed.description = docs.description;
|
|
27
|
+
if (docs.column_descriptions !== undefined) {
|
|
28
|
+
feed.column_descriptions = { ...docs.column_descriptions, ...feed.column_descriptions };
|
|
29
|
+
}
|
|
30
|
+
delete feed.documentation_ref;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Direct resolver callers must load documentation before creating immutable snapshots. */
|
|
34
|
+
export function assertFeedDocumentationResolved(spec) {
|
|
35
|
+
if (spec.type !== 'ingestion')
|
|
36
|
+
return;
|
|
37
|
+
for (const [name, feed] of Object.entries(spec.feeds)) {
|
|
38
|
+
if (feed.documentation_ref !== undefined) {
|
|
39
|
+
throw new SpecDefinitionError(`unresolved documentation_ref '${feed.documentation_ref}' — load specs through parseSpecSources/loadSpecDirectory first`, undefined, `feeds.${name}.documentation_ref`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=documentation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentation.js","sourceRoot":"","sources":["../src/documentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAGjD,8EAA8E;AAC9E,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAA;AAC7E,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;AAEtF,iFAAiF;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CACvC,wBAAwB,EACxB,CAAC,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC5C,CAAA;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,YAAY,CAAC;IACpD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,mBAAmB,EAAE,wBAAwB,CAAC,QAAQ,EAAE;CACzD,CAAC,CAAA;AAIF,mFAAmF;AACnF,MAAM,UAAU,wBAAwB,CAAC,EACvC,IAAI,EACJ,IAAI,EACJ,aAAa,GAKd;IACC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAM;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS;YAAE,SAAQ;QAClD,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QACtD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,mBAAmB,CAC3B,sBAAsB,IAAI,CAAC,iBAAiB,yCAAyC,IAAI,CAAC,iBAAiB,qCAAqC,EAChJ,IAAI,EACJ,SAAS,IAAI,oBAAoB,CAClC,CAAA;QACH,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,KAAK,SAAS;YAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACzG,IAAI,IAAI,CAAC,mBAAmB,KAAK,SAAS,EAAE,CAAC;YAC3C,IAAI,CAAC,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC,mBAAmB,EAAE,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAA;QACzF,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAA;IAC/B,CAAC;AACH,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,+BAA+B,CAAC,IAAe;IAC7D,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;QAAE,OAAM;IACrC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,IAAI,mBAAmB,CAC3B,iCAAiC,IAAI,CAAC,iBAAiB,iEAAiE,EACxH,SAAS,EACT,SAAS,IAAI,oBAAoB,CAClC,CAAA;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|