dataply 0.0.6 → 0.0.8

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/dist/cjs/index.js CHANGED
@@ -32,21 +32,30 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  BPTreeAsync: () => BPTreeAsync,
34
34
  BPTreeSync: () => BPTreeSync,
35
+ BitmapPageManager: () => BitmapPageManager,
35
36
  CacheEntanglementAsync: () => CacheEntanglementAsync2,
36
37
  CacheEntanglementSync: () => CacheEntanglementSync2,
38
+ DataPageManager: () => DataPageManager,
37
39
  Dataply: () => Dataply,
38
40
  DataplyAPI: () => DataplyAPI,
41
+ EmptyPageManager: () => EmptyPageManager,
39
42
  GlobalTransaction: () => GlobalTransaction,
40
43
  InMemoryStoreStrategyAsync: () => InMemoryStoreStrategyAsync,
41
44
  InMemoryStoreStrategySync: () => InMemoryStoreStrategySync,
45
+ IndexPageManager: () => IndexPageManager,
42
46
  InvertedWeakMap: () => InvertedWeakMap,
43
47
  LRUMap: () => LRUMap2,
48
+ MetadataPageManager: () => MetadataPageManager,
44
49
  NumericComparator: () => NumericComparator,
50
+ OverflowPageManager: () => OverflowPageManager,
51
+ PageManager: () => PageManager,
52
+ PageManagerFactory: () => PageManagerFactory,
45
53
  Ryoiki: () => Ryoiki2,
46
54
  SerializeStrategyAsync: () => SerializeStrategyAsync,
47
55
  SerializeStrategySync: () => SerializeStrategySync,
48
56
  StringComparator: () => StringComparator,
49
57
  Transaction: () => Transaction,
58
+ UnknownPageManager: () => UnknownPageManager,
50
59
  ValueComparator: () => ValueComparator
51
60
  });
52
61
  module.exports = __toCommonJS(src_exports);
@@ -2945,323 +2954,6 @@ var InvertedWeakMap = class {
2945
2954
  }
2946
2955
  };
2947
2956
 
2948
- // src/core/DataplyAPI.ts
2949
- var import_node_fs3 = __toESM(require("node:fs"));
2950
-
2951
- // node_modules/hookall/dist/esm/index.mjs
2952
- var HookallStore = class extends WeakMap {
2953
- ensure(obj, key) {
2954
- if (!this.has(obj)) {
2955
- const scope2 = {};
2956
- this.set(obj, scope2);
2957
- }
2958
- const scope = this.get(obj);
2959
- if (!Object.prototype.hasOwnProperty.call(scope, key)) {
2960
- scope[key] = /* @__PURE__ */ new Map();
2961
- }
2962
- return scope[key];
2963
- }
2964
- };
2965
- var Hookall = class _Hookall {
2966
- static Global = {};
2967
- static _Store = new HookallStore();
2968
- beforeHooks;
2969
- afterHooks;
2970
- /**
2971
- * Create hook system. you can pass a target object or undefined.
2972
- * If you pass a object, the hook system will be work for object locally. You're going to want this kind of usage in general.
2973
- * If not specified, will be work for global. This is useful when you want to share your work with multiple files.
2974
- * @param target The object to work with locally. If not specified, will be work for global.
2975
- */
2976
- constructor(target) {
2977
- this.beforeHooks = _Hookall._Store.ensure(target, "before");
2978
- this.afterHooks = _Hookall._Store.ensure(target, "after");
2979
- }
2980
- _ensureCommand(hooks, command) {
2981
- if (!hooks.has(command)) {
2982
- hooks.set(command, []);
2983
- }
2984
- return hooks.get(command);
2985
- }
2986
- _createWrapper(command, callback, repeat) {
2987
- return {
2988
- callback,
2989
- command,
2990
- repeat
2991
- };
2992
- }
2993
- _on(hooks, command, callback, repeat) {
2994
- const wrappers = this._ensureCommand(hooks, command);
2995
- const wrapper = this._createWrapper(command, callback, repeat);
2996
- wrappers.unshift(wrapper);
2997
- }
2998
- /**
2999
- * You register a preprocessing function, which is called before the callback function of the `trigger` method.
3000
- * The value returned by this function is passed as a parameter to the `trigger` method's callback function.
3001
- * If you register multiple preprocessing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
3002
- * @param command Command to work.
3003
- * @param callback Preprocessing function to register.
3004
- */
3005
- onBefore(command, callback) {
3006
- this._on(this.beforeHooks, command, callback, -1);
3007
- return this;
3008
- }
3009
- /**
3010
- * Similar to the `onBefore` method, but it only runs once.
3011
- * For more details, please refer to the `onBefore` method.
3012
- * @param command Command to work.
3013
- * @param callback Preprocessing function to register.
3014
- */
3015
- onceBefore(command, callback) {
3016
- this._on(this.beforeHooks, command, callback, 1);
3017
- return this;
3018
- }
3019
- /**
3020
- * You register a post-processing function which is called after the callback function of the `trigger` method finishes.
3021
- * This function receives the value returned by the `trigger` method's callback function as a parameter.
3022
- * If you register multiple post-processing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
3023
- * @param command Command to work.
3024
- * @param callback Post-preprocessing function to register.
3025
- */
3026
- onAfter(command, callback) {
3027
- this._on(this.afterHooks, command, callback, -1);
3028
- return this;
3029
- }
3030
- /**
3031
- * Similar to the `onAfter` method, but it only runs once.
3032
- * For more details, please refer to the `onAfter` method.
3033
- * @param command Command to work.
3034
- * @param callback Post-preprocessing function to register.
3035
- */
3036
- onceAfter(command, callback) {
3037
- this._on(this.afterHooks, command, callback, 1);
3038
- return this;
3039
- }
3040
- _off(hooks, command, callback) {
3041
- const wrappers = this._ensureCommand(hooks, command);
3042
- if (callback) {
3043
- const i = wrappers.findIndex((wrapper) => wrapper.callback === callback);
3044
- if (i !== -1) {
3045
- wrappers.splice(i, 1);
3046
- }
3047
- } else {
3048
- wrappers.length = 0;
3049
- }
3050
- return this;
3051
- }
3052
- /**
3053
- * You remove the preprocessing functions registered with `onBefore` or `onceBefore` methods.
3054
- * If you don't specify a callback parameter, it removes all preprocessing functions registered for that command.
3055
- * @param command Commands with preprocessing functions to be deleted.
3056
- * @param callback Preprocessing function to be deleted.
3057
- */
3058
- offBefore(command, callback) {
3059
- this._off(this.beforeHooks, command, callback);
3060
- return this;
3061
- }
3062
- /**
3063
- * You remove the post-preprocessing functions registered with `onAfter` or `onceAfter` methods.
3064
- * If you don't specify a callback parameter, it removes all post-preprocessing functions registered for that command.
3065
- * @param command Commands with post-preprocessing functions to be deleted.
3066
- * @param callback post-Preprocessing function to be deleted.
3067
- */
3068
- offAfter(command, callback) {
3069
- this._off(this.afterHooks, command, callback);
3070
- return this;
3071
- }
3072
- async _hookWith(hooks, command, value, ...params) {
3073
- let wrappers = this._ensureCommand(hooks, command);
3074
- let i = wrappers.length;
3075
- while (i--) {
3076
- const wrapper = wrappers[i];
3077
- value = await wrapper.callback(value, ...params);
3078
- wrapper.repeat -= 1;
3079
- if (wrapper.repeat === 0) {
3080
- this._off(hooks, command, wrapper.callback);
3081
- }
3082
- }
3083
- return value;
3084
- }
3085
- /**
3086
- * You execute the callback function provided as a parameter. This callback function receives the 'initialValue' parameter.
3087
- *
3088
- * If preprocessing functions are registered, they run first, and the value returned by the preprocessing functions becomes the 'initialValue' parameter.
3089
- * After the callback function finishes, post-processing functions are called.
3090
- * These post-processing functions receive the value returned by the callback function as a parameter and run sequentially.
3091
- *
3092
- * The final value returned becomes the result of the `trigger` method.
3093
- * @param command Command to work.
3094
- * @param initialValue Initial value to be passed to the callback function.
3095
- * @param callback The callback function to be executed.
3096
- */
3097
- async trigger(command, initialValue, callback, ...params) {
3098
- let value;
3099
- value = await this._hookWith(this.beforeHooks, command, initialValue, ...params);
3100
- value = await callback(value, ...params);
3101
- value = await this._hookWith(this.afterHooks, command, value, ...params);
3102
- return value;
3103
- }
3104
- };
3105
- function useHookall(target = Hookall.Global) {
3106
- return new Hookall(target);
3107
- }
3108
- var HookallStore2 = class extends WeakMap {
3109
- ensure(obj, key) {
3110
- if (!this.has(obj)) {
3111
- const scope2 = {};
3112
- this.set(obj, scope2);
3113
- }
3114
- const scope = this.get(obj);
3115
- if (!Object.prototype.hasOwnProperty.call(scope, key)) {
3116
- scope[key] = /* @__PURE__ */ new Map();
3117
- }
3118
- return scope[key];
3119
- }
3120
- };
3121
- var HookallSync = class _HookallSync {
3122
- static Global = {};
3123
- static _Store = new HookallStore2();
3124
- beforeHooks;
3125
- afterHooks;
3126
- /**
3127
- * Create hook system. you can pass a target object or undefined.
3128
- * If you pass a object, the hook system will be work for object locally. You're going to want this kind of usage in general.
3129
- * If not specified, will be work for global. This is useful when you want to share your work with multiple files.
3130
- * @param target The object to work with locally. If not specified, will be work for global.
3131
- */
3132
- constructor(target) {
3133
- this.beforeHooks = _HookallSync._Store.ensure(target, "before");
3134
- this.afterHooks = _HookallSync._Store.ensure(target, "after");
3135
- }
3136
- _ensureCommand(hooks, command) {
3137
- if (!hooks.has(command)) {
3138
- hooks.set(command, []);
3139
- }
3140
- return hooks.get(command);
3141
- }
3142
- _createWrapper(command, callback, repeat) {
3143
- return {
3144
- callback,
3145
- command,
3146
- repeat
3147
- };
3148
- }
3149
- _on(hooks, command, callback, repeat) {
3150
- const wrappers = this._ensureCommand(hooks, command);
3151
- const wrapper = this._createWrapper(command, callback, repeat);
3152
- wrappers.unshift(wrapper);
3153
- }
3154
- /**
3155
- * You register a preprocessing function, which is called before the callback function of the `trigger` method.
3156
- * The value returned by this function is passed as a parameter to the `trigger` method's callback function.
3157
- * If you register multiple preprocessing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
3158
- * @param command Command to work.
3159
- * @param callback Preprocessing function to register.
3160
- */
3161
- onBefore(command, callback) {
3162
- this._on(this.beforeHooks, command, callback, -1);
3163
- return this;
3164
- }
3165
- /**
3166
- * Similar to the `onBefore` method, but it only runs once.
3167
- * For more details, please refer to the `onBefore` method.
3168
- * @param command Command to work.
3169
- * @param callback Preprocessing function to register.
3170
- */
3171
- onceBefore(command, callback) {
3172
- this._on(this.beforeHooks, command, callback, 1);
3173
- return this;
3174
- }
3175
- /**
3176
- * You register a post-processing function which is called after the callback function of the `trigger` method finishes.
3177
- * This function receives the value returned by the `trigger` method's callback function as a parameter.
3178
- * If you register multiple post-processing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
3179
- * @param command Command to work.
3180
- * @param callback Post-preprocessing function to register.
3181
- */
3182
- onAfter(command, callback) {
3183
- this._on(this.afterHooks, command, callback, -1);
3184
- return this;
3185
- }
3186
- /**
3187
- * Similar to the `onAfter` method, but it only runs once.
3188
- * For more details, please refer to the `onAfter` method.
3189
- * @param command Command to work.
3190
- * @param callback Post-preprocessing function to register.
3191
- */
3192
- onceAfter(command, callback) {
3193
- this._on(this.afterHooks, command, callback, 1);
3194
- return this;
3195
- }
3196
- _off(hooks, command, callback) {
3197
- const wrappers = this._ensureCommand(hooks, command);
3198
- if (callback) {
3199
- const i = wrappers.findIndex((wrapper) => wrapper.callback === callback);
3200
- if (i !== -1) {
3201
- wrappers.splice(i, 1);
3202
- }
3203
- } else {
3204
- wrappers.length = 0;
3205
- }
3206
- return this;
3207
- }
3208
- /**
3209
- * You remove the preprocessing functions registered with `onBefore` or `onceBefore` methods.
3210
- * If you don't specify a callback parameter, it removes all preprocessing functions registered for that command.
3211
- * @param command Commands with preprocessing functions to be deleted.
3212
- * @param callback Preprocessing function to be deleted.
3213
- */
3214
- offBefore(command, callback) {
3215
- this._off(this.beforeHooks, command, callback);
3216
- return this;
3217
- }
3218
- /**
3219
- * You remove the post-preprocessing functions registered with `onAfter` or `onceAfter` methods.
3220
- * If you don't specify a callback parameter, it removes all post-preprocessing functions registered for that command.
3221
- * @param command Commands with post-preprocessing functions to be deleted.
3222
- * @param callback post-Preprocessing function to be deleted.
3223
- */
3224
- offAfter(command, callback) {
3225
- this._off(this.afterHooks, command, callback);
3226
- return this;
3227
- }
3228
- _hookWith(hooks, command, value, ...params) {
3229
- let wrappers = this._ensureCommand(hooks, command);
3230
- let i = wrappers.length;
3231
- while (i--) {
3232
- const wrapper = wrappers[i];
3233
- value = wrapper.callback(value, ...params);
3234
- wrapper.repeat -= 1;
3235
- if (wrapper.repeat === 0) {
3236
- this._off(hooks, command, wrapper.callback);
3237
- }
3238
- }
3239
- return value;
3240
- }
3241
- /**
3242
- * You execute the callback function provided as a parameter. This callback function receives the 'initialValue' parameter.
3243
- *
3244
- * If preprocessing functions are registered, they run first, and the value returned by the preprocessing functions becomes the 'initialValue' parameter.
3245
- * After the callback function finishes, post-processing functions are called.
3246
- * These post-processing functions receive the value returned by the callback function as a parameter and run sequentially.
3247
- *
3248
- * The final value returned becomes the result of the `trigger` method.
3249
- * @param command Command to work.
3250
- * @param initialValue Initial value to be passed to the callback function.
3251
- * @param callback The callback function to be executed.
3252
- */
3253
- trigger(command, initialValue, callback, ...params) {
3254
- let value;
3255
- value = this._hookWith(this.beforeHooks, command, initialValue, ...params);
3256
- value = callback(value, ...params);
3257
- value = this._hookWith(this.afterHooks, command, value, ...params);
3258
- return value;
3259
- }
3260
- };
3261
- function useHookallSync(target = HookallSync.Global) {
3262
- return new HookallSync(target);
3263
- }
3264
-
3265
2957
  // src/utils/numberToBytes.ts
