@gitsheets/core-napi 0.7.0 → 0.9.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 CHANGED
@@ -79,6 +79,16 @@ class ContractError extends GitsheetsError {
79
79
  }
80
80
  }
81
81
 
82
+ class AggregationError extends GitsheetsError {
83
+ constructor(message, opts = {}) {
84
+ super(message, opts);
85
+ this.name = 'AggregationError';
86
+ if (opts.sheet !== undefined) this.sheet = opts.sheet;
87
+ if (opts.aggregate !== undefined) this.aggregate = opts.aggregate;
88
+ if (opts.partition !== undefined) this.partition = opts.partition;
89
+ }
90
+ }
91
+
82
92
  const CLASS_BY_NAME = {
83
93
  ConfigError,
84
94
  ValidationError,
@@ -88,6 +98,7 @@ const CLASS_BY_NAME = {
88
98
  PathTemplateError,
89
99
  NotFoundError,
90
100
  ContractError,
101
+ AggregationError,
91
102
  };
92
103
 
93
104
  // Map a structured error raised by the addon onto its typed class. The mapping
@@ -98,6 +109,9 @@ function mapCoreError(raw) {
98
109
  if (raw.issues !== undefined) opts.issues = raw.issues;
99
110
  if (raw.conflictingPaths !== undefined) opts.conflictingPaths = raw.conflictingPaths;
100
111
  if (raw.contract !== undefined) opts.contract = raw.contract;
112
+ if (raw.sheet !== undefined) opts.sheet = raw.sheet;
113
+ if (raw.aggregate !== undefined) opts.aggregate = raw.aggregate;
114
+ if (raw.partition !== undefined) opts.partition = raw.partition;
101
115
  return new Cls(raw.message, opts);
102
116
  }
103
117
 
@@ -149,9 +163,20 @@ module.exports = {
149
163
  // the filter (equality / nested / `$pred` engine snippets) runs in the core.
150
164
  recordQuery: wrap(addon.recordQuery),
151
165
  recordQueryCandidates: wrap(addon.recordQueryCandidates),
166
+ // Ad-hoc aggregation (behaviors/aggregation.md): a malformed spec throws a
167
+ // plain TypeError; a data-dependent failure an AggregationError.
168
+ recordAggregate: wrap(addon.recordAggregate),
169
+ // Rollup sheets (behaviors/rollups.md): the stamped read-through and the
170
+ // non-fresh survey, opening the rollup sheet from the tree each call.
171
+ rollupQuery: wrap(addon.rollupQuery),
172
+ rollupGet: wrap(addon.rollupGet),
173
+ rollupStatus: wrap(addon.rollupStatus),
174
+ rollupAggregate: wrap(addon.rollupAggregate),
152
175
  treeReadBlob: wrap(addon.treeReadBlob),
153
176
  treeEntryHash: wrap(addon.treeEntryHash),
154
177
  blobRead: wrap(addon.blobRead),
178
+ treeList: wrap(addon.treeList),
179
+ tagSet: wrap(addon.tagSet),
155
180
  blobHeader: wrap(addon.blobHeader),
156
181
  templateFieldNames: wrap(addon.templateFieldNames),
157
182
  // Secondary indexing (lazy, in-memory). A unique conflict surfaces as a typed
@@ -205,4 +230,5 @@ module.exports = {
205
230
  PathTemplateError,
206
231
  NotFoundError,
207
232
  ContractError,
233
+ AggregationError,
208
234
  };
package/index.d.ts CHANGED
@@ -248,6 +248,19 @@ export declare function substrateReset(): void
248
248
  * bytes itself (spec: `rust-core.md` "Query traversal + filtering").
249
249
  */
250
250
  export declare function recordQuery(gitDir: string, treeRef: string, base: string, template: string, filter: object, extension?: string | undefined | null, bodyField?: string | undefined | null, titleField?: string | undefined | null, withBody?: boolean | undefined | null): Array<JsRecordEntry>
251
+ /**
252
+ * Ad-hoc aggregation over the sheet under `base` in `treeRef`: the records
253
+ * matching `filter` (pruned by `template`, read body-less, the filter
254
+ * applied in the core — the same forms `recordQuery` takes) folded in
255
+ * canonical path order by the `aggregates` table (count / sum / avg / min /
256
+ * max / distinct / reduce, each with optional `where` / `groupBy`). Returns
257
+ * one value per aggregate name. `paths`, when given, restricts the
258
+ * contributing set to those record paths (the binding admits records with
259
+ * host-side predicates first). A malformed spec throws `TypeError`; a
260
+ * data-dependent failure throws `AggregationError` (`aggregation_failed`)
261
+ * carrying `sheet` and `aggregate`. Batch-first: one FFI crossing.
262
+ */
263
+ export declare function recordAggregate(gitDir: string, treeRef: string, sheet: string, base: string, template: string, filter: object, aggregates: unknown, extension?: string | undefined | null, bodyField?: string | undefined | null, titleField?: string | undefined | null, paths?: Array<string> | undefined | null): JsValue
251
264
  /**
252
265
  * A blob read by `treeRef:path` — the bytes plus the blob's object id, or
253
266
  * `null` when nothing (or a subtree) lives at `path`. Backs sheet-config
@@ -279,6 +292,24 @@ export interface JsBlobHeader {
279
292
  * "Blob metadata and bounded buffering").
280
293
  */
281
294
  export declare function blobHeader(gitDir: string, hash: string): JsBlobHeader | null
295
+ /** One direct entry of a tree (`repo.listTree`). */
296
+ export interface JsTreeEntry {
297
+ name: string
298
+ /** `blob` / `tree` / `commit`. */
299
+ type: string
300
+ mode: string
301
+ hash: string
302
+ }
303
+ /**
304
+ * The direct entries of the tree at `treeRef:path`, sorted by name; `null`
305
+ * when nothing (or a blob) is at `path`.
306
+ */
307
+ export declare function treeList(gitDir: string, treeRef: string, path: string): Array<JsTreeEntry> | null
308
+ /**
309
+ * Point the lightweight tag `refs/tags/<name>` at `target`; refuses an
310
+ * existing tag unless `force`. Returns the tagged object id.
311
+ */
312
+ export declare function tagSet(gitDir: string, name: string, target: string, force: boolean): string
282
313
  /** A blob read by `treeRef:path`: its object id and bytes. */
283
314
  export interface JsBlobEntry {
284
315
  hash: string
@@ -396,6 +427,45 @@ export interface JsAttachmentEntry {
396
427
  name: string
397
428
  hash: string
398
429
  }
430
+ /** `materialize()`'s result: the rollup record paths written and deleted. */
431
+ export interface JsMaterializeOutcome {
432
+ recomputed: Array<string>
433
+ deleted: Array<string>
434
+ }
435
+ /**
436
+ * One non-fresh rollup partition: its rollup record path and status
437
+ * (`stale` / `missing` / `orphaned`).
438
+ */
439
+ export interface JsRollupEntry {
440
+ path: string
441
+ status: string
442
+ }
443
+ /**
444
+ * Read a rollup sheet through its source (spec: `behaviors/rollups.md`
445
+ * "Reads"): partitions pruned by `filter` (the `recordQuery` forms), each
446
+ * served from its stored record when its `sourceTree` stamp matches and
447
+ * recomputed transiently otherwise; orphans are not yielded. `stale:
448
+ * 'serve'` returns the stored records as committed. Sorted by path.
449
+ */
450
+ export declare function rollupQuery(gitDir: string, treeRef: string, name: string, configPath: string, openRoot: string, prefix: string, filter: object, stale?: string | undefined | null): Array<JsRecordEntry>
451
+ /**
452
+ * One rollup record by path, read through its source (`stale` as on
453
+ * `rollupQuery`). `null` when no partition is there.
454
+ */
455
+ export declare function rollupGet(gitDir: string, treeRef: string, name: string, configPath: string, openRoot: string, prefix: string, path: string, stale?: string | undefined | null): JsValue | null
456
+ /**
457
+ * Ad-hoc aggregation over a rollup sheet's **read-through** records (spec:
458
+ * `behaviors/rollups.md` "Reads"): the rows `rollupQuery` would yield for
459
+ * `filter`, folded by `aggregates` like `recordAggregate` (same forms,
460
+ * `paths`, and errors). A rollup sheet's stored bytes may be stale, so the
461
+ * stateless `recordAggregate` over its root is not used.
462
+ */
463
+ export declare function rollupAggregate(gitDir: string, treeRef: string, name: string, configPath: string, openRoot: string, prefix: string, filter: object, aggregates: unknown, paths?: Array<string> | undefined | null): JsValue
464
+ /**
465
+ * The non-fresh partitions of a rollup sheet at `treeRef` — `git sheet
466
+ * rollup --check`. Writes nothing.
467
+ */
468
+ export declare function rollupStatus(gitDir: string, treeRef: string, name: string, configPath: string, openRoot: string, prefix: string): Array<JsRollupEntry>
399
469
  /** Options for [`sync_branch`]. */
400
470
  export interface JsSyncOptions {
401
471
  /** Local branch (bare name or qualified ref). */
@@ -660,16 +730,49 @@ export declare class CoreTransaction {
660
730
  * as `recordQuery` (equality / nested / `$pred` / ranges). Read-only —
661
731
  * does not mark the transaction mutated.
662
732
  */
663
- query(name: string, filter: object, withBody: boolean): Array<JsRecordEntry>
733
+ query(name: string, filter: object, withBody: boolean, stale?: string | undefined | null): Array<JsRecordEntry>
734
+ /**
735
+ * Ad-hoc aggregation over the sheet's records in the transaction's
736
+ * private tree — the tx-bound `Sheet.aggregate` (spec:
737
+ * `behaviors/aggregation.md`). Same filter / aggregates / `paths` forms
738
+ * and errors as `recordAggregate`; reads body-less. Read-only.
739
+ */
740
+ aggregate(name: string, filter: object, aggregates: unknown, paths?: Array<string> | undefined | null): JsValue
664
741
  /**
665
742
  * Read the one record at `recordPath` (relative to the sheet's base, no
666
743
  * extension) in the transaction's private tree, decoded through the format
667
744
  * codec — the tx-bound `Sheet.get`. `null` when absent; `withBody` is the
668
745
  * lazy-body switch. Read-only.
669
746
  */
670
- readRecord(name: string, recordPath: string, withBody: boolean): JsValue | null
747
+ readRecord(name: string, recordPath: string, withBody: boolean, stale?: string | undefined | null): JsValue | null
748
+ /**
749
+ * A raw file at `path` (repo-root-relative) in this transaction's
750
+ * private tree — staged writes included — as `{ hash, content }`, or
751
+ * `null` when nothing (or a subtree) is there. Backs tx-bound config
752
+ * loading (specs/api/transaction.md "Read isolation").
753
+ */
754
+ readFile(path: string): JsBlobEntry | null
755
+ /**
756
+ * `rollupSheet.materialize()` into this transaction's private tree
757
+ * (spec: `behaviors/rollups.md` "Materializing explicitly"): recompute
758
+ * every stale or missing rollup record and delete orphaned ones. Marks
759
+ * the transaction mutated only when something changed. `TypeError` on a
760
+ * non-rollup sheet.
761
+ */
762
+ materialize(name: string): JsMaterializeOutcome
763
+ /**
764
+ * The non-fresh partitions of a rollup sheet in this transaction's tree
765
+ * (`stale` / `missing` / `orphaned`), writing nothing. `TypeError` on a
766
+ * non-rollup sheet.
767
+ */
768
+ rollupStatus(name: string): Array<JsRollupEntry>
671
769
  /** The parent commit hash captured at open (null on a fresh repo). */
672
770
  parentCommitHash(): string | null
771
+ /**
772
+ * Whether a mutating method has run in this transaction — the flag the
773
+ * core's no-op short-circuit at finalize reads. False once finalized.
774
+ */
775
+ isMutated(): boolean
673
776
  /**
674
777
  * Finalize: commit-on-success-only with no-op detection + `parent_moved`
675
778
  * re-check + CAS ref movement. Consumes the transaction.
package/index.js CHANGED
@@ -310,7 +310,7 @@ if (!nativeBinding) {
310
310
  throw new Error(`Failed to load native binding`)
311
311
  }
312
312
 
313
- const { roundtrip, parseRecords, serializeRecords, renderPathsBatch, validateBatch, canonicalContractHash, validateContractName, contractPath, checkContractDocument, contractLoad, verifySheetContract, runComparator, collatorSort, CompiledDefinition, recordRead, recordWrite, recordDelete, recordList, writeBlob, substrateStats, substrateReset, recordQuery, treeReadBlob, treeEntryHash, blobRead, blobHeader, recordQueryCandidates, templateFieldNames, recordIndexUnique, recordIndexMulti, createPatch, applyMergePatch, diffRecords, simulateCoreError, CoreTransaction, syncBranch, isAncestor, mergeSheets, mergeRecordTexts, coreDiscoverSheets, sheetConfigCheck, 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, recordAggregate, treeReadBlob, treeEntryHash, blobRead, blobHeader, treeList, tagSet, recordQueryCandidates, templateFieldNames, recordIndexUnique, recordIndexMulti, createPatch, applyMergePatch, diffRecords, simulateCoreError, CoreTransaction, rollupQuery, rollupGet, rollupAggregate, rollupStatus, syncBranch, isAncestor, mergeSheets, mergeRecordTexts, coreDiscoverSheets, sheetConfigCheck, coreCheckValidators, markdownSerialize, markdownNormalizeBody, markdownParse, markdownParseHeaderOnly, markdownExtractH1, markdownRewriteH1 } = nativeBinding
314
314
 
315
315
  module.exports.roundtrip = roundtrip
316
316
  module.exports.parseRecords = parseRecords
@@ -334,10 +334,13 @@ module.exports.writeBlob = writeBlob
334
334
  module.exports.substrateStats = substrateStats
335
335
  module.exports.substrateReset = substrateReset
336
336
  module.exports.recordQuery = recordQuery
337
+ module.exports.recordAggregate = recordAggregate
337
338
  module.exports.treeReadBlob = treeReadBlob
338
339
  module.exports.treeEntryHash = treeEntryHash
339
340
  module.exports.blobRead = blobRead
340
341
  module.exports.blobHeader = blobHeader
342
+ module.exports.treeList = treeList
343
+ module.exports.tagSet = tagSet
341
344
  module.exports.recordQueryCandidates = recordQueryCandidates
342
345
  module.exports.templateFieldNames = templateFieldNames
343
346
  module.exports.recordIndexUnique = recordIndexUnique
@@ -347,6 +350,10 @@ module.exports.applyMergePatch = applyMergePatch
347
350
  module.exports.diffRecords = diffRecords
348
351
  module.exports.simulateCoreError = simulateCoreError
349
352
  module.exports.CoreTransaction = CoreTransaction
353
+ module.exports.rollupQuery = rollupQuery
354
+ module.exports.rollupGet = rollupGet
355
+ module.exports.rollupAggregate = rollupAggregate
356
+ module.exports.rollupStatus = rollupStatus
350
357
  module.exports.syncBranch = syncBranch
351
358
  module.exports.isAncestor = isAncestor
352
359
  module.exports.mergeSheets = mergeSheets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsheets/core-napi",
3
- "version": "0.7.0",
3
+ "version": "0.9.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.7.0",
37
- "@gitsheets/core-napi-linux-arm64-gnu": "0.7.0",
38
- "@gitsheets/core-napi-linux-x64-musl": "0.7.0",
39
- "@gitsheets/core-napi-darwin-arm64": "0.7.0",
40
- "@gitsheets/core-napi-darwin-x64": "0.7.0",
41
- "@gitsheets/core-napi-win32-x64-msvc": "0.7.0"
36
+ "@gitsheets/core-napi-linux-x64-gnu": "0.9.0",
37
+ "@gitsheets/core-napi-linux-arm64-gnu": "0.9.0",
38
+ "@gitsheets/core-napi-linux-x64-musl": "0.9.0",
39
+ "@gitsheets/core-napi-darwin-arm64": "0.9.0",
40
+ "@gitsheets/core-napi-darwin-x64": "0.9.0",
41
+ "@gitsheets/core-napi-win32-x64-msvc": "0.9.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 test/contracts.mjs test/sheet-config-check.mjs test/orphan-and-files.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-aggregate.mjs test/record-index.mjs test/sheet-store.mjs test/sheet-markdown.mjs test/sheet-attachments.mjs test/contracts.mjs test/sheet-config-check.mjs test/orphan-and-files.mjs test/rollups.mjs",
49
49
  "bench": "node bench/query-bench.mjs",
50
50
  "version": "napi version"
51
51
  },
@@ -54,6 +54,6 @@
54
54
  "ajv": "^8.20.0",
55
55
  "ajv-formats": "^3.0.1",
56
56
  "rfc6902": "^5.2.0",
57
- "smol-toml": "^1.8.0"
57
+ "smol-toml": "^1.9.1"
58
58
  }
59
59
  }