@tinacms/datalayer 0.0.2 → 0.1.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/CHANGELOG.md +11 -0
- package/dist/database/store/filesystem.d.ts +6 -4
- package/dist/database/store/index.d.ts +102 -34
- package/dist/database/store/level.d.ts +6 -4
- package/dist/index.d.ts +15 -12
- package/dist/index.js +471 -96
- package/package.json +5 -3
- package/dist/database/store/memory.d.ts +0 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# tina-graphql
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a87e1e6fa: Enable query filtering, pagination, sorting
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 8b3be903f: Escape index field separator in input strings
|
|
12
|
+
- b01f2e382: Fixed an issue where `0` as a numerical operand was being evaluated as falsy.
|
|
13
|
+
|
|
3
14
|
## 0.0.2
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -3,14 +3,14 @@ Copyright 2021 Forestry.io Holdings, Inc.
|
|
|
3
3
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
you may not use this file except in compliance with the License.
|
|
5
5
|
You may obtain a copy of the License at
|
|
6
|
-
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
7
|
Unless required by applicable law or agreed to in writing, software
|
|
8
8
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
9
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
10
|
See the License for the specific language governing permissions and
|
|
11
11
|
limitations under the License.
|
|
12
12
|
*/
|
|
13
|
-
import { Store } from '.';
|
|
13
|
+
import { StoreQueryOptions, PutOptions, Store, StoreQueryResponse } from '.';
|
|
14
14
|
export declare class FilesystemStore implements Store {
|
|
15
15
|
rootPath: string;
|
|
16
16
|
clear(): Promise<void>;
|
|
@@ -18,13 +18,15 @@ export declare class FilesystemStore implements Store {
|
|
|
18
18
|
constructor({ rootPath }: {
|
|
19
19
|
rootPath?: string;
|
|
20
20
|
});
|
|
21
|
-
query(
|
|
21
|
+
query(queryOptions: StoreQueryOptions): Promise<StoreQueryResponse>;
|
|
22
22
|
seed(): Promise<void>;
|
|
23
23
|
get<T extends object>(filepath: string): Promise<T>;
|
|
24
24
|
supportsSeeding(): boolean;
|
|
25
25
|
supportsIndexing(): boolean;
|
|
26
26
|
glob(pattern: string, callback: any): Promise<any[]>;
|
|
27
|
-
put(filepath: string, data: object,
|
|
27
|
+
put(filepath: string, data: object, options?: PutOptions): Promise<void>;
|
|
28
|
+
open(): Promise<void>;
|
|
29
|
+
close(): Promise<void>;
|
|
28
30
|
}
|
|
29
31
|
export declare class AuditFilesystemStore extends FilesystemStore {
|
|
30
32
|
put(_filepath: string, _data: object): Promise<void>;
|
|
@@ -10,42 +10,93 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
10
10
|
See the License for the specific language governing permissions and
|
|
11
11
|
limitations under the License.
|
|
12
12
|
*/
|
|
13
|
+
import { FilterOperand } from '../../index';
|
|
14
|
+
export declare const DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
|
|
15
|
+
export declare const INDEX_KEY_FIELD_SEPARATOR = "#";
|
|
16
|
+
export declare const DEFAULT_NUMERIC_LPAD = 4;
|
|
17
|
+
export declare enum OP {
|
|
18
|
+
EQ = "eq",
|
|
19
|
+
GT = "gt",
|
|
20
|
+
LT = "lt",
|
|
21
|
+
GTE = "gte",
|
|
22
|
+
LTE = "lte",
|
|
23
|
+
STARTS_WITH = "startsWith",
|
|
24
|
+
IN = "in"
|
|
25
|
+
}
|
|
26
|
+
export declare type PadDefinition = {
|
|
27
|
+
fillString: string;
|
|
28
|
+
maxLength: number;
|
|
29
|
+
};
|
|
30
|
+
export declare type BinaryFilter = {
|
|
31
|
+
pathExpression: string;
|
|
32
|
+
rightOperand: FilterOperand;
|
|
33
|
+
operator: OP.EQ | OP.GT | OP.LT | OP.GTE | OP.LTE | OP.STARTS_WITH | OP.IN;
|
|
34
|
+
type: string;
|
|
35
|
+
pad?: PadDefinition;
|
|
36
|
+
};
|
|
37
|
+
export declare type TernaryFilter = {
|
|
38
|
+
pathExpression: string;
|
|
39
|
+
leftOperand: FilterOperand;
|
|
40
|
+
rightOperand: FilterOperand;
|
|
41
|
+
leftOperator: OP.GTE | OP.GT;
|
|
42
|
+
rightOperator: OP.LT | OP.LTE;
|
|
43
|
+
type: string;
|
|
44
|
+
pad?: PadDefinition;
|
|
45
|
+
};
|
|
46
|
+
/** Options for {@link Store.query} */
|
|
47
|
+
export declare type StoreQueryOptions = {
|
|
48
|
+
collection: string;
|
|
49
|
+
indexDefinitions?: Record<string, IndexDefinition>;
|
|
50
|
+
filterChain: (BinaryFilter | TernaryFilter)[];
|
|
51
|
+
sort?: string;
|
|
52
|
+
gt?: string;
|
|
53
|
+
gte?: string;
|
|
54
|
+
lt?: string;
|
|
55
|
+
lte?: string;
|
|
56
|
+
reverse?: boolean;
|
|
57
|
+
limit?: number;
|
|
58
|
+
};
|
|
59
|
+
export declare type PageInfo = {
|
|
60
|
+
hasPreviousPage: boolean;
|
|
61
|
+
hasNextPage: boolean;
|
|
62
|
+
startCursor: string;
|
|
63
|
+
endCursor: string;
|
|
64
|
+
};
|
|
65
|
+
export declare type StoreQueryResponse = {
|
|
66
|
+
edges: {
|
|
67
|
+
cursor: string;
|
|
68
|
+
path: string;
|
|
69
|
+
}[];
|
|
70
|
+
pageInfo: PageInfo;
|
|
71
|
+
};
|
|
72
|
+
export declare type IndexDefinition = {
|
|
73
|
+
fields: {
|
|
74
|
+
name: string;
|
|
75
|
+
type?: string;
|
|
76
|
+
pad?: PadDefinition;
|
|
77
|
+
}[];
|
|
78
|
+
};
|
|
79
|
+
export declare type SeedOptions = {
|
|
80
|
+
collection?: string;
|
|
81
|
+
indexDefinitions?: Record<string, IndexDefinition>;
|
|
82
|
+
includeTemplate?: boolean;
|
|
83
|
+
keepTemplateKey?: boolean;
|
|
84
|
+
};
|
|
85
|
+
export declare type PutOptions = SeedOptions & {
|
|
86
|
+
seed?: boolean;
|
|
87
|
+
};
|
|
13
88
|
export interface Store {
|
|
14
89
|
glob(pattern: string, hydrator?: (fullPath: string) => Promise<object>): Promise<string[]>;
|
|
15
90
|
get<T extends object>(filepath: string): Promise<T>;
|
|
16
91
|
clear(): void;
|
|
92
|
+
close(): void;
|
|
93
|
+
open(): void;
|
|
17
94
|
/**
|
|
18
|
-
*
|
|
19
|
-
* @param
|
|
20
|
-
*
|
|
21
|
-
* of the key is the value provided by the query
|
|
22
|
-
* ```graphql
|
|
23
|
-
* {
|
|
24
|
-
* getPostsList(filter: {
|
|
25
|
-
* title: {
|
|
26
|
-
* eq: "Hello, World"
|
|
27
|
-
* }
|
|
28
|
-
* }) {
|
|
29
|
-
* ...
|
|
30
|
-
* }
|
|
31
|
-
* }
|
|
32
|
-
* ```
|
|
33
|
-
* Would equate to a query string of:
|
|
34
|
-
* ```
|
|
35
|
-
* __attribute__#posts#posts#title#Hello, World
|
|
36
|
-
* ```
|
|
37
|
-
* This can be used by a data store as a secondary index of sorts
|
|
38
|
-
*
|
|
39
|
-
* It's important to note that for now each query string acts as an "AND" clause,
|
|
40
|
-
* meaning the resulting records need to be present in _each_ query string.
|
|
41
|
-
*
|
|
42
|
-
* @param hydrator
|
|
43
|
-
* hydrator is an optional callback, which may be useful depending on the storage mechanism.
|
|
44
|
-
* For example, the in-memory storage only stores the path to its records as its value,
|
|
45
|
-
* but in something like DynamoDB the query strings may be used to look up the full record,
|
|
46
|
-
* meaning there's no need to "hydrate" the return value
|
|
95
|
+
* Executes a query against a collection
|
|
96
|
+
* @param queryOptions - options for the query
|
|
97
|
+
* @returns the results of the query
|
|
47
98
|
*/
|
|
48
|
-
query(
|
|
99
|
+
query(queryOptions: StoreQueryOptions): Promise<StoreQueryResponse>;
|
|
49
100
|
/**
|
|
50
101
|
* In this context, seeding is the act of putting records and indexing data into an ephemeral
|
|
51
102
|
* storage layer for use during the GraphQL runtime. What might seem suprising is that some stores
|
|
@@ -56,9 +107,7 @@ export interface Store {
|
|
|
56
107
|
* At this time it seems that it would never make sense to be able to "query" without "seed"-ing, and
|
|
57
108
|
* there'd be no value in "seeding" without "query"-ing.
|
|
58
109
|
*/
|
|
59
|
-
seed(filepath: string, data: object, options?:
|
|
60
|
-
includeTemplate?: boolean;
|
|
61
|
-
}): Promise<void>;
|
|
110
|
+
seed(filepath: string, data: object, options?: PutOptions): Promise<void>;
|
|
62
111
|
supportsSeeding(): boolean;
|
|
63
112
|
/**
|
|
64
113
|
* Whether this store supports the ability to index data.
|
|
@@ -68,5 +117,24 @@ export interface Store {
|
|
|
68
117
|
* user's repo.
|
|
69
118
|
*/
|
|
70
119
|
supportsIndexing(): boolean;
|
|
71
|
-
put(filepath: string, data: object,
|
|
120
|
+
put(filepath: string, data: object, options?: PutOptions): Promise<void>;
|
|
72
121
|
}
|
|
122
|
+
export declare type FilterCondition = {
|
|
123
|
+
filterExpression: Record<string, FilterOperand>;
|
|
124
|
+
filterPath: string;
|
|
125
|
+
};
|
|
126
|
+
export declare const makeFilterChain: ({ conditions, }: {
|
|
127
|
+
conditions: FilterCondition[];
|
|
128
|
+
}) => (BinaryFilter | TernaryFilter)[];
|
|
129
|
+
export declare const makeFilter: ({ filterChain, }: {
|
|
130
|
+
filterChain?: (BinaryFilter | TernaryFilter)[];
|
|
131
|
+
}) => (values: Record<string, object | FilterOperand>) => boolean;
|
|
132
|
+
declare type StringEscaper = <T extends string | string[]>(input: T) => T;
|
|
133
|
+
export declare const makeStringEscaper: (regex: RegExp, replacement: string) => StringEscaper;
|
|
134
|
+
export declare const coerceFilterChainOperands: (filterChain: (BinaryFilter | TernaryFilter)[], stringEscaper: StringEscaper) => (BinaryFilter | TernaryFilter)[];
|
|
135
|
+
export declare const makeFilterSuffixes: (filterChain: (BinaryFilter | TernaryFilter)[], index: IndexDefinition) => {
|
|
136
|
+
left?: string;
|
|
137
|
+
right?: string;
|
|
138
|
+
} | undefined;
|
|
139
|
+
export declare const makeKeyForField: (definition: IndexDefinition, data: object, stringEscaper: StringEscaper) => string | null;
|
|
140
|
+
export {};
|
|
@@ -10,14 +10,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
10
10
|
See the License for the specific language governing permissions and
|
|
11
11
|
limitations under the License.
|
|
12
12
|
*/
|
|
13
|
-
import type { Store } from './index';
|
|
13
|
+
import type { StoreQueryOptions, StoreQueryResponse, PutOptions, SeedOptions, Store } from './index';
|
|
14
14
|
import { LevelDB } from 'level';
|
|
15
15
|
export declare class LevelStore implements Store {
|
|
16
16
|
rootPath: any;
|
|
17
17
|
db: LevelDB;
|
|
18
|
+
useMemory: boolean;
|
|
18
19
|
constructor(rootPath: string, useMemory?: boolean);
|
|
19
|
-
query(
|
|
20
|
-
seed(filepath: string, data: object): Promise<void>;
|
|
20
|
+
query(queryOptions: StoreQueryOptions): Promise<StoreQueryResponse>;
|
|
21
|
+
seed(filepath: string, data: object, options?: SeedOptions): Promise<void>;
|
|
21
22
|
supportsSeeding(): boolean;
|
|
22
23
|
supportsIndexing(): boolean;
|
|
23
24
|
print(): Promise<void>;
|
|
@@ -25,5 +26,6 @@ export declare class LevelStore implements Store {
|
|
|
25
26
|
clear(): Promise<void>;
|
|
26
27
|
glob(pattern: string, callback: any): Promise<any[]>;
|
|
27
28
|
get(filepath: string): Promise<any>;
|
|
28
|
-
|
|
29
|
+
close(): Promise<void>;
|
|
30
|
+
put(filepath: string, data: object, options?: PutOptions): Promise<void>;
|
|
29
31
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
Copyright 2021 Forestry.io Holdings, Inc.
|
|
3
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
you may not use this file except in compliance with the License.
|
|
5
|
-
You may obtain a copy of the License at
|
|
6
|
-
|
|
7
|
-
Unless required by applicable law or agreed to in writing, software
|
|
8
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
-
See the License for the specific language governing permissions and
|
|
11
|
-
limitations under the License.
|
|
12
|
-
*/
|
|
2
|
+
Copyright 2021 Forestry.io Holdings, Inc.
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
See the License for the specific language governing permissions and
|
|
11
|
+
limitations under the License.
|
|
12
|
+
*/
|
|
13
13
|
export { FilesystemBridge, AuditFileSystemBridge, } from './database/bridge/filesystem';
|
|
14
14
|
export { FilesystemStore, AuditFilesystemStore, } from './database/store/filesystem';
|
|
15
|
-
export { MemoryStore } from './database/store/memory';
|
|
16
15
|
export { LevelStore } from './database/store/level';
|
|
16
|
+
export { coerceFilterChainOperands, DEFAULT_COLLECTION_SORT_KEY, DEFAULT_NUMERIC_LPAD, INDEX_KEY_FIELD_SEPARATOR, makeFilter, makeFilterChain, makeFilterSuffixes, makeKeyForField, makeStringEscaper, OP, } from './database/store';
|
|
17
|
+
export type { BinaryFilter, FilterCondition, IndexDefinition, PadDefinition, StoreQueryOptions, StoreQueryResponse, PageInfo, PutOptions, SeedOptions, Store, TernaryFilter, } from './database/store';
|
|
18
|
+
export declare type FilterOperand = string | number | boolean | string[] | number[];
|
|
19
|
+
export { atob, btoa } from './util';
|
package/dist/index.js
CHANGED
|
@@ -55,10 +55,21 @@ var __toModule = (module2) => {
|
|
|
55
55
|
__export(exports, {
|
|
56
56
|
AuditFileSystemBridge: () => AuditFileSystemBridge,
|
|
57
57
|
AuditFilesystemStore: () => AuditFilesystemStore,
|
|
58
|
+
DEFAULT_COLLECTION_SORT_KEY: () => DEFAULT_COLLECTION_SORT_KEY,
|
|
59
|
+
DEFAULT_NUMERIC_LPAD: () => DEFAULT_NUMERIC_LPAD,
|
|
58
60
|
FilesystemBridge: () => FilesystemBridge,
|
|
59
61
|
FilesystemStore: () => FilesystemStore,
|
|
62
|
+
INDEX_KEY_FIELD_SEPARATOR: () => INDEX_KEY_FIELD_SEPARATOR,
|
|
60
63
|
LevelStore: () => LevelStore,
|
|
61
|
-
|
|
64
|
+
OP: () => OP,
|
|
65
|
+
atob: () => atob,
|
|
66
|
+
btoa: () => btoa,
|
|
67
|
+
coerceFilterChainOperands: () => coerceFilterChainOperands,
|
|
68
|
+
makeFilter: () => makeFilter,
|
|
69
|
+
makeFilterChain: () => makeFilterChain,
|
|
70
|
+
makeFilterSuffixes: () => makeFilterSuffixes,
|
|
71
|
+
makeKeyForField: () => makeKeyForField,
|
|
72
|
+
makeStringEscaper: () => makeStringEscaper
|
|
62
73
|
});
|
|
63
74
|
|
|
64
75
|
// pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/bridge/filesystem.ts
|
|
@@ -140,6 +151,12 @@ function assertShape(value, yupSchema, errorMessage) {
|
|
|
140
151
|
});
|
|
141
152
|
}
|
|
142
153
|
}
|
|
154
|
+
var atob = (b64Encoded) => {
|
|
155
|
+
return Buffer.from(b64Encoded, "base64").toString();
|
|
156
|
+
};
|
|
157
|
+
var btoa = (string) => {
|
|
158
|
+
return Buffer.from(string).toString("base64");
|
|
159
|
+
};
|
|
143
160
|
|
|
144
161
|
// pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/util.ts
|
|
145
162
|
var stringifyFile = (content, format, keepTemplateKey) => {
|
|
@@ -205,7 +222,7 @@ var FilesystemStore = class {
|
|
|
205
222
|
constructor({ rootPath }) {
|
|
206
223
|
this.rootPath = rootPath || "";
|
|
207
224
|
}
|
|
208
|
-
async query(
|
|
225
|
+
async query(queryOptions) {
|
|
209
226
|
throw new Error(`Unable to perform query for Filesystem store`);
|
|
210
227
|
}
|
|
211
228
|
async seed() {
|
|
@@ -237,8 +254,12 @@ var FilesystemStore = class {
|
|
|
237
254
|
return items;
|
|
238
255
|
}
|
|
239
256
|
}
|
|
240
|
-
async put(filepath, data,
|
|
241
|
-
await import_fs_extra2.default.outputFileSync(import_path2.default.join(this.rootPath, filepath), stringifyFile(data, import_path2.default.extname(filepath), keepTemplateKey));
|
|
257
|
+
async put(filepath, data, options) {
|
|
258
|
+
await import_fs_extra2.default.outputFileSync(import_path2.default.join(this.rootPath, filepath), stringifyFile(data, import_path2.default.extname(filepath), options.keepTemplateKey));
|
|
259
|
+
}
|
|
260
|
+
async open() {
|
|
261
|
+
}
|
|
262
|
+
async close() {
|
|
242
263
|
}
|
|
243
264
|
};
|
|
244
265
|
var AuditFilesystemStore = class extends FilesystemStore {
|
|
@@ -247,72 +268,342 @@ var AuditFilesystemStore = class extends FilesystemStore {
|
|
|
247
268
|
}
|
|
248
269
|
};
|
|
249
270
|
|
|
250
|
-
// pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/
|
|
251
|
-
var
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
271
|
+
// pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/index.ts
|
|
272
|
+
var import_jsonpath_plus = __toModule(require("jsonpath-plus"));
|
|
273
|
+
var DEFAULT_COLLECTION_SORT_KEY = "__filepath__";
|
|
274
|
+
var INDEX_KEY_FIELD_SEPARATOR = "#";
|
|
275
|
+
var DEFAULT_NUMERIC_LPAD = 4;
|
|
276
|
+
var OP;
|
|
277
|
+
(function(OP2) {
|
|
278
|
+
OP2["EQ"] = "eq";
|
|
279
|
+
OP2["GT"] = "gt";
|
|
280
|
+
OP2["LT"] = "lt";
|
|
281
|
+
OP2["GTE"] = "gte";
|
|
282
|
+
OP2["LTE"] = "lte";
|
|
283
|
+
OP2["STARTS_WITH"] = "startsWith";
|
|
284
|
+
OP2["IN"] = "in";
|
|
285
|
+
})(OP || (OP = {}));
|
|
286
|
+
var inferOperatorFromFilter = (filterOperator) => {
|
|
287
|
+
switch (filterOperator) {
|
|
288
|
+
case "after":
|
|
289
|
+
return OP.GT;
|
|
290
|
+
case "before":
|
|
291
|
+
return OP.LT;
|
|
292
|
+
case "eq":
|
|
293
|
+
return OP.EQ;
|
|
294
|
+
case "startsWith":
|
|
295
|
+
return OP.STARTS_WITH;
|
|
296
|
+
case "lt":
|
|
297
|
+
return OP.LT;
|
|
298
|
+
case "lte":
|
|
299
|
+
return OP.LTE;
|
|
300
|
+
case "gt":
|
|
301
|
+
return OP.GT;
|
|
302
|
+
case "gte":
|
|
303
|
+
return OP.GTE;
|
|
304
|
+
case "in":
|
|
305
|
+
return OP.IN;
|
|
306
|
+
default:
|
|
307
|
+
throw new Error(`unsupported filter condition: '${filterOperator}'`);
|
|
264
308
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
309
|
+
};
|
|
310
|
+
var getFilterOperator = (expression, operand) => {
|
|
311
|
+
return (expression[operand] || expression[operand] === 0) && operand;
|
|
312
|
+
};
|
|
313
|
+
var makeFilterChain = ({
|
|
314
|
+
conditions
|
|
315
|
+
}) => {
|
|
316
|
+
const filterChain = [];
|
|
317
|
+
if (!conditions) {
|
|
318
|
+
return filterChain;
|
|
319
|
+
}
|
|
320
|
+
for (const condition of conditions) {
|
|
321
|
+
const { filterPath, filterExpression } = condition;
|
|
322
|
+
const _a = filterExpression, { _type } = _a, keys = __objRest(_a, ["_type"]);
|
|
323
|
+
const [key1, key2, ...extraKeys] = Object.keys(keys);
|
|
324
|
+
if (extraKeys.length) {
|
|
325
|
+
throw new Error(`Unexpected keys: [${extraKeys.join(",")}] in filter expression`);
|
|
326
|
+
}
|
|
327
|
+
if (key1 && !key2) {
|
|
328
|
+
filterChain.push({
|
|
329
|
+
pathExpression: filterPath,
|
|
330
|
+
rightOperand: filterExpression[key1],
|
|
331
|
+
operator: inferOperatorFromFilter(key1),
|
|
332
|
+
type: _type,
|
|
333
|
+
pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
|
|
334
|
+
});
|
|
335
|
+
} else if (key1 && key2) {
|
|
336
|
+
const leftFilterOperator = getFilterOperator(filterExpression, "gt") || getFilterOperator(filterExpression, "gte") || getFilterOperator(filterExpression, "after") || void 0;
|
|
337
|
+
const rightFilterOperator = getFilterOperator(filterExpression, "lt") || getFilterOperator(filterExpression, "lte") || getFilterOperator(filterExpression, "before") || void 0;
|
|
338
|
+
let leftOperand;
|
|
339
|
+
let rightOperand;
|
|
340
|
+
if (rightFilterOperator && leftFilterOperator) {
|
|
341
|
+
if (key1 === leftFilterOperator) {
|
|
342
|
+
leftOperand = filterExpression[key1];
|
|
343
|
+
rightOperand = filterExpression[key2];
|
|
344
|
+
} else {
|
|
345
|
+
rightOperand = filterExpression[key1];
|
|
346
|
+
leftOperand = filterExpression[key2];
|
|
347
|
+
}
|
|
348
|
+
filterChain.push({
|
|
349
|
+
pathExpression: filterPath,
|
|
350
|
+
rightOperand,
|
|
351
|
+
leftOperand,
|
|
352
|
+
leftOperator: inferOperatorFromFilter(leftFilterOperator),
|
|
353
|
+
rightOperator: inferOperatorFromFilter(rightFilterOperator),
|
|
354
|
+
type: _type,
|
|
355
|
+
pad: _type === "number" ? { fillString: "0", maxLength: DEFAULT_NUMERIC_LPAD } : void 0
|
|
356
|
+
});
|
|
357
|
+
} else {
|
|
358
|
+
throw new Error(`Filter on field '${filterPath}' has invalid combination of conditions: '${key1}, ${key2}'`);
|
|
359
|
+
}
|
|
273
360
|
}
|
|
274
|
-
return sequential(items, async (documentString) => {
|
|
275
|
-
return hydrator(documentString);
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
async seed(filepath, data) {
|
|
279
|
-
await this.put(filepath, data);
|
|
280
|
-
}
|
|
281
|
-
supportsSeeding() {
|
|
282
|
-
return true;
|
|
283
|
-
}
|
|
284
|
-
supportsIndexing() {
|
|
285
|
-
return true;
|
|
286
|
-
}
|
|
287
|
-
async print() {
|
|
288
|
-
}
|
|
289
|
-
async clear() {
|
|
290
|
-
this.map = {};
|
|
291
361
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
362
|
+
return filterChain;
|
|
363
|
+
};
|
|
364
|
+
var makeFilter = ({
|
|
365
|
+
filterChain
|
|
366
|
+
}) => {
|
|
367
|
+
return (values) => {
|
|
368
|
+
for (const filter of filterChain) {
|
|
369
|
+
const dataType = filter.type;
|
|
370
|
+
const resolvedValues = (0, import_jsonpath_plus.JSONPath)({
|
|
371
|
+
path: filter.pathExpression,
|
|
372
|
+
json: values
|
|
373
|
+
});
|
|
374
|
+
if (!resolvedValues || !resolvedValues.length) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
let operands;
|
|
378
|
+
if (dataType === "string" || dataType === "reference") {
|
|
379
|
+
operands = resolvedValues;
|
|
380
|
+
} else if (dataType === "number" || dataType === "datetime") {
|
|
381
|
+
operands = resolvedValues.map((resolvedValue) => Number(resolvedValue));
|
|
382
|
+
} else if (dataType === "boolean") {
|
|
383
|
+
operands = resolvedValues.map((resolvedValue) => typeof resolvedValue === "boolean" && resolvedValue || resolvedValue === "true" || resolvedValue === "1");
|
|
296
384
|
} else {
|
|
385
|
+
throw new Error(`Unexpected datatype ${dataType}`);
|
|
386
|
+
}
|
|
387
|
+
const { operator } = filter;
|
|
388
|
+
let matches = false;
|
|
389
|
+
if (operator) {
|
|
390
|
+
switch (operator) {
|
|
391
|
+
case OP.EQ:
|
|
392
|
+
if (operands.findIndex((operand) => operand === filter.rightOperand) >= 0) {
|
|
393
|
+
matches = true;
|
|
394
|
+
}
|
|
395
|
+
break;
|
|
396
|
+
case OP.GT:
|
|
397
|
+
for (const operand of operands) {
|
|
398
|
+
if (operand > filter.rightOperand) {
|
|
399
|
+
matches = true;
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
case OP.LT:
|
|
405
|
+
for (const operand of operands) {
|
|
406
|
+
if (operand < filter.rightOperand) {
|
|
407
|
+
matches = true;
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
break;
|
|
412
|
+
case OP.GTE:
|
|
413
|
+
for (const operand of operands) {
|
|
414
|
+
if (operand >= filter.rightOperand) {
|
|
415
|
+
matches = true;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
case OP.LTE:
|
|
421
|
+
for (const operand of operands) {
|
|
422
|
+
if (operand <= filter.rightOperand) {
|
|
423
|
+
matches = true;
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
case OP.IN:
|
|
429
|
+
for (const operand of operands) {
|
|
430
|
+
if (filter.rightOperand.indexOf(operand) >= 0) {
|
|
431
|
+
matches = true;
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
break;
|
|
436
|
+
case OP.STARTS_WITH:
|
|
437
|
+
for (const operand of operands) {
|
|
438
|
+
if (operand.startsWith(filter.rightOperand)) {
|
|
439
|
+
matches = true;
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
break;
|
|
444
|
+
default:
|
|
445
|
+
throw new Error(`unexpected operator ${operator}`);
|
|
446
|
+
}
|
|
447
|
+
} else {
|
|
448
|
+
const { rightOperator, leftOperator, rightOperand, leftOperand } = filter;
|
|
449
|
+
for (const operand of operands) {
|
|
450
|
+
let rightMatches = false;
|
|
451
|
+
let leftMatches = false;
|
|
452
|
+
if (rightOperator === OP.LTE && operand <= rightOperand) {
|
|
453
|
+
rightMatches = true;
|
|
454
|
+
} else if (rightOperator === OP.LT && operand < rightOperand) {
|
|
455
|
+
rightMatches = true;
|
|
456
|
+
}
|
|
457
|
+
if (leftOperator === OP.GTE && operand >= leftOperand) {
|
|
458
|
+
leftMatches = true;
|
|
459
|
+
} else if (leftOperator === OP.GT && operand > leftOperand) {
|
|
460
|
+
leftMatches = true;
|
|
461
|
+
}
|
|
462
|
+
if (rightMatches && leftMatches) {
|
|
463
|
+
matches = true;
|
|
464
|
+
break;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
if (!matches) {
|
|
297
469
|
return false;
|
|
298
470
|
}
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
471
|
+
}
|
|
472
|
+
return true;
|
|
473
|
+
};
|
|
474
|
+
};
|
|
475
|
+
var makeStringEscaper = (regex, replacement) => {
|
|
476
|
+
return (input) => {
|
|
477
|
+
if (Array.isArray(input)) {
|
|
478
|
+
return input.map((val) => val.replace(regex, replacement));
|
|
304
479
|
} else {
|
|
305
|
-
return
|
|
480
|
+
return input.replace(regex, replacement);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
var applyPadding = (input, pad) => {
|
|
485
|
+
if (pad) {
|
|
486
|
+
if (Array.isArray(input)) {
|
|
487
|
+
return input.map((val) => String(val).padStart(pad.maxLength, pad.fillString));
|
|
488
|
+
} else {
|
|
489
|
+
return String(input).padStart(pad.maxLength, pad.fillString);
|
|
306
490
|
}
|
|
307
491
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
492
|
+
return input;
|
|
493
|
+
};
|
|
494
|
+
var coerceFilterChainOperands = (filterChain, stringEscaper) => {
|
|
495
|
+
const result = [];
|
|
496
|
+
if (filterChain.length) {
|
|
497
|
+
for (const filter of filterChain) {
|
|
498
|
+
const dataType = filter.type;
|
|
499
|
+
if (dataType === "datetime") {
|
|
500
|
+
if (filter.leftOperand !== void 0) {
|
|
501
|
+
result.push(__spreadProps(__spreadValues({}, filter), {
|
|
502
|
+
rightOperand: new Date(filter.rightOperand).getTime(),
|
|
503
|
+
leftOperand: new Date(filter.leftOperand).getTime()
|
|
504
|
+
}));
|
|
505
|
+
} else {
|
|
506
|
+
if (Array.isArray(filter.rightOperand)) {
|
|
507
|
+
result.push(__spreadProps(__spreadValues({}, filter), {
|
|
508
|
+
rightOperand: filter.rightOperand.map((operand) => new Date(operand).getTime())
|
|
509
|
+
}));
|
|
510
|
+
} else {
|
|
511
|
+
result.push(__spreadProps(__spreadValues({}, filter), {
|
|
512
|
+
rightOperand: new Date(filter.rightOperand).getTime()
|
|
513
|
+
}));
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
} else if (dataType === "string") {
|
|
517
|
+
if (filter.leftOperand !== void 0) {
|
|
518
|
+
result.push(__spreadProps(__spreadValues({}, filter), {
|
|
519
|
+
rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad),
|
|
520
|
+
leftOperand: applyPadding(stringEscaper(filter.leftOperand), filter.pad)
|
|
521
|
+
}));
|
|
522
|
+
} else {
|
|
523
|
+
result.push(__spreadProps(__spreadValues({}, filter), {
|
|
524
|
+
rightOperand: applyPadding(stringEscaper(filter.rightOperand), filter.pad)
|
|
525
|
+
}));
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
result.push(__spreadValues({}, filter));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
311
531
|
}
|
|
312
|
-
|
|
313
|
-
|
|
532
|
+
return result;
|
|
533
|
+
};
|
|
534
|
+
var makeFilterSuffixes = (filterChain, index) => {
|
|
535
|
+
if (filterChain && filterChain.length) {
|
|
536
|
+
const indexFields = index.fields.map((field) => field.name);
|
|
537
|
+
const orderedFilterChain = [];
|
|
538
|
+
for (const filter of filterChain) {
|
|
539
|
+
const idx = indexFields.indexOf(filter.pathExpression);
|
|
540
|
+
if (idx === -1) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
if (filter.operator && filter.operator === OP.IN) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
orderedFilterChain[idx] = filter;
|
|
547
|
+
}
|
|
548
|
+
const baseFragments = [];
|
|
549
|
+
let rightSuffix;
|
|
550
|
+
let leftSuffix;
|
|
551
|
+
let ternaryFilter = false;
|
|
552
|
+
if (orderedFilterChain[filterChain.length - 1] && !orderedFilterChain[filterChain.length - 1].operator) {
|
|
553
|
+
ternaryFilter = true;
|
|
554
|
+
}
|
|
555
|
+
for (let i = 0; i < orderedFilterChain.length; i++) {
|
|
556
|
+
const filter = orderedFilterChain[i];
|
|
557
|
+
if (!filter) {
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
if (Number(i) < indexFields.length - 1) {
|
|
561
|
+
if (!filter.operator) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const binaryFilter = filter;
|
|
565
|
+
if (binaryFilter.operator !== OP.EQ) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
baseFragments.push(applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad));
|
|
569
|
+
} else {
|
|
570
|
+
if (ternaryFilter) {
|
|
571
|
+
leftSuffix = applyPadding(orderedFilterChain[i].leftOperand, orderedFilterChain[i].pad);
|
|
572
|
+
rightSuffix = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
|
|
573
|
+
} else {
|
|
574
|
+
const op = orderedFilterChain[i].operator;
|
|
575
|
+
const operand = applyPadding(orderedFilterChain[i].rightOperand, orderedFilterChain[i].pad);
|
|
576
|
+
if (op === OP.LT || op === OP.LTE) {
|
|
577
|
+
rightSuffix = operand;
|
|
578
|
+
} else if (op === OP.GT || op === OP.GTE) {
|
|
579
|
+
leftSuffix = operand;
|
|
580
|
+
} else {
|
|
581
|
+
rightSuffix = operand;
|
|
582
|
+
leftSuffix = operand;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return {
|
|
588
|
+
left: leftSuffix && [...baseFragments, leftSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0,
|
|
589
|
+
right: rightSuffix && [...baseFragments, rightSuffix].join(INDEX_KEY_FIELD_SEPARATOR) || void 0
|
|
590
|
+
};
|
|
591
|
+
} else {
|
|
592
|
+
return {};
|
|
314
593
|
}
|
|
315
594
|
};
|
|
595
|
+
var makeKeyForField = (definition, data, stringEscaper) => {
|
|
596
|
+
const valueParts = [];
|
|
597
|
+
for (const field of definition.fields) {
|
|
598
|
+
if (field.name in data) {
|
|
599
|
+
const resolvedValue = String(field.type === "datetime" ? new Date(data[field.name]).getTime() : field.type === "string" ? stringEscaper(data[field.name]) : data[field.name]);
|
|
600
|
+
valueParts.push(applyPadding(resolvedValue, field.pad));
|
|
601
|
+
} else {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return valueParts.join(INDEX_KEY_FIELD_SEPARATOR);
|
|
606
|
+
};
|
|
316
607
|
|
|
317
608
|
// pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/datalayer/src/database/store/level.ts
|
|
318
609
|
var import_path3 = __toModule(require("path"));
|
|
@@ -320,47 +611,89 @@ var import_level = __toModule(require("level"));
|
|
|
320
611
|
var import_levelup = __toModule(require("levelup"));
|
|
321
612
|
var import_memdown = __toModule(require("memdown"));
|
|
322
613
|
var import_encoding_down = __toModule(require("encoding-down"));
|
|
614
|
+
var defaultPrefix = "_ROOT_";
|
|
615
|
+
var escapeStr = makeStringEscaper(new RegExp(INDEX_KEY_FIELD_SEPARATOR, "gm"), encodeURIComponent(INDEX_KEY_FIELD_SEPARATOR));
|
|
323
616
|
var LevelStore = class {
|
|
324
617
|
constructor(rootPath, useMemory = false) {
|
|
325
618
|
this.rootPath = rootPath || "";
|
|
619
|
+
this.useMemory = useMemory;
|
|
326
620
|
if (useMemory) {
|
|
327
|
-
|
|
328
|
-
this.db = db;
|
|
621
|
+
this.db = (0, import_levelup.default)((0, import_encoding_down.default)((0, import_memdown.default)(), { valueEncoding: "json" }));
|
|
329
622
|
} else {
|
|
330
|
-
|
|
623
|
+
this.db = (0, import_level.default)(import_path3.default.join(rootPath, ".tina/__generated__/db"), {
|
|
331
624
|
valueEncoding: "json"
|
|
332
625
|
});
|
|
333
|
-
this.db = db;
|
|
334
626
|
}
|
|
335
627
|
}
|
|
336
|
-
async query(
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (
|
|
356
|
-
|
|
628
|
+
async query(queryOptions) {
|
|
629
|
+
var _b;
|
|
630
|
+
const _a = queryOptions, {
|
|
631
|
+
filterChain: rawFilterChain,
|
|
632
|
+
sort = DEFAULT_COLLECTION_SORT_KEY,
|
|
633
|
+
collection,
|
|
634
|
+
indexDefinitions,
|
|
635
|
+
limit = 10
|
|
636
|
+
} = _a, query = __objRest(_a, [
|
|
637
|
+
"filterChain",
|
|
638
|
+
"sort",
|
|
639
|
+
"collection",
|
|
640
|
+
"indexDefinitions",
|
|
641
|
+
"limit"
|
|
642
|
+
]);
|
|
643
|
+
const filterChain = coerceFilterChainOperands(rawFilterChain, escapeStr);
|
|
644
|
+
const indexDefinition = sort && (indexDefinitions == null ? void 0 : indexDefinitions[sort]);
|
|
645
|
+
const filterSuffixes = indexDefinition && makeFilterSuffixes(filterChain, indexDefinition);
|
|
646
|
+
const indexPrefix = indexDefinition ? `${collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}` : `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`;
|
|
647
|
+
if (!query.gt && !query.gte) {
|
|
648
|
+
query.gte = (filterSuffixes == null ? void 0 : filterSuffixes.left) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.left}` : indexPrefix;
|
|
357
649
|
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
}
|
|
650
|
+
if (!query.lt && !query.lte) {
|
|
651
|
+
query.lte = (filterSuffixes == null ? void 0 : filterSuffixes.right) ? `${indexPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filterSuffixes.right}\xFF` : `${indexPrefix}\xFF`;
|
|
652
|
+
}
|
|
653
|
+
let edges = [];
|
|
654
|
+
let startKey = "";
|
|
655
|
+
let endKey = "";
|
|
656
|
+
let hasPreviousPage = false;
|
|
657
|
+
let hasNextPage = false;
|
|
658
|
+
const fieldsPattern = ((_b = indexDefinition == null ? void 0 : indexDefinition.fields) == null ? void 0 : _b.length) ? `${indexDefinition.fields.map((p) => `${INDEX_KEY_FIELD_SEPARATOR}(?<${p.name}>.+)`).join("")}${INDEX_KEY_FIELD_SEPARATOR}` : INDEX_KEY_FIELD_SEPARATOR;
|
|
659
|
+
const valuesRegex = indexDefinition ? new RegExp(`^${indexPrefix}${fieldsPattern}(?<_filepath_>.+)`) : new RegExp(`^${indexPrefix}(?<_filepath_>.+)`);
|
|
660
|
+
const itemFilter = makeFilter({ filterChain });
|
|
661
|
+
for await (const [key, value] of this.db.iterator(query)) {
|
|
662
|
+
const matcher = valuesRegex.exec(key);
|
|
663
|
+
if (!matcher || indexDefinition && matcher.length !== indexDefinition.fields.length + 2) {
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
const filepath = matcher.groups["_filepath_"];
|
|
667
|
+
if (!itemFilter(filterSuffixes ? matcher.groups : indexDefinition ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : value)) {
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
if (limit !== -1 && edges.length >= limit) {
|
|
671
|
+
if (query.reverse) {
|
|
672
|
+
hasPreviousPage = true;
|
|
673
|
+
} else {
|
|
674
|
+
hasNextPage = true;
|
|
675
|
+
}
|
|
676
|
+
break;
|
|
677
|
+
}
|
|
678
|
+
startKey = startKey || key || "";
|
|
679
|
+
endKey = key || "";
|
|
680
|
+
edges = [...edges, { cursor: key, path: filepath }];
|
|
681
|
+
}
|
|
682
|
+
return {
|
|
683
|
+
edges,
|
|
684
|
+
pageInfo: {
|
|
685
|
+
hasPreviousPage,
|
|
686
|
+
hasNextPage,
|
|
687
|
+
startCursor: startKey,
|
|
688
|
+
endCursor: endKey
|
|
689
|
+
}
|
|
690
|
+
};
|
|
361
691
|
}
|
|
362
|
-
async seed(filepath, data) {
|
|
363
|
-
await this.put(filepath, data
|
|
692
|
+
async seed(filepath, data, options) {
|
|
693
|
+
await this.put(filepath, data, __spreadValues({
|
|
694
|
+
keepTemplateKey: false,
|
|
695
|
+
seed: true
|
|
696
|
+
}, options));
|
|
364
697
|
}
|
|
365
698
|
supportsSeeding() {
|
|
366
699
|
return true;
|
|
@@ -389,10 +722,10 @@ var LevelStore = class {
|
|
|
389
722
|
const strings = [];
|
|
390
723
|
const p = new Promise((resolve, reject) => {
|
|
391
724
|
this.db.createKeyStream({
|
|
392
|
-
gte: pattern
|
|
393
|
-
lte: pattern
|
|
725
|
+
gte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}`,
|
|
726
|
+
lte: `${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${pattern}\xFF`
|
|
394
727
|
}).on("data", (data) => {
|
|
395
|
-
strings.push(data);
|
|
728
|
+
strings.push(data.split(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}`)[1]);
|
|
396
729
|
}).on("error", (message) => {
|
|
397
730
|
reject(message);
|
|
398
731
|
}).on("end", function() {
|
|
@@ -410,22 +743,64 @@ var LevelStore = class {
|
|
|
410
743
|
}
|
|
411
744
|
async get(filepath) {
|
|
412
745
|
try {
|
|
413
|
-
|
|
414
|
-
return content;
|
|
746
|
+
return await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`);
|
|
415
747
|
} catch (e) {
|
|
416
748
|
return void 0;
|
|
417
749
|
}
|
|
418
750
|
}
|
|
419
|
-
async
|
|
420
|
-
await this.db.
|
|
751
|
+
async close() {
|
|
752
|
+
await this.db.close();
|
|
753
|
+
}
|
|
754
|
+
async put(filepath, data, options) {
|
|
755
|
+
let existingData;
|
|
756
|
+
try {
|
|
757
|
+
existingData = options && !options.seed ? await this.db.get(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`) : null;
|
|
758
|
+
} catch (err) {
|
|
759
|
+
if (!err.notFound) {
|
|
760
|
+
throw err;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
await this.db.put(`${defaultPrefix}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`, data);
|
|
764
|
+
if (options == null ? void 0 : options.indexDefinitions) {
|
|
765
|
+
for (const [sort, definition] of Object.entries(options.indexDefinitions)) {
|
|
766
|
+
const indexedValue = makeKeyForField(definition, data, escapeStr);
|
|
767
|
+
const existingIndexedValue = existingData ? makeKeyForField(definition, existingData, escapeStr) : null;
|
|
768
|
+
let indexKey;
|
|
769
|
+
let existingIndexKey = null;
|
|
770
|
+
if (sort === DEFAULT_COLLECTION_SORT_KEY) {
|
|
771
|
+
indexKey = `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${filepath}`;
|
|
772
|
+
existingIndexKey = indexKey;
|
|
773
|
+
} else {
|
|
774
|
+
indexKey = indexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${indexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
|
|
775
|
+
existingIndexKey = existingIndexedValue ? `${options.collection}${INDEX_KEY_FIELD_SEPARATOR}${sort}${INDEX_KEY_FIELD_SEPARATOR}${existingIndexedValue}${INDEX_KEY_FIELD_SEPARATOR}${filepath}` : null;
|
|
776
|
+
}
|
|
777
|
+
if (indexKey) {
|
|
778
|
+
if (existingIndexKey && indexKey != existingIndexKey) {
|
|
779
|
+
await this.db.del(existingIndexKey);
|
|
780
|
+
}
|
|
781
|
+
await this.db.put(indexKey, "");
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
}
|
|
421
785
|
}
|
|
422
786
|
};
|
|
423
787
|
// Annotate the CommonJS export names for ESM import in node:
|
|
424
788
|
0 && (module.exports = {
|
|
425
789
|
AuditFileSystemBridge,
|
|
426
790
|
AuditFilesystemStore,
|
|
791
|
+
DEFAULT_COLLECTION_SORT_KEY,
|
|
792
|
+
DEFAULT_NUMERIC_LPAD,
|
|
427
793
|
FilesystemBridge,
|
|
428
794
|
FilesystemStore,
|
|
795
|
+
INDEX_KEY_FIELD_SEPARATOR,
|
|
429
796
|
LevelStore,
|
|
430
|
-
|
|
797
|
+
OP,
|
|
798
|
+
atob,
|
|
799
|
+
btoa,
|
|
800
|
+
coerceFilterChainOperands,
|
|
801
|
+
makeFilter,
|
|
802
|
+
makeFilterChain,
|
|
803
|
+
makeFilterSuffixes,
|
|
804
|
+
makeKeyForField,
|
|
805
|
+
makeStringEscaper
|
|
431
806
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinacms/datalayer",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
"graphql": "^15.3.0",
|
|
33
33
|
"gray-matter": "^4.0.2",
|
|
34
34
|
"js-yaml": "^3.14.0",
|
|
35
|
+
"jsonpath-plus": "^6.0.1",
|
|
35
36
|
"level": "^7.0.1",
|
|
37
|
+
"leveldown": "^6.1.0",
|
|
36
38
|
"levelup": "^5.1.1",
|
|
37
39
|
"lodash": "^4.17.20",
|
|
38
40
|
"memdown": "^6.1.1",
|
|
@@ -48,9 +50,9 @@
|
|
|
48
50
|
"directory": "packages/@tinacms/datalayer"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
|
-
"@tinacms/scripts": "0.50.
|
|
53
|
+
"@tinacms/scripts": "0.50.7",
|
|
52
54
|
"@types/fs-extra": "^9.0.2",
|
|
53
|
-
"@types/jest": "^
|
|
55
|
+
"@types/jest": "^27.4.1",
|
|
54
56
|
"@types/js-yaml": "^3.12.5",
|
|
55
57
|
"@types/level": "^6.0.0",
|
|
56
58
|
"@types/lodash": "^4.14.161",
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
Copyright 2021 Forestry.io Holdings, Inc.
|
|
3
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
you may not use this file except in compliance with the License.
|
|
5
|
-
You may obtain a copy of the License at
|
|
6
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
-
Unless required by applicable law or agreed to in writing, software
|
|
8
|
-
distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
-
See the License for the specific language governing permissions and
|
|
11
|
-
limitations under the License.
|
|
12
|
-
*/
|
|
13
|
-
import type { Store } from './index';
|
|
14
|
-
/**
|
|
15
|
-
* This is the bridge from whatever datasource we need for I/O.
|
|
16
|
-
* The basic example here is for the filesystem, one is needed
|
|
17
|
-
* for Github has well.
|
|
18
|
-
*/
|
|
19
|
-
export declare class MemoryStore implements Store {
|
|
20
|
-
rootPath: any;
|
|
21
|
-
db: any;
|
|
22
|
-
private map;
|
|
23
|
-
constructor(rootPath: string, object?: object);
|
|
24
|
-
query(queryStrings: string[], hydrator: any): Promise<any[]>;
|
|
25
|
-
seed(filepath: string, data: object): Promise<void>;
|
|
26
|
-
supportsSeeding(): boolean;
|
|
27
|
-
supportsIndexing(): boolean;
|
|
28
|
-
print(): Promise<void>;
|
|
29
|
-
clear(): Promise<void>;
|
|
30
|
-
glob(pattern: string, callback: any): Promise<any[]>;
|
|
31
|
-
get(filepath: string): Promise<any>;
|
|
32
|
-
put(filepath: string, data: object): Promise<void>;
|
|
33
|
-
}
|