@tinacms/graphql 1.1.0 → 1.2.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/dist/index.js CHANGED
@@ -39,22 +39,26 @@ var __export = (target, all) => {
39
39
  for (var name2 in all)
40
40
  __defProp(target, name2, { get: all[name2], enumerable: true });
41
41
  };
42
- var __reExport = (target, module2, desc) => {
43
- if (module2 && typeof module2 === "object" || typeof module2 === "function") {
44
- for (let key of __getOwnPropNames(module2))
42
+ var __reExport = (target, module3, desc) => {
43
+ if (module3 && typeof module3 === "object" || typeof module3 === "function") {
44
+ for (let key of __getOwnPropNames(module3))
45
45
  if (!__hasOwnProp.call(target, key) && key !== "default")
46
- __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
46
+ __defProp(target, key, { get: () => module3[key], enumerable: !(desc = __getOwnPropDesc(module3, key)) || desc.enumerable });
47
47
  }
48
48
  return target;
49
49
  };
50
- var __toModule = (module2) => {
51
- return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
50
+ var __toModule = (module3) => {
51
+ return __reExport(__markAsModule(__defProp(module3 != null ? __create(__getProtoOf(module3)) : {}, "default", module3 && module3.__esModule && "default" in module3 ? { get: () => module3.default, enumerable: true } : { value: module3, enumerable: true })), module3);
52
52
  };
53
53
 
54
54
  // src/index.ts
55
55
  __export(exports, {
56
+ AuditFileSystemBridge: () => AuditFileSystemBridge,
57
+ FilesystemBridge: () => FilesystemBridge,
58
+ IsomorphicBridge: () => IsomorphicBridge,
56
59
  TinaFetchError: () => TinaFetchError,
57
60
  TinaGraphQLError: () => TinaGraphQLError,
61
+ TinaLevelClient: () => TinaLevelClient,
58
62
  TinaParseDocumentError: () => TinaParseDocumentError,
59
63
  TinaQueryError: () => TinaQueryError,
60
64
  assertShape: () => assertShape,
@@ -69,9 +73,9 @@ __export(exports, {
69
73
  sequential: () => sequential,
70
74
  stringifyFile: () => stringifyFile
71
75
  });
72
- var import_fs_extra2 = __toModule(require("fs-extra"));
73
- var import_path4 = __toModule(require("path"));
74
- var import_graphql6 = __toModule(require("graphql"));
76
+ var import_fs_extra4 = __toModule(require("fs-extra"));
77
+ var import_path6 = __toModule(require("path"));
78
+ var import_graphql7 = __toModule(require("graphql"));
75
79
 
76
80
  // src/build.ts
77
81
  var import_lodash3 = __toModule(require("lodash"));
@@ -113,6 +117,12 @@ function assertShape(value, yupSchema, errorMessage) {
113
117
  });
114
118
  }
115
119
  }
120
+ var atob = (b64Encoded) => {
121
+ return Buffer.from(b64Encoded, "base64").toString();
122
+ };
123
+ var btoa = (string2) => {
124
+ return Buffer.from(string2).toString("base64");
125
+ };
116
126
  var lastItem = (arr) => {
117
127
  return arr[arr.length - 1];
118
128
  };
@@ -2186,14 +2196,14 @@ var Builder = class {
2186
2196
  collection,
2187
2197
  collections
2188
2198
  }) => {
2189
- const extra = this.database.store.supportsIndexing() ? [
2199
+ const extra = [
2190
2200
  await this._connectionFilterBuilder({
2191
2201
  fieldName,
2192
2202
  namespace,
2193
2203
  collection,
2194
2204
  collections
2195
2205
  })
2196
- ] : [];
2206
+ ];
2197
2207
  return astBuilder.FieldDefinition({
2198
2208
  name: fieldName,
2199
2209
  required: true,
@@ -2473,14 +2483,19 @@ var validateField = async (field) => {
2473
2483
 
2474
2484
  // package.json
2475
2485
  var name = "@tinacms/graphql";
2476
- var version = "1.1.0";
2486
+ var version = "1.2.0";
2477
2487
  var main = "dist/index.js";
2488
+ var module2 = "dist/index.es.js";
2478
2489
  var typings = "dist/index.d.ts";
2479
2490
  var files = [
2480
2491
  "package.json",
2481
2492
  "dist"
2482
2493
  ];
2483
- var license = "Apache-2.0";
2494
+ var exports = {
2495
+ import: "./dist/index.es.js",
2496
+ require: "./dist/index.js"
2497
+ };
2498
+ var license = "SEE LICENSE IN LICENSE";
2484
2499
  var buildConfig = {
2485
2500
  entryPoints: [
2486
2501
  {
@@ -2501,9 +2516,9 @@ var scripts = {
2501
2516
  var dependencies = {
2502
2517
  "@graphql-tools/relay-operation-optimizer": "^6.4.1",
2503
2518
  "@iarna/toml": "^2.2.5",
2504
- "@tinacms/datalayer": "workspace:*",
2505
2519
  "@tinacms/mdx": "workspace:*",
2506
2520
  "@tinacms/schema-tools": "workspace:*",
2521
+ "abstract-level": "^1.0.3",
2507
2522
  "body-parser": "^1.19.0",
2508
2523
  cors: "^2.8.5",
2509
2524
  dataloader: "^2.0.0",
@@ -2515,12 +2530,16 @@ var dependencies = {
2515
2530
  "fast-glob": "^3.2.5",
2516
2531
  flat: "^5.0.2",
2517
2532
  "fs-extra": "^9.0.1",
2533
+ "glob-parent": "^6.0.2",
2518
2534
  graphql: "15.8.0",
2519
2535
  "graphql-type-json": "^0.3.2",
2520
2536
  "gray-matter": "^4.0.2",
2537
+ "isomorphic-git": "^1.21.0",
2521
2538
  "js-yaml": "^3.14.1",
2539
+ "jsonpath-plus": "^6.0.1",
2522
2540
  leveldown: "^6.1.0",
2523
2541
  lodash: "^4.17.20",
2542
+ "many-level": "^2.0.0",
2524
2543
  mdast: "^3.0.0",
2525
2544
  "mdast-util-from-markdown": "^1.0.0",
2526
2545
  "mdast-util-mdx": "^1.1.0",
@@ -2529,6 +2548,7 @@ var dependencies = {
2529
2548
  "micromark-extension-mdxjs": "^1.0.0",
2530
2549
  "normalize-path": "^3.0.0",
2531
2550
  prettier: "^2.2.1",
2551
+ "readable-stream": "^4.3.0",
2532
2552
  "rehype-format": "^3.1.0",
2533
2553
  "rehype-stringify": "^8.0.0",
2534
2554
  remark: "^13.0.0",
@@ -2553,7 +2573,6 @@ var repository = {
2553
2573
  directory: "packages/tina-graphql"
2554
2574
  };
2555
2575
  var devDependencies = {
2556
- "@tinacms/datalayer": "workspace:*",
2557
2576
  "@tinacms/schema-tools": "workspace:*",
2558
2577
  "@tinacms/scripts": "workspace:*",
2559
2578
  "@types/cors": "^2.8.7",
@@ -2575,6 +2594,7 @@ var devDependencies = {
2575
2594
  "jest-diff": "27.0.6",
2576
2595
  "jest-file-snapshot": "^0.5.0",
2577
2596
  "jest-matcher-utils": "27.0.6",
2597
+ "memory-level": "^1.0.0",
2578
2598
  nodemon: "2.0.19",
2579
2599
  typescript: "4.3.5"
2580
2600
  };
@@ -2582,8 +2602,10 @@ var package_default = {
2582
2602
  name,
2583
2603
  version,
2584
2604
  main,
2605
+ module: module2,
2585
2606
  typings,
2586
2607
  files,
2608
+ exports,
2587
2609
  license,
2588
2610
  buildConfig,
2589
2611
  scripts,
@@ -2623,10 +2645,8 @@ var buildDotTinaFiles = async ({
2623
2645
  flags = [],
2624
2646
  buildSDK = true
2625
2647
  }) => {
2626
- if (database.store.supportsIndexing()) {
2627
- if (flags.indexOf("experimentalData") === -1) {
2628
- flags.push("experimentalData");
2629
- }
2648
+ if (flags.indexOf("experimentalData") === -1) {
2649
+ flags.push("experimentalData");
2630
2650
  }
2631
2651
  const tinaSchema = await createSchema({ schema: config, flags });
2632
2652
  const builder = await createBuilder({
@@ -2800,9 +2820,6 @@ var handleFetchErrorError = (e, verbose) => {
2800
2820
  throw e;
2801
2821
  };
2802
2822
 
2803
- // src/resolver/index.ts
2804
- var import_datalayer = __toModule(require("@tinacms/datalayer"));
2805
-
2806
2823
  // src/resolver/filter-utils.ts
2807
2824
  var resolveReferences = async (filter, fields, resolver) => {
2808
2825
  for (const fieldKey of Object.keys(filter)) {
@@ -2931,9 +2948,9 @@ var resolveMediaRelativeToCloud = (value, config = { useRelativeMedia: true }, s
2931
2948
  return value;
2932
2949
  }
2933
2950
  };
2934
- var cleanUpSlashes = (path5) => {
2935
- if (path5) {
2936
- return `/${path5.replace(/^\/+|\/+$/gm, "")}`;
2951
+ var cleanUpSlashes = (path6) => {
2952
+ if (path6) {
2953
+ return `/${path6.replace(/^\/+|\/+$/gm, "")}`;
2937
2954
  }
2938
2955
  return "";
2939
2956
  };
@@ -2947,6 +2964,389 @@ var hasTinaMediaConfig = (schema) => {
2947
2964
 
2948
2965
  // src/resolver/index.ts
2949
2966
  var import_graphql3 = __toModule(require("graphql"));
2967
+
2968
+ // src/database/datalayer.ts
2969
+ var import_jsonpath_plus = __toModule(require("jsonpath-plus"));
2970
+
2971
+ // src/database/level.ts
2972
+ var INDEX_KEY_FIELD_SEPARATOR = "";
2973
+ var CONTENT_ROOT_PREFIX = "~";
2974
+ var SUBLEVEL_OPTIONS = {
2975
+ separator: INDEX_KEY_FIELD_SEPARATOR,
2976
+ valueEncoding: "json"
2977
+ };
2978
+
2979
+ // src/database/datalayer.ts
2980
+ var OP;
2981
+ (function(OP2) {
2982
+ OP2["EQ"] = "eq";
2983
+ OP2["GT"] = "gt";
2984
+ OP2["LT"] = "lt";
2985
+ OP2["GTE"] = "gte";
2986
+ OP2["LTE"] = "lte";
2987
+ OP2["STARTS_WITH"] = "startsWith";
2988
+ OP2["IN"] = "in";
2989
+ })(OP || (OP = {}));
2990
+ var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
2991
+ var DEFAULT_NUMERIC_LPAD = 4;
2992
+ var applyPadding = (input, pad) => {
2993
+ if (pad) {
2994
+ if (Array.isArray(input)) {
2995
+ return input.map((val) => String(val).padStart(pad.maxLength, pad.fillString));
2996
+ } else {
2997
+ return String(input).padStart(pad.maxLength, pad.fillString);
2998
+ }
2999
+ }
3000
+ return input;
3001
+ };
3002
+ var getFilterOperator = (expression, operand) => {
3003
+ return (expression[operand] || expression[operand] === 0) && operand;
3004
+ };
3005
+ var inferOperatorFromFilter = (filterOperator) => {
3006
+ switch (filterOperator) {
3007
+ case "after":
3008
+ return OP.GT;
3009
+ case "before":
3010
+ return OP.LT;
3011
+ case "eq":
3012
+ return OP.EQ;
3013
+ case "startsWith":
3014
+ return OP.STARTS_WITH;
3015
+ case "lt":
3016
+ return OP.LT;
3017
+ case "lte":
3018
+ return OP.LTE;
3019
+ case "gt":
3020
+ return OP.GT;
3021
+ case "gte":
3022
+ return OP.GTE;
3023
+ case "in":
3024
+ return OP.IN;
3025
+ default:
3026
+ throw new Error(`unsupported filter condition: '${filterOperator}'`);
3027
+ }
3028
+ };
3029
+ var makeKeyForField = (definition, data, stringEscaper2, maxStringLength = 100) => {
3030
+ const valueParts = [];
3031
+ for (const field of definition.fields) {
3032
+ if (field.name in data && data[field.name] !== void 0 && data[field.name] !== null) {
3033
+ const rawValue = data[field.name];
3034
+ const resolvedValue = String(field.type === "datetime" ? new Date(rawValue).getTime() : field.type === "string" ? stringEscaper2(rawValue) : rawValue).substring(0, maxStringLength);
3035
+ valueParts.push(applyPadding(resolvedValue, field.pad));
3036
+ } else {
3037
+ return null;
3038
+ }
3039
+ }
3040
+ return valueParts.join(INDEX_KEY_FIELD_SEPARATOR);
3041
+ };
3042
+ var coerceFilterChainOperands = (filterChain, escapeString = stringEscaper) => {
3043
+ const result = [];
3044
+ if (filterChain.length) {
3045
+ for (const filter of filterChain) {
3046
+ const dataType = filter.type;
3047
+ if (dataType === "datetime") {
3048
+ if (filter.leftOperand !== void 0) {
3049
+ result.push(__spreadProps(__spreadValues({}, filter), {
3050
+ rightOperand: new Date(filter.rightOperand).getTime(),
3051
+ leftOperand: new Date(filter.leftOperand).getTime()
3052
+ }));
3053
+ } else {
3054
+ if (Array.isArray(filter.rightOperand)) {
3055
+ result.push(__spreadProps(__spreadValues({}, filter), {
3056
+ rightOperand: filter.rightOperand.map((operand) => new Date(operand).getTime())
3057
+ }));
3058
+ } else {
3059
+ result.push(__spreadProps(__spreadValues({}, filter), {
3060
+ rightOperand: new Date(filter.rightOperand).getTime()
3061
+ }));
3062
+ }
3063
+ }
3064
+ } else if (dataType === "string") {
3065
+ if (filter.leftOperand !== void 0) {
3066
+ result.push(__spreadProps(__spreadValues({}, filter), {
3067
+ rightOperand: applyPadding(escapeString(filter.rightOperand), filter.pad),
3068
+ leftOperand: applyPadding(escapeString(filter.leftOperand), filter.pad)
3069
+ }));
3070
+ } else {
3071
+ result.push(__spreadProps(__spreadValues({}, filter), {
3072
+ rightOperand: applyPadding(escapeString(filter.rightOperand), filter.pad)
3073
+ }));
3074
+ }
3075
+ } else {
3076
+ result.push(__spreadValues({}, filter));
3077
+ }
3078
+ }
3079
+ }
3080
+ return result;
3081
+ };
3082
+ var makeFilter = ({
3083
+ filterChain
3084
+ }) => {
3085
+ return (values) => {
3086
+ for (const filter of filterChain) {
3087
+ const dataType = filter.type;
3088
+ const resolvedValues = (0, import_jsonpath_plus.JSONPath)({
3089
+ path: filter.pathExpression,
3090
+ json: values
3091
+ });
3092
+ if (!resolvedValues || !resolvedValues.length) {
3093
+ return false;
3094
+ }
3095
+ let operands;
3096
+ if (dataType === "string" || dataType === "reference") {
3097
+ operands = resolvedValues;
3098
+ } else if (dataType === "number") {
3099
+ operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
3100
+ } else if (dataType === "datetime") {
3101
+ operands = resolvedValues.map((resolvedValue) => {
3102
+ const coerced = new Date(resolvedValue).getTime();
3103
+ return isNaN(coerced) ? Number(resolvedValue) : coerced;
3104
+ });
3105
+ } else if (dataType === "boolean") {
3106
+ operands = resolvedValues.map((resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1");
3107
+ } else {
3108
+ throw new Error(`Unexpected datatype ${dataType}`);
3109
+ }
3110
+ const { operator } = filter;
3111
+ let matches = false;
3112
+ if (operator) {
3113
+ switch (operator) {
3114
+ case OP.EQ:
3115
+ if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
3116
+ matches = true;
3117
+ }
3118
+ break;
3119
+ case OP.GT:
3120
+ for (const operand of operands) {
3121
+ if (operand > filter.rightOperand) {
3122
+ matches = true;
3123
+ break;
3124
+ }
3125
+ }
3126
+ break;
3127
+ case OP.LT:
3128
+ for (const operand of operands) {
3129
+ if (operand < filter.rightOperand) {
3130
+ matches = true;
3131
+ break;
3132
+ }
3133
+ }
3134
+ break;
3135
+ case OP.GTE:
3136
+ for (const operand of operands) {
3137
+ if (operand >= filter.rightOperand) {
3138
+ matches = true;
3139
+ break;
3140
+ }
3141
+ }
3142
+ break;
3143
+ case OP.LTE:
3144
+ for (const operand of operands) {
3145
+ if (operand <= filter.rightOperand) {
3146
+ matches = true;
3147
+ break;
3148
+ }
3149
+ }
3150
+ break;
3151
+ case OP.IN:
3152
+ for (const operand of operands) {
3153
+ if (filter.rightOperand.indexOf(operand) >= 0) {
3154
+ matches = true;
3155
+ break;
3156
+ }
3157
+ }
3158
+ break;
3159
+ case OP.STARTS_WITH:
3160
+ for (const operand of operands) {
3161
+ if (operand.startsWith(filter.rightOperand)) {
3162
+ matches = true;
3163
+ break;
3164
+ }
3165
+ }
3166
+ break;
3167
+ default:
3168
+ throw new Error(`unexpected operator ${operator}`);
3169
+ }
3170
+ } else {
3171
+ const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
3172
+ for (const operand of operands) {
3173
+ let rightMatches = false;
3174
+ let leftMatches = false;
3175
+ if (rightOperator === OP.LTE && operand <= rightOperand) {
3176
+ rightMatches = true;
3177
+ } else if (rightOperator === OP.LT && operand < rightOperand) {
3178
+ rightMatches = true;
3179
+ }
3180
+ if (leftOperator === OP.GTE && operand >= leftOperand) {
3181
+ leftMatches = true;
3182
+ } else if (leftOperator === OP.GT && operand > leftOperand) {
3183
+ leftMatches = true;
3184
+ }
3185
+ if (rightMatches && leftMatches) {
3186
+ matches = true;
3187
+ break;
3188
+ }
3189
+ }
3190
+ }
3191
+ if (!matches) {
3192
+ return false;
3193
+ }
3194
+ }
3195
+ return true;
3196
+ };
3197
+ };
3198
+ var makeFilterChain = ({
3199
+ conditions
3200
+ }) => {
3201
+ const filterChain = [];
3202
+ if (!conditions) {
3203
+ return filterChain;
3204
+ }
3205
+ for (const condition of conditions) {
3206
+ const { filterPath, filterExpression } = condition;
3207
+ const _a = filterExpression, { _type } = _a, keys = __objRest(_a, ["_type"]);
3208
+ const [key1, key2, ...extraKeys] = Object.keys(keys);
3209
+ if (extraKeys.length) {
3210
+ throw new Error(`Unexpected keys: [${extraKeys.join(",")}] in filter expression`);
3211
+ }
3212
+ if (key1 && !key2) {
3213
+ filterChain.push({
3214
+ pathExpression: filterPath,
3215
+ rightOperand: filterExpression[key1],
3216
+ operator: inferOperatorFromFilter(key1),
3217
+ type: _type,
3218
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
3219
+ });
3220
+ } else if (key1 && key2) {
3221
+ const leftFilterOperator = getFilterOperator(filterExpression, "gt") || getFilterOperator(filterExpression, "gte") || getFilterOperator(filterExpression, "after") || void 0;
3222
+ const rightFilterOperator = getFilterOperator(filterExpression, "lt") || getFilterOperator(filterExpression, "lte") || getFilterOperator(filterExpression, "before") || void 0;
3223
+ let leftOperand;
3224
+ let rightOperand;
3225
+ if (rightFilterOperator && leftFilterOperator) {
3226
+ if (key1 === leftFilterOperator) {
3227
+ leftOperand = filterExpression[key1];
3228
+ rightOperand = filterExpression[key2];
3229
+ } else {
3230
+ rightOperand = filterExpression[key1];
3231
+ leftOperand = filterExpression[key2];
3232
+ }
3233
+ filterChain.push({
3234
+ pathExpression: filterPath,
3235
+ rightOperand,
3236
+ leftOperand,
3237
+ leftOperator: inferOperatorFromFilter(leftFilterOperator),
3238
+ rightOperator: inferOperatorFromFilter(rightFilterOperator),
3239
+ type: _type,
3240
+ pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
3241
+ });
3242
+ } else {
3243
+ throw new Error(`Filter on field '${filterPath}' has invalid combination of conditions: '${key1}, ${key2}'`);
3244
+ }
3245
+ }
3246
+ }
3247
+ return filterChain;
3248
+ };
3249
+ var makeFilterSuffixes = (filterChain, index) => {
3250
+ if (filterChain && filterChain.length) {
3251
+ const indexFields = index.fields.map((field) => field.name);
3252
+ const orderedFilterChain = [];
3253
+ for (const filter of filterChain) {
3254
+ const idx = indexFields.indexOf(filter.pathExpression);
3255
+ if (idx === -1) {
3256
+ return;
3257
+ }
3258
+ if (filter.operator && filter.operator === OP.IN) {
3259
+ return;
3260
+ }
3261
+ orderedFilterChain[idx] = filter;
3262
+ }
3263
+ const baseFragments = [];
3264
+ let rightSuffix;
3265
+ let leftSuffix;
3266
+ let ternaryFilter = false;
3267
+ if (orderedFilterChain[filterChain.length - 1] && !orderedFilterChain[filterChain.length - 1].operator) {
3268
+ ternaryFilter = true;
3269
+ }
3270
+ for (let i = 0; i < orderedFilterChain.length; i++) {
3271
+ const filter = orderedFilterChain[i];
3272
+ if (!filter) {
3273
+ return;
3274
+ }
3275
+ if (Number(i) < indexFields.length - 1) {
3276
+ if (!filter.operator) {
3277
+ return;
3278
+ }
3279
+ const binaryFilter = filter;
3280
+ if (binaryFilter.operator !== OP.EQ) {
3281
+ return;
3282
+ }
3283
+ baseFragments.push(applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad));
3284
+ } else {
3285
+ if (ternaryFilter) {
3286
+ leftSuffix = applyPadding(orderedFilterChain[i].leftOperand, orderedFilterChain[i].pad);
3287
+ rightSuffix = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
3288
+ } else {
3289
+ const op = orderedFilterChain[i].operator;
3290
+ const operand = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
3291
+ if (op === OP.LT || op === OP.LTE) {
3292
+ rightSuffix = operand;
3293
+ } else if (op === OP.GT || op === OP.GTE) {
3294
+ leftSuffix = operand;
3295
+ } else {
3296
+ rightSuffix = operand;
3297
+ leftSuffix = operand;
3298
+ }
3299
+ }
3300
+ }
3301
+ }
3302
+ return {
3303
+ left: leftSuffix && [...baseFragments, leftSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0,
3304
+ right: rightSuffix && [...baseFragments, rightSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0
3305
+ };
3306
+ } else {
3307
+ return {};
3308
+ }
3309
+ };
3310
+ var makeIndexOpsForDocument = (filepath, collection, indexDefinitions, data, opType, level, escapeStr = stringEscaper) => {
3311
+ const result = [];
3312
+ if (collection) {
3313
+ const collectionSublevel = level.sublevel(collection, SUBLEVEL_OPTIONS);
3314
+ for (const [sort, definition] of Object.entries(indexDefinitions)) {
3315
+ const indexedValue = makeKeyForField(definition, data, escapeStr);
3316
+ const indexSublevel = collectionSublevel.sublevel(sort, SUBLEVEL_OPTIONS);
3317
+ if (sort === DEFAULT_COLLECTION_SORT_KEY) {
3318
+ result.push({
3319
+ type: opType,
3320
+ key: filepath,
3321
+ sublevel: indexSublevel,
3322
+ value: opType === "put" ? {} : void 0
3323
+ });
3324
+ } else {
3325
+ if (indexedValue) {
3326
+ result.push({
3327
+ type: opType,
3328
+ key: `${indexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`,
3329
+ sublevel: indexSublevel,
3330
+ value: opType === "put" ? {} : void 0
3331
+ });
3332
+ }
3333
+ }
3334
+ }
3335
+ }
3336
+ return result;
3337
+ };
3338
+ var makeStringEscaper = (regex, replacement) => {
3339
+ return (input) => {
3340
+ if (Array.isArray(input)) {
3341
+ return input.map((val) => val.replace(regex, replacement));
3342
+ } else {
3343
+ return input.replace(regex, replacement);
3344
+ }
3345
+ };
3346
+ };
3347
+ var stringEscaper = makeStringEscaper(new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"), encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR));
3348
+
3349
+ // src/resolver/index.ts
2950
3350
  var createResolver = (args) => {
2951
3351
  return new Resolver(args);
2952
3352
  };
@@ -3250,7 +3650,7 @@ var Resolver = class {
3250
3650
  first: -1
3251
3651
  },
3252
3652
  collection: referencedCollection,
3253
- hydrator: (path5) => path5
3653
+ hydrator: (path6) => path6
3254
3654
  });
3255
3655
  const { edges } = resolvedCollectionConnection;
3256
3656
  const values = edges.map((edge) => edge.node);
@@ -3277,7 +3677,7 @@ var Resolver = class {
3277
3677
  }
3278
3678
  }
3279
3679
  const queryOptions = {
3280
- filterChain: (0, import_datalayer.makeFilterChain)({
3680
+ filterChain: makeFilterChain({
3281
3681
  conditions: conditions || []
3282
3682
  }),
3283
3683
  collection: collection.name,
@@ -3518,7 +3918,7 @@ var resolve = async ({
3518
3918
  }
3519
3919
  },
3520
3920
  fieldResolver: async (source = {}, _args = {}, _context, info) => {
3521
- var _a2;
3921
+ var _a2, _b, _c, _d;
3522
3922
  try {
3523
3923
  const args = JSON.parse(JSON.stringify(_args));
3524
3924
  const returnType = (0, import_graphql4.getNamedType)(info.returnType).toString();
@@ -3607,8 +4007,14 @@ var resolve = async ({
3607
4007
  })
3608
4008
  };
3609
4009
  } else if (info.fieldName === "documents" && (value == null ? void 0 : value.collection) && (value == null ? void 0 : value.hasDocuments)) {
4010
+ let filter = args.filter;
4011
+ if (typeof (args == null ? void 0 : args.filter) !== "undefined" && (args == null ? void 0 : args.filter) !== null && typeof ((_b = value == null ? void 0 : value.collection) == null ? void 0 : _b.name) === "string" && Object.keys(args.filter).includes((_c = value == null ? void 0 : value.collection) == null ? void 0 : _c.name) && typeof args.filter[(_d = value == null ? void 0 : value.collection) == null ? void 0 : _d.name] !== "undefined") {
4012
+ filter = args.filter[value.collection.name];
4013
+ }
3610
4014
  return resolver.resolveCollectionConnection({
3611
- args,
4015
+ args: __spreadProps(__spreadValues({}, args), {
4016
+ filter
4017
+ }),
3612
4018
  collection: value.collection
3613
4019
  });
3614
4020
  } else {
@@ -3776,31 +4182,32 @@ var parseFile = (content, format, yupSchema, markdownParseConfig) => {
3776
4182
  var normalizePath = (filepath) => filepath.replace(/\\/g, "/");
3777
4183
 
3778
4184
  // src/database/index.ts
3779
- var import_datalayer2 = __toModule(require("@tinacms/datalayer"));
3780
- var createDatabase = async (config) => {
4185
+ var createDatabase = (config) => {
3781
4186
  return new Database(__spreadProps(__spreadValues({}, config), {
3782
4187
  bridge: config.bridge,
3783
- store: config.store
4188
+ level: config.level
3784
4189
  }));
3785
4190
  };
3786
4191
  var SYSTEM_FILES = ["_schema", "_graphql", "_lookup"];
3787
4192
  var defaultStatusCallback = () => Promise.resolve();
4193
+ var defaultOnPut = () => Promise.resolve();
4194
+ var defaultOnDelete = () => Promise.resolve();
3788
4195
  var Database = class {
3789
4196
  constructor(config) {
3790
4197
  this.config = config;
3791
4198
  this.collectionForPath = async (filepath) => {
3792
- const tinaSchema = await this.getSchema();
3793
- const collection = tinaSchema.getCollectionByFullPath(filepath);
3794
- return collection;
4199
+ const tinaSchema = await this.getSchema(this.level);
4200
+ return tinaSchema.getCollectionByFullPath(filepath);
3795
4201
  };
3796
4202
  this.getGeneratedFolder = () => import_path3.default.join(this.tinaDirectory, "__generated__");
3797
4203
  this.get = async (filepath) => {
4204
+ await this.initLevel();
3798
4205
  if (SYSTEM_FILES.includes(filepath)) {
3799
4206
  throw new Error(`Unexpected get for config file ${filepath}`);
3800
4207
  } else {
3801
- const tinaSchema = await this.getSchema();
4208
+ const tinaSchema = await this.getSchema(this.level);
3802
4209
  const extension = import_path3.default.extname(filepath);
3803
- const contentObject = await this.store.get(normalizePath(filepath));
4210
+ const contentObject = await this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(normalizePath(filepath));
3804
4211
  if (!contentObject) {
3805
4212
  throw new import_graphql5.GraphQLError(`Unable to find record ${filepath}`);
3806
4213
  }
@@ -3832,41 +4239,79 @@ var Database = class {
3832
4239
  }
3833
4240
  };
3834
4241
  this.addPendingDocument = async (filepath, data) => {
3835
- const { stringifiedFile, payload, keepTemplateKey } = await this.stringifyFile(filepath, data);
4242
+ await this.initLevel();
4243
+ const { stringifiedFile, payload } = await this.stringifyFile(filepath, data);
3836
4244
  const collection = await this.collectionForPath(filepath);
3837
4245
  let collectionIndexDefinitions;
3838
4246
  if (collection) {
3839
- const indexDefinitions = await this.getIndexDefinitions();
4247
+ const indexDefinitions = await this.getIndexDefinitions(this.level);
3840
4248
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
3841
4249
  }
3842
- if (this.store.supportsSeeding()) {
3843
- await this.bridge.put(normalizePath(filepath), stringifiedFile);
4250
+ const normalizedPath = normalizePath(filepath);
4251
+ if (this.bridge) {
4252
+ await this.bridge.put(normalizedPath, stringifiedFile);
3844
4253
  }
3845
- await this.store.put(normalizePath(filepath), payload, {
3846
- keepTemplateKey,
3847
- collection: collection == null ? void 0 : collection.name,
3848
- indexDefinitions: collectionIndexDefinitions
3849
- });
4254
+ await this.onPut(normalizedPath, stringifiedFile);
4255
+ const putOps = makeIndexOpsForDocument(normalizedPath, collection == null ? void 0 : collection.name, collectionIndexDefinitions, payload, "put", this.level);
4256
+ let existingItem;
4257
+ try {
4258
+ existingItem = await this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(normalizedPath);
4259
+ } catch (e) {
4260
+ if (e.code !== "LEVEL_NOT_FOUND") {
4261
+ throw e;
4262
+ }
4263
+ }
4264
+ const delOps = existingItem ? makeIndexOpsForDocument(normalizedPath, collection == null ? void 0 : collection.name, collectionIndexDefinitions, existingItem, "del", this.level) : [];
4265
+ const ops = [
4266
+ ...delOps,
4267
+ ...putOps,
4268
+ {
4269
+ type: "put",
4270
+ key: normalizedPath,
4271
+ value: payload,
4272
+ sublevel: this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS)
4273
+ }
4274
+ ];
4275
+ await this.level.batch(ops);
3850
4276
  };
3851
4277
  this.put = async (filepath, data, collection) => {
4278
+ await this.initLevel();
3852
4279
  try {
3853
4280
  if (SYSTEM_FILES.includes(filepath)) {
3854
4281
  throw new Error(`Unexpected put for config file ${filepath}`);
3855
4282
  } else {
3856
4283
  let collectionIndexDefinitions;
3857
4284
  if (collection) {
3858
- const indexDefinitions = await this.getIndexDefinitions();
4285
+ const indexDefinitions = await this.getIndexDefinitions(this.level);
3859
4286
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection];
3860
4287
  }
3861
- const { stringifiedFile, payload, keepTemplateKey } = await this.stringifyFile(filepath, data);
3862
- if (this.store.supportsSeeding()) {
3863
- await this.bridge.put(normalizePath(filepath), stringifiedFile);
4288
+ const normalizedPath = normalizePath(filepath);
4289
+ const { stringifiedFile, payload } = await this.stringifyFile(filepath, data);
4290
+ if (this.bridge) {
4291
+ await this.bridge.put(normalizedPath, stringifiedFile);
3864
4292
  }
3865
- await this.store.put(normalizePath(filepath), payload, {
3866
- keepTemplateKey,
3867
- collection,
3868
- indexDefinitions: collectionIndexDefinitions
3869
- });
4293
+ await this.onPut(normalizedPath, stringifiedFile);
4294
+ const putOps = makeIndexOpsForDocument(normalizedPath, collection, collectionIndexDefinitions, payload, "put", this.level);
4295
+ let existingItem;
4296
+ try {
4297
+ existingItem = await this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(normalizedPath);
4298
+ } catch (e) {
4299
+ if (e.code !== "LEVEL_NOT_FOUND") {
4300
+ throw e;
4301
+ }
4302
+ }
4303
+ const delOps = existingItem ? makeIndexOpsForDocument(normalizedPath, collection, collectionIndexDefinitions, existingItem, "del", this.level) : [];
4304
+ const ops = [
4305
+ ...delOps,
4306
+ ...putOps,
4307
+ {
4308
+ type: "put",
4309
+ key: normalizedPath,
4310
+ value: payload,
4311
+ sublevel: this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS)
4312
+ }
4313
+ ];
4314
+ await this.level.batch(ops);
3870
4315
  }
3871
4316
  return true;
3872
4317
  } catch (error) {
@@ -3882,7 +4327,7 @@ var Database = class {
3882
4327
  if (SYSTEM_FILES.includes(filepath)) {
3883
4328
  throw new Error(`Unexpected put for config file ${filepath}`);
3884
4329
  } else {
3885
- const tinaSchema = await this.getSchema();
4330
+ const tinaSchema = await this.getSchema(this.level);
3886
4331
  const collection = tinaSchema.getCollectionByFullPath(filepath);
3887
4332
  const templateInfo = await tinaSchema.getTemplatesForCollectable(collection);
3888
4333
  let template;
@@ -3936,43 +4381,51 @@ var Database = class {
3936
4381
  return stringifiedFile;
3937
4382
  };
3938
4383
  this.getLookup = async (returnType) => {
3939
- const lookupPath = import_path3.default.join(this.getGeneratedFolder(), `_lookup.json`);
4384
+ await this.initLevel();
4385
+ const lookupPath = normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_lookup.json`));
3940
4386
  if (!this._lookup) {
3941
- const _lookup = await this.store.get(normalizePath(lookupPath));
4387
+ const _lookup = await this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(lookupPath);
3942
4388
  this._lookup = _lookup;
3943
4389
  }
3944
4390
  return this._lookup[returnType];
3945
4391
  };
3946
4392
  this.getGraphQLSchema = async () => {
3947
- const graphqlPath = import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`);
3948
- return this.store.get(normalizePath(graphqlPath));
4393
+ await this.initLevel();
4394
+ const graphqlPath = normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`));
4395
+ return await this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(graphqlPath);
3949
4396
  };
3950
4397
  this.getGraphQLSchemaFromBridge = async () => {
3951
- const graphqlPath = import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`);
3952
- const _graphql = await this.bridge.get(normalizePath(graphqlPath));
4398
+ if (!this.bridge) {
4399
+ throw new Error(`No bridge configured`);
4400
+ }
4401
+ const graphqlPath = normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`));
4402
+ const _graphql = await this.bridge.get(graphqlPath);
3953
4403
  return JSON.parse(_graphql);
3954
4404
  };
3955
- this.getTinaSchema = async () => {
3956
- const schemaPath = import_path3.default.join(this.getGeneratedFolder(), `_schema.json`);
3957
- return this.store.get(normalizePath(schemaPath));
4405
+ this.getTinaSchema = async (level) => {
4406
+ await this.initLevel();
4407
+ const schemaPath = normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_schema.json`));
4408
+ return await (level || this.level).sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS).get(schemaPath);
3958
4409
  };
3959
- this.getSchema = async () => {
4410
+ this.getSchema = async (level) => {
3960
4411
  if (this.tinaSchema) {
3961
4412
  return this.tinaSchema;
3962
4413
  }
3963
- const schema = await this.getTinaSchema();
4414
+ await this.initLevel();
4415
+ const schema = await this.getTinaSchema(level || this.level);
3964
4416
  this.tinaSchema = await createSchema({ schema });
3965
4417
  return this.tinaSchema;
3966
4418
  };
3967
- this.getIndexDefinitions = async () => {
4419
+ this.getIndexDefinitions = async (level) => {
3968
4420
  if (!this.collectionIndexDefinitions) {
3969
4421
  await new Promise(async (resolve2, reject) => {
4422
+ await this.initLevel();
3970
4423
  try {
3971
- const schema = await this.getSchema();
4424
+ const schema = await this.getSchema(level || this.level);
3972
4425
  const collections = schema.getCollections();
3973
4426
  for (const collection of collections) {
3974
4427
  const indexDefinitions = {
3975
- [import_datalayer2.DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
4428
+ [DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
3976
4429
  };
3977
4430
  if (collection.fields) {
3978
4431
  for (const field of collection.fields) {
@@ -3984,7 +4437,7 @@ var Database = class {
3984
4437
  {
3985
4438
  name: field.name,
3986
4439
  type: field.type,
3987
- pad: field.type === "number" ? { fillString: "0", maxLength: import_datalayer2.DEFAULT_NUMERIC_LPAD } : void 0
4440
+ pad: field.type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
3988
4441
  }
3989
4442
  ]
3990
4443
  };
@@ -4023,43 +4476,82 @@ var Database = class {
4023
4476
  return true;
4024
4477
  };
4025
4478
  this.query = async (queryOptions, hydrator) => {
4026
- const { first, after, last, before, sort, collection, filterChain } = queryOptions;
4027
- const storeQueryOptions = {
4028
- sort,
4479
+ var _a;
4480
+ await this.initLevel();
4481
+ const {
4482
+ first,
4483
+ after,
4484
+ last,
4485
+ before,
4486
+ sort = DEFAULT_COLLECTION_SORT_KEY,
4029
4487
  collection,
4030
- filterChain
4031
- };
4488
+ filterChain: rawFilterChain
4489
+ } = queryOptions;
4490
+ let limit = 50;
4032
4491
  if (first) {
4033
- storeQueryOptions.limit = first;
4492
+ limit = first;
4034
4493
  } else if (last) {
4035
- storeQueryOptions.limit = last;
4036
- } else {
4037
- storeQueryOptions.limit = 50;
4494
+ limit = last;
4038
4495
  }
4496
+ const query = { reverse: !!last };
4039
4497
  if (after) {
4040
- storeQueryOptions.gt = (0, import_datalayer2.atob)(after);
4498
+ query.gt = atob(after);
4041
4499
  } else if (before) {
4042
- storeQueryOptions.lt = (0, import_datalayer2.atob)(before);
4043
- }
4044
- if (last) {
4045
- storeQueryOptions.reverse = true;
4500
+ query.lt = atob(before);
4046
4501
  }
4047
- const indexDefinitions = await this.getIndexDefinitions();
4048
- storeQueryOptions.indexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[queryOptions.collection];
4049
- if (!storeQueryOptions.indexDefinitions) {
4502
+ const allIndexDefinitions = await this.getIndexDefinitions(this.level);
4503
+ const indexDefinitions = allIndexDefinitions == null ? void 0 : allIndexDefinitions[queryOptions.collection];
4504
+ if (!indexDefinitions) {
4050
4505
  throw new Error(`No indexDefinitions for collection ${queryOptions.collection}`);
4051
4506
  }
4052
- const {
4053
- edges,
4054
- pageInfo: { hasPreviousPage, hasNextPage, startCursor, endCursor }
4055
- } = await this.store.query(storeQueryOptions);
4507
+ const filterChain = coerceFilterChainOperands(rawFilterChain);
4508
+ const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
4509
+ const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
4510
+ const rootLevel = this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
4511
+ const sublevel = indexDefinition ? this.level.sublevel(collection, SUBLEVEL_OPTIONS).sublevel(sort, SUBLEVEL_OPTIONS) : rootLevel;
4512
+ if (!query.gt && !query.gte) {
4513
+ query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? filterSuffixes.left : "";
4514
+ }
4515
+ if (!query.lt && !query.lte) {
4516
+ query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${filterSuffixes.right}\xFF` : "\xFF";
4517
+ }
4518
+ let edges = [];
4519
+ let startKey = "";
4520
+ let endKey = "";
4521
+ let hasPreviousPage = false;
4522
+ let hasNextPage = false;
4523
+ const fieldsPattern = ((_a = indexDefinition == null ? void 0 : indexDefinition.fields) == null ? void 0 : _a.length) ? `${indexDefinition.fields.map((p) => `(?<${p.name}>.+)${INDEX_KEY_FIELD_SEPARATOR}`).join("")}` : "";
4524
+ const valuesRegex = indexDefinition ? new RegExp(`^${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^(?<_filepath_>.+)`);
4525
+ const itemFilter = makeFilter({ filterChain });
4526
+ const iterator = sublevel.iterator(query);
4527
+ for await (const [key, value] of iterator) {
4528
+ const matcher = valuesRegex.exec(key);
4529
+ if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
4530
+ continue;
4531
+ }
4532
+ const filepath = matcher.groups["_filepath_"];
4533
+ if (!itemFilter(filterSuffixes ? matcher.groups : indexDefinition ? await rootLevel.get(filepath) : value)) {
4534
+ continue;
4535
+ }
4536
+ if (limit !== -1 && edges.length >= limit) {
4537
+ if (query.reverse) {
4538
+ hasPreviousPage = true;
4539
+ } else {
4540
+ hasNextPage = true;
4541
+ }
4542
+ break;
4543
+ }
4544
+ startKey = startKey || key || "";
4545
+ endKey = key || "";
4546
+ edges = [...edges, { cursor: key, path: filepath }];
4547
+ }
4056
4548
  return {
4057
4549
  edges: await sequential(edges, async (edge) => {
4058
4550
  try {
4059
4551
  const node = await hydrator(edge.path);
4060
4552
  return {
4061
4553
  node,
4062
- cursor: (0, import_datalayer2.btoa)(edge.cursor)
4554
+ cursor: btoa(edge.cursor)
4063
4555
  };
4064
4556
  } catch (error) {
4065
4557
  if (error instanceof Error && (!edge.path.includes(".tina/__generated__/_graphql.json") || !edge.path.includes("tina/__generated__/_graphql.json"))) {
@@ -4077,8 +4569,8 @@ var Database = class {
4077
4569
  pageInfo: {
4078
4570
  hasPreviousPage,
4079
4571
  hasNextPage,
4080
- startCursor: (0, import_datalayer2.btoa)(startCursor),
4081
- endCursor: (0, import_datalayer2.btoa)(endCursor)
4572
+ startCursor: btoa(startKey),
4573
+ endCursor: btoa(endKey)
4082
4574
  }
4083
4575
  };
4084
4576
  };
@@ -4086,7 +4578,7 @@ var Database = class {
4086
4578
  graphQLSchema,
4087
4579
  tinaSchema
4088
4580
  }) => {
4089
- if (this.bridge.supportsBuilding()) {
4581
+ if (this.bridge && this.bridge.supportsBuilding()) {
4090
4582
  await this.bridge.putConfig(normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_graphql.json`)), JSON.stringify(graphQLSchema));
4091
4583
  await this.bridge.putConfig(normalizePath(import_path3.default.join(this.getGeneratedFolder(), `_schema.json`)), JSON.stringify(tinaSchema.schema));
4092
4584
  }
@@ -4096,60 +4588,125 @@ var Database = class {
4096
4588
  tinaSchema,
4097
4589
  lookup: lookupFromLockFile
4098
4590
  }) => {
4591
+ if (!this.bridge) {
4592
+ throw new Error("No bridge configured");
4593
+ }
4594
+ await this.initLevel();
4099
4595
  await this.indexStatusCallbackWrapper(async () => {
4100
4596
  const lookup = lookupFromLockFile || JSON.parse(await this.bridge.get(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_lookup.json"))));
4101
- if (this.store.supportsSeeding()) {
4102
- await this.store.clear();
4103
- await this.store.seed(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_graphql.json")), graphQLSchema);
4104
- await this.store.seed(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_schema.json")), tinaSchema.schema);
4105
- await this.store.seed(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_lookup.json")), lookup);
4106
- await this._indexAllContent();
4597
+ let nextLevel;
4598
+ let nextVersion;
4599
+ if (!this.config.version) {
4600
+ await this.level.clear();
4601
+ nextLevel = this.level;
4107
4602
  } else {
4108
- if (this.store.supportsIndexing()) {
4109
- throw new Error(`Schema must be indexed with provided Store`);
4603
+ const version2 = await this.getDatabaseVersion();
4604
+ nextVersion = version2 ? `${parseInt(version2) + 1}` : "0";
4605
+ nextLevel = this.rootLevel.sublevel(nextVersion, SUBLEVEL_OPTIONS);
4606
+ }
4607
+ const contentRootLevel = nextLevel.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
4608
+ await contentRootLevel.put(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_graphql.json")), graphQLSchema);
4609
+ await contentRootLevel.put(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_schema.json")), tinaSchema.schema);
4610
+ await contentRootLevel.put(normalizePath(import_path3.default.join(this.getGeneratedFolder(), "_lookup.json")), lookup);
4611
+ await this._indexAllContent(nextLevel);
4612
+ if (this.config.version) {
4613
+ await this.updateDatabaseVersion(nextVersion);
4614
+ if (this.level) {
4615
+ await this.level.clear();
4110
4616
  }
4617
+ this.level = nextLevel;
4111
4618
  }
4112
4619
  });
4113
4620
  };
4114
4621
  this.deleteContentByPaths = async (documentPaths) => {
4622
+ await this.initLevel();
4623
+ const operations = [];
4624
+ const enqueueOps = async (ops) => {
4625
+ operations.push(...ops);
4626
+ while (operations.length >= 25) {
4627
+ await this.level.batch(operations.splice(0, 25));
4628
+ }
4629
+ };
4115
4630
  await this.indexStatusCallbackWrapper(async () => {
4116
4631
  const { pathsByCollection, nonCollectionPaths, collections } = await this.partitionPathsByCollection(documentPaths);
4117
4632
  for (const collection of Object.keys(pathsByCollection)) {
4118
- await _deleteIndexContent(this, pathsByCollection[collection], collections[collection]);
4633
+ await _deleteIndexContent(this, pathsByCollection[collection], enqueueOps, collections[collection]);
4119
4634
  }
4120
- await _deleteIndexContent(this, nonCollectionPaths, null);
4635
+ await _deleteIndexContent(this, nonCollectionPaths, enqueueOps, null);
4121
4636
  });
4637
+ while (operations.length) {
4638
+ await this.level.batch(operations.splice(0, 25));
4639
+ }
4122
4640
  };
4123
4641
  this.indexContentByPaths = async (documentPaths) => {
4642
+ await this.initLevel();
4643
+ const operations = [];
4644
+ const enqueueOps = async (ops) => {
4645
+ operations.push(...ops);
4646
+ while (operations.length >= 25) {
4647
+ await this.level.batch(operations.splice(0, 25));
4648
+ }
4649
+ };
4124
4650
  await this.indexStatusCallbackWrapper(async () => {
4125
4651
  const { pathsByCollection, nonCollectionPaths, collections } = await this.partitionPathsByCollection(documentPaths);
4126
4652
  for (const collection of Object.keys(pathsByCollection)) {
4127
- await _indexContent(this, pathsByCollection[collection], collections[collection]);
4653
+ await _indexContent(this, this.level, pathsByCollection[collection], enqueueOps, collections[collection]);
4128
4654
  }
4129
- await _indexContent(this, nonCollectionPaths);
4655
+ await _indexContent(this, this.level, nonCollectionPaths, enqueueOps);
4130
4656
  });
4657
+ while (operations.length) {
4658
+ await this.level.batch(operations.splice(0, 25));
4659
+ }
4131
4660
  };
4132
4661
  this.delete = async (filepath) => {
4662
+ await this.initLevel();
4133
4663
  const collection = await this.collectionForPath(filepath);
4134
4664
  let collectionIndexDefinitions;
4135
4665
  if (collection) {
4136
- const indexDefinitions = await this.getIndexDefinitions();
4666
+ const indexDefinitions = await this.getIndexDefinitions(this.level);
4137
4667
  collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4138
4668
  }
4139
- await this.store.delete(normalizePath(filepath), {
4140
- collection: collection.name,
4141
- indexDefinitions: collectionIndexDefinitions
4142
- });
4143
- await this.bridge.delete(normalizePath(filepath));
4669
+ this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
4670
+ const itemKey = normalizePath(filepath);
4671
+ const rootSublevel = this.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
4672
+ const item = await rootSublevel.get(itemKey);
4673
+ if (item) {
4674
+ await this.level.batch([
4675
+ ...makeIndexOpsForDocument(filepath, collection.name, collectionIndexDefinitions, item, "del", this.level),
4676
+ {
4677
+ type: "del",
4678
+ key: itemKey,
4679
+ sublevel: rootSublevel
4680
+ }
4681
+ ]);
4682
+ }
4683
+ if (this.bridge) {
4684
+ await this.bridge.delete(normalizePath(filepath));
4685
+ }
4686
+ await this.onDelete(normalizePath(filepath));
4144
4687
  };
4145
- this._indexAllContent = async () => {
4146
- const tinaSchema = await this.getSchema();
4688
+ this._indexAllContent = async (level) => {
4689
+ const tinaSchema = await this.getSchema(level);
4690
+ const operations = [];
4691
+ const enqueueOps = async (ops) => {
4692
+ operations.push(...ops);
4693
+ while (operations.length >= 25) {
4694
+ const batchOps = operations.splice(0, 25);
4695
+ await level.batch(batchOps);
4696
+ }
4697
+ };
4147
4698
  await sequential(tinaSchema.getCollections(), async (collection) => {
4148
4699
  const documentPaths = await this.bridge.glob(normalizePath(collection.path), collection.format || "md");
4149
- await _indexContent(this, documentPaths, collection);
4700
+ await _indexContent(this, level, documentPaths, enqueueOps, collection);
4150
4701
  });
4702
+ while (operations.length) {
4703
+ await level.batch(operations.splice(0, 25));
4704
+ }
4151
4705
  };
4152
4706
  this.addToLookupMap = async (lookup) => {
4707
+ if (!this.bridge) {
4708
+ throw new Error("No bridge configured");
4709
+ }
4153
4710
  const lookupPath = import_path3.default.join(this.getGeneratedFolder(), `_lookup.json`);
4154
4711
  let lookupMap;
4155
4712
  try {
@@ -4164,8 +4721,10 @@ var Database = class {
4164
4721
  };
4165
4722
  this.tinaDirectory = config.tinaDirectory || ".tina";
4166
4723
  this.bridge = config.bridge;
4167
- this.store = config.store;
4724
+ this.rootLevel = config.level;
4168
4725
  this.indexStatusCallback = config.indexStatusCallback || defaultStatusCallback;
4726
+ this.onPut = config.onPut || defaultOnPut;
4727
+ this.onDelete = config.onDelete || defaultOnDelete;
4169
4728
  }
4170
4729
  async partitionPathsByCollection(documentPaths) {
4171
4730
  const pathsByCollection = {};
@@ -4185,6 +4744,39 @@ var Database = class {
4185
4744
  }
4186
4745
  return { pathsByCollection, nonCollectionPaths, collections };
4187
4746
  }
4747
+ async updateDatabaseVersion(version2) {
4748
+ const metadataLevel = await this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
4749
+ await metadataLevel.put("metadata", { version: version2 });
4750
+ }
4751
+ async getDatabaseVersion() {
4752
+ const metadataLevel = await this.rootLevel.sublevel("_metadata", SUBLEVEL_OPTIONS);
4753
+ let version2;
4754
+ try {
4755
+ const metadata = await metadataLevel.get("metadata");
4756
+ version2 = metadata.version || version2;
4757
+ } catch (e) {
4758
+ if (e.code !== "LEVEL_NOT_FOUND") {
4759
+ throw e;
4760
+ }
4761
+ if (version2) {
4762
+ await metadataLevel.put("metadata", { version: version2 });
4763
+ }
4764
+ }
4765
+ return version2;
4766
+ }
4767
+ async initLevel() {
4768
+ if (this.level) {
4769
+ return;
4770
+ }
4771
+ if (!this.config.version) {
4772
+ this.level = this.rootLevel;
4773
+ } else {
4774
+ const version2 = await this.getDatabaseVersion();
4775
+ if (version2) {
4776
+ this.level = this.rootLevel.sublevel(version2, SUBLEVEL_OPTIONS);
4777
+ }
4778
+ }
4779
+ }
4188
4780
  clearCache() {
4189
4781
  this.tinaSchema = null;
4190
4782
  this._lookup = null;
@@ -4203,22 +4795,14 @@ var Database = class {
4203
4795
  function hasOwnProperty(obj, prop) {
4204
4796
  return obj.hasOwnProperty(prop);
4205
4797
  }
4206
- var _indexContent = async (database, documentPaths, collection) => {
4207
- let seedOptions = void 0;
4798
+ var _indexContent = async (database, level, documentPaths, enqueueOps, collection) => {
4799
+ let collectionIndexDefinitions;
4208
4800
  if (collection) {
4209
- const indexDefinitions = await database.getIndexDefinitions();
4210
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4801
+ const indexDefinitions = await database.getIndexDefinitions(level);
4802
+ collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4211
4803
  if (!collectionIndexDefinitions) {
4212
4804
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
4213
4805
  }
4214
- const numIndexes = Object.keys(collectionIndexDefinitions).length;
4215
- if (numIndexes > 20) {
4216
- throw new Error(`A maximum of 20 indexes are allowed per field. Currently collection ${collection.name} has ${numIndexes} indexes. Add 'indexed: false' to exclude a field from indexing.`);
4217
- }
4218
- seedOptions = {
4219
- collection: collection.name,
4220
- indexDefinitions: collectionIndexDefinitions
4221
- };
4222
4806
  }
4223
4807
  await sequential(documentPaths, async (filepath) => {
4224
4808
  try {
@@ -4227,9 +4811,16 @@ var _indexContent = async (database, documentPaths, collection) => {
4227
4811
  frontmatterDelimiters: collection == null ? void 0 : collection.frontmatterDelimiters,
4228
4812
  frontmatterFormat: collection == null ? void 0 : collection.frontmatterFormat
4229
4813
  });
4230
- if (database.store.supportsSeeding()) {
4231
- await database.store.seed(normalizePath(filepath), data, seedOptions);
4232
- }
4814
+ const normalizedPath = normalizePath(filepath);
4815
+ await enqueueOps([
4816
+ ...makeIndexOpsForDocument(normalizedPath, collection == null ? void 0 : collection.name, collectionIndexDefinitions, data, "put", level),
4817
+ {
4818
+ type: "put",
4819
+ key: normalizedPath,
4820
+ value: data,
4821
+ sublevel: level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS)
4822
+ }
4823
+ ]);
4233
4824
  } catch (error) {
4234
4825
  throw new TinaFetchError(`Unable to seed ${filepath}`, {
4235
4826
  originalError: error,
@@ -4240,29 +4831,444 @@ var _indexContent = async (database, documentPaths, collection) => {
4240
4831
  }
4241
4832
  });
4242
4833
  };
4243
- var _deleteIndexContent = async (database, documentPaths, collection) => {
4244
- let deleteOptions = void 0;
4834
+ var _deleteIndexContent = async (database, documentPaths, enequeueOps, collection) => {
4835
+ let collectionIndexDefinitions;
4245
4836
  if (collection) {
4246
- const indexDefinitions = await database.getIndexDefinitions();
4247
- const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4837
+ const indexDefinitions = await database.getIndexDefinitions(database.level);
4838
+ collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
4248
4839
  if (!collectionIndexDefinitions) {
4249
4840
  throw new Error(`No indexDefinitions for collection ${collection.name}`);
4250
4841
  }
4251
- deleteOptions = {
4252
- collection: collection.name,
4253
- indexDefinitions: collectionIndexDefinitions
4254
- };
4255
4842
  }
4843
+ const rootLevel = database.level.sublevel(CONTENT_ROOT_PREFIX, SUBLEVEL_OPTIONS);
4256
4844
  await sequential(documentPaths, async (filepath) => {
4257
- database.store.delete(filepath, deleteOptions);
4845
+ const itemKey = normalizePath(filepath);
4846
+ try {
4847
+ const item = await rootLevel.get(itemKey);
4848
+ if (item) {
4849
+ await enequeueOps([
4850
+ ...makeIndexOpsForDocument(itemKey, collection.name, collectionIndexDefinitions, item, "del", database.level),
4851
+ { type: "del", key: itemKey, sublevel: rootLevel }
4852
+ ]);
4853
+ }
4854
+ } catch (e) {
4855
+ if (e.code !== "LEVEL_NOT_FOUND") {
4856
+ throw e;
4857
+ }
4858
+ }
4258
4859
  });
4259
4860
  };
4260
4861
 
4862
+ // src/level/tinaLevel.ts
4863
+ var import_many_level = __toModule(require("many-level"));
4864
+ var import_readable_stream = __toModule(require("readable-stream"));
4865
+ var import_net = __toModule(require("net"));
4866
+ var TinaLevelClient = class extends import_many_level.ManyLevelGuest {
4867
+ constructor() {
4868
+ super(...arguments);
4869
+ this._connected = false;
4870
+ }
4871
+ openConnection() {
4872
+ if (this._connected)
4873
+ return;
4874
+ const socket = (0, import_net.connect)(9e3);
4875
+ (0, import_readable_stream.pipeline)(socket, this.createRpcStream(), socket, () => {
4876
+ this._connected = false;
4877
+ });
4878
+ this._connected = true;
4879
+ }
4880
+ };
4881
+
4882
+ // src/database/bridge/filesystem.ts
4883
+ var import_fs_extra2 = __toModule(require("fs-extra"));
4884
+ var import_fast_glob = __toModule(require("fast-glob"));
4885
+ var import_path4 = __toModule(require("path"));
4886
+ var import_normalize_path = __toModule(require("normalize-path"));
4887
+ var FilesystemBridge = class {
4888
+ constructor(rootPath) {
4889
+ this.rootPath = rootPath || "";
4890
+ this.outputPath = rootPath || "";
4891
+ }
4892
+ addOutputPath(outputPath) {
4893
+ this.outputPath = outputPath;
4894
+ }
4895
+ async glob(pattern, extension) {
4896
+ const basePath = import_path4.default.join(this.outputPath, ...pattern.split("/"));
4897
+ const items = await (0, import_fast_glob.default)(import_path4.default.join(basePath, "**", `/*${extension}`).replace(/\\/g, "/"), {
4898
+ dot: true
4899
+ });
4900
+ const posixRootPath = (0, import_normalize_path.default)(this.outputPath);
4901
+ return items.map((item) => {
4902
+ return item.replace(posixRootPath, "").replace(/^\/|\/$/g, "");
4903
+ });
4904
+ }
4905
+ supportsBuilding() {
4906
+ return true;
4907
+ }
4908
+ async delete(filepath) {
4909
+ await import_fs_extra2.default.remove(import_path4.default.join(this.outputPath, filepath));
4910
+ }
4911
+ async get(filepath) {
4912
+ return import_fs_extra2.default.readFileSync(import_path4.default.join(this.outputPath, filepath)).toString();
4913
+ }
4914
+ async putConfig(filepath, data) {
4915
+ if (this.rootPath !== this.outputPath) {
4916
+ await this.put(filepath, data);
4917
+ await this.put(filepath, data, this.rootPath);
4918
+ } else {
4919
+ await this.put(filepath, data);
4920
+ }
4921
+ }
4922
+ async put(filepath, data, basePathOverride) {
4923
+ const basePath = basePathOverride || this.outputPath;
4924
+ await import_fs_extra2.default.outputFileSync(import_path4.default.join(basePath, filepath), data);
4925
+ }
4926
+ };
4927
+ var AuditFileSystemBridge = class extends FilesystemBridge {
4928
+ async put(filepath, data) {
4929
+ if ([
4930
+ ".tina/__generated__/_lookup.json",
4931
+ ".tina/__generated__/_schema.json",
4932
+ ".tina/__generated__/_graphql.json"
4933
+ ].includes(filepath)) {
4934
+ return super.put(filepath, data);
4935
+ }
4936
+ return;
4937
+ }
4938
+ };
4939
+
4940
+ // src/database/bridge/isomorphic.ts
4941
+ var import_isomorphic_git = __toModule(require("isomorphic-git"));
4942
+ var import_fs_extra3 = __toModule(require("fs-extra"));
4943
+ var import_glob_parent = __toModule(require("glob-parent"));
4944
+ var import_normalize_path2 = __toModule(require("normalize-path"));
4945
+ var import_graphql6 = __toModule(require("graphql"));
4946
+ var import_path5 = __toModule(require("path"));
4947
+ var flat = typeof Array.prototype.flat === "undefined" ? (entries) => entries.reduce((acc, x) => acc.concat(x), []) : (entries) => entries.flat();
4948
+ var toUint8Array = (buf) => {
4949
+ const ab = new ArrayBuffer(buf.length);
4950
+ const view = new Uint8Array(ab);
4951
+ for (let i = 0; i < buf.length; ++i) {
4952
+ view[i] = buf[i];
4953
+ }
4954
+ return view;
4955
+ };
4956
+ var IsomorphicBridge = class {
4957
+ constructor(rootPath, {
4958
+ gitRoot,
4959
+ author,
4960
+ committer,
4961
+ fsModule = import_fs_extra3.default,
4962
+ commitMessage = "Update from GraphQL client",
4963
+ ref,
4964
+ onPut,
4965
+ onDelete
4966
+ }) {
4967
+ this.cache = {};
4968
+ this.rootPath = rootPath;
4969
+ this.gitRoot = gitRoot;
4970
+ this.relativePath = rootPath.slice(this.gitRoot.length).replace(/\\/g, "/");
4971
+ if (this.relativePath.startsWith("/")) {
4972
+ this.relativePath = this.relativePath.slice(1);
4973
+ }
4974
+ this.fsModule = fsModule;
4975
+ this.author = author;
4976
+ this.committer = committer || author;
4977
+ this.isomorphicConfig = {
4978
+ dir: (0, import_normalize_path2.default)(this.gitRoot),
4979
+ fs: this.fsModule
4980
+ };
4981
+ this.ref = ref;
4982
+ this.commitMessage = commitMessage;
4983
+ this.onPut = onPut || (() => {
4984
+ });
4985
+ this.onDelete = onDelete || (() => {
4986
+ });
4987
+ }
4988
+ getAuthor() {
4989
+ return __spreadProps(__spreadValues({}, this.author), {
4990
+ timestamp: Math.round(new Date().getTime() / 1e3),
4991
+ timezoneOffset: 0
4992
+ });
4993
+ }
4994
+ getCommitter() {
4995
+ return __spreadProps(__spreadValues({}, this.committer), {
4996
+ timestamp: Math.round(new Date().getTime() / 1e3),
4997
+ timezoneOffset: 0
4998
+ });
4999
+ }
5000
+ async listEntries({
5001
+ pattern,
5002
+ entry,
5003
+ path: path6,
5004
+ results
5005
+ }) {
5006
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5007
+ oid: entry.oid,
5008
+ cache: this.cache
5009
+ }));
5010
+ const children = [];
5011
+ for (const childEntry of treeResult.tree) {
5012
+ const childPath = path6 ? `${path6}/${childEntry.path}` : childEntry.path;
5013
+ if (childEntry.type === "tree") {
5014
+ children.push(childEntry);
5015
+ } else {
5016
+ if (childPath.startsWith(pattern)) {
5017
+ results.push(childPath);
5018
+ }
5019
+ }
5020
+ }
5021
+ for (const childEntry of children) {
5022
+ const childPath = path6 ? `${path6}/${childEntry.path}` : childEntry.path;
5023
+ await this.listEntries({
5024
+ pattern,
5025
+ entry: childEntry,
5026
+ path: childPath,
5027
+ results
5028
+ });
5029
+ }
5030
+ }
5031
+ async resolvePathEntries(path6, ref) {
5032
+ let pathParts = path6.split("/");
5033
+ const result = await import_isomorphic_git.default.walk(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5034
+ map: async (filepath, [head]) => {
5035
+ if (head._fullpath === ".") {
5036
+ return head;
5037
+ }
5038
+ if (path6.startsWith(filepath)) {
5039
+ if ((0, import_path5.dirname)(path6) === (0, import_path5.dirname)(filepath)) {
5040
+ if (path6 === filepath) {
5041
+ return head;
5042
+ }
5043
+ } else {
5044
+ return head;
5045
+ }
5046
+ }
5047
+ },
5048
+ cache: this.cache,
5049
+ trees: [import_isomorphic_git.default.TREE({ ref })]
5050
+ }));
5051
+ const pathEntries = flat(result);
5052
+ if (pathParts.indexOf(".") === -1) {
5053
+ pathParts = [".", ...pathParts];
5054
+ }
5055
+ while (pathParts.length > pathEntries.length) {
5056
+ pathEntries.push(null);
5057
+ }
5058
+ return { pathParts, pathEntries };
5059
+ }
5060
+ async updateTreeHierarchy(existingOid, updatedOid, path6, type, pathEntries, pathParts) {
5061
+ const lastIdx = pathEntries.length - 1;
5062
+ const parentEntry = pathEntries[lastIdx];
5063
+ const parentPath = pathParts[lastIdx];
5064
+ let parentOid;
5065
+ let tree;
5066
+ const mode = type === "blob" ? "100644" : "040000";
5067
+ if (parentEntry) {
5068
+ parentOid = await parentEntry.oid();
5069
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5070
+ oid: parentOid,
5071
+ cache: this.cache
5072
+ }));
5073
+ tree = existingOid ? treeResult.tree.map((entry) => {
5074
+ if (entry.path === path6) {
5075
+ entry.oid = updatedOid;
5076
+ }
5077
+ return entry;
5078
+ }) : [
5079
+ ...treeResult.tree,
5080
+ {
5081
+ oid: updatedOid,
5082
+ type,
5083
+ path: path6,
5084
+ mode
5085
+ }
5086
+ ];
5087
+ } else {
5088
+ tree = [
5089
+ {
5090
+ oid: updatedOid,
5091
+ type,
5092
+ path: path6,
5093
+ mode
5094
+ }
5095
+ ];
5096
+ }
5097
+ const updatedParentOid = await import_isomorphic_git.default.writeTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5098
+ tree
5099
+ }));
5100
+ if (lastIdx === 0) {
5101
+ return updatedParentOid;
5102
+ } else {
5103
+ return await this.updateTreeHierarchy(parentOid, updatedParentOid, parentPath, "tree", pathEntries.slice(0, lastIdx), pathParts.slice(0, lastIdx));
5104
+ }
5105
+ }
5106
+ async commitTree(treeSha, ref) {
5107
+ const commitSha = await import_isomorphic_git.default.writeCommit(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5108
+ commit: {
5109
+ tree: treeSha,
5110
+ parent: [
5111
+ await import_isomorphic_git.default.resolveRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5112
+ ref
5113
+ }))
5114
+ ],
5115
+ message: this.commitMessage,
5116
+ author: this.getAuthor(),
5117
+ committer: this.getCommitter()
5118
+ }
5119
+ }));
5120
+ await import_isomorphic_git.default.writeRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5121
+ ref,
5122
+ value: commitSha,
5123
+ force: true
5124
+ }));
5125
+ }
5126
+ async getRef() {
5127
+ if (this.ref) {
5128
+ return this.ref;
5129
+ }
5130
+ const ref = await import_isomorphic_git.default.currentBranch(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5131
+ fullname: true
5132
+ }));
5133
+ if (!ref) {
5134
+ throw new import_graphql6.GraphQLError(`Unable to determine current branch from HEAD`, null, null, null, null, null, {});
5135
+ }
5136
+ this.ref = ref;
5137
+ return ref;
5138
+ }
5139
+ async glob(pattern, extension) {
5140
+ const ref = await this.getRef();
5141
+ const parent = (0, import_glob_parent.default)(this.qualifyPath(pattern));
5142
+ const { pathParts, pathEntries } = await this.resolvePathEntries(parent, ref);
5143
+ const leafEntry = pathEntries[pathEntries.length - 1];
5144
+ const entryPath = pathParts[pathParts.length - 1];
5145
+ const parentEntry = pathEntries[pathEntries.length - 2];
5146
+ let treeEntry;
5147
+ let parentPath;
5148
+ if (parentEntry) {
5149
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5150
+ oid: await parentEntry.oid(),
5151
+ cache: this.cache
5152
+ }));
5153
+ treeEntry = treeResult.tree.find((entry) => entry.path === entryPath);
5154
+ parentPath = pathParts.slice(1, pathParts.length).join("/");
5155
+ } else {
5156
+ treeEntry = {
5157
+ type: "tree",
5158
+ oid: await leafEntry.oid()
5159
+ };
5160
+ parentPath = "";
5161
+ }
5162
+ const results = [];
5163
+ await this.listEntries({
5164
+ pattern: this.qualifyPath(pattern),
5165
+ entry: treeEntry,
5166
+ path: parentPath,
5167
+ results
5168
+ });
5169
+ return results.map((path6) => this.unqualifyPath(path6)).filter((path6) => path6.endsWith(extension));
5170
+ }
5171
+ supportsBuilding() {
5172
+ return true;
5173
+ }
5174
+ async delete(filepath) {
5175
+ const ref = await this.getRef();
5176
+ const { pathParts, pathEntries } = await this.resolvePathEntries(this.qualifyPath(filepath), ref);
5177
+ let oidToRemove;
5178
+ let ptr = pathEntries.length - 1;
5179
+ while (ptr >= 1) {
5180
+ const leafEntry = pathEntries[ptr];
5181
+ const nodePath = pathParts[ptr];
5182
+ if (leafEntry) {
5183
+ oidToRemove = oidToRemove || await leafEntry.oid();
5184
+ const parentEntry = pathEntries[ptr - 1];
5185
+ const existingOid = await parentEntry.oid();
5186
+ const treeResult = await import_isomorphic_git.default.readTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5187
+ oid: existingOid,
5188
+ cache: this.cache
5189
+ }));
5190
+ const updatedTree = treeResult.tree.filter((value) => value.path !== nodePath);
5191
+ if (updatedTree.length === 0) {
5192
+ ptr -= 1;
5193
+ continue;
5194
+ }
5195
+ const updatedTreeOid = await import_isomorphic_git.default.writeTree(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5196
+ tree: updatedTree
5197
+ }));
5198
+ const updatedRootTreeOid = await this.updateTreeHierarchy(existingOid, updatedTreeOid, pathParts[ptr - 1], "tree", pathEntries.slice(0, ptr - 1), pathParts.slice(0, ptr - 1));
5199
+ await this.commitTree(updatedRootTreeOid, ref);
5200
+ break;
5201
+ } else {
5202
+ throw new import_graphql6.GraphQLError(`Unable to resolve path: ${filepath}`, null, null, null, null, null, { status: 404 });
5203
+ }
5204
+ }
5205
+ if (oidToRemove) {
5206
+ await import_isomorphic_git.default.updateIndex(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5207
+ filepath: this.qualifyPath(filepath),
5208
+ force: true,
5209
+ remove: true,
5210
+ oid: oidToRemove,
5211
+ cache: this.cache
5212
+ }));
5213
+ }
5214
+ await this.onDelete(filepath);
5215
+ }
5216
+ qualifyPath(filepath) {
5217
+ return this.relativePath ? `${this.relativePath}/${filepath}` : filepath;
5218
+ }
5219
+ unqualifyPath(filepath) {
5220
+ return this.relativePath ? filepath.slice(this.relativePath.length + 1) : filepath;
5221
+ }
5222
+ async get(filepath) {
5223
+ const ref = await this.getRef();
5224
+ const oid = await import_isomorphic_git.default.resolveRef(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5225
+ ref
5226
+ }));
5227
+ const { blob } = await import_isomorphic_git.default.readBlob(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5228
+ oid,
5229
+ filepath: this.qualifyPath(filepath),
5230
+ cache: this.cache
5231
+ }));
5232
+ return Buffer.from(blob).toString("utf8");
5233
+ }
5234
+ async putConfig(filepath, data) {
5235
+ await this.put(filepath, data);
5236
+ }
5237
+ async put(filepath, data) {
5238
+ const ref = await this.getRef();
5239
+ const { pathParts, pathEntries } = await this.resolvePathEntries(this.qualifyPath(filepath), ref);
5240
+ const blobUpdate = toUint8Array(Buffer.from(data));
5241
+ let existingOid;
5242
+ const leafEntry = pathEntries[pathEntries.length - 1];
5243
+ const nodePath = pathParts[pathParts.length - 1];
5244
+ if (leafEntry) {
5245
+ existingOid = await leafEntry.oid();
5246
+ const hash = await import_isomorphic_git.default.hashBlob({ object: blobUpdate });
5247
+ if (hash.oid === existingOid) {
5248
+ await this.onPut(filepath, data);
5249
+ return;
5250
+ }
5251
+ }
5252
+ const updatedOid = await import_isomorphic_git.default.writeBlob(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5253
+ blob: blobUpdate
5254
+ }));
5255
+ const updatedRootSha = await this.updateTreeHierarchy(existingOid, updatedOid, nodePath, "blob", pathEntries.slice(0, pathEntries.length - 1), pathParts.slice(0, pathParts.length - 1));
5256
+ await this.commitTree(updatedRootSha, ref);
5257
+ await import_isomorphic_git.default.updateIndex(__spreadProps(__spreadValues({}, this.isomorphicConfig), {
5258
+ filepath: this.qualifyPath(filepath),
5259
+ add: true,
5260
+ oid: updatedOid,
5261
+ cache: this.cache
5262
+ }));
5263
+ await this.onPut(filepath, data);
5264
+ }
5265
+ };
5266
+
4261
5267
  // src/index.ts
4262
5268
  var buildSchema = async (rootPath, database, flags) => {
4263
- const tempConfig = import_path4.default.join(rootPath, ".tina", "__generated__", "config");
4264
- const config = await import_fs_extra2.default.readFileSync(import_path4.default.join(tempConfig, "schema.json")).toString();
4265
- await import_fs_extra2.default.remove(tempConfig);
5269
+ const tempConfig = import_path6.default.join(rootPath, ".tina", "__generated__", "config");
5270
+ const config = await import_fs_extra4.default.readFileSync(import_path6.default.join(tempConfig, "schema.json")).toString();
5271
+ await import_fs_extra4.default.remove(tempConfig);
4266
5272
  const { graphQLSchema, tinaSchema } = await buildDotTinaFiles({
4267
5273
  database,
4268
5274
  config: JSON.parse(config),
@@ -4272,12 +5278,16 @@ var buildSchema = async (rootPath, database, flags) => {
4272
5278
  };
4273
5279
  var getASTSchema = async (database) => {
4274
5280
  const gqlAst = await database.getGraphQLSchemaFromBridge();
4275
- return (0, import_graphql6.buildASTSchema)(gqlAst);
5281
+ return (0, import_graphql7.buildASTSchema)(gqlAst);
4276
5282
  };
4277
5283
  // Annotate the CommonJS export names for ESM import in node:
4278
5284
  0 && (module.exports = {
5285
+ AuditFileSystemBridge,
5286
+ FilesystemBridge,
5287
+ IsomorphicBridge,
4279
5288
  TinaFetchError,
4280
5289
  TinaGraphQLError,
5290
+ TinaLevelClient,
4281
5291
  TinaParseDocumentError,
4282
5292
  TinaQueryError,
4283
5293
  assertShape,