@gitsheets/core-napi 0.8.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,6 +163,15 @@ 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),
@@ -207,4 +230,5 @@ module.exports = {
207
230
  PathTemplateError,
208
231
  NotFoundError,
209
232
  ContractError,
233
+ AggregationError,
210
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
@@ -414,6 +427,45 @@ export interface JsAttachmentEntry {
414
427
  name: string
415
428
  hash: string
416
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>
417
469
  /** Options for [`sync_branch`]. */
418
470
  export interface JsSyncOptions {
419
471
  /** Local branch (bare name or qualified ref). */
@@ -678,14 +730,21 @@ export declare class CoreTransaction {
678
730
  * as `recordQuery` (equality / nested / `$pred` / ranges). Read-only —
679
731
  * does not mark the transaction mutated.
680
732
  */
681
- 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
682
741
  /**
683
742
  * Read the one record at `recordPath` (relative to the sheet's base, no
684
743
  * extension) in the transaction's private tree, decoded through the format
685
744
  * codec — the tx-bound `Sheet.get`. `null` when absent; `withBody` is the
686
745
  * lazy-body switch. Read-only.
687
746
  */
688
- readRecord(name: string, recordPath: string, withBody: boolean): JsValue | null
747
+ readRecord(name: string, recordPath: string, withBody: boolean, stale?: string | undefined | null): JsValue | null
689
748
  /**
690
749
  * A raw file at `path` (repo-root-relative) in this transaction's
691
750
  * private tree — staged writes included — as `{ hash, content }`, or
@@ -693,8 +752,27 @@ export declare class CoreTransaction {
693
752
  * loading (specs/api/transaction.md "Read isolation").
694
753
  */
695
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>
696
769
  /** The parent commit hash captured at open (null on a fresh repo). */
697
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
698
776
  /**
699
777
  * Finalize: commit-on-success-only with no-op detection + `parent_moved`
700
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, treeList, tagSet, 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,6 +334,7 @@ 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
@@ -349,6 +350,10 @@ module.exports.applyMergePatch = applyMergePatch
349
350
  module.exports.diffRecords = diffRecords
350
351
  module.exports.simulateCoreError = simulateCoreError
351
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
352
357
  module.exports.syncBranch = syncBranch
353
358
  module.exports.isAncestor = isAncestor
354
359
  module.exports.mergeSheets = mergeSheets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitsheets/core-napi",
3
- "version": "0.8.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.8.0",
37
- "@gitsheets/core-napi-linux-arm64-gnu": "0.8.0",
38
- "@gitsheets/core-napi-linux-x64-musl": "0.8.0",
39
- "@gitsheets/core-napi-darwin-arm64": "0.8.0",
40
- "@gitsheets/core-napi-darwin-x64": "0.8.0",
41
- "@gitsheets/core-napi-win32-x64-msvc": "0.8.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
  },