@esposter/azure 4.3.1 → 4.4.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/README.md CHANGED
@@ -5,15 +5,14 @@
5
5
  [![NPM downloads][badge-npm-downloads]][url-npm]
6
6
  [![NPM Unpacked Size (with version)][badge-npm-unpacked-size]][url-npm]
7
7
 
8
- The parts of Azure's wire contract that both a real client and a fake one have to agree on: the OData filter
9
- clause vocabulary shared by Table Storage and Search, the entity key casing convention, and the service limits.
10
- No SDK client is constructed here and no credential is read — this package is pure data and pure functions, so
11
- it runs anywhere.
8
+ The Azure wire conventions that a real client and a fake one both have to speak: the OData filter clause vocabulary shared by Table Storage and Search, the entity key casing convention, and the service limits.
9
+
10
+ Design notes live in [the specs](https://github.com/Esposter/Esposter/tree/main/openspec/specs).
12
11
 
13
12
  ## Table of Contents
14
13
 
15
14
  - 🚀 [Getting Started](#getting-started)
16
- - 📖 [Documentation](#documentation)
15
+ - 🧩 [Key Exports](#key-exports)
17
16
  - ⚖️ [License](#license)
18
17
 
19
18
  ---
@@ -24,9 +23,22 @@ it runs anywhere.
24
23
  pnpm add @esposter/azure
25
24
  ```
26
25
 
27
- ## <a name="documentation">📖 Documentation</a>
28
-
29
- We highly recommend you take a look at the [documentation](https://github.com/Esposter/Esposter/tree/main/openspec/specs) to level up.
26
+ ## <a name="key-exports">🧩 Key Exports</a>
27
+
28
+ | Export | Kind | Purpose |
29
+ | --------------------------- | -------- | ---------------------------------------------------------------------------- |
30
+ | `AZURE_MAX_PAGE_SIZE` | const | Largest page size the service returns in one call |
31
+ | `BinaryOperator` | enum | Comparison operators Table Storage understands |
32
+ | `Clause` | type | A filter condition on one property, the unit OData strings are built from |
33
+ | `CompositeKey` | class | The `partitionKey` and `rowKey` pair every Table entity carries |
34
+ | `CompositeKeyPropertyNames` | const | The `CompositeKey` property names, so callers never restate the strings |
35
+ | `deserializeClause` | function | Parses a serialized filter clause back into a `Clause`, throwing on no match |
36
+ | `escapeValue` | function | Quotes a string as an OData literal, doubling embedded single quotes |
37
+ | `getPartitionKeyFilter` | function | The filter selecting everything under one partition key |
38
+ | `getTableNullClause` | function | The Table Storage "is null" clause, a negated `NaN` comparison |
39
+ | `SearchOperator` | enum | Collection predicates only Azure Search supports |
40
+ | `serializeClauses` | function | Serializes clauses into a Table Storage OData filter string |
41
+ | `serializeValue` | function | Renders one `SerializableValue` as a literal for Table or Search |
30
42
 
31
43
  ### Clauses
32
44
 
@@ -57,10 +69,9 @@ import { escapeValue, serializeValue } from "@esposter/azure";
57
69
  ### Filters
58
70
 
59
71
  `serializeClauses` turns a clause array into a Table Storage filter string and `serializeSearchClauses` into a
60
- Search one; the two differ only in how a `Date` renders, which is why they share a single core. Clauses on the
61
- same key are grouped — a range pair is joined with `and`, anything else with `or` — so a caller never assembles
62
- the boolean structure by hand. `deserializeClause` is the inverse, and is what lets a fake client evaluate a
63
- filter it was handed rather than pattern-matching the string.
72
+ Search one; the two differ only in how a `Date` renders. Clauses on the same key are grouped — a range pair is
73
+ joined with `and`, anything else with `or` — so a caller never assembles the boolean structure by hand.
74
+ `deserializeClause` is the inverse.
64
75
 
65
76
  ```ts
66
77
  import { BinaryOperator, CompositeKeyPropertyNames, getTableNullClause, serializeClauses } from "@esposter/azure";
@@ -72,17 +83,13 @@ const filter = serializeClauses([
72
83
  ]);
73
84
  ```
74
85
 
75
- Null is where the two services diverge and the helpers carry the difference: Table Storage cannot compare
76
- against null at all, so `getTableNullClause` expresses "is null" as a negated `NaN` comparison, while Search
77
- supports it directly through `getSearchNullClause` / `getSearchNonNullClause`. `getPartitionKeyFilter` is the
78
- one-clause case worth naming, since a read, a count and a purge of the same entity must all start from it.
86
+ Null is where the two services diverge and the helpers carry the difference: `getTableNullClause` expresses "is null" for Table Storage, while Search supports it directly through `getSearchNullClause` / `getSearchNonNullClause`. `getPartitionKeyFilter` is the one-clause case worth naming, since a read, a count and a purge of the same entity must all start from it.
79
87
 
80
88
  ### Keys
81
89
 
82
90
  `CompositeKey` is the `partitionKey`/`rowKey` pair every Table entity carries, and `CompositeKeyPropertyNames`
83
- is how those names are referred to without restating the strings. The wire spells those two capitalized and
84
- JavaScript does not, so `serializeKey` and `deserializeKey` convert at the boundary and nothing in between has
85
- to know.
91
+ is how those names are referred to without restating the strings. `serializeKey` and `deserializeKey` convert
92
+ at the boundary.
86
93
 
87
94
  ```ts
88
95
  import { CompositeKey, CompositeKeyPropertyNames, serializeKey } from "@esposter/azure";
@@ -93,17 +100,6 @@ import { CompositeKey, CompositeKeyPropertyNames, serializeKey } from "@esposter
93
100
  `AZURE_MAX_BATCH_SIZE`, `AZURE_MAX_PAGE_SIZE` and `AZURE_MAX_QUEUE_VISIBILITY_TIMEOUT_MS` are the service's own
94
101
  ceilings, named so a caller paginating, batching or enqueueing does not hard-code them.
95
102
 
96
- ### Commands
97
-
98
- Run from `packages/azure/`:
99
-
100
- ```bash
101
- pnpm build # compile to dist/
102
- pnpm test # vitest watch mode (coverage is run from the repo root)
103
- pnpm lint:fix # auto-fix lint
104
- pnpm typecheck # type check
105
- ```
106
-
107
103
  ## <a name="license">⚖️ License</a>
108
104
 
109
105
  This project is licensed under the [Apache-2.0 license](https://github.com/Esposter/Esposter/blob/main/LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esposter/azure",
3
- "version": "4.3.1",
3
+ "version": "4.4.0",
4
4
  "description": "The Azure wire conventions Esposter's clients and its mocks both speak — OData filter clauses, entity key casing, and service limits.",
5
5
  "keywords": [
6
6
  "azure",
@@ -41,14 +41,14 @@
41
41
  "lint": "eslint .",
42
42
  "lint:fix": "eslint --fix .",
43
43
  "test": "vitest",
44
- "typecheck": "tsc"
44
+ "typecheck": "tsrs --fast"
45
45
  },
46
46
  "dependencies": {
47
- "@esposter/shared": "4.3.1"
47
+ "@esposter/shared": "4.4.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@esposter/configuration": "4.3.1",
51
- "tsdown": "^0.23.1",
50
+ "@esposter/configuration": "4.4.0",
51
+ "tsdown": "0.23.2",
52
52
  "type-fest": "^5.10.0"
53
53
  },
54
54
  "peerDependencies": {
@@ -58,5 +58,5 @@
58
58
  "inlinedDependencies": {
59
59
  "type-fest": "5.10.0"
60
60
  },
61
- "gitHead": "777a39636b789c13af33ed13370246ccf6dbaf31"
61
+ "gitHead": "e1a416c4b91da69cc2aa259b50a4d656f204d272"
62
62
  }
package/dist/index.d.ts DELETED
@@ -1,209 +0,0 @@
1
- import { z } from "zod";
2
- import { PropertyNames } from "@esposter/shared";
3
- import { TableEntity } from "@azure/data-tables";
4
- //#region src/models/search/SearchOperator.d.ts
5
- export declare enum SearchOperator {
6
- ArrayAny = "arrayAny",
7
- ArrayContains = "arrayContains"
8
- }
9
- //#endregion
10
- //#region src/models/shared/BinaryOperator.d.ts
11
- export declare enum BinaryOperator {
12
- Eq = "eq",
13
- Ge = "ge",
14
- Gt = "gt",
15
- Le = "le",
16
- Lt = "lt",
17
- Ne = "ne"
18
- }
19
- export declare const BinaryOperators: readonly BinaryOperator[];
20
- //#endregion
21
- //#region src/models/shared/SerializableValue.d.ts
22
- export type SerializableValue = boolean | Date | null | number | string;
23
- export declare const serializableValueSchema: z.ZodType<SerializableValue, SerializableValue>;
24
- //#endregion
25
- //#region src/models/shared/Clause.d.ts
26
- export type Clause<T extends object> = {
27
- key: keyof T & string;
28
- not?: boolean;
29
- } & ({
30
- operator: BinaryOperator;
31
- value: SerializableValue;
32
- } | {
33
- operator: SearchOperator.ArrayAny;
34
- } | {
35
- operator: SearchOperator.ArrayContains;
36
- value: SerializableValue[];
37
- });
38
- //#endregion
39
- //#region src/models/shared/UnaryOperator.d.ts
40
- export declare enum UnaryOperator {
41
- And = "and",
42
- Not = "not",
43
- Or = "or"
44
- }
45
- //#endregion
46
- //#region ../../node_modules/.pnpm/type-fest@5.10.0/node_modules/type-fest/source/omit-index-signature.d.ts
47
- /**
48
- Omit any index signatures from the given object type, leaving only explicitly defined properties.
49
-
50
- This is the counterpart of `PickIndexSignature`.
51
-
52
- Use-cases:
53
- - Remove overly permissive signatures from third-party types.
54
-
55
- This type was taken from this [StackOverflow answer](https://stackoverflow.com/a/68261113/420747).
56
-
57
- It relies on the fact that an empty object (`{}`) is assignable to an object with just an index signature, like `Record<string, unknown>`, but not to an object with explicitly defined keys, like `Record<'foo' | 'bar', unknown>`.
58
-
59
- (The actual value type, `unknown`, is irrelevant and could be any type. Only the key type matters.)
60
-
61
- ```
62
- const indexed: Record<string, unknown> = {}; // Allowed
63
-
64
- // @ts-expect-error
65
- const keyed: Record<'foo', unknown> = {}; // Error
66
- // TS2739: Type '{}' is missing the following properties from type 'Record<"foo" | "bar", unknown>': foo, bar
67
- ```
68
-
69
- Instead of causing a type error like the above, you can also use a [conditional type](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html) to test whether a type is assignable to another:
70
-
71
- ```
72
- type Indexed = {} extends Record<string, unknown>
73
- ? '✅ `{}` is assignable to `Record<string, unknown>`'
74
- : '❌ `{}` is NOT assignable to `Record<string, unknown>`';
75
-
76
- type IndexedResult = Indexed;
77
- //=> '✅ `{}` is assignable to `Record<string, unknown>`'
78
-
79
- type Keyed = {} extends Record<'foo' | 'bar', unknown>
80
- ? '✅ `{}` is assignable to `Record<\'foo\' | \'bar\', unknown>`'
81
- : '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`';
82
-
83
- type KeyedResult = Keyed;
84
- //=> '❌ `{}` is NOT assignable to `Record<\'foo\' | \'bar\', unknown>`'
85
- ```
86
-
87
- Using a [mapped type](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#further-exploration), you can then check for each `KeyType` of `ObjectType`...
88
-
89
- ```
90
- type OmitIndexSignature<ObjectType> = {
91
- [KeyType in keyof ObjectType // Map each key of `ObjectType`...
92
- ]: ObjectType[KeyType]; // ...to its original value, i.e. `OmitIndexSignature<Foo> == Foo`.
93
- };
94
- ```
95
-
96
- ...whether an empty object (`{}`) would be assignable to an object with that `KeyType` (`Record<KeyType, unknown>`)...
97
-
98
- ```
99
- type OmitIndexSignature<ObjectType> = {
100
- [KeyType in keyof ObjectType
101
- // Is `{}` assignable to `Record<KeyType, unknown>`?
102
- as {} extends Record<KeyType, unknown>
103
- ? never // ✅ `{}` is assignable to `Record<KeyType, unknown>`
104
- : KeyType // ❌ `{}` is NOT assignable to `Record<KeyType, unknown>`
105
- ]: ObjectType[KeyType];
106
- };
107
- ```
108
-
109
- If `{}` is assignable, it means that `KeyType` is an index signature and we want to remove it. If it is not assignable, `KeyType` is a "real" key and we want to keep it.
110
-
111
- @example
112
- ```
113
- import type {OmitIndexSignature} from 'type-fest';
114
-
115
- type Example = {
116
- // These index signatures will be removed.
117
- [x: string]: any;
118
- [x: number]: any;
119
- [x: symbol]: any;
120
- [x: `head-${string}`]: string;
121
- [x: `${string}-tail`]: string;
122
- [x: `head-${string}-tail`]: string;
123
- [x: `${bigint}`]: string;
124
- [x: `embedded-${number}`]: string;
125
-
126
- // These explicitly defined keys will remain.
127
- foo: 'bar';
128
- qux?: 'baz';
129
- };
130
-
131
- type ExampleWithoutIndexSignatures = OmitIndexSignature<Example>;
132
- //=> {foo: 'bar'; qux?: 'baz'}
133
- ```
134
-
135
- @see {@link PickIndexSignature}
136
- @category Object
137
- */
138
- type OmitIndexSignature<ObjectType> = { [KeyType in keyof ObjectType as {} extends Record<KeyType, unknown> ? never : KeyType]: ObjectType[KeyType]; };
139
- //#endregion
140
- //#region src/models/table/CompositeKey.d.ts
141
- export declare class CompositeKey implements OmitIndexSignature<TableEntity> {
142
- partitionKey: string;
143
- rowKey: string;
144
- }
145
- export declare const CompositeKeyPropertyNames: PropertyNames<CompositeKey>;
146
- //#endregion
147
- //#region src/services/search/getSearchNonNullClause.d.ts
148
- export declare const getSearchNonNullClause: <T extends object>(key: keyof T & string) => Clause<T>;
149
- //#endregion
150
- //#region src/services/search/getSearchNullClause.d.ts
151
- export declare const getSearchNullClause: <T extends object>(key: keyof T & string) => Clause<T>;
152
- //#endregion
153
- //#region src/services/shared/constants.d.ts
154
- export declare const AZURE_MAX_BATCH_SIZE = 100;
155
- export declare const AZURE_MAX_PAGE_SIZE = 1e3;
156
- export declare const SERIALIZABLE_VALUE_MAX_LENGTH = 100;
157
- export declare const AZURE_MAX_QUEUE_VISIBILITY_TIMEOUT_MS: number;
158
- export declare const AZURE_MAX_STRING_PROPERTY_LENGTH: number;
159
- //#endregion
160
- //#region src/services/table/constants.d.ts
161
- export declare const KEYS_TO_CAPITALIZE: ReadonlySet<string>;
162
- export declare const KEYS_TO_UNCAPITALIZE: ReadonlySet<string>;
163
- //#endregion
164
- //#region src/services/table/deserializeKey.d.ts
165
- export declare const deserializeKey: (key: string) => string;
166
- //#endregion
167
- //#region src/services/table/getTableNullClause.d.ts
168
- export declare const getTableNullClause: <T extends object>(key: keyof T & string) => Clause<T>;
169
- //#endregion
170
- //#region src/services/table/serializeKey.d.ts
171
- export declare const serializeKey: (key: string) => string;
172
- //#endregion
173
- //#region src/services/transformer/RangeOperators.d.ts
174
- export declare const RangeOperators: (BinaryOperator | SearchOperator)[];
175
- //#endregion
176
- //#region src/services/transformer/constants.d.ts
177
- export declare const DATETIME_LITERAL_PREFIX = "datetime'";
178
- export declare const CLAUSE_REGEX: RegExp;
179
- //#endregion
180
- //#region src/services/transformer/deserializeClause.d.ts
181
- export declare const deserializeClause: (serializedClause: string) => Extract<Clause<Record<string, unknown>>, {
182
- operator: BinaryOperator;
183
- }>;
184
- //#endregion
185
- //#region src/services/transformer/deserializeValue.d.ts
186
- export declare const deserializeValue: (serializedValue: string) => SerializableValue;
187
- //#endregion
188
- //#region src/services/transformer/escapeValue.d.ts
189
- export declare const escapeValue: (value: string) => string;
190
- //#endregion
191
- //#region src/services/transformer/getPartitionKeyFilter.d.ts
192
- export declare const getPartitionKeyFilter: (partitionKey: CompositeKey["partitionKey"]) => string;
193
- //#endregion
194
- //#region src/services/transformer/serializeClause.d.ts
195
- export declare const serializeClause: (clause: Clause<Record<string, unknown>>, isTableFilter?: boolean) => string;
196
- //#endregion
197
- //#region src/services/transformer/serializeClauses.d.ts
198
- export declare const serializeClauses: (clauses: Clause<Record<string, unknown>>[]) => string;
199
- //#endregion
200
- //#region src/services/transformer/serializeClausesCore.d.ts
201
- export declare const serializeClausesCore: (clauses: Clause<Record<string, unknown>>[], isTableFilter: boolean) => string;
202
- //#endregion
203
- //#region src/services/transformer/serializeSearchClauses.d.ts
204
- export declare const serializeSearchClauses: (clauses: Clause<Record<string, unknown>>[]) => string;
205
- //#endregion
206
- //#region src/services/transformer/serializeValue.d.ts
207
- export declare const serializeValue: (value: SerializableValue, isTableFilter?: boolean) => string;
208
- //#endregion
209
- export {};
package/dist/index.js DELETED
@@ -1,190 +0,0 @@
1
- import { z } from "zod";
2
- import { InvalidOperationError, NotFoundError, Operation, capitalize, getPropertyNames, getResult, normalizeString, takeOne, uncapitalize } from "@esposter/shared";
3
- //#region src/models/search/SearchOperator.ts
4
- let SearchOperator = /* @__PURE__ */ function(SearchOperator) {
5
- SearchOperator["ArrayAny"] = "arrayAny";
6
- SearchOperator["ArrayContains"] = "arrayContains";
7
- return SearchOperator;
8
- }({});
9
- //#endregion
10
- //#region src/models/shared/BinaryOperator.ts
11
- let BinaryOperator = /* @__PURE__ */ function(BinaryOperator) {
12
- BinaryOperator["Eq"] = "eq";
13
- BinaryOperator["Ge"] = "ge";
14
- BinaryOperator["Gt"] = "gt";
15
- BinaryOperator["Le"] = "le";
16
- BinaryOperator["Lt"] = "lt";
17
- BinaryOperator["Ne"] = "ne";
18
- return BinaryOperator;
19
- }({});
20
- const BinaryOperators = Object.values(BinaryOperator);
21
- //#endregion
22
- //#region src/services/shared/constants.ts
23
- const AZURE_MAX_BATCH_SIZE = 100;
24
- const AZURE_MAX_PAGE_SIZE = 1e3;
25
- const SERIALIZABLE_VALUE_MAX_LENGTH = 100;
26
- const AZURE_MAX_QUEUE_VISIBILITY_TIMEOUT_MS = Temporal.Duration.from({ days: 7 }).total("milliseconds");
27
- const AZURE_MAX_STRING_PROPERTY_LENGTH = 32768;
28
- //#endregion
29
- //#region src/models/shared/SerializableValue.ts
30
- const serializableValueSchema = z.union([
31
- z.boolean(),
32
- z.date(),
33
- z.null(),
34
- z.number(),
35
- z.string().min(1).max(100)
36
- ]);
37
- //#endregion
38
- //#region src/models/shared/UnaryOperator.ts
39
- let UnaryOperator = /* @__PURE__ */ function(UnaryOperator) {
40
- UnaryOperator["And"] = "and";
41
- UnaryOperator["Not"] = "not";
42
- UnaryOperator["Or"] = "or";
43
- return UnaryOperator;
44
- }({});
45
- //#endregion
46
- //#region src/models/table/CompositeKey.ts
47
- var CompositeKey = class {};
48
- const CompositeKeyPropertyNames = getPropertyNames();
49
- //#endregion
50
- //#region src/services/search/getSearchNonNullClause.ts
51
- const getSearchNonNullClause = (key) => ({
52
- key,
53
- operator: "ne",
54
- value: null
55
- });
56
- //#endregion
57
- //#region src/services/search/getSearchNullClause.ts
58
- const getSearchNullClause = (key) => ({
59
- key,
60
- operator: "eq",
61
- value: null
62
- });
63
- //#endregion
64
- //#region src/services/table/constants.ts
65
- const KEYS_TO_CAPITALIZE = /* @__PURE__ */ new Set([CompositeKeyPropertyNames.partitionKey, CompositeKeyPropertyNames.rowKey]);
66
- const KEYS_TO_UNCAPITALIZE = /* @__PURE__ */ new Set([capitalize(CompositeKeyPropertyNames.partitionKey), capitalize(CompositeKeyPropertyNames.rowKey)]);
67
- //#endregion
68
- //#region src/services/table/deserializeKey.ts
69
- const deserializeKey = (key) => KEYS_TO_UNCAPITALIZE.has(key) ? uncapitalize(key) : key;
70
- //#endregion
71
- //#region src/services/table/getTableNullClause.ts
72
- const getTableNullClause = (key) => ({
73
- key,
74
- not: true,
75
- operator: "ne",
76
- value: NaN
77
- });
78
- //#endregion
79
- //#region src/services/table/serializeKey.ts
80
- const serializeKey = (key) => KEYS_TO_CAPITALIZE.has(key) ? capitalize(key) : key;
81
- //#endregion
82
- //#region src/services/transformer/RangeOperators.ts
83
- const RangeOperators = [
84
- "ge",
85
- "gt",
86
- "le",
87
- "lt"
88
- ];
89
- //#endregion
90
- //#region src/services/transformer/constants.ts
91
- const DATETIME_LITERAL_PREFIX = "datetime'";
92
- const VALUE_REGEX = [
93
- true,
94
- false,
95
- String.raw`${DATETIME_LITERAL_PREFIX}[^']*'`,
96
- String.raw`\d{4}-\d{2}-\d{2}T[^\s]+`,
97
- String(null),
98
- String.raw`-?\d+(?:\.\d+)?`,
99
- String(NaN),
100
- "'(?:[^']|'')*'"
101
- ].join("|");
102
- const CLAUSE_REGEX = new RegExp(String.raw`^(?<not>not\s+)?(?<key>[A-Za-z0-9_]*)\s*(?<operator>${BinaryOperators.join("|")})\s+(?<value>${VALUE_REGEX})$`, "iu");
103
- //#endregion
104
- //#region src/services/transformer/deserializeValue.ts
105
- const parseIsoDate = (isoValue) => getResult(() => new Date(Temporal.Instant.from(isoValue).epochMilliseconds)).unwrapOr(void 0);
106
- const deserializeValue = (serializedValue) => {
107
- if (serializedValue === String(true)) return true;
108
- else if (serializedValue === String(false)) return false;
109
- else if (serializedValue === String(null)) return null;
110
- else if (Number.isFinite(Number(serializedValue))) return Number(serializedValue);
111
- else if (serializedValue === String(NaN)) return NaN;
112
- else if (serializedValue.startsWith("datetime'") && serializedValue.endsWith("'")) return parseIsoDate(serializedValue.slice(9, -1)) ?? serializedValue;
113
- else if (serializedValue.startsWith("'") && serializedValue.endsWith("'")) return serializedValue.slice(1, -1).replaceAll("''", "'");
114
- else return parseIsoDate(serializedValue) ?? serializedValue;
115
- };
116
- //#endregion
117
- //#region src/services/transformer/deserializeClause.ts
118
- const deserializeClause = (serializedClause) => {
119
- const normalizedClause = normalizeString(serializedClause);
120
- const match = CLAUSE_REGEX.exec(normalizedClause);
121
- if (!match) throw new NotFoundError(deserializeClause.name, normalizedClause);
122
- const groups = match.groups;
123
- if (!groups) throw new NotFoundError(deserializeClause.name, normalizedClause);
124
- return {
125
- key: deserializeKey(groups.key),
126
- not: Boolean(groups.not),
127
- operator: groups.operator.toLowerCase(),
128
- value: deserializeValue(groups.value)
129
- };
130
- };
131
- //#endregion
132
- //#region src/services/transformer/escapeValue.ts
133
- const escapeValue = (value) => `'${value.replaceAll("'", "''")}'`;
134
- //#endregion
135
- //#region src/services/transformer/serializeValue.ts
136
- const serializeValue = (value, isTableFilter = false) => {
137
- if (value instanceof Date) return isTableFilter ? `${DATETIME_LITERAL_PREFIX}${value.toISOString()}'` : value.toISOString();
138
- else if (typeof value === "string") return escapeValue(value);
139
- else return String(value);
140
- };
141
- //#endregion
142
- //#region src/services/transformer/serializeClause.ts
143
- const serializeClause = (clause, isTableFilter = false) => {
144
- const keys = clause.key.split("/").map((key) => serializeKey(key));
145
- const clauseKey = keys.join("/");
146
- if (clause.operator === "arrayAny") return `${clauseKey}/any()`;
147
- else if (clause.operator === "arrayContains") {
148
- const serializedValue = serializeValue(clause.value.join(","));
149
- if (keys.length === 1) return `${clauseKey}/any(x: search.in(x, ${serializedValue}))`;
150
- else if (keys.length === 2) {
151
- const [collectionName, propertyName] = keys;
152
- return `${collectionName}/any(x: search.in(x/${propertyName}, ${serializedValue}))`;
153
- } else throw new InvalidOperationError(Operation.Read, serializeClause.name, clause.key);
154
- }
155
- const { not, operator, value } = clause;
156
- const baseClause = `${clauseKey} ${operator} ${serializeValue(value, isTableFilter)}`;
157
- return not ? `not(${baseClause})` : baseClause;
158
- };
159
- //#endregion
160
- //#region src/services/transformer/serializeClausesCore.ts
161
- const serializeClausesCore = (clauses, isTableFilter) => {
162
- if (clauses.length === 0) return "";
163
- else if (clauses.length === 1) return serializeClause(takeOne(clauses), isTableFilter);
164
- else {
165
- const groupedClauses = Object.groupBy(clauses, ({ key }) => key);
166
- const groupedStrings = [];
167
- for (const clauseGroup of Object.values(groupedClauses)) if (clauseGroup.length === 1) groupedStrings.push(serializeClause(takeOne(clauseGroup), isTableFilter));
168
- else {
169
- const serializedClauses = clauseGroup.map((clause) => serializeClause(clause, isTableFilter));
170
- const groupedString = clauseGroup.some(({ operator }) => RangeOperators.includes(operator)) ? serializedClauses.join(` and `) : `(${serializedClauses.join(` or `)})`;
171
- groupedStrings.push(groupedString);
172
- }
173
- return groupedStrings.join(` and `);
174
- }
175
- };
176
- //#endregion
177
- //#region src/services/transformer/serializeClauses.ts
178
- const serializeClauses = (clauses) => serializeClausesCore(clauses, true);
179
- //#endregion
180
- //#region src/services/transformer/getPartitionKeyFilter.ts
181
- const getPartitionKeyFilter = (partitionKey) => serializeClauses([{
182
- key: CompositeKeyPropertyNames.partitionKey,
183
- operator: "eq",
184
- value: partitionKey
185
- }]);
186
- //#endregion
187
- //#region src/services/transformer/serializeSearchClauses.ts
188
- const serializeSearchClauses = (clauses) => serializeClausesCore(clauses, false);
189
- //#endregion
190
- export { AZURE_MAX_BATCH_SIZE, AZURE_MAX_PAGE_SIZE, AZURE_MAX_QUEUE_VISIBILITY_TIMEOUT_MS, AZURE_MAX_STRING_PROPERTY_LENGTH, BinaryOperator, BinaryOperators, CLAUSE_REGEX, CompositeKey, CompositeKeyPropertyNames, DATETIME_LITERAL_PREFIX, KEYS_TO_CAPITALIZE, KEYS_TO_UNCAPITALIZE, RangeOperators, SERIALIZABLE_VALUE_MAX_LENGTH, SearchOperator, UnaryOperator, deserializeClause, deserializeKey, deserializeValue, escapeValue, getPartitionKeyFilter, getSearchNonNullClause, getSearchNullClause, getTableNullClause, serializableValueSchema, serializeClause, serializeClauses, serializeClausesCore, serializeKey, serializeSearchClauses, serializeValue };