autotel-schema 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.
Files changed (61) hide show
  1. package/README.md +131 -0
  2. package/dist/cli.cjs +111 -0
  3. package/dist/cli.cjs.map +1 -0
  4. package/dist/cli.d.cts +14 -0
  5. package/dist/cli.d.cts.map +1 -0
  6. package/dist/cli.d.ts +14 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +82 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/contract-DGjxR9nb.d.cts +123 -0
  11. package/dist/contract-DGjxR9nb.d.cts.map +1 -0
  12. package/dist/contract-DGjxR9nb.d.ts +123 -0
  13. package/dist/contract-DGjxR9nb.d.ts.map +1 -0
  14. package/dist/diff-BQPh72vY.d.cts +89 -0
  15. package/dist/diff-BQPh72vY.d.cts.map +1 -0
  16. package/dist/diff-D7qkNn0-.d.ts +89 -0
  17. package/dist/diff-D7qkNn0-.d.ts.map +1 -0
  18. package/dist/diff.cjs +185 -0
  19. package/dist/diff.cjs.map +1 -0
  20. package/dist/diff.d.cts +2 -0
  21. package/dist/diff.d.ts +2 -0
  22. package/dist/diff.js +181 -0
  23. package/dist/diff.js.map +1 -0
  24. package/dist/index.cjs +63 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.cts +33 -0
  27. package/dist/index.d.cts.map +1 -0
  28. package/dist/index.d.ts +33 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +43 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/processor-CK7LAdaa.d.ts +100 -0
  33. package/dist/processor-CK7LAdaa.d.ts.map +1 -0
  34. package/dist/processor-CkBkzK6y.d.cts +100 -0
  35. package/dist/processor-CkBkzK6y.d.cts.map +1 -0
  36. package/dist/processor-D93TAXvZ.cjs +366 -0
  37. package/dist/processor-D93TAXvZ.cjs.map +1 -0
  38. package/dist/processor-FmvKYllX.js +306 -0
  39. package/dist/processor-FmvKYllX.js.map +1 -0
  40. package/dist/processor.cjs +5 -0
  41. package/dist/processor.d.cts +2 -0
  42. package/dist/processor.d.ts +2 -0
  43. package/dist/processor.js +3 -0
  44. package/dist/snapshot-CyWGJaJT.cjs +119 -0
  45. package/dist/snapshot-CyWGJaJT.cjs.map +1 -0
  46. package/dist/snapshot-h8pb_Up_.js +89 -0
  47. package/dist/snapshot-h8pb_Up_.js.map +1 -0
  48. package/package.json +80 -0
  49. package/src/attrs.ts +23 -0
  50. package/src/cli.ts +117 -0
  51. package/src/contract.test.ts +67 -0
  52. package/src/contract.ts +231 -0
  53. package/src/diff.ts +282 -0
  54. package/src/index.ts +88 -0
  55. package/src/processor.test.ts +74 -0
  56. package/src/processor.ts +152 -0
  57. package/src/redaction.ts +64 -0
  58. package/src/snapshot.test.ts +88 -0
  59. package/src/snapshot.ts +119 -0
  60. package/src/validate.test.ts +100 -0
  61. package/src/validate.ts +237 -0