3266
2958
  function numberToBytes(value, buffer, offset = 0, length = buffer.length) {
3267
2959
  if (length === 4) {
@@ -3738,888 +3430,1205 @@ var DataPageManager = class _DataPageManager extends PageManager {
3738
3430
  return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_DATA;
3739
3431
  }
3740
3432
  /**
3741
- * Checks if the page type is `DataPage`.
3433
+ * Checks if the page type is `DataPage`.
3434
+ * @param page Page data
3435
+ * @returns boolean indicating if the page type is `DataPage`
3436
+ */
3437
+ isDataPage(page) {
3438
+ return _DataPageManager.IsDataPage(page);
3439
+ }
3440
+ /**
3441
+ * Returns the offset of a row within the page.
3442
+ * @param page Page data
3443
+ * @param slotIndex Slot index
3444
+ * @returns Row offset within the page
3445
+ */
3446
+ getRowOffset(page, slotIndex) {
3447
+ return bytesToNumber(
3448
+ page,
3449
+ page.length - PageManager.CONSTANT.SIZE_SLOT_OFFSET - slotIndex * PageManager.CONSTANT.SIZE_SLOT_OFFSET,
3450
+ PageManager.CONSTANT.SIZE_SLOT_OFFSET
3451
+ );
3452
+ }
3453
+ /**
3454
+ * Returns the row from the page.
3455
+ * @param page Page data
3456
+ * @param slotIndex Slot index
3457
+ * @returns Row data within the page
3458
+ */
3459
+ getRow(page, slotIndex) {
3460
+ const offset = this.getRowOffset(page, slotIndex);
3461
+ const headerSize = Row.CONSTANT.SIZE_HEADER;
3462
+ const bodySize = this.row.getBodySize(page.subarray(offset));
3463
+ const row = page.subarray(offset, offset + headerSize + bodySize);
3464
+ return row;
3465
+ }
3466
+ /**
3467
+ * Returns the number of rows inserted into the page.
3468
+ * @param page Page data
3469
+ * @returns Number of rows inserted
3470
+ */
3471
+ getInsertedRowCount(page) {
3472
+ return bytesToNumber(
3473
+ page,
3474
+ PageManager.CONSTANT.OFFSET_INSERTED_ROW_COUNT,
3475
+ PageManager.CONSTANT.SIZE_INSERTED_ROW_COUNT
3476
+ );
3477
+ }
3478
+ /**
3479
+ * Sets the offset of a row within the page.
3480
+ * @param page Page data
3481
+ * @param slotIndex Slot index
3482
+ * @param offset Row offset within the page
3483
+ */
3484
+ setRowOffset(page, slotIndex, offset) {
3485
+ numberToBytes(
3486
+ offset,
3487
+ page,
3488
+ page.length - PageManager.CONSTANT.SIZE_SLOT_OFFSET - slotIndex * PageManager.CONSTANT.SIZE_SLOT_OFFSET,
3489
+ PageManager.CONSTANT.SIZE_SLOT_OFFSET
3490
+ );
3491
+ }
3492
+ /**
3493
+ * Sets the number of rows inserted into the page.
3494
+ * @param page Page data
3495
+ * @param insertedRowCount Number of rows inserted
3496
+ */
3497
+ setInsertedRowCount(page, insertedRowCount) {
3498
+ numberToBytes(
3499
+ insertedRowCount,
3500
+ page,
3501
+ PageManager.CONSTANT.OFFSET_INSERTED_ROW_COUNT,
3502
+ PageManager.CONSTANT.SIZE_INSERTED_ROW_COUNT
3503
+ );
3504
+ }
3505
+ /**
3506
+ * Calculates if there is space for a row in the page and determines insertability.
3507
+ * If insertable, returns the slot index to be inserted.
3508
+ * If not, returns -1.
3509
+ * @param page Page data
3510
+ * @param row Row data
3511
+ * @returns Slot index for the row
3512
+ */
3513
+ getNextSlotIndex(page, row) {
3514
+ const slotOffsetSize = PageManager.CONSTANT.SIZE_SLOT_OFFSET;
3515
+ const remainingCapacity = this.getRemainingCapacity(page);
3516
+ const totalSize = row.length + slotOffsetSize;
3517
+ return remainingCapacity >= totalSize ? this.getInsertedRowCount(page) : -1;
3518
+ }
3519
+ /**
3520
+ * Returns the position for the next row to be inserted.
3521
+ * @param page Page data
3522
+ * @returns Next insert position
3523
+ */
3524
+ getNextInsertPosition(page) {
3525
+ const insertedRowCount = this.getInsertedRowCount(page);
3526
+ if (insertedRowCount === 0) {
3527
+ return _DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
3528
+ }
3529
+ const lastRowIndex = insertedRowCount - 1;
3530
+ const lastRowOffset = this.getRowOffset(page, lastRowIndex);
3531
+ const lastRow = this.getRow(page, lastRowIndex);
3532
+ return lastRowOffset + lastRow.length;
3533
+ }
3534
+ /**
3535
+ * Inserts a row into the page. `getNextSlotIndex` should be called beforehand to verify availability.
3536
+ * @param page Page data
3537
+ * @param row Row data
3538
+ */
3539
+ insert(page, row) {
3540
+ const slotOffsetSize = PageManager.CONSTANT.SIZE_SLOT_OFFSET;
3541
+ const remainingCapacity = this.getRemainingCapacity(page);
3542
+ const totalSize = row.length + slotOffsetSize;
3543
+ if (remainingCapacity < totalSize) {
3544
+ throw new Error("Not enough space to insert row");
3545
+ }
3546
+ const insertedRowCount = this.getInsertedRowCount(page);
3547
+ const offset = this.getNextInsertPosition(page);
3548
+ page.set(row, offset);
3549
+ this.setRowOffset(page, insertedRowCount, offset);
3550
+ this.setInsertedRowCount(page, insertedRowCount + 1);
3551
+ this.setRemainingCapacity(page, remainingCapacity - totalSize);
3552
+ }
3553
+ };
3554
+ var IndexPageManager = class _IndexPageManager extends PageManager {
3555
+ get pageType() {
3556
+ return PageManager.CONSTANT.PAGE_TYPE_INDEX;
3557
+ }
3558
+ static CONSTANT = {
3559
+ ...PageManager.CONSTANT,
3560
+ OFFSET_INDEX_ID: 100,
3561
+ OFFSET_PARENT_INDEX_ID: 104,
3562
+ OFFSET_NEXT_INDEX_ID: 108,
3563
+ OFFSET_PREV_INDEX_ID: 112,
3564
+ OFFSET_IS_LEAF: 116,
3565
+ OFFSET_KEYS_COUNT: 117,
3566
+ OFFSET_VALUES_COUNT: 121,
3567
+ OFFSET_KEYS_AND_VALUES: 128,
3568
+ // 8-byte aligned (original 125 -> 128)
3569
+ SIZE_INDEX_ID: 4,
3570
+ SIZE_PARENT_INDEX_ID: 4,
3571
+ SIZE_NEXT_INDEX_ID: 4,
3572
+ SIZE_PREV_INDEX_ID: 4,
3573
+ SIZE_IS_LEAF: 1,
3574
+ SIZE_KEYS_COUNT: 4,
3575
+ SIZE_VALUES_COUNT: 4,
3576
+ SIZE_KEY: 8,
3577
+ // Updated to 8 bytes for Float64
3578
+ SIZE_VALUE: 8
3579
+ // Updated to 8 bytes for Float64
3580
+ };
3581
+ /**
3582
+ * Checks if the page type is `IndexPage`.
3583
+ * @param page Page data
3584
+ * @returns boolean indicating if the page type is `IndexPage`
3585
+ */
3586
+ static IsIndexPage(page) {
3587
+ return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_INDEX;
3588
+ }
3589
+ /**
3590
+ * Checks if the page type is `IndexPage`.
3591
+ * @param page Page data
3592
+ * @returns boolean indicating if the page type is `IndexPage`
3593
+ */
3594
+ isIndexPage(page) {
3595
+ return _IndexPageManager.IsIndexPage(page);
3596
+ }
3597
+ /**
3598
+ * Gets the index ID of the page.
3599
+ * @param page Page data
3600
+ * @returns Index ID
3601
+ */
3602
+ getIndexId(page) {
3603
+ return bytesToNumber(
3604
+ page,
3605
+ _IndexPageManager.CONSTANT.OFFSET_INDEX_ID,
3606
+ _IndexPageManager.CONSTANT.SIZE_INDEX_ID
3607
+ );
3608
+ }
3609
+ /**
3610
+ * Gets the parent index ID of the page.
3611
+ * @param page Page data
3612
+ * @returns Parent index ID
3613
+ */
3614
+ getParentIndexId(page) {
3615
+ return bytesToNumber(
3616
+ page,
3617
+ _IndexPageManager.CONSTANT.OFFSET_PARENT_INDEX_ID,
3618
+ _IndexPageManager.CONSTANT.SIZE_PARENT_INDEX_ID
3619
+ );
3620
+ }
3621
+ /**
3622
+ * Gets the next index ID of the page.
3623
+ * @param page Page data
3624
+ * @returns Next index ID
3625
+ */
3626
+ getNextIndexId(page) {
3627
+ return bytesToNumber(
3628
+ page,
3629
+ _IndexPageManager.CONSTANT.OFFSET_NEXT_INDEX_ID,
3630
+ _IndexPageManager.CONSTANT.SIZE_NEXT_INDEX_ID
3631
+ );
3632
+ }
3633
+ /**
3634
+ * Gets the previous index ID of the page.
3635
+ * @param page Page data
3636
+ * @returns Previous index ID
3637
+ */
3638
+ getPrevIndexId(page) {
3639
+ return bytesToNumber(
3640
+ page,
3641
+ _IndexPageManager.CONSTANT.OFFSET_PREV_INDEX_ID,
3642
+ _IndexPageManager.CONSTANT.SIZE_PREV_INDEX_ID
3643
+ );
3644
+ }
3645
+ /**
3646
+ * Gets the is leaf of the page.
3647
+ * @param page Page data
3648
+ * @returns Is leaf
3649
+ */
3650
+ getIsLeaf(page) {
3651
+ return bytesToNumber(
3652
+ page,
3653
+ _IndexPageManager.CONSTANT.OFFSET_IS_LEAF,
3654
+ _IndexPageManager.CONSTANT.SIZE_IS_LEAF
3655
+ ) === 1;
3656
+ }
3657
+ /**
3658
+ * Gets the keys count of the page.
3659
+ * @param page Page data
3660
+ * @returns Keys count
3661
+ */
3662
+ getKeysCount(page) {
3663
+ return bytesToNumber(
3664
+ page,
3665
+ _IndexPageManager.CONSTANT.OFFSET_KEYS_COUNT,
3666
+ _IndexPageManager.CONSTANT.SIZE_KEYS_COUNT
3667
+ );
3668
+ }
3669
+ /**
3670
+ * Gets the values count of the page.
3671
+ * @param page Page data
3672
+ * @returns Values count
3673
+ */
3674
+ getValuesCount(page) {
3675
+ return bytesToNumber(
3676
+ page,
3677
+ _IndexPageManager.CONSTANT.OFFSET_VALUES_COUNT,
3678
+ _IndexPageManager.CONSTANT.SIZE_VALUES_COUNT
3679
+ );
3680
+ }
3681
+ /**
3682
+ * Sets the index ID of the page.
3683
+ * @param page Page data
3684
+ * @param indexId Index ID
3685
+ */
3686
+ setIndexId(page, indexId) {
3687
+ numberToBytes(
3688
+ indexId,
3689
+ page,
3690
+ _IndexPageManager.CONSTANT.OFFSET_INDEX_ID,
3691
+ _IndexPageManager.CONSTANT.SIZE_INDEX_ID
3692
+ );
3693
+ }
3694
+ /**
3695
+ * Sets the parent index ID of the page.
3742
3696
  * @param page Page data
3743
- * @returns boolean indicating if the page type is `DataPage`
3697
+ * @param parentIndexId Parent index ID
3744
3698
  */
3745
- isDataPage(page) {
3746
- return _DataPageManager.IsDataPage(page);
3699
+ setParentIndexId(page, parentIndexId) {
3700
+ numberToBytes(
3701
+ parentIndexId,
3702
+ page,
3703
+ _IndexPageManager.CONSTANT.OFFSET_PARENT_INDEX_ID,
3704
+ _IndexPageManager.CONSTANT.SIZE_PARENT_INDEX_ID
3705
+ );
3747
3706
  }
3748
3707
  /**
3749
- * Returns the offset of a row within the page.
3708
+ * Sets the next index ID of the page.
3750
3709
  * @param page Page data
3751
- * @param slotIndex Slot index
3752
- * @returns Row offset within the page
3710
+ * @param nextIndexId Next index ID
3753
3711
  */
3754
- getRowOffset(page, slotIndex) {
3755
- return bytesToNumber(
3712
+ setNextIndexId(page, nextIndexId) {
3713
+ numberToBytes(
3714
+ nextIndexId,
3756
3715
  page,
3757
- page.length - PageManager.CONSTANT.SIZE_SLOT_OFFSET - slotIndex * PageManager.CONSTANT.SIZE_SLOT_OFFSET,
3758
- PageManager.CONSTANT.SIZE_SLOT_OFFSET
3716
+ _IndexPageManager.CONSTANT.OFFSET_NEXT_INDEX_ID,
3717
+ _IndexPageManager.CONSTANT.SIZE_NEXT_INDEX_ID
3759
3718
  );
3760
3719
  }
3761
3720
  /**
3762
- * Returns the row from the page.
3721
+ * Sets the previous index ID of the page.
3763
3722
  * @param page Page data
3764
- * @param slotIndex Slot index
3765
- * @returns Row data within the page
3723
+ * @param prevIndexId Previous index ID
3766
3724
  */
3767
- getRow(page, slotIndex) {
3768
- const offset = this.getRowOffset(page, slotIndex);
3769
- const headerSize = Row.CONSTANT.SIZE_HEADER;
3770
- const bodySize = this.row.getBodySize(page.subarray(offset));
3771
- const row = page.subarray(offset, offset + headerSize + bodySize);
3772
- return row;
3725
+ setPrevIndexId(page, prevIndexId) {
3726
+ numberToBytes(
3727
+ prevIndexId,
3728
+ page,
3729
+ _IndexPageManager.CONSTANT.OFFSET_PREV_INDEX_ID,
3730
+ _IndexPageManager.CONSTANT.SIZE_PREV_INDEX_ID
3731
+ );
3773
3732
  }
3774
3733
  /**
3775
- * Returns the number of rows inserted into the page.
3734
+ * Sets the is leaf of the page.
3776
3735
  * @param page Page data
3777
- * @returns Number of rows inserted
3736
+ * @param isLeaf Is leaf
3778
3737
  */
3779
- getInsertedRowCount(page) {
3780
- return bytesToNumber(
3738
+ setIsLeaf(page, isLeaf) {
3739
+ numberToBytes(
3740
+ isLeaf ? 1 : 0,
3781
3741
  page,
3782
- PageManager.CONSTANT.OFFSET_INSERTED_ROW_COUNT,
3783
- PageManager.CONSTANT.SIZE_INSERTED_ROW_COUNT
3742
+ _IndexPageManager.CONSTANT.OFFSET_IS_LEAF,
3743
+ _IndexPageManager.CONSTANT.SIZE_IS_LEAF
3784
3744
  );
3785
3745
  }
3786
3746
  /**
3787
- * Sets the offset of a row within the page.
3747
+ * Sets the keys count of the page.
3788
3748
  * @param page Page data
3789
- * @param slotIndex Slot index
3790
- * @param offset Row offset within the page
3749
+ * @param keysCount Keys count
3791
3750
  */
3792
- setRowOffset(page, slotIndex, offset) {
3751
+ setKeysCount(page, keysCount) {
3793
3752
  numberToBytes(
3794
- offset,
3753
+ keysCount,
3795
3754
  page,
3796
- page.length - PageManager.CONSTANT.SIZE_SLOT_OFFSET - slotIndex * PageManager.CONSTANT.SIZE_SLOT_OFFSET,
3797
- PageManager.CONSTANT.SIZE_SLOT_OFFSET
3755
+ _IndexPageManager.CONSTANT.OFFSET_KEYS_COUNT,
3756
+ _IndexPageManager.CONSTANT.SIZE_KEYS_COUNT
3798
3757
  );
3799
3758
  }
3800
3759
  /**
3801
- * Sets the number of rows inserted into the page.
3760
+ * Sets the values count of the page.
3802
3761
  * @param page Page data
3803
- * @param insertedRowCount Number of rows inserted
3762
+ * @param valuesCount Values count
3804
3763
  */
3805
- setInsertedRowCount(page, insertedRowCount) {
3764
+ setValuesCount(page, valuesCount) {
3806
3765
  numberToBytes(
3807
- insertedRowCount,
3766
+ valuesCount,
3808
3767
  page,
3809
- PageManager.CONSTANT.OFFSET_INSERTED_ROW_COUNT,
3810
- PageManager.CONSTANT.SIZE_INSERTED_ROW_COUNT
3768
+ _IndexPageManager.CONSTANT.OFFSET_VALUES_COUNT,
3769
+ _IndexPageManager.CONSTANT.SIZE_VALUES_COUNT
3811
3770
  );
3812
3771
  }
3813
3772
  /**
3814
- * Calculates if there is space for a row in the page and determines insertability.
3815
- * If insertable, returns the slot index to be inserted.
3816
- * If not, returns -1.
3773
+ * Gets the keys of the page.
3817
3774
  * @param page Page data
3818
- * @param row Row data
3819
- * @returns Slot index for the row
3775
+ * @returns Keys
3820
3776
  */
3821
- getNextSlotIndex(page, row) {
3822
- const slotOffsetSize = PageManager.CONSTANT.SIZE_SLOT_OFFSET;
3823
- const remainingCapacity = this.getRemainingCapacity(page);
3824
- const totalSize = row.length + slotOffsetSize;
3825
- return remainingCapacity >= totalSize ? this.getInsertedRowCount(page) : -1;
3777
+ getKeys(page) {
3778
+ const keysCount = this.getKeysCount(page);
3779
+ const byteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES;
3780
+ const keys = new Float64Array(page.buffer, byteOffset, keysCount);
3781
+ return Array.from(keys);
3826
3782
  }
3827
3783
  /**
3828
- * Returns the position for the next row to be inserted.
3784
+ * Gets the values of the page.
3829
3785
  * @param page Page data
3830
- * @returns Next insert position
3786
+ * @returns Values
3831
3787
  */
3832
- getNextInsertPosition(page) {
3833
- const insertedRowCount = this.getInsertedRowCount(page);
3834
- if (insertedRowCount === 0) {
3835
- return _DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
3836
- }
3837
- const lastRowIndex = insertedRowCount - 1;
3838
- const lastRowOffset = this.getRowOffset(page, lastRowIndex);
3839
- const lastRow = this.getRow(page, lastRowIndex);
3840
- return lastRowOffset + lastRow.length;
3788
+ getValues(page) {
3789
+ const keysCount = this.getKeysCount(page);
3790
+ const valuesCount = this.getValuesCount(page);
3791
+ const byteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES + keysCount * _IndexPageManager.CONSTANT.SIZE_KEY;
3792
+ const values = new Float64Array(page.buffer, byteOffset, valuesCount);
3793
+ return Array.from(values);
3841
3794
  }
3842
3795
  /**
3843
- * Inserts a row into the page. `getNextSlotIndex` should be called beforehand to verify availability.
3796
+ * Sets the keys and values of the page.
3844
3797
  * @param page Page data
3845
- * @param row Row data
3798
+ * @param keys Keys
3799
+ * @param values Values
3846
3800
  */
3847
- insert(page, row) {
3848
- const slotOffsetSize = PageManager.CONSTANT.SIZE_SLOT_OFFSET;
3849
- const remainingCapacity = this.getRemainingCapacity(page);
3850
- const totalSize = row.length + slotOffsetSize;
3851
- if (remainingCapacity < totalSize) {
3852
- throw new Error("Not enough space to insert row");
3853
- }
3854
- const insertedRowCount = this.getInsertedRowCount(page);
3855
- const offset = this.getNextInsertPosition(page);
3856
- page.set(row, offset);
3857
- this.setRowOffset(page, insertedRowCount, offset);
3858
- this.setInsertedRowCount(page, insertedRowCount + 1);
3859
- this.setRemainingCapacity(page, remainingCapacity - totalSize);
3801
+ setKeysAndValues(page, keys, values) {
3802
+ const keysCount = keys.length;
3803
+ const valuesCount = values.length;
3804
+ const keyByteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES;
3805
+ const keyDest = new Float64Array(page.buffer, keyByteOffset, keysCount);
3806
+ keyDest.set(keys);
3807
+ const valByteOffset = keyByteOffset + keysCount * _IndexPageManager.CONSTANT.SIZE_KEY;
3808
+ const valDest = new Float64Array(page.buffer, valByteOffset, valuesCount);
3809
+ valDest.set(values);
3860
3810
  }
3861
3811
  };
3862
- var IndexPageManager = class _IndexPageManager extends PageManager {
3812
+ var MetadataPageManager = class _MetadataPageManager extends PageManager {
3863
3813
  get pageType() {
3864
- return PageManager.CONSTANT.PAGE_TYPE_INDEX;
3814
+ return PageManager.CONSTANT.PAGE_TYPE_METADATA;
3865
3815
  }
3866
3816
  static CONSTANT = {
3867
3817
  ...PageManager.CONSTANT,
3868
- OFFSET_INDEX_ID: 100,
3869
- OFFSET_PARENT_INDEX_ID: 104,
3870
- OFFSET_NEXT_INDEX_ID: 108,
3871
- OFFSET_PREV_INDEX_ID: 112,
3872
- OFFSET_IS_LEAF: 116,
3873
- OFFSET_KEYS_COUNT: 117,
3874
- OFFSET_VALUES_COUNT: 121,
3875
- OFFSET_KEYS_AND_VALUES: 128,
3876
- // 8-byte aligned (original 125 -> 128)
3877
- SIZE_INDEX_ID: 4,
3878
- SIZE_PARENT_INDEX_ID: 4,
3879
- SIZE_NEXT_INDEX_ID: 4,
3880
- SIZE_PREV_INDEX_ID: 4,
3881
- SIZE_IS_LEAF: 1,
3882
- SIZE_KEYS_COUNT: 4,
3883
- SIZE_VALUES_COUNT: 4,
3884
- SIZE_KEY: 8,
3885
- // Updated to 8 bytes for Float64
3886
- SIZE_VALUE: 8
3887
- // Updated to 8 bytes for Float64
3818
+ MAGIC_STRING: "DATAPLY",
3819
+ OFFSET_MAGIC_STRING: 100,
3820
+ OFFSET_PAGE_COUNT: 108,
3821
+ OFFSET_PAGE_SIZE: 112,
3822
+ OFFSET_ROW_COUNT: 116,
3823
+ OFFSET_ROOT_INDEX_PAGE_ID: 122,
3824
+ OFFSET_ROOT_INDEX_ORDER: 126,
3825
+ OFFSET_LAST_INSERT_PAGE_ID: 130,
3826
+ OFFSET_LAST_ROW_PK: 134,
3827
+ OFFSET_BITMAP_PAGE_ID: 140,
3828
+ OFFSET_FREE_PAGE_ID: 144,
3829
+ SIZE_PAGE_COUNT: 4,
3830
+ SIZE_PAGE_SIZE: 4,
3831
+ SIZE_ROOT_INDEX_PAGE_ID: 4,
3832
+ SIZE_ROOT_INDEX_ORDER: 4,
3833
+ SIZE_LAST_INSERT_PAGE_ID: 4,
3834
+ SIZE_ROW_PK: 6,
3835
+ SIZE_BITMAP_PAGE_ID: 4,
3836
+ SIZE_FREE_PAGE_ID: 4
3888
3837
  };
3889
3838
  /**
3890
- * Checks if the page type is `IndexPage`.
3839
+ * Checks if the page type is `MetadataPage`.
3891
3840
  * @param page Page data
3892
- * @returns boolean indicating if the page type is `IndexPage`
3841
+ * @returns boolean indicating if the page type is `MetadataPage`
3893
3842
  */
3894
- static IsIndexPage(page) {
3895
- return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_INDEX;
3843
+ static IsMetadataPage(page) {
3844
+ return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_METADATA;
3896
3845
  }
3897
3846
  /**
3898
- * Checks if the page type is `IndexPage`.
3847
+ * Checks if the page type is `MetadataPage`.
3899
3848
  * @param page Page data
3900
- * @returns boolean indicating if the page type is `IndexPage`
3849
+ * @returns boolean indicating if the page type is `MetadataPage`
3901
3850
  */
3902
- isIndexPage(page) {
3903
- return _IndexPageManager.IsIndexPage(page);
3851
+ isMetadataPage(page) {
3852
+ return _MetadataPageManager.IsMetadataPage(page);
3853
+ }
3854
+ /**
3855
+ * Verifies if the page is a valid metadata page.
3856
+ * @param page Page data
3857
+ * @returns Whether it is a metadata page
3858
+ */
3859
+ static Verify(page) {
3860
+ const start = _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING;
3861
+ const end = _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING + _MetadataPageManager.CONSTANT.MAGIC_STRING.length;
3862
+ const magicString = page.subarray(start, end);
3863
+ if (!magicString.every((byte, index) => byte === _MetadataPageManager.CONSTANT.MAGIC_STRING.charCodeAt(index))) {
3864
+ return false;
3865
+ }
3866
+ return true;
3867
+ }
3868
+ /**
3869
+ * Returns the number of pages stored in the database.
3870
+ * @param page Page data
3871
+ * @returns Number of pages
3872
+ */
3873
+ getPageCount(page) {
3874
+ return bytesToNumber(
3875
+ page,
3876
+ _MetadataPageManager.CONSTANT.OFFSET_PAGE_COUNT,
3877
+ _MetadataPageManager.CONSTANT.SIZE_PAGE_COUNT
3878
+ );
3879
+ }
3880
+ /**
3881
+ * Returns the database page size.
3882
+ * @param page Page data
3883
+ * @returns Page size
3884
+ */
3885
+ getPageSize(page) {
3886
+ return bytesToNumber(
3887
+ page,
3888
+ _MetadataPageManager.CONSTANT.OFFSET_PAGE_SIZE,
3889
+ _MetadataPageManager.CONSTANT.SIZE_PAGE_SIZE
3890
+ );
3891
+ }
3892
+ /**
3893
+ * Returns the Root Index Page ID of the database.
3894
+ * @param page Page data
3895
+ * @returns Root Index Page ID
3896
+ */
3897
+ getRootIndexPageId(page) {
3898
+ const id = bytesToNumber(
3899
+ page,
3900
+ _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_PAGE_ID,
3901
+ _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_PAGE_ID
3902
+ );
3903
+ return id === 4294967295 ? -1 : id;
3904
3904
  }
3905
3905
  /**
3906
- * Gets the index ID of the page.
3906
+ * Returns the order of the database Root Index Page.
3907
3907
  * @param page Page data
3908
- * @returns Index ID
3908
+ * @returns Root Index Page order
3909
3909
  */
3910
- getIndexId(page) {
3910
+ getRootIndexOrder(page) {
3911
3911
  return bytesToNumber(
3912
3912
  page,
3913
- _IndexPageManager.CONSTANT.OFFSET_INDEX_ID,
3914
- _IndexPageManager.CONSTANT.SIZE_INDEX_ID
3913
+ _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_ORDER,
3914
+ _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_ORDER
3915
3915
  );
3916
3916
  }
3917
3917
  /**
3918
- * Gets the parent index ID of the page.
3918
+ * Returns the ID of the last insertion page.
3919
3919
  * @param page Page data
3920
- * @returns Parent index ID
3920
+ * @returns Last insert page ID
3921
3921
  */
3922
- getParentIndexId(page) {
3922
+ getLastInsertPageId(page) {
3923
3923
  return bytesToNumber(
3924
3924
  page,
3925
- _IndexPageManager.CONSTANT.OFFSET_PARENT_INDEX_ID,
3926
- _IndexPageManager.CONSTANT.SIZE_PARENT_INDEX_ID
3925
+ _MetadataPageManager.CONSTANT.OFFSET_LAST_INSERT_PAGE_ID,
3926
+ _MetadataPageManager.CONSTANT.SIZE_LAST_INSERT_PAGE_ID
3927
3927
  );
3928
3928
  }
3929
3929
  /**
3930
- * Gets the next index ID of the page.
3930
+ * Returns the PK of the last inserted row in the database.
3931
3931
  * @param page Page data
3932
- * @returns Next index ID
3932
+ * @returns Last inserted row PK
3933
3933
  */
3934
- getNextIndexId(page) {
3934
+ getLastRowPk(page) {
3935
3935
  return bytesToNumber(
3936
3936
  page,
3937
- _IndexPageManager.CONSTANT.OFFSET_NEXT_INDEX_ID,
3938
- _IndexPageManager.CONSTANT.SIZE_NEXT_INDEX_ID
3937
+ _MetadataPageManager.CONSTANT.OFFSET_LAST_ROW_PK,
3938
+ _MetadataPageManager.CONSTANT.SIZE_ROW_PK
3939
3939
  );
3940
3940
  }
3941
3941
  /**
3942
- * Gets the previous index ID of the page.
3942
+ * Returns the number of rows in the database.
3943
3943
  * @param page Page data
3944
- * @returns Previous index ID
3944
+ * @returns Number of rows
3945
3945
  */
3946
- getPrevIndexId(page) {
3946
+ getRowCount(page) {
3947
3947
  return bytesToNumber(
3948
3948
  page,
3949
- _IndexPageManager.CONSTANT.OFFSET_PREV_INDEX_ID,
3950
- _IndexPageManager.CONSTANT.SIZE_PREV_INDEX_ID
3949
+ _MetadataPageManager.CONSTANT.OFFSET_ROW_COUNT,
3950
+ _MetadataPageManager.CONSTANT.SIZE_ROW_PK
3951
3951
  );
3952
3952
  }
3953
3953
  /**
3954
- * Gets the is leaf of the page.
3954
+ * Returns the ID of the bitmap page.
3955
3955
  * @param page Page data
3956
- * @returns Is leaf
3956
+ * @returns Bitmap page ID
3957
3957
  */
3958
- getIsLeaf(page) {
3958
+ getBitmapPageId(page) {
3959
3959
  return bytesToNumber(
3960
3960
  page,
3961
- _IndexPageManager.CONSTANT.OFFSET_IS_LEAF,
3962
- _IndexPageManager.CONSTANT.SIZE_IS_LEAF
3963
- ) === 1;
3961
+ _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
3962
+ _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
3963
+ );
3964
3964
  }
3965
3965
  /**
3966
- * Gets the keys count of the page.
3966
+ * Returns the ID of the free page.
3967
3967
  * @param page Page data
3968
- * @returns Keys count
3968
+ * @returns Free page ID
3969
3969
  */
3970
- getKeysCount(page) {
3971
- return bytesToNumber(
3970
+ getFreePageId(page) {
3971
+ const id = bytesToNumber(
3972
3972
  page,
3973
- _IndexPageManager.CONSTANT.OFFSET_KEYS_COUNT,
3974
- _IndexPageManager.CONSTANT.SIZE_KEYS_COUNT
3973
+ _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
3974
+ _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
3975
3975
  );
3976
+ return id === 4294967295 ? -1 : id;
3976
3977
  }
3977
3978
  /**
3978
- * Gets the values count of the page.
3979
+ * Sets the number of pages stored in the database.
3979
3980
  * @param page Page data
3980
- * @returns Values count
3981
+ * @param pageCount Number of pages
3981
3982
  */
3982
- getValuesCount(page) {
3983
- return bytesToNumber(
3983
+ setPageCount(page, pageCount) {
3984
+ numberToBytes(
3985
+ pageCount,
3984
3986
  page,
3985
- _IndexPageManager.CONSTANT.OFFSET_VALUES_COUNT,
3986
- _IndexPageManager.CONSTANT.SIZE_VALUES_COUNT
3987
+ _MetadataPageManager.CONSTANT.OFFSET_PAGE_COUNT,
3988
+ _MetadataPageManager.CONSTANT.SIZE_PAGE_COUNT
3987
3989
  );
3988
3990
  }
3989
3991
  /**
3990
- * Sets the index ID of the page.
3992
+ * Sets the database page size.
3991
3993
  * @param page Page data
3992
- * @param indexId Index ID
3994
+ * @param pageSize Page size
3993
3995
  */
3994
- setIndexId(page, indexId) {
3996
+ setPageSize(page, pageSize) {
3995
3997
  numberToBytes(
3996
- indexId,
3998
+ pageSize,
3997
3999
  page,
3998
- _IndexPageManager.CONSTANT.OFFSET_INDEX_ID,
3999
- _IndexPageManager.CONSTANT.SIZE_INDEX_ID
4000
+ _MetadataPageManager.CONSTANT.OFFSET_PAGE_SIZE,
4001
+ _MetadataPageManager.CONSTANT.SIZE_PAGE_SIZE
4000
4002
  );
4001
4003
  }
4002
4004
  /**
4003
- * Sets the parent index ID of the page.
4005
+ * Sets the Root Index Page ID of the database.
4004
4006
  * @param page Page data
4005
- * @param parentIndexId Parent index ID
4007
+ * @param rootIndexPageId Root Index Page ID
4006
4008
  */
4007
- setParentIndexId(page, parentIndexId) {
4009
+ setRootIndexPageId(page, rootIndexPageId) {
4008
4010
  numberToBytes(
4009
- parentIndexId,
4011
+ rootIndexPageId,
4010
4012
  page,
4011
- _IndexPageManager.CONSTANT.OFFSET_PARENT_INDEX_ID,
4012
- _IndexPageManager.CONSTANT.SIZE_PARENT_INDEX_ID
4013
+ _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_PAGE_ID,
4014
+ _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_PAGE_ID
4013
4015
  );
4014
4016
  }
4015
4017
  /**
4016
- * Sets the next index ID of the page.
4018
+ * Sets the order of the database Root Index Page.
4017
4019
  * @param page Page data
4018
- * @param nextIndexId Next index ID
4020
+ * @param order Root Index Page order
4019
4021
  */
4020
- setNextIndexId(page, nextIndexId) {
4022
+ setRootIndexOrder(page, order) {
4021
4023
  numberToBytes(
4022
- nextIndexId,
4024
+ order,
4023
4025
  page,
4024
- _IndexPageManager.CONSTANT.OFFSET_NEXT_INDEX_ID,
4025
- _IndexPageManager.CONSTANT.SIZE_NEXT_INDEX_ID
4026
+ _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_ORDER,
4027
+ _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_ORDER
4026
4028
  );
4027
4029
  }
4028
4030
  /**
4029
- * Sets the previous index ID of the page.
4031
+ * Sets the magic string of the page.
4030
4032
  * @param page Page data
4031
- * @param prevIndexId Previous index ID
4032
4033
  */
4033
- setPrevIndexId(page, prevIndexId) {
4034
+ setMagicString(page) {
4035
+ const encoding = new TextEncoder();
4036
+ const buffer = encoding.encode(_MetadataPageManager.CONSTANT.MAGIC_STRING);
4037
+ page.set(buffer, _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING);
4038
+ }
4039
+ /**
4040
+ * Sets the ID of the last insertion page.
4041
+ * @param page Page data
4042
+ * @param lastInsertPageId Last insert page ID
4043
+ */
4044
+ setLastInsertPageId(page, lastInsertPageId) {
4034
4045
  numberToBytes(
4035
- prevIndexId,
4046
+ lastInsertPageId,
4036
4047
  page,
4037
- _IndexPageManager.CONSTANT.OFFSET_PREV_INDEX_ID,
4038
- _IndexPageManager.CONSTANT.SIZE_PREV_INDEX_ID
4048
+ _MetadataPageManager.CONSTANT.OFFSET_LAST_INSERT_PAGE_ID,
4049
+ _MetadataPageManager.CONSTANT.SIZE_LAST_INSERT_PAGE_ID
4039
4050
  );
4040
4051
  }
4041
4052
  /**
4042
- * Sets the is leaf of the page.
4053
+ * Sets the PK of the last inserted row in the database.
4043
4054
  * @param page Page data
4044
- * @param isLeaf Is leaf
4055
+ * @param lastRowPk Last inserted row PK
4045
4056
  */
4046
- setIsLeaf(page, isLeaf) {
4057
+ setLastRowPk(page, lastRowPk) {
4047
4058
  numberToBytes(
4048
- isLeaf ? 1 : 0,
4059
+ lastRowPk,
4049
4060
  page,
4050
- _IndexPageManager.CONSTANT.OFFSET_IS_LEAF,
4051
- _IndexPageManager.CONSTANT.SIZE_IS_LEAF
4061
+ _MetadataPageManager.CONSTANT.OFFSET_LAST_ROW_PK,
4062
+ Row.CONSTANT.SIZE_PK
4052
4063
  );
4053
4064
  }
4054
4065
  /**
4055
- * Sets the keys count of the page.
4066
+ * Sets the number of rows in the database.
4056
4067
  * @param page Page data
4057
- * @param keysCount Keys count
4068
+ * @param rowCount Number of rows
4058
4069
  */
4059
- setKeysCount(page, keysCount) {
4070
+ setRowCount(page, rowCount) {
4060
4071
  numberToBytes(
4061
- keysCount,
4072
+ rowCount,
4062
4073
  page,
4063
- _IndexPageManager.CONSTANT.OFFSET_KEYS_COUNT,
4064
- _IndexPageManager.CONSTANT.SIZE_KEYS_COUNT
4074
+ _MetadataPageManager.CONSTANT.OFFSET_ROW_COUNT,
4075
+ Row.CONSTANT.SIZE_PK
4065
4076
  );
4066
4077
  }
4067
4078
  /**
4068
- * Sets the values count of the page.
4079
+ * Sets the ID of the bitmap page.
4069
4080
  * @param page Page data
4070
- * @param valuesCount Values count
4081
+ * @param bitmapPageId Bitmap page ID
4071
4082
  */
4072
- setValuesCount(page, valuesCount) {
4083
+ setBitmapPageId(page, bitmapPageId) {
4073
4084
  numberToBytes(
4074
- valuesCount,
4085
+ bitmapPageId,
4075
4086
  page,
4076
- _IndexPageManager.CONSTANT.OFFSET_VALUES_COUNT,
4077
- _IndexPageManager.CONSTANT.SIZE_VALUES_COUNT
4087
+ _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
4088
+ _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
4078
4089
  );
4079
4090
  }
4080
4091
  /**
4081
- * Gets the keys of the page.
4092
+ * Sets the ID of the free page.
4082
4093
  * @param page Page data
4083
- * @returns Keys
4094
+ * @param pageId Free page ID
4084
4095
  */
4085
- getKeys(page) {
4086
- const keysCount = this.getKeysCount(page);
4087
- const byteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES;
4088
- const keys = new Float64Array(page.buffer, byteOffset, keysCount);
4089
- return Array.from(keys);
4096
+ setFreePageId(page, pageId) {
4097
+ numberToBytes(
4098
+ pageId,
4099
+ page,
4100
+ _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
4101
+ _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
4102
+ );
4103
+ }
4104
+ };
4105
+ var BitmapPageManager = class _BitmapPageManager extends PageManager {
4106
+ get pageType() {
4107
+ return PageManager.CONSTANT.PAGE_TYPE_BITMAP;
4090
4108
  }
4091
4109
  /**
4092
- * Gets the values of the page.
4110
+ * Checks if the page type is `BitmapPage`.
4093
4111
  * @param page Page data
4094
- * @returns Values
4112
+ * @returns boolean indicating if the page type is `BitmapPage`
4095
4113
  */
4096
- getValues(page) {
4097
- const keysCount = this.getKeysCount(page);
4098
- const valuesCount = this.getValuesCount(page);
4099
- const byteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES + keysCount * _IndexPageManager.CONSTANT.SIZE_KEY;
4100
- const values = new Float64Array(page.buffer, byteOffset, valuesCount);
4101
- return Array.from(values);
4114
+ static IsBitmapPage(page) {
4115
+ return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_BITMAP;
4102
4116
  }
4103
4117
  /**
4104
- * Sets the keys and values of the page.
4118
+ * Checks if the page type is `BitmapPage`.
4105
4119
  * @param page Page data
4106
- * @param keys Keys
4107
- * @param values Values
4120
+ * @returns boolean indicating if the page type is `BitmapPage`
4108
4121
  */
4109
- setKeysAndValues(page, keys, values) {
4110
- const keysCount = keys.length;
4111
- const valuesCount = values.length;
4112
- const keyByteOffset = page.byteOffset + _IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES;
4113
- const keyDest = new Float64Array(page.buffer, keyByteOffset, keysCount);
4114
- keyDest.set(keys);
4115
- const valByteOffset = keyByteOffset + keysCount * _IndexPageManager.CONSTANT.SIZE_KEY;
4116
- const valDest = new Float64Array(page.buffer, valByteOffset, valuesCount);
4117
- valDest.set(values);
4118
- }
4119
- };
4120
- var MetadataPageManager = class _MetadataPageManager extends PageManager {
4121
- get pageType() {
4122
- return PageManager.CONSTANT.PAGE_TYPE_METADATA;
4123
- }
4124
- static CONSTANT = {
4125
- ...PageManager.CONSTANT,
4126
- MAGIC_STRING: "DATAPLY",
4127
- OFFSET_MAGIC_STRING: 100,
4128
- OFFSET_PAGE_COUNT: 108,
4129
- OFFSET_PAGE_SIZE: 112,
4130
- OFFSET_ROW_COUNT: 116,
4131
- OFFSET_ROOT_INDEX_PAGE_ID: 122,
4132
- OFFSET_ROOT_INDEX_ORDER: 126,
4133
- OFFSET_LAST_INSERT_PAGE_ID: 130,
4134
- OFFSET_LAST_ROW_PK: 134,
4135
- OFFSET_BITMAP_PAGE_ID: 140,
4136
- OFFSET_FREE_PAGE_ID: 144,
4137
- SIZE_PAGE_COUNT: 4,
4138
- SIZE_PAGE_SIZE: 4,
4139
- SIZE_ROOT_INDEX_PAGE_ID: 4,
4140
- SIZE_ROOT_INDEX_ORDER: 4,
4141
- SIZE_LAST_INSERT_PAGE_ID: 4,
4142
- SIZE_ROW_PK: 6,
4143
- SIZE_BITMAP_PAGE_ID: 4,
4144
- SIZE_FREE_PAGE_ID: 4
4145
- };
4122
+ isBitmapPage(page) {
4123
+ return _BitmapPageManager.IsBitmapPage(page);
4124
+ }
4146
4125
  /**
4147
- * Checks if the page type is `MetadataPage`.
4126
+ * Checks if a page is empty.
4148
4127
  * @param page Page data
4149
- * @returns boolean indicating if the page type is `MetadataPage`
4128
+ * @param index Bitmap index
4129
+ * @returns boolean indicating if the page is empty
4150
4130
  */
4151
- static IsMetadataPage(page) {
4152
- return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_METADATA;
4131
+ isEmptyPage(page, index) {
4132
+ return bytesToNumber(page, index, 1) === 0;
4153
4133
  }
4154
4134
  /**
4155
- * Checks if the page type is `MetadataPage`.
4135
+ * Gets a bit from the bitmap page.
4156
4136
  * @param page Page data
4157
- * @returns boolean indicating if the page type is `MetadataPage`
4137
+ * @param index Bit index
4138
+ * @returns boolean indicating if the bit is set
4158
4139
  */
4159
- isMetadataPage(page) {
4160
- return _MetadataPageManager.IsMetadataPage(page);
4140
+ getBit(page, index) {
4141
+ const bitOffset = Math.floor(index / 8);
4142
+ const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4143
+ const value = bytesToNumber(page, offset, 1);
4144
+ return getBit(value, index % 8);
4161
4145
  }
4162
4146
  /**
4163
- * Verifies if the page is a valid metadata page.
4147
+ * Sets a bit in the bitmap page.
4164
4148
  * @param page Page data
4165
- * @returns Whether it is a metadata page
4149
+ * @param index Bit index
4150
+ * @param flag boolean indicating if the bit is set
4166
4151
  */
4167
- static Verify(page) {
4168
- const start = _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING;
4169
- const end = _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING + _MetadataPageManager.CONSTANT.MAGIC_STRING.length;
4170
- const magicString = page.subarray(start, end);
4171
- if (!magicString.every((byte, index) => byte === _MetadataPageManager.CONSTANT.MAGIC_STRING.charCodeAt(index))) {
4172
- return false;
4173
- }
4174
- return true;
4152
+ setBit(page, index, flag) {
4153
+ const bitOffset = Math.floor(index / 8);
4154
+ const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4155
+ const value = bytesToNumber(page, offset, 1);
4156
+ const newValue = setBit(value, index % 8, flag);
4157
+ numberToBytes(newValue, page, offset, 1);
4158
+ }
4159
+ };
4160
+ var OverflowPageManager = class _OverflowPageManager extends PageManager {
4161
+ get pageType() {
4162
+ return PageManager.CONSTANT.PAGE_TYPE_OVERFLOW;
4175
4163
  }
4176
4164
  /**
4177
- * Returns the number of pages stored in the database.
4165
+ * Checks if the page type is `OverflowPage`.
4178
4166
  * @param page Page data
4179
- * @returns Number of pages
4167
+ * @returns boolean indicating if the page type is `OverflowPage`
4180
4168
  */
4181
- getPageCount(page) {
4182
- return bytesToNumber(
4183
- page,
4184
- _MetadataPageManager.CONSTANT.OFFSET_PAGE_COUNT,
4185
- _MetadataPageManager.CONSTANT.SIZE_PAGE_COUNT
4186
- );
4169
+ static IsOverflowPage(page) {
4170
+ return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_OVERFLOW;
4187
4171
  }
4188
4172
  /**
4189
- * Returns the database page size.
4173
+ * Checks if the page type is `OverflowPage`.
4190
4174
  * @param page Page data
4191
- * @returns Page size
4175
+ * @returns boolean indicating if the page type is `OverflowPage`
4192
4176
  */
4193
- getPageSize(page) {
4194
- return bytesToNumber(
4195
- page,
4196
- _MetadataPageManager.CONSTANT.OFFSET_PAGE_SIZE,
4197
- _MetadataPageManager.CONSTANT.SIZE_PAGE_SIZE
4198
- );
4177
+ isOverflowPage(page) {
4178
+ return _OverflowPageManager.IsOverflowPage(page);
4179
+ }
4180
+ };
4181
+ var UnknownPageManager = class _UnknownPageManager extends PageManager {
4182
+ get pageType() {
4183
+ return PageManager.CONSTANT.PAGE_TYPE_UNKNOWN;
4199
4184
  }
4200
4185
  /**
4201
- * Returns the Root Index Page ID of the database.
4186
+ * Checks if the page type is `UnknownPage`.
4202
4187
  * @param page Page data
4203
- * @returns Root Index Page ID
4188
+ * @returns boolean indicating if the page type is `UnknownPage`
4204
4189
  */
4205
- getRootIndexPageId(page) {
4206
- const id = bytesToNumber(
4207
- page,
4208
- _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_PAGE_ID,
4209
- _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_PAGE_ID
4210
- );
4211
- return id === 4294967295 ? -1 : id;
4190
+ static IsUnknownPage(page) {
4191
+ return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_UNKNOWN;
4212
4192
  }
4213
4193
  /**
4214
- * Returns the order of the database Root Index Page.
4194
+ * Checks if the page is `UnknownPage`.
4215
4195
  * @param page Page data
4216
- * @returns Root Index Page order
4196
+ * @returns `true` if the page is `UnknownPage`, otherwise `false`
4217
4197
  */
4218
- getRootIndexOrder(page) {
4219
- return bytesToNumber(
4220
- page,
4221
- _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_ORDER,
4222
- _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_ORDER
4223
- );
4198
+ isUnknownPage(page) {
4199
+ return _UnknownPageManager.IsUnknownPage(page);
4224
4200
  }
4201
+ };
4202
+ var PageManagerFactory = class _PageManagerFactory {
4203
+ static EmptyPage = new EmptyPageManager();
4204
+ static DataPage = new DataPageManager();
4205
+ static IndexPage = new IndexPageManager();
4206
+ static MetadataPage = new MetadataPageManager();
4207
+ static BitmapPage = new BitmapPageManager();
4208
+ static OverflowPage = new OverflowPageManager();
4209
+ static UnknownPage = new UnknownPageManager();
4225
4210
  /**
4226
- * Returns the ID of the last insertion page.
4211
+ * Returns the page type.
4227
4212
  * @param page Page data
4228
- * @returns Last insert page ID
4213
+ * @returns Page type
4229
4214
  */
4230
- getLastInsertPageId(page) {
4231
- return bytesToNumber(
4232
- page,
4233
- _MetadataPageManager.CONSTANT.OFFSET_LAST_INSERT_PAGE_ID,
4234
- _MetadataPageManager.CONSTANT.SIZE_LAST_INSERT_PAGE_ID
4235
- );
4215
+ getPageType(page) {
4216
+ return bytesToNumber(page, PageManager.CONSTANT.OFFSET_PAGE_TYPE, PageManager.CONSTANT.SIZE_PAGE_TYPE);
4236
4217
  }
4237
4218
  /**
4238
- * Returns the PK of the last inserted row in the database.
4219
+ * Checks if the page is `EmptyPage`.
4239
4220
  * @param page Page data
4240
- * @returns Last inserted row PK
4221
+ * @returns `true` if the page is `EmptyPage`, otherwise `false`
4241
4222
  */
4242
- getLastRowPk(page) {
4243
- return bytesToNumber(
4244
- page,
4245
- _MetadataPageManager.CONSTANT.OFFSET_LAST_ROW_PK,
4246
- _MetadataPageManager.CONSTANT.SIZE_ROW_PK
4247
- );
4223
+ isEmptyPage(page) {
4224
+ return EmptyPageManager.IsEmptyPage(page);
4248
4225
  }
4249
4226
  /**
4250
- * Returns the number of rows in the database.
4227
+ * Checks if the page is `DataPage`.
4251
4228
  * @param page Page data
4252
- * @returns Number of rows
4229
+ * @returns `true` if the page is `DataPage`, otherwise `false`
4253
4230
  */
4254
- getRowCount(page) {
4255
- return bytesToNumber(
4256
- page,
4257
- _MetadataPageManager.CONSTANT.OFFSET_ROW_COUNT,
4258
- _MetadataPageManager.CONSTANT.SIZE_ROW_PK
4259
- );
4231
+ isDataPage(page) {
4232
+ return DataPageManager.IsDataPage(page);
4260
4233
  }
4261
4234
  /**
4262
- * Returns the ID of the bitmap page.
4235
+ * Checks if the page is `IndexPage`.
4263
4236
  * @param page Page data
4264
- * @returns Bitmap page ID
4237
+ * @returns `true` if the page is `IndexPage`, otherwise `false`
4265
4238
  */
4266
- getBitmapPageId(page) {
4267
- return bytesToNumber(
4268
- page,
4269
- _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
4270
- _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
4271
- );
4239
+ isIndexPage(page) {
4240
+ return IndexPageManager.IsIndexPage(page);
4272
4241
  }
4273
4242
  /**
4274
- * Returns the ID of the free page.
4243
+ * Checks if the page is `MetadataPage`.
4275
4244
  * @param page Page data
4276
- * @returns Free page ID
4245
+ * @returns `true` if the page is `MetadataPage`, otherwise `false`
4277
4246
  */
4278
- getFreePageId(page) {
4279
- const id = bytesToNumber(
4280
- page,
4281
- _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
4282
- _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
4283
- );
4284
- return id === 4294967295 ? -1 : id;
4247
+ isMetadataPage(page) {
4248
+ return MetadataPageManager.IsMetadataPage(page);
4285
4249
  }
4286
4250
  /**
4287
- * Sets the number of pages stored in the database.
4251
+ * Checks if the page is `BitmapPage`.
4288
4252
  * @param page Page data
4289
- * @param pageCount Number of pages
4253
+ * @returns `true` if the page is `BitmapPage`, otherwise `false`
4290
4254
  */
4291
- setPageCount(page, pageCount) {
4292
- numberToBytes(
4293
- pageCount,
4294
- page,
4295
- _MetadataPageManager.CONSTANT.OFFSET_PAGE_COUNT,
4296
- _MetadataPageManager.CONSTANT.SIZE_PAGE_COUNT
4297
- );
4255
+ isBitmapPage(page) {
4256
+ return BitmapPageManager.IsBitmapPage(page);
4298
4257
  }
4299
4258
  /**
4300
- * Sets the database page size.
4259
+ * Checks if the page is `OverflowPage`.
4301
4260
  * @param page Page data
4302
- * @param pageSize Page size
4261
+ * @returns `true` if the page is `OverflowPage`, otherwise `false`
4303
4262
  */
4304
- setPageSize(page, pageSize) {
4305
- numberToBytes(
4306
- pageSize,
4307
- page,
4308
- _MetadataPageManager.CONSTANT.OFFSET_PAGE_SIZE,
4309
- _MetadataPageManager.CONSTANT.SIZE_PAGE_SIZE
4310
- );
4263
+ isOverflowPage(page) {
4264
+ return OverflowPageManager.IsOverflowPage(page);
4265
+ }
4266
+ /**
4267
+ * Checks if the page is `UnknownPage`.
4268
+ * @param page Page data
4269
+ * @returns `true` if the page is `UnknownPage`, otherwise `false`
4270
+ */
4271
+ isUnknownPage(page) {
4272
+ return UnknownPageManager.IsUnknownPage(page);
4273
+ }
4274
+ getManager(page) {
4275
+ switch (this.getPageType(page)) {
4276
+ case PageManager.CONSTANT.PAGE_TYPE_EMPTY:
4277
+ return _PageManagerFactory.EmptyPage;
4278
+ case PageManager.CONSTANT.PAGE_TYPE_METADATA:
4279
+ return _PageManagerFactory.MetadataPage;
4280
+ case PageManager.CONSTANT.PAGE_TYPE_BITMAP:
4281
+ return _PageManagerFactory.BitmapPage;
4282
+ case PageManager.CONSTANT.PAGE_TYPE_INDEX:
4283
+ return _PageManagerFactory.IndexPage;
4284
+ case PageManager.CONSTANT.PAGE_TYPE_DATA:
4285
+ return _PageManagerFactory.DataPage;
4286
+ case PageManager.CONSTANT.PAGE_TYPE_OVERFLOW:
4287
+ return _PageManagerFactory.OverflowPage;
4288
+ case PageManager.CONSTANT.PAGE_TYPE_UNKNOWN:
4289
+ return _PageManagerFactory.UnknownPage;
4290
+ default:
4291
+ throw new Error(`Invalid page type: ${this.getPageType(page)}`);
4292
+ }
4293
+ }
4294
+ getManagerFromType(pageType) {
4295
+ switch (pageType) {
4296
+ case PageManager.CONSTANT.PAGE_TYPE_EMPTY:
4297
+ return _PageManagerFactory.EmptyPage;
4298
+ case PageManager.CONSTANT.PAGE_TYPE_METADATA:
4299
+ return _PageManagerFactory.MetadataPage;
4300
+ case PageManager.CONSTANT.PAGE_TYPE_BITMAP:
4301
+ return _PageManagerFactory.BitmapPage;
4302
+ case PageManager.CONSTANT.PAGE_TYPE_INDEX:
4303
+ return _PageManagerFactory.IndexPage;
4304
+ case PageManager.CONSTANT.PAGE_TYPE_DATA:
4305
+ return _PageManagerFactory.DataPage;
4306
+ case PageManager.CONSTANT.PAGE_TYPE_OVERFLOW:
4307
+ return _PageManagerFactory.OverflowPage;
4308
+ case PageManager.CONSTANT.PAGE_TYPE_UNKNOWN:
4309
+ return _PageManagerFactory.UnknownPage;
4310
+ default:
4311
+ throw new Error(`Invalid page type: ${pageType}`);
4312
+ }
4313
+ }
4314
+ };
4315
+
4316
+ // src/core/DataplyAPI.ts
4317
+ var import_node_fs3 = __toESM(require("node:fs"));
4318
+
4319
+ // node_modules/hookall/dist/esm/index.mjs
4320
+ var HookallStore = class extends WeakMap {
4321
+ ensure(obj, key) {
4322
+ if (!this.has(obj)) {
4323
+ const scope2 = {};
4324
+ this.set(obj, scope2);
4325
+ }
4326
+ const scope = this.get(obj);
4327
+ if (!Object.prototype.hasOwnProperty.call(scope, key)) {
4328
+ scope[key] = /* @__PURE__ */ new Map();
4329
+ }
4330
+ return scope[key];
4311
4331
  }
4332
+ };
4333
+ var Hookall = class _Hookall {
4334
+ static Global = {};
4335
+ static _Store = new HookallStore();
4336
+ beforeHooks;
4337
+ afterHooks;
4312
4338
  /**
4313
- * Sets the Root Index Page ID of the database.
4314
- * @param page Page data
4315
- * @param rootIndexPageId Root Index Page ID
4339
+ * Create hook system. you can pass a target object or undefined.
4340
+ * If you pass a object, the hook system will be work for object locally. You're going to want this kind of usage in general.
4341
+ * If not specified, will be work for global. This is useful when you want to share your work with multiple files.
4342
+ * @param target The object to work with locally. If not specified, will be work for global.
4316
4343
  */
4317
- setRootIndexPageId(page, rootIndexPageId) {
4318
- numberToBytes(
4319
- rootIndexPageId,
4320
- page,
4321
- _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_PAGE_ID,
4322
- _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_PAGE_ID
4323
- );
4344
+ constructor(target) {
4345
+ this.beforeHooks = _Hookall._Store.ensure(target, "before");
4346
+ this.afterHooks = _Hookall._Store.ensure(target, "after");
4324
4347
  }
4325
- /**
4326
- * Sets the order of the database Root Index Page.
4327
- * @param page Page data
4328
- * @param order Root Index Page order
4329
- */
4330
- setRootIndexOrder(page, order) {
4331
- numberToBytes(
4332
- order,
4333
- page,
4334
- _MetadataPageManager.CONSTANT.OFFSET_ROOT_INDEX_ORDER,
4335
- _MetadataPageManager.CONSTANT.SIZE_ROOT_INDEX_ORDER
4336
- );
4348
+ _ensureCommand(hooks, command) {
4349
+ if (!hooks.has(command)) {
4350
+ hooks.set(command, []);
4351
+ }
4352
+ return hooks.get(command);
4337
4353
  }
4338
- /**
4339
- * Sets the magic string of the page.
4340
- * @param page Page data
4341
- */
4342
- setMagicString(page) {
4343
- const encoding = new TextEncoder();
4344
- const buffer = encoding.encode(_MetadataPageManager.CONSTANT.MAGIC_STRING);
4345
- page.set(buffer, _MetadataPageManager.CONSTANT.OFFSET_MAGIC_STRING);
4354
+ _createWrapper(command, callback, repeat) {
4355
+ return {
4356
+ callback,
4357
+ command,
4358
+ repeat
4359
+ };
4346
4360
  }
4347
- /**
4348
- * Sets the ID of the last insertion page.
4349
- * @param page Page data
4350
- * @param lastInsertPageId Last insert page ID
4351
- */
4352
- setLastInsertPageId(page, lastInsertPageId) {
4353
- numberToBytes(
4354
- lastInsertPageId,
4355
- page,
4356
- _MetadataPageManager.CONSTANT.OFFSET_LAST_INSERT_PAGE_ID,
4357
- _MetadataPageManager.CONSTANT.SIZE_LAST_INSERT_PAGE_ID
4358
- );
4361
+ _on(hooks, command, callback, repeat) {
4362
+ const wrappers = this._ensureCommand(hooks, command);
4363
+ const wrapper = this._createWrapper(command, callback, repeat);
4364
+ wrappers.unshift(wrapper);
4359
4365
  }
4360
4366
  /**
4361
- * Sets the PK of the last inserted row in the database.
4362
- * @param page Page data
4363
- * @param lastRowPk Last inserted row PK
4367
+ * You register a preprocessing function, which is called before the callback function of the `trigger` method.
4368
+ * The value returned by this function is passed as a parameter to the `trigger` method's callback function.
4369
+ * If you register multiple preprocessing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
4370
+ * @param command Command to work.
4371
+ * @param callback Preprocessing function to register.
4364
4372
  */
4365
- setLastRowPk(page, lastRowPk) {
4366
- numberToBytes(
4367
- lastRowPk,
4368
- page,
4369
- _MetadataPageManager.CONSTANT.OFFSET_LAST_ROW_PK,
4370
- Row.CONSTANT.SIZE_PK
4371
- );
4373
+ onBefore(command, callback) {
4374
+ this._on(this.beforeHooks, command, callback, -1);
4375
+ return this;
4372
4376
  }
4373
4377
  /**
4374
- * Sets the number of rows in the database.
4375
- * @param page Page data
4376
- * @param rowCount Number of rows
4378
+ * Similar to the `onBefore` method, but it only runs once.
4379
+ * For more details, please refer to the `onBefore` method.
4380
+ * @param command Command to work.
4381
+ * @param callback Preprocessing function to register.
4377
4382
  */
4378
- setRowCount(page, rowCount) {
4379
- numberToBytes(
4380
- rowCount,
4381
- page,
4382
- _MetadataPageManager.CONSTANT.OFFSET_ROW_COUNT,
4383
- Row.CONSTANT.SIZE_PK
4384
- );
4383
+ onceBefore(command, callback) {
4384
+ this._on(this.beforeHooks, command, callback, 1);
4385
+ return this;
4385
4386
  }
4386
4387
  /**
4387
- * Sets the ID of the bitmap page.
4388
- * @param page Page data
4389
- * @param bitmapPageId Bitmap page ID
4388
+ * You register a post-processing function which is called after the callback function of the `trigger` method finishes.
4389
+ * This function receives the value returned by the `trigger` method's callback function as a parameter.
4390
+ * If you register multiple post-processing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
4391
+ * @param command Command to work.
4392
+ * @param callback Post-preprocessing function to register.
4390
4393
  */
4391
- setBitmapPageId(page, bitmapPageId) {
4392
- numberToBytes(
4393
- bitmapPageId,
4394
- page,
4395
- _MetadataPageManager.CONSTANT.OFFSET_BITMAP_PAGE_ID,
4396
- _MetadataPageManager.CONSTANT.SIZE_BITMAP_PAGE_ID
4397
- );
4394
+ onAfter(command, callback) {
4395
+ this._on(this.afterHooks, command, callback, -1);
4396
+ return this;
4398
4397
  }
4399
4398
  /**
4400
- * Sets the ID of the free page.
4401
- * @param page Page data
4402
- * @param pageId Free page ID
4399
+ * Similar to the `onAfter` method, but it only runs once.
4400
+ * For more details, please refer to the `onAfter` method.
4401
+ * @param command Command to work.
4402
+ * @param callback Post-preprocessing function to register.
4403
4403
  */
4404
- setFreePageId(page, pageId) {
4405
- numberToBytes(
4406
- pageId,
4407
- page,
4408
- _MetadataPageManager.CONSTANT.OFFSET_FREE_PAGE_ID,
4409
- _MetadataPageManager.CONSTANT.SIZE_FREE_PAGE_ID
4410
- );
4404
+ onceAfter(command, callback) {
4405
+ this._on(this.afterHooks, command, callback, 1);
4406
+ return this;
4411
4407
  }
4412
- };
4413
- var BitmapPageManager = class _BitmapPageManager extends PageManager {
4414
- get pageType() {
4415
- return PageManager.CONSTANT.PAGE_TYPE_BITMAP;
4408
+ _off(hooks, command, callback) {
4409
+ const wrappers = this._ensureCommand(hooks, command);
4410
+ if (callback) {
4411
+ const i = wrappers.findIndex((wrapper) => wrapper.callback === callback);
4412
+ if (i !== -1) {
4413
+ wrappers.splice(i, 1);
4414
+ }
4415
+ } else {
4416
+ wrappers.length = 0;
4417
+ }
4418
+ return this;
4416
4419
  }
4417
4420
  /**
4418
- * Checks if the page type is `BitmapPage`.
4419
- * @param page Page data
4420
- * @returns boolean indicating if the page type is `BitmapPage`
4421
+ * You remove the preprocessing functions registered with `onBefore` or `onceBefore` methods.
4422
+ * If you don't specify a callback parameter, it removes all preprocessing functions registered for that command.
4423
+ * @param command Commands with preprocessing functions to be deleted.
4424
+ * @param callback Preprocessing function to be deleted.
4421
4425
  */
4422
- static IsBitmapPage(page) {
4423
- return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_BITMAP;
4426
+ offBefore(command, callback) {
4427
+ this._off(this.beforeHooks, command, callback);
4428
+ return this;
4424
4429
  }
4425
4430
  /**
4426
- * Checks if the page type is `BitmapPage`.
4427
- * @param page Page data
4428
- * @returns boolean indicating if the page type is `BitmapPage`
4431
+ * You remove the post-preprocessing functions registered with `onAfter` or `onceAfter` methods.
4432
+ * If you don't specify a callback parameter, it removes all post-preprocessing functions registered for that command.
4433
+ * @param command Commands with post-preprocessing functions to be deleted.
4434
+ * @param callback post-Preprocessing function to be deleted.
4429
4435
  */
4430
- isBitmapPage(page) {
4431
- return _BitmapPageManager.IsBitmapPage(page);
4436
+ offAfter(command, callback) {
4437
+ this._off(this.afterHooks, command, callback);
4438
+ return this;
4432
4439
  }
4433
- /**
4434
- * Checks if a page is empty.
4435
- * @param page Page data
4436
- * @param index Bitmap index
4437
- * @returns boolean indicating if the page is empty
4438
- */
4439
- isEmptyPage(page, index) {
4440
- return bytesToNumber(page, index, 1) === 0;
4440
+ async _hookWith(hooks, command, value, ...params) {
4441
+ let wrappers = this._ensureCommand(hooks, command);
4442
+ let i = wrappers.length;
4443
+ while (i--) {
4444
+ const wrapper = wrappers[i];
4445
+ value = await wrapper.callback(value, ...params);
4446
+ wrapper.repeat -= 1;
4447
+ if (wrapper.repeat === 0) {
4448
+ this._off(hooks, command, wrapper.callback);
4449
+ }
4450
+ }
4451
+ return value;
4441
4452
  }
4442
4453
  /**
4443
- * Gets a bit from the bitmap page.
4444
- * @param page Page data
4445
- * @param index Bit index
4446
- * @returns boolean indicating if the bit is set
4454
+ * You execute the callback function provided as a parameter. This callback function receives the 'initialValue' parameter.
4455
+ *
4456
+ * If preprocessing functions are registered, they run first, and the value returned by the preprocessing functions becomes the 'initialValue' parameter.
4457
+ * After the callback function finishes, post-processing functions are called.
4458
+ * These post-processing functions receive the value returned by the callback function as a parameter and run sequentially.
4459
+ *
4460
+ * The final value returned becomes the result of the `trigger` method.
4461
+ * @param command Command to work.
4462
+ * @param initialValue Initial value to be passed to the callback function.
4463
+ * @param callback The callback function to be executed.
4447
4464
  */
4448
- getBit(page, index) {
4449
- const bitOffset = Math.floor(index / 8);
4450
- const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4451
- const value = bytesToNumber(page, offset, 1);
4452
- return getBit(value, index % 8);
4465
+ async trigger(command, initialValue, callback, ...params) {
4466
+ let value;
4467
+ value = await this._hookWith(this.beforeHooks, command, initialValue, ...params);
4468
+ value = await callback(value, ...params);
4469
+ value = await this._hookWith(this.afterHooks, command, value, ...params);
4470
+ return value;
4453
4471
  }
4454
- /**
4455
- * Sets a bit in the bitmap page.
4456
- * @param page Page data
4457
- * @param index Bit index
4458
- * @param flag boolean indicating if the bit is set
4459
- */
4460
- setBit(page, index, flag) {
4461
- const bitOffset = Math.floor(index / 8);
4462
- const offset = _BitmapPageManager.CONSTANT.SIZE_PAGE_HEADER + bitOffset;
4463
- const value = bytesToNumber(page, offset, 1);
4464
- const newValue = setBit(value, index % 8, flag);
4465
- numberToBytes(newValue, page, offset, 1);
4472
+ };
4473
+ function useHookall(target = Hookall.Global) {
4474
+ return new Hookall(target);
4475
+ }
4476
+ var HookallStore2 = class extends WeakMap {
4477
+ ensure(obj, key) {
4478
+ if (!this.has(obj)) {
4479
+ const scope2 = {};
4480
+ this.set(obj, scope2);
4481
+ }
4482
+ const scope = this.get(obj);
4483
+ if (!Object.prototype.hasOwnProperty.call(scope, key)) {
4484
+ scope[key] = /* @__PURE__ */ new Map();
4485
+ }
4486
+ return scope[key];
4466
4487
  }
4467
4488
  };
4468
- var OverflowPageManager = class _OverflowPageManager extends PageManager {
4469
- get pageType() {
4470
- return PageManager.CONSTANT.PAGE_TYPE_OVERFLOW;
4471
- }
4489
+ var HookallSync = class _HookallSync {
4490
+ static Global = {};
4491
+ static _Store = new HookallStore2();
4492
+ beforeHooks;
4493
+ afterHooks;
4472
4494
  /**
4473
- * Checks if the page type is `OverflowPage`.
4474
- * @param page Page data
4475
- * @returns boolean indicating if the page type is `OverflowPage`
4495
+ * Create hook system. you can pass a target object or undefined.
4496
+ * If you pass a object, the hook system will be work for object locally. You're going to want this kind of usage in general.
4497
+ * If not specified, will be work for global. This is useful when you want to share your work with multiple files.
4498
+ * @param target The object to work with locally. If not specified, will be work for global.
4476
4499
  */
4477
- static IsOverflowPage(page) {
4478
- return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_OVERFLOW;
4500
+ constructor(target) {
4501
+ this.beforeHooks = _HookallSync._Store.ensure(target, "before");
4502
+ this.afterHooks = _HookallSync._Store.ensure(target, "after");
4479
4503
  }
4480
- /**
4481
- * Checks if the page type is `OverflowPage`.
4482
- * @param page Page data
4483
- * @returns boolean indicating if the page type is `OverflowPage`
4484
- */
4485
- isOverflowPage(page) {
4486
- return _OverflowPageManager.IsOverflowPage(page);
4504
+ _ensureCommand(hooks, command) {
4505
+ if (!hooks.has(command)) {
4506
+ hooks.set(command, []);
4507
+ }
4508
+ return hooks.get(command);
4487
4509
  }
4488
- };
4489
- var UnknownPageManager = class _UnknownPageManager extends PageManager {
4490
- get pageType() {
4491
- return PageManager.CONSTANT.PAGE_TYPE_UNKNOWN;
4510
+ _createWrapper(command, callback, repeat) {
4511
+ return {
4512
+ callback,
4513
+ command,
4514
+ repeat
4515
+ };
4492
4516
  }
4493
- /**
4494
- * Checks if the page type is `UnknownPage`.
4495
- * @param page Page data
4496
- * @returns boolean indicating if the page type is `UnknownPage`
4497
- */
4498
- static IsUnknownPage(page) {
4499
- return PageManager.GetPageType(page) === PageManager.CONSTANT.PAGE_TYPE_UNKNOWN;
4517
+ _on(hooks, command, callback, repeat) {
4518
+ const wrappers = this._ensureCommand(hooks, command);
4519
+ const wrapper = this._createWrapper(command, callback, repeat);
4520
+ wrappers.unshift(wrapper);
4500
4521
  }
4501
4522
  /**
4502
- * Checks if the page is `UnknownPage`.
4503
- * @param page Page data
4504
- * @returns `true` if the page is `UnknownPage`, otherwise `false`
4523
+ * You register a preprocessing function, which is called before the callback function of the `trigger` method.
4524
+ * The value returned by this function is passed as a parameter to the `trigger` method's callback function.
4525
+ * If you register multiple preprocessing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
4526
+ * @param command Command to work.
4527
+ * @param callback Preprocessing function to register.
4505
4528
  */
4506
- isUnknownPage(page) {
4507
- return _UnknownPageManager.IsUnknownPage(page);
4529
+ onBefore(command, callback) {
4530
+ this._on(this.beforeHooks, command, callback, -1);
4531
+ return this;
4508
4532
  }
4509
- };
4510
- var PageManagerFactory = class _PageManagerFactory {
4511
- static EmptyPage = new EmptyPageManager();
4512
- static DataPage = new DataPageManager();
4513
- static IndexPage = new IndexPageManager();
4514
- static MetadataPage = new MetadataPageManager();
4515
- static BitmapPage = new BitmapPageManager();
4516
- static OverflowPage = new OverflowPageManager();
4517
- static UnknownPage = new UnknownPageManager();
4518
4533
  /**
4519
- * Returns the page type.
4520
- * @param page Page data
4521
- * @returns Page type
4534
+ * Similar to the `onBefore` method, but it only runs once.
4535
+ * For more details, please refer to the `onBefore` method.
4536
+ * @param command Command to work.
4537
+ * @param callback Preprocessing function to register.
4522
4538
  */
4523
- getPageType(page) {
4524
- return bytesToNumber(page, PageManager.CONSTANT.OFFSET_PAGE_TYPE, PageManager.CONSTANT.SIZE_PAGE_TYPE);
4539
+ onceBefore(command, callback) {
4540
+ this._on(this.beforeHooks, command, callback, 1);
4541
+ return this;
4525
4542
  }
4526
4543
  /**
4527
- * Checks if the page is `EmptyPage`.
4528
- * @param page Page data
4529
- * @returns `true` if the page is `EmptyPage`, otherwise `false`
4544
+ * You register a post-processing function which is called after the callback function of the `trigger` method finishes.
4545
+ * This function receives the value returned by the `trigger` method's callback function as a parameter.
4546
+ * If you register multiple post-processing functions, they are executed in order, with each function receiving the value returned by the previous one as a parameter.
4547
+ * @param command Command to work.
4548
+ * @param callback Post-preprocessing function to register.
4530
4549
  */
4531
- isEmptyPage(page) {
4532
- return EmptyPageManager.IsEmptyPage(page);
4550
+ onAfter(command, callback) {
4551
+ this._on(this.afterHooks, command, callback, -1);
4552
+ return this;
4533
4553
  }
4534
4554
  /**
4535
- * Checks if the page is `DataPage`.
4536
- * @param page Page data
4537
- * @returns `true` if the page is `DataPage`, otherwise `false`
4555
+ * Similar to the `onAfter` method, but it only runs once.
4556
+ * For more details, please refer to the `onAfter` method.
4557
+ * @param command Command to work.
4558
+ * @param callback Post-preprocessing function to register.
4538
4559
  */
4539
- isDataPage(page) {
4540
- return DataPageManager.IsDataPage(page);
4560
+ onceAfter(command, callback) {
4561
+ this._on(this.afterHooks, command, callback, 1);
4562
+ return this;
4541
4563
  }
4542
- /**
4543
- * Checks if the page is `IndexPage`.
4544
- * @param page Page data
4545
- * @returns `true` if the page is `IndexPage`, otherwise `false`
4546
- */
4547
- isIndexPage(page) {
4548
- return IndexPageManager.IsIndexPage(page);
4564
+ _off(hooks, command, callback) {
4565
+ const wrappers = this._ensureCommand(hooks, command);
4566
+ if (callback) {
4567
+ const i = wrappers.findIndex((wrapper) => wrapper.callback === callback);
4568
+ if (i !== -1) {
4569
+ wrappers.splice(i, 1);
4570
+ }
4571
+ } else {
4572
+ wrappers.length = 0;
4573
+ }
4574
+ return this;
4549
4575
  }
4550
4576
  /**
4551
- * Checks if the page is `MetadataPage`.
4552
- * @param page Page data
4553
- * @returns `true` if the page is `MetadataPage`, otherwise `false`
4577
+ * You remove the preprocessing functions registered with `onBefore` or `onceBefore` methods.
4578
+ * If you don't specify a callback parameter, it removes all preprocessing functions registered for that command.
4579
+ * @param command Commands with preprocessing functions to be deleted.
4580
+ * @param callback Preprocessing function to be deleted.
4554
4581
  */
4555
- isMetadataPage(page) {
4556
- return MetadataPageManager.IsMetadataPage(page);
4582
+ offBefore(command, callback) {
4583
+ this._off(this.beforeHooks, command, callback);
4584
+ return this;
4557
4585
  }
4558
4586
  /**
4559
- * Checks if the page is `BitmapPage`.
4560
- * @param page Page data
4561
- * @returns `true` if the page is `BitmapPage`, otherwise `false`
4587
+ * You remove the post-preprocessing functions registered with `onAfter` or `onceAfter` methods.
4588
+ * If you don't specify a callback parameter, it removes all post-preprocessing functions registered for that command.
4589
+ * @param command Commands with post-preprocessing functions to be deleted.
4590
+ * @param callback post-Preprocessing function to be deleted.
4562
4591
  */
4563
- isBitmapPage(page) {
4564
- return BitmapPageManager.IsBitmapPage(page);
4592
+ offAfter(command, callback) {
4593
+ this._off(this.afterHooks, command, callback);
4594
+ return this;
4565
4595
  }
4566
- /**
4567
- * Checks if the page is `OverflowPage`.
4568
- * @param page Page data
4569
- * @returns `true` if the page is `OverflowPage`, otherwise `false`
4570
- */
4571
- isOverflowPage(page) {
4572
- return OverflowPageManager.IsOverflowPage(page);
4596
+ _hookWith(hooks, command, value, ...params) {
4597
+ let wrappers = this._ensureCommand(hooks, command);
4598
+ let i = wrappers.length;
4599
+ while (i--) {
4600
+ const wrapper = wrappers[i];
4601
+ value = wrapper.callback(value, ...params);
4602
+ wrapper.repeat -= 1;
4603
+ if (wrapper.repeat === 0) {
4604
+ this._off(hooks, command, wrapper.callback);
4605
+ }
4606
+ }
4607
+ return value;
4573
4608
  }
4574
4609
  /**
4575
- * Checks if the page is `UnknownPage`.
4576
- * @param page Page data
4577
- * @returns `true` if the page is `UnknownPage`, otherwise `false`
4610
+ * You execute the callback function provided as a parameter. This callback function receives the 'initialValue' parameter.
4611
+ *
4612
+ * If preprocessing functions are registered, they run first, and the value returned by the preprocessing functions becomes the 'initialValue' parameter.
4613
+ * After the callback function finishes, post-processing functions are called.
4614
+ * These post-processing functions receive the value returned by the callback function as a parameter and run sequentially.
4615
+ *
4616
+ * The final value returned becomes the result of the `trigger` method.
4617
+ * @param command Command to work.
4618
+ * @param initialValue Initial value to be passed to the callback function.
4619
+ * @param callback The callback function to be executed.
4578
4620
  */
4579
- isUnknownPage(page) {
4580
- return UnknownPageManager.IsUnknownPage(page);
4581
- }
4582
- getManager(page) {
4583
- switch (this.getPageType(page)) {
4584
- case PageManager.CONSTANT.PAGE_TYPE_EMPTY:
4585
- return _PageManagerFactory.EmptyPage;
4586
- case PageManager.CONSTANT.PAGE_TYPE_METADATA:
4587
- return _PageManagerFactory.MetadataPage;
4588
- case PageManager.CONSTANT.PAGE_TYPE_BITMAP:
4589
- return _PageManagerFactory.BitmapPage;
4590
- case PageManager.CONSTANT.PAGE_TYPE_INDEX:
4591
- return _PageManagerFactory.IndexPage;
4592
- case PageManager.CONSTANT.PAGE_TYPE_DATA:
4593
- return _PageManagerFactory.DataPage;
4594
- case PageManager.CONSTANT.PAGE_TYPE_OVERFLOW:
4595
- return _PageManagerFactory.OverflowPage;
4596
- case PageManager.CONSTANT.PAGE_TYPE_UNKNOWN:
4597
- return _PageManagerFactory.UnknownPage;
4598
- default:
4599
- throw new Error(`Invalid page type: ${this.getPageType(page)}`);
4600
- }
4601
- }
4602
- getManagerFromType(pageType) {
4603
- switch (pageType) {
4604
- case PageManager.CONSTANT.PAGE_TYPE_EMPTY:
4605
- return _PageManagerFactory.EmptyPage;
4606
- case PageManager.CONSTANT.PAGE_TYPE_METADATA:
4607
- return _PageManagerFactory.MetadataPage;
4608
- case PageManager.CONSTANT.PAGE_TYPE_BITMAP:
4609
- return _PageManagerFactory.BitmapPage;
4610
- case PageManager.CONSTANT.PAGE_TYPE_INDEX:
4611
- return _PageManagerFactory.IndexPage;
4612
- case PageManager.CONSTANT.PAGE_TYPE_DATA:
4613
- return _PageManagerFactory.DataPage;
4614
- case PageManager.CONSTANT.PAGE_TYPE_OVERFLOW:
4615
- return _PageManagerFactory.OverflowPage;
4616
- case PageManager.CONSTANT.PAGE_TYPE_UNKNOWN:
4617
- return _PageManagerFactory.UnknownPage;
4618
- default:
4619
- throw new Error(`Invalid page type: ${pageType}`);
4620
- }
4621
+ trigger(command, initialValue, callback, ...params) {
4622
+ let value;
4623
+ value = this._hookWith(this.beforeHooks, command, initialValue, ...params);
4624
+ value = callback(value, ...params);
4625
+ value = this._hookWith(this.afterHooks, command, value, ...params);
4626
+ return value;
4621
4627
  }
4622
4628
  };
4629
+ function useHookallSync(target = HookallSync.Global) {
4630
+ return new HookallSync(target);
4631
+ }
4623
4632
 
4624
4633
  // src/core/VirtualFileSystem.ts
4625
4634
  var import_node_fs2 = __toESM(require("node:fs"));
@@ -5714,7 +5723,7 @@ var RowTableEngine = class {
5714
5723
  * @param tx Transaction
5715
5724
  * @returns PK of the inserted data
5716
5725
  */
5717
- async insert(data, incrementRowCount, tx) {
5726
+ async insert(data, incrementRowCount, overflowForcly, tx) {
5718
5727
  await tx.__acquireWriteLock(0);
5719
5728
  const metadataPage = await this.pfs.getMetadata(tx);
5720
5729
  const pk = this.metadataPageManager.getLastRowPk(metadataPage) + 1;
@@ -5724,7 +5733,7 @@ var RowTableEngine = class {
5724
5733
  throw new Error(`Last insert page is not data page`);
5725
5734
  }
5726
5735
  const willRowSize = this.getRequiredRowSize(data);
5727
- if (willRowSize > this.maxBodySize) {
5736
+ if (willRowSize > this.maxBodySize || overflowForcly) {
5728
5737
  const overflowPageId = await this.pfs.appendNewPage(this.overflowPageManager.pageType, tx);
5729
5738
  const row = new Uint8Array(Row.CONSTANT.SIZE_HEADER + 4);
5730
5739
  this.rowManager.setPK(row, pk);
@@ -6426,7 +6435,26 @@ var DataplyAPI = class {
6426
6435
  if (typeof data === "string") {
6427
6436
  data = this.textCodec.encode(data);
6428
6437
  }
6429
- return this.rowTableEngine.insert(data, incrementRowCount, tx2);
6438
+ return this.rowTableEngine.insert(data, incrementRowCount, false, tx2);
6439
+ }, tx);
6440
+ }
6441
+ /**
6442
+ * Inserts overflow data forcly. Returns the PK of the added row.
6443
+ * @param data Data to add
6444
+ * @param incrementRowCount Whether to increment the row count to metadata
6445
+ * @param tx Transaction
6446
+ * @returns PK of the added data
6447
+ */
6448
+ async insertAsOverflow(data, incrementRowCount, tx) {
6449
+ if (!this.initialized) {
6450
+ throw new Error("Dataply instance is not initialized");
6451
+ }
6452
+ return this.runWithDefault((tx2) => {
6453
+ incrementRowCount = incrementRowCount ?? true;
6454
+ if (typeof data === "string") {
6455
+ data = this.textCodec.encode(data);
6456
+ }
6457
+ return this.rowTableEngine.insert(data, incrementRowCount, true, tx2);
6430
6458
  }, tx);
6431
6459
  }
6432
6460
  /**
@@ -6446,7 +6474,7 @@ var DataplyAPI = class {
6446
6474
  const pks = [];
6447
6475
  for (const data of dataList) {
6448
6476
  const encoded = typeof data === "string" ? this.textCodec.encode(data) : data;
6449
- const pk = await this.rowTableEngine.insert(encoded, incrementRowCount, tx2);
6477
+ const pk = await this.rowTableEngine.insert(encoded, incrementRowCount, false, tx2);
6450
6478
  pks.push(pk);
6451
6479
  }
6452
6480
  return pks;
@@ -6642,20 +6670,29 @@ var GlobalTransaction = class {
6642
6670
  0 && (module.exports = {
6643
6671
  BPTreeAsync,
6644
6672
  BPTreeSync,
6673
+ BitmapPageManager,
6645
6674
  CacheEntanglementAsync,
6646
6675
  CacheEntanglementSync,
6676
+ DataPageManager,
6647
6677
  Dataply,
6648
6678
  DataplyAPI,
6679
+ EmptyPageManager,
6649
6680
  GlobalTransaction,
6650
6681
  InMemoryStoreStrategyAsync,
6651
6682
  InMemoryStoreStrategySync,
6683
+ IndexPageManager,
6652
6684
  InvertedWeakMap,
6653
6685
  LRUMap,
6686
+ MetadataPageManager,
6654
6687
  NumericComparator,
6688
+ OverflowPageManager,
6689
+ PageManager,
6690
+ PageManagerFactory,
6655
6691
  Ryoiki,
6656
6692
  SerializeStrategyAsync,
6657
6693
  SerializeStrategySync,
6658
6694
  StringComparator,
6659
6695
  Transaction,
6696
+ UnknownPageManager,
6660
6697
  ValueComparator
6661
6698
  });