@gitsheets/core-napi 0.2.0 → 0.4.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/binding.cjs +21 -0
- package/index.d.ts +100 -0
- package/index.js +7 -1
- package/package.json +8 -8
package/binding.cjs
CHANGED
|
@@ -70,6 +70,15 @@ class NotFoundError extends GitsheetsError {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
class ContractError extends GitsheetsError {
|
|
74
|
+
constructor(message, opts = {}) {
|
|
75
|
+
super(message, opts);
|
|
76
|
+
this.name = 'ContractError';
|
|
77
|
+
if (opts.contract !== undefined) this.contract = opts.contract;
|
|
78
|
+
if (opts.issues !== undefined) this.issues = opts.issues;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
const CLASS_BY_NAME = {
|
|
74
83
|
ConfigError,
|
|
75
84
|
ValidationError,
|
|
@@ -78,6 +87,7 @@ const CLASS_BY_NAME = {
|
|
|
78
87
|
RefError,
|
|
79
88
|
PathTemplateError,
|
|
80
89
|
NotFoundError,
|
|
90
|
+
ContractError,
|
|
81
91
|
};
|
|
82
92
|
|
|
83
93
|
// Map a structured error raised by the addon onto its typed class. The mapping
|
|
@@ -87,6 +97,7 @@ function mapCoreError(raw) {
|
|
|
87
97
|
const opts = { code: raw.code, status: raw.status, cause: raw };
|
|
88
98
|
if (raw.issues !== undefined) opts.issues = raw.issues;
|
|
89
99
|
if (raw.conflictingPaths !== undefined) opts.conflictingPaths = raw.conflictingPaths;
|
|
100
|
+
if (raw.contract !== undefined) opts.contract = raw.contract;
|
|
90
101
|
return new Cls(raw.message, opts);
|
|
91
102
|
}
|
|
92
103
|
|
|
@@ -113,6 +124,10 @@ module.exports = {
|
|
|
113
124
|
// PathTemplateError; schema compilation raises a typed ConfigError.
|
|
114
125
|
renderPathsBatch: wrap(addon.renderPathsBatch),
|
|
115
126
|
validateBatch: wrap(addon.validateBatch),
|
|
127
|
+
// The contract identity primitive (specs/behaviors/contracts.md "Canonical
|
|
128
|
+
// form" / "Contract identity"): canonicalize → SHA-256 hex. A string input
|
|
129
|
+
// with no/invalid `format` raises a typed ConfigError.
|
|
130
|
+
canonicalContractHash: wrap(addon.canonicalContractHash),
|
|
116
131
|
runComparator: wrap(addon.runComparator),
|
|
117
132
|
// Native locale array sort (declarative `sort = true`) — the ICU collator
|
|
118
133
|
// matching V8 `localeCompare`. Pure (no structured errors), so unwrapped.
|
|
@@ -152,6 +167,11 @@ module.exports = {
|
|
|
152
167
|
CoreTransaction: addon.CoreTransaction,
|
|
153
168
|
coreDiscoverSheets: wrap(addon.coreDiscoverSheets),
|
|
154
169
|
coreCheckValidators: wrap(addon.coreCheckValidators),
|
|
170
|
+
// Consumer-side contract verification — the two-rung ladder behind
|
|
171
|
+
// `openSheet(name, { contract })` (specs/behaviors/contracts.md "Consumer
|
|
172
|
+
// verification"). A verification failure raises a typed
|
|
173
|
+
// ContractError(contract_unsatisfied) carrying the conformance report.
|
|
174
|
+
verifySheetContract: wrap(addon.verifySheetContract),
|
|
155
175
|
// Markdown / mdx content-type codec. serialize/parse can raise a typed
|
|
156
176
|
// ValidationError/ConfigError; the H1 + normalize helpers are pure. Body
|
|
157
177
|
// NORMALIZATION is native — `markdownSerialize` runs the embedded
|
|
@@ -175,4 +195,5 @@ module.exports = {
|
|
|
175
195
|
RefError,
|
|
176
196
|
PathTemplateError,
|
|
177
197
|
NotFoundError,
|
|
198
|
+
ContractError,
|
|
178
199
|
};
|
package/index.d.ts
CHANGED
|
@@ -33,6 +33,17 @@ export interface JsValidationIssue {
|
|
|
33
33
|
source: string
|
|
34
34
|
schemaPath?: string
|
|
35
35
|
code?: string
|
|
36
|
+
/**
|
|
37
|
+
* The contract name, when the failing branch is a declared contract
|
|
38
|
+
* composed via `allOf` (specs/behaviors/contracts.md).
|
|
39
|
+
*/
|
|
40
|
+
contract?: string
|
|
41
|
+
/**
|
|
42
|
+
* The record's sheet-relative path, in a multi-record conformance
|
|
43
|
+
* report (`ContractError.issues` from consumer-side contract
|
|
44
|
+
* verification — specs/behaviors/contracts.md "Consumer verification").
|
|
45
|
+
*/
|
|
46
|
+
record?: string
|
|
36
47
|
}
|
|
37
48
|
/**
|
|
38
49
|
* Render a path template against a **batch** of records, returning one path per
|
|
@@ -53,6 +64,87 @@ export declare function renderPathsBatch(template: string, records: Array<JsValu
|
|
|
53
64
|
* compile surfaces as a structured, typed `ConfigError` (`config_invalid`).
|
|
54
65
|
*/
|
|
55
66
|
export declare function validateBatch(schema: JsValue, records: Array<JsValue>): Array<Array<JsValidationIssue>>
|
|
67
|
+
/**
|
|
68
|
+
* The contract identity primitive (specs/behaviors/contracts.md "Canonical
|
|
69
|
+
* form" / "Contract identity"): canonicalize `input` → SHA-256 hex of the
|
|
70
|
+
* canonical TOML bytes. `input` is either already-parsed data (a JS
|
|
71
|
+
* object/array/etc.) or a string, in which case `format` says how to parse
|
|
72
|
+
* it (`"json"` or `"toml"` — required for a string input; a
|
|
73
|
+
* `ConfigError(config_invalid)` names the omission). The minimal JS surface
|
|
74
|
+
* over [`gitsheets_core::contract::canonical_contract_hash`].
|
|
75
|
+
*/
|
|
76
|
+
export declare function canonicalContractHash(input: string | JsValue, format?: string | undefined | null): string
|
|
77
|
+
/**
|
|
78
|
+
* Validate a contract name (`specs/behaviors/contracts.md` "Contract names
|
|
79
|
+
* and the derived path") — the same check a sheet's `implements` entries run
|
|
80
|
+
* through at sheet-open. `contracts adopt` runs it on the name derived from a
|
|
81
|
+
* candidate document's `$id` before vendoring. Throws
|
|
82
|
+
* `ConfigError(config_invalid)` naming the violated rule.
|
|
83
|
+
*/
|
|
84
|
+
export declare function validateContractName(name: string): void
|
|
85
|
+
/**
|
|
86
|
+
* The derived vendored path for a contract name — mechanical, no manifest:
|
|
87
|
+
* `.gitsheets/contracts/<name>.toml`. The minimal JS surface over
|
|
88
|
+
* [`gitsheets_core::contract_path`].
|
|
89
|
+
*/
|
|
90
|
+
export declare function contractPath(name: string): string
|
|
91
|
+
/**
|
|
92
|
+
* Enforce the contract document requirements
|
|
93
|
+
* (`specs/behaviors/contracts.md` "Contract document requirements") against a
|
|
94
|
+
* NOT-yet-vendored candidate document — `contracts adopt`'s pre-vendor gate.
|
|
95
|
+
*
|
|
96
|
+
* `input` is either already-parsed data (a JS object) or a string, in which
|
|
97
|
+
* case `format` says how to parse it — mirrors `canonicalContractHash`'s
|
|
98
|
+
* shape exactly, for the same reason: a **JSON-text** input is parsed with
|
|
99
|
+
* `serde_json::from_str` directly (preserving a literal JSON `null`),
|
|
100
|
+
* deliberately NOT via the `JsValue`/core-`Value` marshalling boundary,
|
|
101
|
+
* which silently *drops* null-valued keys per the type-fidelity rules at the
|
|
102
|
+
* top of this file. Requirement 4 (no null-bearing keywords — `default:
|
|
103
|
+
* null`, `const: null`, a null in `enum`) can only ever be violated by a
|
|
104
|
+
* JSON-sourced document (TOML has no null literal at all), so routing
|
|
105
|
+
* through the null-dropping path would make that check silently unreachable
|
|
106
|
+
* for exactly the input shape it exists to catch. A TOML-text or
|
|
107
|
+
* already-parsed-data input has no such hazard (nothing they carry can be a
|
|
108
|
+
* TOML/core `Value` null in the first place), so those still go through the
|
|
109
|
+
* shared `value_to_json` conversion.
|
|
110
|
+
* Throws `ContractError(contract_invalid)` naming the violated rule.
|
|
111
|
+
*/
|
|
112
|
+
export declare function checkContractDocument(name: string, input: string | JsValue, format?: string | undefined | null): void
|
|
113
|
+
/**
|
|
114
|
+
* Load a vendored contract document `name` from the committed tree at
|
|
115
|
+
* `treeRef` (scoped under `openRoot`), returning it as JSON text on success.
|
|
116
|
+
* The minimal JS surface over [`gitsheets_core::contract::load_contract`] —
|
|
117
|
+
* runs the exact compile-time check (byte-canonical, document requirements,
|
|
118
|
+
* `$id`↔path) `Sheet::open` composition relies on, so `contracts verify` /
|
|
119
|
+
* `contracts adopt --sheet` get the identical guarantee. Throws
|
|
120
|
+
* `ContractError('contract_missing' | 'contract_invalid')` on failure.
|
|
121
|
+
*/
|
|
122
|
+
export declare function contractLoad(gitDir: string, treeRef: string, openRoot: string, name: string): string
|
|
123
|
+
/**
|
|
124
|
+
* The result of a successful [`verify_sheet_contract`] call — the wire shape
|
|
125
|
+
* for `sheet.contractVerification` minus `tree` (the JS binding attaches that
|
|
126
|
+
* from the read snapshot it already resolved to open the sheet).
|
|
127
|
+
*/
|
|
128
|
+
export interface JsConformanceReport {
|
|
129
|
+
name: string
|
|
130
|
+
/** `"declared"` or `"structural"` — which rung passed. */
|
|
131
|
+
rung: string
|
|
132
|
+
conforming: boolean
|
|
133
|
+
issues: Array<JsValidationIssue>
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Consumer-side contract verification — the two-rung ladder behind
|
|
137
|
+
* `openSheet(name, { contract })` (specs/behaviors/contracts.md "Consumer
|
|
138
|
+
* verification", specs/api/repository.md `opts.contract`). Opens `sheetName`
|
|
139
|
+
* read-only against `treeRef` (config read + effective-schema compile, same
|
|
140
|
+
* as any other read), then verifies it against `schema` — parsed data, or
|
|
141
|
+
* text with `format` naming which text form (mirrors
|
|
142
|
+
* `canonicalContractHash`'s input handling: no format auto-detection). A
|
|
143
|
+
* verification failure (both rungs missed, or the attempted rung missed in
|
|
144
|
+
* `declared`/`structural` mode) surfaces as `ContractError(contract_unsatisfied)`
|
|
145
|
+
* carrying the conformance report in `issues`.
|
|
146
|
+
*/
|
|
147
|
+
export declare function verifySheetContract(gitDir: string, treeRef: string, sheetName: string, configPath: string, openRoot: string, prefix: string, schema: string | JsValue, format?: string | undefined | null, mode?: string | undefined | null): JsConformanceReport
|
|
56
148
|
/**
|
|
57
149
|
* Compile a raw-JS sort comparator (`rule`, the body of `(a, b) => { … }`) and
|
|
58
150
|
* run it once against `a`/`b`, returning its numeric result. The direct
|
|
@@ -384,6 +476,14 @@ export declare class CoreTransaction {
|
|
|
384
476
|
* else. `path` is repo-root-relative. Returns the written blob hash.
|
|
385
477
|
*/
|
|
386
478
|
writeFile(path: string, content: string): string
|
|
479
|
+
/**
|
|
480
|
+
* Delete a raw file at `path` (repo-root-relative) in this transaction's
|
|
481
|
+
* private tree *(mutating)* — `write_file`'s inverse. Returns whether a
|
|
482
|
+
* blob existed at `path` before the delete. Used by `contracts prune` to
|
|
483
|
+
* remove undeclared vendored contract documents; deep (slash-separated)
|
|
484
|
+
* paths are supported directly via `MutableTree::delete_child_deep`.
|
|
485
|
+
*/
|
|
486
|
+
deleteFile(path: string): boolean
|
|
387
487
|
/**
|
|
388
488
|
* The blob-hash map of a record's attachments (`name → hash`, sorted by
|
|
389
489
|
* name), or `null` when the record has no attachment directory. Read-only.
|
package/index.js
CHANGED
|
@@ -310,13 +310,19 @@ if (!nativeBinding) {
|
|
|
310
310
|
throw new Error(`Failed to load native binding`)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
const { roundtrip, parseRecords, serializeRecords, renderPathsBatch, validateBatch, runComparator, collatorSort, CompiledDefinition, recordRead, recordWrite, recordDelete, recordList, writeBlob, substrateStats, substrateReset, recordQuery, recordQueryCandidates, templateFieldNames, recordIndexUnique, recordIndexMulti, createPatch, applyMergePatch, diffRecords, simulateCoreError, CoreTransaction, coreDiscoverSheets, coreCheckValidators, markdownSerialize, markdownNormalizeBody, markdownParse, markdownParseHeaderOnly, markdownExtractH1, markdownRewriteH1 } = nativeBinding
|
|
313
|
+
const { roundtrip, parseRecords, serializeRecords, renderPathsBatch, validateBatch, canonicalContractHash, validateContractName, contractPath, checkContractDocument, contractLoad, verifySheetContract, runComparator, collatorSort, CompiledDefinition, recordRead, recordWrite, recordDelete, recordList, writeBlob, substrateStats, substrateReset, recordQuery, recordQueryCandidates, templateFieldNames, recordIndexUnique, recordIndexMulti, createPatch, applyMergePatch, diffRecords, simulateCoreError, CoreTransaction, coreDiscoverSheets, coreCheckValidators, markdownSerialize, markdownNormalizeBody, markdownParse, markdownParseHeaderOnly, markdownExtractH1, markdownRewriteH1 } = nativeBinding
|
|
314
314
|
|
|
315
315
|
module.exports.roundtrip = roundtrip
|
|
316
316
|
module.exports.parseRecords = parseRecords
|
|
317
317
|
module.exports.serializeRecords = serializeRecords
|
|
318
318
|
module.exports.renderPathsBatch = renderPathsBatch
|
|
319
319
|
module.exports.validateBatch = validateBatch
|
|
320
|
+
module.exports.canonicalContractHash = canonicalContractHash
|
|
321
|
+
module.exports.validateContractName = validateContractName
|
|
322
|
+
module.exports.contractPath = contractPath
|
|
323
|
+
module.exports.checkContractDocument = checkContractDocument
|
|
324
|
+
module.exports.contractLoad = contractLoad
|
|
325
|
+
module.exports.verifySheetContract = verifySheetContract
|
|
320
326
|
module.exports.runComparator = runComparator
|
|
321
327
|
module.exports.collatorSort = collatorSort
|
|
322
328
|
module.exports.CompiledDefinition = CompiledDefinition
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitsheets/core-napi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Node.js native binding for gitsheets-core — the FFI marshalling boundary.",
|
|
5
5
|
"main": "binding.cjs",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
"index.d.ts"
|
|
34
34
|
],
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@gitsheets/core-napi-linux-x64-gnu": "0.
|
|
37
|
-
"@gitsheets/core-napi-linux-arm64-gnu": "0.
|
|
38
|
-
"@gitsheets/core-napi-linux-x64-musl": "0.
|
|
39
|
-
"@gitsheets/core-napi-darwin-arm64": "0.
|
|
40
|
-
"@gitsheets/core-napi-darwin-x64": "0.
|
|
41
|
-
"@gitsheets/core-napi-win32-x64-msvc": "0.
|
|
36
|
+
"@gitsheets/core-napi-linux-x64-gnu": "0.4.0",
|
|
37
|
+
"@gitsheets/core-napi-linux-arm64-gnu": "0.4.0",
|
|
38
|
+
"@gitsheets/core-napi-linux-x64-musl": "0.4.0",
|
|
39
|
+
"@gitsheets/core-napi-darwin-arm64": "0.4.0",
|
|
40
|
+
"@gitsheets/core-napi-darwin-x64": "0.4.0",
|
|
41
|
+
"@gitsheets/core-napi-win32-x64-msvc": "0.4.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"artifacts": "napi artifacts",
|
|
45
45
|
"build": "napi build --platform --release",
|
|
46
46
|
"build:debug": "napi build --platform",
|
|
47
47
|
"prepublishOnly": "napi prepublish -t npm --skip-gh-release",
|
|
48
|
-
"test": "node --test test/roundtrip.mjs test/errors.mjs test/canonical.mjs test/path-template.mjs test/validation-parity.mjs test/engine-parity.mjs test/collator-parity.mjs test/record-crud.mjs test/record-query.mjs test/record-index.mjs test/sheet-store.mjs test/sheet-markdown.mjs test/sheet-attachments.mjs",
|
|
48
|
+
"test": "node --test test/roundtrip.mjs test/errors.mjs test/canonical.mjs test/path-template.mjs test/validation-parity.mjs test/engine-parity.mjs test/collator-parity.mjs test/record-crud.mjs test/record-query.mjs test/record-index.mjs test/sheet-store.mjs test/sheet-markdown.mjs test/sheet-attachments.mjs test/contracts.mjs",
|
|
49
49
|
"bench": "node bench/query-bench.mjs",
|
|
50
50
|
"version": "napi version"
|
|
51
51
|
},
|