package/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # autotel-schema
2
+
3
+ > A typed, versioned contract for your telemetry surface. Declare the spans and attributes your service emits, validate live spans against the contract, and diff it across commits to catch breaking trace changes before release.
4
+
5
+ When the main reader of your telemetry is an **agent**, your span names and attribute keys are a **public API**. Rename `fast_path_hit` to `fast_path_taken` in a refactor and you break the prompts and alerts that mention it. No compiler catches the change, because to the compiler these are strings in a JSON blob.
6
+
7
+ `autotel-schema` makes that surface explicit, typed, and versionable. With [`autotel-pact`](../autotel-pact) it forms autotel's observability-contract pair. Both use telemetry to answer a contract question:
8
+
9
+ - **`autotel-schema`** (this package): the telemetry contract you emit (span names + attributes)
10
+ - [`autotel-pact`](../autotel-pact): evidence that contracted interactions actually ran
11
+
12
+ An optional adjacent package, [`autotel-message-contract`](../autotel-message-contract), extends the idea beyond telemetry to serialized payload compatibility. It runs at test time and needs no runtime observability.
13
+
14
+ The contract model is **dependency-free and side-effect-free**, so you can import it anywhere (browser, edge, CLI) without pulling in the OpenTelemetry SDK.
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pnpm add autotel-schema
20
+ # autotel is an optional peer dependency
21
+ ```
22
+
23
+ ## 1. Declare the contract
24
+
25
+ ```ts
26
+ import { defineContract } from 'autotel-schema';
27
+
28
+ export const contract = defineContract({
29
+ service: 'checkout',
30
+ version: '1.2.0', // semver of the *contract*, not the app
31
+ commonAttributes: {
32
+ 'user.id': { type: 'string', highCardinality: true, description: 'Authenticated user' },
33
+ },
34
+ spans: {
35
+ 'checkout.charge': {
36
+ description: 'Charge a payment method',
37
+ attributes: {
38
+ 'payment.provider': { type: 'string', required: true, enum: ['stripe', 'paypal'] },
39
+ 'payment.amount_cents': { type: 'number', required: true },
40
+ },
41
+ },
42
+ },
43
+ });
44
+ ```
45
+
46
+ `defineContract()` validates structure (semver, attribute types, deprecations) when the module loads and freezes the result, so a malformed contract throws at startup rather than at runtime.
47
+
48
+ ## 2. Validate live spans
49
+
50
+ Add the span processor to your OpenTelemetry setup. It validates each ending span against the contract with bounded, deduplicated warnings. It is **fail-open**: a bug in validation cannot break your export. In production it stays off unless you opt in.
51
+
52
+ ```ts
53
+ import { createSchemaValidationProcessor } from 'autotel-schema/processor';
54
+ import { contract } from './telemetry.contract';
55
+
56
+ const processor = createSchemaValidationProcessor({
57
+ contract,
58
+ mode: 'warn', // 'warn' (default) | 'throw' (tests/CI) | 'silent' (collect via onViolation)
59
+ strictSpanNames: true, // also flag spans not in the contract
60
+ });
61
+ // register `processor` with your TracerProvider
62
+ ```
63
+
64
+ Or validate a span shape directly (e.g. in a unit test):
65
+
66
+ ```ts
67
+ import { validateSpan, hasErrors, formatViolation } from 'autotel-schema';
68
+
69
+ const violations = validateSpan(
70
+ { name: 'checkout.charge', attributes: { 'payment.provider': 'bitcoin' } },
71
+ contract,
72
+ );
73
+ // → [missing_required payment.amount_cents, enum_violation payment.provider]
74
+ if (hasErrors(violations)) violations.forEach((v) => console.error(formatViolation(v)));
75
+ ```
76
+
77
+ Violation codes: `missing_required`, `type_mismatch`, `enum_violation`, `unknown_attribute` (with a "did you mean?" suggestion via edit distance), and `unknown_span`.
78
+
79
+ ## 3. Gate breaking changes in CI
80
+
81
+ Snapshot the contract, commit the baseline, and diff it on every PR. A removed span or a tightened type is **breaking**; a new span or attribute is **additive**.
82
+
83
+ ```ts
84
+ import { contractToSnapshot, serializeSnapshot } from 'autotel-schema';
85
+ import { writeFileSync } from 'node:fs';
86
+ import { contract } from './telemetry.contract';
87
+
88
+ writeFileSync('telemetry.snapshot.json', serializeSnapshot(contractToSnapshot(contract)));
89
+ ```
90
+
91
+ Then in CI, with the bundled `autotel-schema` CLI:
92
+
93
+ ```bash
94
+ # regenerate the current snapshot, then:
95
+ autotel-schema check telemetry.baseline.json telemetry.current.json
96
+ # exits 1 with a markdown diff if any breaking change is found
97
+ autotel-schema diff telemetry.baseline.json telemetry.current.json --json
98
+ ```
99
+
100
+ Programmatically:
101
+
102
+ ```ts
103
+ import { diffSnapshots, hasBreakingChanges, formatDiff } from 'autotel-schema/diff';
104
+
105
+ const diff = diffSnapshots(baseline, current);
106
+ if (hasBreakingChanges(diff)) throw new Error(formatDiff(diff));
107
+ ```
108
+
109
+ ## 4. Protect high-cardinality keys from redaction
110
+
111
+ The old "keep cardinality down" rule exists because dashboards have pixels. An agent reads the spans rather than scanning a graph, and a high-cardinality field like a user id or request id is often the one attribute that pins down a single failure. Mark those `highCardinality: true` and feed them to your redactor as a **protect list**:
112
+
113
+ ```ts
114
+ import { init } from 'autotel';
115
+ import { highCardinalityKeys } from 'autotel-schema';
116
+ import { contract } from './telemetry.contract';
117
+
118
+ init({
119
+ service: 'checkout',
120
+ attributeRedactor: { allowKeys: highCardinalityKeys(contract), preset: 'strict' },
121
+ });
122
+ ```
123
+
124
+ ## What this is / isn't
125
+
126
+ - **Is**: a contract for your telemetry surface: span names, attribute keys, types, enums, stability, and breaking-vs-additive evolution.
127
+ - **Isn't**: a contract for application message payloads (use [`autotel-message-contract`](../autotel-message-contract)) or evidence that interactions ran (use [`autotel-pact`](../autotel-pact)). It does not require the OpenTelemetry SDK. The processor works against structural span types.
128
+
129
+ ## License
130
+
131
+ MIT © Jag Reehal
package/dist/cli.cjs ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env node
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
+ //#region \0rolldown/runtime.js
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
13
+ key = keys[i];
14
+ if (!__hasOwnProp.call(to, key) && key !== except) {
15
+ __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ }
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+
29
+ //#endregion
30
+ const require_snapshot = require('./snapshot-CyWGJaJT.cjs');
31
+ const require_diff = require('./diff.cjs');
32
+ let node_fs = require("node:fs");
33
+ let node_path = require("node:path");
34
+ node_path = __toESM(node_path, 1);
35
+
36
+ //#region src/cli.ts
37
+ /**
38
+ * autotel-schema CLI — the CI gate for your telemetry's public API.
39
+ *
40
+ * autotel-schema diff <baseline.json> <current.json> # classify changes
41
+ * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking
42
+ *
43
+ * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.
44
+ * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.
45
+ */
46
+ function parseArgs(argv) {
47
+ const positional = [];
48
+ let json = false;
49
+ for (const arg of argv) if (arg === "--json") json = true;
50
+ else if (arg === "-h" || arg === "--help") positional.unshift("help");
51
+ else positional.push(arg);
52
+ return {
53
+ command: positional[0],
54
+ baseline: positional[1],
55
+ current: positional[2],
56
+ json
57
+ };
58
+ }
59
+ const USAGE = `autotel-schema — treat your trace surface like a versioned public API
60
+
61
+ Usage:
62
+ autotel-schema diff <baseline.json> <current.json> [--json]
63
+ autotel-schema check <baseline.json> <current.json> [--json]
64
+
65
+ Commands:
66
+ diff Print every change (breaking / additive / neutral). Always exits 0.
67
+ check Like diff, but exits 1 if any breaking change is found (CI gate).
68
+
69
+ Snapshots are produced with serializeSnapshot(contractToSnapshot(contract)).`;
70
+ function loadDiff(baseline, current) {
71
+ return require_diff.diffSnapshots(require_snapshot.parseSnapshot((0, node_fs.readFileSync)(baseline, "utf8")), require_snapshot.parseSnapshot((0, node_fs.readFileSync)(current, "utf8")));
72
+ }
73
+ function emit(diff, json) {
74
+ if (json) console.log(JSON.stringify(diff, null, 2));
75
+ else console.log(require_diff.formatDiff(diff));
76
+ }
77
+ function run(argv) {
78
+ const { command, baseline, current, json } = parseArgs(argv);
79
+ if (!command || command === "help") {
80
+ console.log(USAGE);
81
+ return command ? 0 : 1;
82
+ }
83
+ if (command !== "diff" && command !== "check") {
84
+ console.error(`autotel-schema: unknown command "${command}"\n\n${USAGE}`);
85
+ return 1;
86
+ }
87
+ if (!baseline || !current) {
88
+ console.error("autotel-schema: both <baseline.json> and <current.json> are required\n");
89
+ console.error(USAGE);
90
+ return 1;
91
+ }
92
+ let diff;
93
+ try {
94
+ diff = loadDiff(baseline, current);
95
+ } catch (error) {
96
+ console.error(`autotel-schema: ${error instanceof Error ? error.message : String(error)}`);
97
+ return 1;
98
+ }
99
+ emit(diff, json);
100
+ if (command === "check" && require_diff.hasBreakingChanges(diff)) {
101
+ console.error(`\nautotel-schema: ${diff.breaking.length} breaking change(s) to the telemetry contract. Bump the contract major version and update the committed snapshot.`);
102
+ return 1;
103
+ }
104
+ return 0;
105
+ }
106
+ const entry = process.argv[1] ? node_path.default.basename(process.argv[1]) : "";
107
+ if (entry === "autotel-schema" || entry === "cli.js" || entry === "cli.cjs") process.exit(run(process.argv.slice(2)));
108
+
109
+ //#endregion
110
+ exports.run = run;
111
+ //# sourceMappingURL=cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.cjs","names":["diffSnapshots","parseSnapshot","formatDiff","hasBreakingChanges","path"],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * autotel-schema CLI — the CI gate for your telemetry's public API.\n *\n * autotel-schema diff <baseline.json> <current.json> # classify changes\n * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking\n *\n * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.\n * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.\n */\n\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { parseSnapshot } from './snapshot.js';\nimport {\n diffSnapshots,\n formatDiff,\n hasBreakingChanges,\n type SnapshotDiff,\n} from './diff.js';\n\ninterface Parsed {\n command: string | undefined;\n baseline: string | undefined;\n current: string | undefined;\n json: boolean;\n}\n\nfunction parseArgs(argv: string[]): Parsed {\n const positional: string[] = [];\n let json = false;\n for (const arg of argv) {\n if (arg === '--json') json = true;\n else if (arg === '-h' || arg === '--help') positional.unshift('help');\n else positional.push(arg);\n }\n return {\n command: positional[0],\n baseline: positional[1],\n current: positional[2],\n json,\n };\n}\n\nconst USAGE = `autotel-schema — treat your trace surface like a versioned public API\n\nUsage:\n autotel-schema diff <baseline.json> <current.json> [--json]\n autotel-schema check <baseline.json> <current.json> [--json]\n\nCommands:\n diff Print every change (breaking / additive / neutral). Always exits 0.\n check Like diff, but exits 1 if any breaking change is found (CI gate).\n\nSnapshots are produced with serializeSnapshot(contractToSnapshot(contract)).`;\n\nfunction loadDiff(baseline: string, current: string): SnapshotDiff {\n const prev = parseSnapshot(readFileSync(baseline, 'utf8'));\n const next = parseSnapshot(readFileSync(current, 'utf8'));\n return diffSnapshots(prev, next);\n}\n\nfunction emit(diff: SnapshotDiff, json: boolean): void {\n if (json) {\n console.log(JSON.stringify(diff, null, 2));\n } else {\n console.log(formatDiff(diff));\n }\n}\n\nexport function run(argv: string[]): number {\n const { command, baseline, current, json } = parseArgs(argv);\n\n if (!command || command === 'help') {\n console.log(USAGE);\n return command ? 0 : 1;\n }\n\n if (command !== 'diff' && command !== 'check') {\n console.error(`autotel-schema: unknown command \"${command}\"\\n\\n${USAGE}`);\n return 1;\n }\n\n if (!baseline || !current) {\n console.error('autotel-schema: both <baseline.json> and <current.json> are required\\n');\n console.error(USAGE);\n return 1;\n }\n\n let diff: SnapshotDiff;\n try {\n diff = loadDiff(baseline, current);\n } catch (error) {\n console.error(\n `autotel-schema: ${error instanceof Error ? error.message : String(error)}`,\n );\n return 1;\n }\n\n emit(diff, json);\n\n if (command === 'check' && hasBreakingChanges(diff)) {\n console.error(\n `\\nautotel-schema: ${diff.breaking.length} breaking change(s) to the telemetry contract. ` +\n `Bump the contract major version and update the committed snapshot.`,\n );\n return 1;\n }\n return 0;\n}\n\n// Only auto-run when invoked directly as the binary, not when imported in tests.\n// Match the basename so a repo path containing \"autotel-schema\" can't trigger it.\nconst entry = process.argv[1] ? path.basename(process.argv[1]) : '';\nif (entry === 'autotel-schema' || entry === 'cli.js' || entry === 'cli.cjs') {\n process.exit(run(process.argv.slice(2)));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAS,UAAU,MAAwB;CACzC,MAAM,aAAuB,CAAC;CAC9B,IAAI,OAAO;CACX,KAAK,MAAM,OAAO,MAChB,IAAI,QAAQ,UAAU,OAAO;MACxB,IAAI,QAAQ,QAAQ,QAAQ,UAAU,WAAW,QAAQ,MAAM;MAC/D,WAAW,KAAK,GAAG;CAE1B,OAAO;EACL,SAAS,WAAW;EACpB,UAAU,WAAW;EACrB,SAAS,WAAW;EACpB;CACF;AACF;AAEA,MAAM,QAAQ;;;;;;;;;;;AAYd,SAAS,SAAS,UAAkB,SAA+B;CAGjE,OAAOA,2BAFMC,yDAA2B,UAAU,MAAM,CAEhC,GADXA,yDAA2B,SAAS,MAAM,CACzB,CAAC;AACjC;AAEA,SAAS,KAAK,MAAoB,MAAqB;CACrD,IAAI,MACF,QAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;MAEzC,QAAQ,IAAIC,wBAAW,IAAI,CAAC;AAEhC;AAEA,SAAgB,IAAI,MAAwB;CAC1C,MAAM,EAAE,SAAS,UAAU,SAAS,SAAS,UAAU,IAAI;CAE3D,IAAI,CAAC,WAAW,YAAY,QAAQ;EAClC,QAAQ,IAAI,KAAK;EACjB,OAAO,UAAU,IAAI;CACvB;CAEA,IAAI,YAAY,UAAU,YAAY,SAAS;EAC7C,QAAQ,MAAM,oCAAoC,QAAQ,OAAO,OAAO;EACxE,OAAO;CACT;CAEA,IAAI,CAAC,YAAY,CAAC,SAAS;EACzB,QAAQ,MAAM,wEAAwE;EACtF,QAAQ,MAAM,KAAK;EACnB,OAAO;CACT;CAEA,IAAI;CACJ,IAAI;EACF,OAAO,SAAS,UAAU,OAAO;CACnC,SAAS,OAAO;EACd,QAAQ,MACN,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1E;EACA,OAAO;CACT;CAEA,KAAK,MAAM,IAAI;CAEf,IAAI,YAAY,WAAWC,gCAAmB,IAAI,GAAG;EACnD,QAAQ,MACN,qBAAqB,KAAK,SAAS,OAAO,kHAE5C;EACA,OAAO;CACT;CACA,OAAO;AACT;AAIA,MAAM,QAAQ,QAAQ,KAAK,KAAKC,kBAAK,SAAS,QAAQ,KAAK,EAAE,IAAI;AACjE,IAAI,UAAU,oBAAoB,UAAU,YAAY,UAAU,WAChE,QAAQ,KAAK,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC"}
package/dist/cli.d.cts ADDED
@@ -0,0 +1,14 @@
1
+ //#region src/cli.d.ts
2
+ /**
3
+ * autotel-schema CLI — the CI gate for your telemetry's public API.
4
+ *
5
+ * autotel-schema diff <baseline.json> <current.json> # classify changes
6
+ * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking
7
+ *
8
+ * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.
9
+ * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.
10
+ */
11
+ declare function run(argv: string[]): number;
12
+ //#endregion
13
+ export { run };
14
+ //# sourceMappingURL=cli.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.cts","names":[],"sources":["../src/cli.ts"],"mappings":";AAsEA;;;;AAAkC;;;;;AAAlC,iBAAgB,GAAA,CAAI,IAAc"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ //#region src/cli.d.ts
2
+ /**
3
+ * autotel-schema CLI — the CI gate for your telemetry's public API.
4
+ *
5
+ * autotel-schema diff <baseline.json> <current.json> # classify changes
6
+ * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking
7
+ *
8
+ * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.
9
+ * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.
10
+ */
11
+ declare function run(argv: string[]): number;
12
+ //#endregion
13
+ export { run };
14
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","names":[],"sources":["../src/cli.ts"],"mappings":";AAsEA;;;;AAAkC;;;;;AAAlC,iBAAgB,GAAA,CAAI,IAAc"}
package/dist/cli.js ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ import { n as parseSnapshot } from "./snapshot-h8pb_Up_.js";
3
+ import { diffSnapshots, formatDiff, hasBreakingChanges } from "./diff.js";
4
+ import { readFileSync } from "node:fs";
5
+ import path from "node:path";
6
+
7
+ //#region src/cli.ts
8
+ /**
9
+ * autotel-schema CLI — the CI gate for your telemetry's public API.
10
+ *
11
+ * autotel-schema diff <baseline.json> <current.json> # classify changes
12
+ * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking
13
+ *
14
+ * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.
15
+ * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.
16
+ */
17
+ function parseArgs(argv) {
18
+ const positional = [];
19
+ let json = false;
20
+ for (const arg of argv) if (arg === "--json") json = true;
21
+ else if (arg === "-h" || arg === "--help") positional.unshift("help");
22
+ else positional.push(arg);
23
+ return {
24
+ command: positional[0],
25
+ baseline: positional[1],
26
+ current: positional[2],
27
+ json
28
+ };
29
+ }
30
+ const USAGE = `autotel-schema — treat your trace surface like a versioned public API
31
+
32
+ Usage:
33
+ autotel-schema diff <baseline.json> <current.json> [--json]
34
+ autotel-schema check <baseline.json> <current.json> [--json]
35
+
36
+ Commands:
37
+ diff Print every change (breaking / additive / neutral). Always exits 0.
38
+ check Like diff, but exits 1 if any breaking change is found (CI gate).
39
+
40
+ Snapshots are produced with serializeSnapshot(contractToSnapshot(contract)).`;
41
+ function loadDiff(baseline, current) {
42
+ return diffSnapshots(parseSnapshot(readFileSync(baseline, "utf8")), parseSnapshot(readFileSync(current, "utf8")));
43
+ }
44
+ function emit(diff, json) {
45
+ if (json) console.log(JSON.stringify(diff, null, 2));
46
+ else console.log(formatDiff(diff));
47
+ }
48
+ function run(argv) {
49
+ const { command, baseline, current, json } = parseArgs(argv);
50
+ if (!command || command === "help") {
51
+ console.log(USAGE);
52
+ return command ? 0 : 1;
53
+ }
54
+ if (command !== "diff" && command !== "check") {
55
+ console.error(`autotel-schema: unknown command "${command}"\n\n${USAGE}`);
56
+ return 1;
57
+ }
58
+ if (!baseline || !current) {
59
+ console.error("autotel-schema: both <baseline.json> and <current.json> are required\n");
60
+ console.error(USAGE);
61
+ return 1;
62
+ }
63
+ let diff;
64
+ try {
65
+ diff = loadDiff(baseline, current);
66
+ } catch (error) {
67
+ console.error(`autotel-schema: ${error instanceof Error ? error.message : String(error)}`);
68
+ return 1;
69
+ }
70
+ emit(diff, json);
71
+ if (command === "check" && hasBreakingChanges(diff)) {
72
+ console.error(`\nautotel-schema: ${diff.breaking.length} breaking change(s) to the telemetry contract. Bump the contract major version and update the committed snapshot.`);
73
+ return 1;
74
+ }
75
+ return 0;
76
+ }
77
+ const entry = process.argv[1] ? path.basename(process.argv[1]) : "";
78
+ if (entry === "autotel-schema" || entry === "cli.js" || entry === "cli.cjs") process.exit(run(process.argv.slice(2)));
79
+
80
+ //#endregion
81
+ export { run };
82
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * autotel-schema CLI — the CI gate for your telemetry's public API.\n *\n * autotel-schema diff <baseline.json> <current.json> # classify changes\n * autotel-schema check <baseline.json> <current.json> # exit 1 on breaking\n *\n * Both operate on snapshot JSON produced by `serializeSnapshot(contractToSnapshot(contract))`.\n * Commit the baseline; regenerate `current` in CI; gate the merge on `check`.\n */\n\nimport { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { parseSnapshot } from './snapshot.js';\nimport {\n diffSnapshots,\n formatDiff,\n hasBreakingChanges,\n type SnapshotDiff,\n} from './diff.js';\n\ninterface Parsed {\n command: string | undefined;\n baseline: string | undefined;\n current: string | undefined;\n json: boolean;\n}\n\nfunction parseArgs(argv: string[]): Parsed {\n const positional: string[] = [];\n let json = false;\n for (const arg of argv) {\n if (arg === '--json') json = true;\n else if (arg === '-h' || arg === '--help') positional.unshift('help');\n else positional.push(arg);\n }\n return {\n command: positional[0],\n baseline: positional[1],\n current: positional[2],\n json,\n };\n}\n\nconst USAGE = `autotel-schema — treat your trace surface like a versioned public API\n\nUsage:\n autotel-schema diff <baseline.json> <current.json> [--json]\n autotel-schema check <baseline.json> <current.json> [--json]\n\nCommands:\n diff Print every change (breaking / additive / neutral). Always exits 0.\n check Like diff, but exits 1 if any breaking change is found (CI gate).\n\nSnapshots are produced with serializeSnapshot(contractToSnapshot(contract)).`;\n\nfunction loadDiff(baseline: string, current: string): SnapshotDiff {\n const prev = parseSnapshot(readFileSync(baseline, 'utf8'));\n const next = parseSnapshot(readFileSync(current, 'utf8'));\n return diffSnapshots(prev, next);\n}\n\nfunction emit(diff: SnapshotDiff, json: boolean): void {\n if (json) {\n console.log(JSON.stringify(diff, null, 2));\n } else {\n console.log(formatDiff(diff));\n }\n}\n\nexport function run(argv: string[]): number {\n const { command, baseline, current, json } = parseArgs(argv);\n\n if (!command || command === 'help') {\n console.log(USAGE);\n return command ? 0 : 1;\n }\n\n if (command !== 'diff' && command !== 'check') {\n console.error(`autotel-schema: unknown command \"${command}\"\\n\\n${USAGE}`);\n return 1;\n }\n\n if (!baseline || !current) {\n console.error('autotel-schema: both <baseline.json> and <current.json> are required\\n');\n console.error(USAGE);\n return 1;\n }\n\n let diff: SnapshotDiff;\n try {\n diff = loadDiff(baseline, current);\n } catch (error) {\n console.error(\n `autotel-schema: ${error instanceof Error ? error.message : String(error)}`,\n );\n return 1;\n }\n\n emit(diff, json);\n\n if (command === 'check' && hasBreakingChanges(diff)) {\n console.error(\n `\\nautotel-schema: ${diff.breaking.length} breaking change(s) to the telemetry contract. ` +\n `Bump the contract major version and update the committed snapshot.`,\n );\n return 1;\n }\n return 0;\n}\n\n// Only auto-run when invoked directly as the binary, not when imported in tests.\n// Match the basename so a repo path containing \"autotel-schema\" can't trigger it.\nconst entry = process.argv[1] ? path.basename(process.argv[1]) : '';\nif (entry === 'autotel-schema' || entry === 'cli.js' || entry === 'cli.cjs') {\n process.exit(run(process.argv.slice(2)));\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA4BA,SAAS,UAAU,MAAwB;CACzC,MAAM,aAAuB,CAAC;CAC9B,IAAI,OAAO;CACX,KAAK,MAAM,OAAO,MAChB,IAAI,QAAQ,UAAU,OAAO;MACxB,IAAI,QAAQ,QAAQ,QAAQ,UAAU,WAAW,QAAQ,MAAM;MAC/D,WAAW,KAAK,GAAG;CAE1B,OAAO;EACL,SAAS,WAAW;EACpB,UAAU,WAAW;EACrB,SAAS,WAAW;EACpB;CACF;AACF;AAEA,MAAM,QAAQ;;;;;;;;;;;AAYd,SAAS,SAAS,UAAkB,SAA+B;CAGjE,OAAO,cAFM,cAAc,aAAa,UAAU,MAAM,CAEhC,GADX,cAAc,aAAa,SAAS,MAAM,CACzB,CAAC;AACjC;AAEA,SAAS,KAAK,MAAoB,MAAqB;CACrD,IAAI,MACF,QAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;MAEzC,QAAQ,IAAI,WAAW,IAAI,CAAC;AAEhC;AAEA,SAAgB,IAAI,MAAwB;CAC1C,MAAM,EAAE,SAAS,UAAU,SAAS,SAAS,UAAU,IAAI;CAE3D,IAAI,CAAC,WAAW,YAAY,QAAQ;EAClC,QAAQ,IAAI,KAAK;EACjB,OAAO,UAAU,IAAI;CACvB;CAEA,IAAI,YAAY,UAAU,YAAY,SAAS;EAC7C,QAAQ,MAAM,oCAAoC,QAAQ,OAAO,OAAO;EACxE,OAAO;CACT;CAEA,IAAI,CAAC,YAAY,CAAC,SAAS;EACzB,QAAQ,MAAM,wEAAwE;EACtF,QAAQ,MAAM,KAAK;EACnB,OAAO;CACT;CAEA,IAAI;CACJ,IAAI;EACF,OAAO,SAAS,UAAU,OAAO;CACnC,SAAS,OAAO;EACd,QAAQ,MACN,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1E;EACA,OAAO;CACT;CAEA,KAAK,MAAM,IAAI;CAEf,IAAI,YAAY,WAAW,mBAAmB,IAAI,GAAG;EACnD,QAAQ,MACN,qBAAqB,KAAK,SAAS,OAAO,kHAE5C;EACA,OAAO;CACT;CACA,OAAO;AACT;AAIA,MAAM,QAAQ,QAAQ,KAAK,KAAK,KAAK,SAAS,QAAQ,KAAK,EAAE,IAAI;AACjE,IAAI,UAAU,oBAAoB,UAAU,YAAY,UAAU,WAChE,QAAQ,KAAK,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC"}
@@ -0,0 +1,123 @@
1
+ //#region src/contract.d.ts
2
+ /**
3
+ * Telemetry contract model.
4
+ *
5
+ * The premise: when the primary reader of your telemetry is an agent, your
6
+ * span names and attribute keys are a **public API**. Renaming `fast_path_hit`
7
+ * to `fast_path_taken` in a refactor PR silently breaks every prompt that
8
+ * mentions it — there is no compiler to catch it, because to the compiler these
9
+ * are just strings in a JSON blob.
10
+ *
11
+ * `defineContract()` makes that surface explicit, typed, and versionable: you
12
+ * declare which spans your service emits and which attributes live on them,
13
+ * then validate live spans against it ({@link ./validate}) and diff it across
14
+ * commits to catch breaking changes before they ship ({@link ./diff}).
15
+ *
16
+ * This module is dependency-free and side-effect-free by design — safe to
17
+ * import anywhere (browser, edge, CLI) without pulling in the OpenTelemetry SDK.
18
+ */
19
+ /** Scalar and array attribute types permitted on a span (OTLP value shapes). */
20
+ type AttributeType = 'string' | 'number' | 'boolean' | 'string[]' | 'number[]' | 'boolean[]';
21
+ declare const ATTRIBUTE_TYPES: readonly AttributeType[];
22
+ /**
23
+ * Lifecycle of a span or attribute, mirroring how the OpenTelemetry semantic
24
+ * conventions stage their own surface. `stable` is a promise to agent readers
25
+ * that the name will not change without a major contract bump.
26
+ */
27
+ type Stability = 'stable' | 'experimental' | 'deprecated';
28
+ declare const STABILITIES: readonly Stability[];
29
+ /** Declaration for a single attribute key on a span. */
30
+ interface AttributeSpec {
31
+ /** OTLP value shape. Validated at runtime against the emitted value. */
32
+ type: AttributeType;
33
+ /** Lifecycle stage. Defaults to `stable`. */
34
+ stability?: Stability;
35
+ /** When `true`, the attribute must be present on every matching span. */
36
+ required?: boolean;
37
+ /** Human/agent-facing description of what the attribute means. */
38
+ description?: string;
39
+ /**
40
+ * Marks an attribute as intentionally high-cardinality (user id, sender
41
+ * domain, request id). For an agent reader these are the single most useful
42
+ * fields on a trace, so {@link ./redaction.highCardinalityKeys} surfaces them
43
+ * as a *protect* list — telling redactors/normalizers NOT to strip them.
44
+ */
45
+ highCardinality?: boolean;
46
+ /** Closed set of permitted values. Reported as `enum_violation` if exceeded. */
47
+ enum?: readonly (string | number)[];
48
+ /** Set when `stability: 'deprecated'`; explains what to use instead. */
49
+ replacedBy?: string;
50
+ /** Free-text note shown alongside deprecation warnings. */
51
+ deprecatedReason?: string;
52
+ }
53
+ /** Declaration for a single span name your service emits. */
54
+ interface SpanSpec {
55
+ /** Human/agent-facing description of when this span is produced. */
56
+ description?: string;
57
+ /** Lifecycle stage. Defaults to `stable`. */
58
+ stability?: Stability;
59
+ /** Attributes specific to this span, keyed by attribute name. */
60
+ attributes?: Record<string, AttributeSpec>;
61
+ /**
62
+ * When `true`, attributes not declared here are allowed without an
63
+ * `unknown_attribute` violation. Defaults to the contract-level setting.
64
+ */
65
+ additionalAttributes?: boolean;
66
+ }
67
+ /** The full telemetry contract for one service. */
68
+ interface TelemetryContract {
69
+ /** `service.name` this contract describes. */
70
+ service: string;
71
+ /**
72
+ * Semver of the *contract itself* (not the app). Bumped when the trace
73
+ * surface changes; surfaced to readers as the `telemetry.schema.version`
74
+ * resource attribute via {@link ./attrs.SCHEMA_ATTRS}.
75
+ */
76
+ version: string;
77
+ /** Spans this service emits, keyed by span name. */
78
+ spans: Record<string, SpanSpec>;
79
+ /** Attributes permitted on *any* span (e.g. `user.id`, `tenant.id`). */
80
+ commonAttributes?: Record<string, AttributeSpec>;
81
+ /**
82
+ * Default for `SpanSpec.additionalAttributes` when a span does not set it.
83
+ * Defaults to `false` (declared-only — the stricter, agent-friendlier mode).
84
+ */
85
+ additionalAttributes?: boolean;
86
+ }
87
+ /**
88
+ * Validate and freeze a telemetry contract. Throws on structural mistakes
89
+ * (bad semver, unknown attribute type, deprecation with no replacement) so the
90
+ * contract fails loudly at module load, not silently at runtime.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * export const contract = defineContract({
95
+ * service: 'checkout',
96
+ * version: '1.2.0',
97
+ * commonAttributes: {
98
+ * 'user.id': { type: 'string', highCardinality: true, description: 'Authenticated user' },
99
+ * },
100
+ * spans: {
101
+ * 'checkout.charge': {
102
+ * description: 'Charge a payment method',
103
+ * attributes: {
104
+ * 'payment.provider': { type: 'string', required: true, enum: ['stripe', 'paypal'] },
105
+ * 'payment.amount_cents': { type: 'number', required: true },
106
+ * },
107
+ * },
108
+ * },
109
+ * });
110
+ * ```
111
+ */
112
+ declare function defineContract(contract: TelemetryContract): TelemetryContract;
113
+ /**
114
+ * Resolve the effective attribute spec for `key` on `spanName`: span-specific
115
+ * attributes win over common attributes. Returns `undefined` when the key is
116
+ * declared nowhere.
117
+ */
118
+ declare function resolveAttributeSpec(contract: TelemetryContract, spanName: string, key: string): AttributeSpec | undefined;
119
+ /** Whether attributes outside the declared set are tolerated for a span. */
120
+ declare function allowsAdditionalAttributes(contract: TelemetryContract, spanName: string): boolean;
121
+ //#endregion
122
+ export { SpanSpec as a, allowsAdditionalAttributes as c, STABILITIES as i, defineContract as l, AttributeSpec as n, Stability as o, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u };
123
+ //# sourceMappingURL=contract-DGjxR9nb.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-DGjxR9nb.d.cts","names":[],"sources":["../src/contract.ts"],"mappings":";;AAmBA;;;;AAAyB;AAQzB;;;;AAAoD;AAcpD;;;;AAAqB;AAErB;;KAxBY,aAAA;AAAA,cAQC,eAAA,WAA0B,aAAa;AAgBR;AAO5C;;;;AAP4C,KAFhC,SAAA;AAAA,cAEC,WAAA,WAAsB,SAAS;;UAO3B,aAAA;EAMf;EAJA,IAAA,EAAM,aAAA;EAaN;EAXA,SAAA,GAAY,SAAS;EAerB;EAbA,QAAA;EAegB;EAbhB,WAAA;EAiBe;;;;;;EAVf,eAAA;EAgBmB;EAdnB,IAAA;EAYA;EAVA,UAAA;EAYA;EAVA,gBAAA;AAAA;;UAIe,QAAA;EAWK;EATpB,WAAA;EAagC;EAXhC,SAAA,GAAY,SAAA;EAqBU;EAnBtB,UAAA,GAAa,MAAA,SAAe,aAAA;EAqBM;;;;EAhBlC,oBAAA;AAAA;;UAIe,iBAAA;EAUO;EARtB,OAAA;EAUmB;;;;AAKC;EATpB,OAAA;EA0E4B;EAxE5B,KAAA,EAAO,MAAA,SAAe,QAAA;EAwEsD;EAtE5E,gBAAA,GAAmB,MAAA,SAAe,aAAA;EAsEL;;;AAA+C;EAjE5E,oBAAA;AAAA;;;;;;;;;AA0Gc;AAQhB;;;;;;;;AAEkB;;;;;;;;iBAnDF,cAAA,CAAe,QAAA,EAAU,iBAAA,GAAoB,iBAAiB;;;;;;iBAqC9D,oBAAA,CACd,QAAA,EAAU,iBAAA,EACV,QAAA,UACA,GAAA,WACC,aAAa;;iBAQA,0BAAA,CACd,QAAA,EAAU,iBAAiB,EAC3B,QAAA"}
@@ -0,0 +1,123 @@
1
+ //#region src/contract.d.ts
2
+ /**
3
+ * Telemetry contract model.
4
+ *
5
+ * The premise: when the primary reader of your telemetry is an agent, your
6
+ * span names and attribute keys are a **public API**. Renaming `fast_path_hit`
7
+ * to `fast_path_taken` in a refactor PR silently breaks every prompt that
8
+ * mentions it — there is no compiler to catch it, because to the compiler these
9
+ * are just strings in a JSON blob.
10
+ *
11
+ * `defineContract()` makes that surface explicit, typed, and versionable: you
12
+ * declare which spans your service emits and which attributes live on them,
13
+ * then validate live spans against it ({@link ./validate}) and diff it across
14
+ * commits to catch breaking changes before they ship ({@link ./diff}).
15
+ *
16
+ * This module is dependency-free and side-effect-free by design — safe to
17
+ * import anywhere (browser, edge, CLI) without pulling in the OpenTelemetry SDK.
18
+ */
19
+ /** Scalar and array attribute types permitted on a span (OTLP value shapes). */
20
+ type AttributeType = 'string' | 'number' | 'boolean' | 'string[]' | 'number[]' | 'boolean[]';
21
+ declare const ATTRIBUTE_TYPES: readonly AttributeType[];
22
+ /**
23
+ * Lifecycle of a span or attribute, mirroring how the OpenTelemetry semantic
24
+ * conventions stage their own surface. `stable` is a promise to agent readers
25
+ * that the name will not change without a major contract bump.
26
+ */
27
+ type Stability = 'stable' | 'experimental' | 'deprecated';
28
+ declare const STABILITIES: readonly Stability[];
29
+ /** Declaration for a single attribute key on a span. */
30
+ interface AttributeSpec {
31
+ /** OTLP value shape. Validated at runtime against the emitted value. */
32
+ type: AttributeType;
33
+ /** Lifecycle stage. Defaults to `stable`. */
34
+ stability?: Stability;
35
+ /** When `true`, the attribute must be present on every matching span. */
36
+ required?: boolean;
37
+ /** Human/agent-facing description of what the attribute means. */
38
+ description?: string;
39
+ /**
40
+ * Marks an attribute as intentionally high-cardinality (user id, sender
41
+ * domain, request id). For an agent reader these are the single most useful
42
+ * fields on a trace, so {@link ./redaction.highCardinalityKeys} surfaces them
43
+ * as a *protect* list — telling redactors/normalizers NOT to strip them.
44
+ */
45
+ highCardinality?: boolean;
46
+ /** Closed set of permitted values. Reported as `enum_violation` if exceeded. */
47
+ enum?: readonly (string | number)[];
48
+ /** Set when `stability: 'deprecated'`; explains what to use instead. */
49
+ replacedBy?: string;
50
+ /** Free-text note shown alongside deprecation warnings. */
51
+ deprecatedReason?: string;
52
+ }
53
+ /** Declaration for a single span name your service emits. */
54
+ interface SpanSpec {
55
+ /** Human/agent-facing description of when this span is produced. */
56
+ description?: string;
57
+ /** Lifecycle stage. Defaults to `stable`. */
58
+ stability?: Stability;
59
+ /** Attributes specific to this span, keyed by attribute name. */
60
+ attributes?: Record<string, AttributeSpec>;
61
+ /**
62
+ * When `true`, attributes not declared here are allowed without an
63
+ * `unknown_attribute` violation. Defaults to the contract-level setting.
64
+ */
65
+ additionalAttributes?: boolean;
66
+ }
67
+ /** The full telemetry contract for one service. */
68
+ interface TelemetryContract {
69
+ /** `service.name` this contract describes. */
70
+ service: string;
71
+ /**
72
+ * Semver of the *contract itself* (not the app). Bumped when the trace
73
+ * surface changes; surfaced to readers as the `telemetry.schema.version`
74
+ * resource attribute via {@link ./attrs.SCHEMA_ATTRS}.
75
+ */
76
+ version: string;
77
+ /** Spans this service emits, keyed by span name. */
78
+ spans: Record<string, SpanSpec>;
79
+ /** Attributes permitted on *any* span (e.g. `user.id`, `tenant.id`). */
80
+ commonAttributes?: Record<string, AttributeSpec>;
81
+ /**
82
+ * Default for `SpanSpec.additionalAttributes` when a span does not set it.
83
+ * Defaults to `false` (declared-only — the stricter, agent-friendlier mode).
84
+ */
85
+ additionalAttributes?: boolean;
86
+ }
87
+ /**
88
+ * Validate and freeze a telemetry contract. Throws on structural mistakes
89
+ * (bad semver, unknown attribute type, deprecation with no replacement) so the
90
+ * contract fails loudly at module load, not silently at runtime.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * export const contract = defineContract({
95
+ * service: 'checkout',
96
+ * version: '1.2.0',
97
+ * commonAttributes: {
98
+ * 'user.id': { type: 'string', highCardinality: true, description: 'Authenticated user' },
99
+ * },
100
+ * spans: {
101
+ * 'checkout.charge': {
102
+ * description: 'Charge a payment method',
103
+ * attributes: {
104
+ * 'payment.provider': { type: 'string', required: true, enum: ['stripe', 'paypal'] },
105
+ * 'payment.amount_cents': { type: 'number', required: true },
106
+ * },
107
+ * },
108
+ * },
109
+ * });
110
+ * ```
111
+ */
112
+ declare function defineContract(contract: TelemetryContract): TelemetryContract;
113
+ /**
114
+ * Resolve the effective attribute spec for `key` on `spanName`: span-specific
115
+ * attributes win over common attributes. Returns `undefined` when the key is
116
+ * declared nowhere.
117
+ */
118
+ declare function resolveAttributeSpec(contract: TelemetryContract, spanName: string, key: string): AttributeSpec | undefined;
119
+ /** Whether attributes outside the declared set are tolerated for a span. */
120
+ declare function allowsAdditionalAttributes(contract: TelemetryContract, spanName: string): boolean;
121
+ //#endregion
122
+ export { SpanSpec as a, allowsAdditionalAttributes as c, STABILITIES as i, defineContract as l, AttributeSpec as n, Stability as o, AttributeType as r, TelemetryContract as s, ATTRIBUTE_TYPES as t, resolveAttributeSpec as u };
123
+ //# sourceMappingURL=contract-DGjxR9nb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-DGjxR9nb.d.ts","names":[],"sources":["../src/contract.ts"],"mappings":";;AAmBA;;;;AAAyB;AAQzB;;;;AAAoD;AAcpD;;;;AAAqB;AAErB;;KAxBY,aAAA;AAAA,cAQC,eAAA,WAA0B,aAAa;AAgBR;AAO5C;;;;AAP4C,KAFhC,SAAA;AAAA,cAEC,WAAA,WAAsB,SAAS;;UAO3B,aAAA;EAMf;EAJA,IAAA,EAAM,aAAA;EAaN;EAXA,SAAA,GAAY,SAAS;EAerB;EAbA,QAAA;EAegB;EAbhB,WAAA;EAiBe;;;;;;EAVf,eAAA;EAgBmB;EAdnB,IAAA;EAYA;EAVA,UAAA;EAYA;EAVA,gBAAA;AAAA;;UAIe,QAAA;EAWK;EATpB,WAAA;EAagC;EAXhC,SAAA,GAAY,SAAA;EAqBU;EAnBtB,UAAA,GAAa,MAAA,SAAe,aAAA;EAqBM;;;;EAhBlC,oBAAA;AAAA;;UAIe,iBAAA;EAUO;EARtB,OAAA;EAUmB;;;;AAKC;EATpB,OAAA;EA0E4B;EAxE5B,KAAA,EAAO,MAAA,SAAe,QAAA;EAwEsD;EAtE5E,gBAAA,GAAmB,MAAA,SAAe,aAAA;EAsEL;;;AAA+C;EAjE5E,oBAAA;AAAA;;;;;;;;;AA0Gc;AAQhB;;;;;;;;AAEkB;;;;;;;;iBAnDF,cAAA,CAAe,QAAA,EAAU,iBAAA,GAAoB,iBAAiB;;;;;;iBAqC9D,oBAAA,CACd,QAAA,EAAU,iBAAA,EACV,QAAA,UACA,GAAA,WACC,aAAa;;iBAQA,0BAAA,CACd,QAAA,EAAU,iBAAiB,EAC3B,QAAA"}