@dangreaves/groq-query-builder
Advanced tools
Comparing version 0.18.0 to 0.18.1
@@ -5,40 +5,5 @@ import { TSchema, TUnion, TNull, TArray, TObject, TIntersect, TString, Static, TProperties, TLiteral } from '@sinclair/typebox'; | ||
/** | ||
* Symbols for additional attributes on schema. | ||
* | ||
* We don't use actual symbols here, because they could cause issues with bundling where | ||
* if this package is included multiple times, you end up with multiple symbols. | ||
* | ||
* Instead, we use strings which we have made as unique as possible, so as not to conflict | ||
* with JSON Schema attributes. | ||
*/ | ||
declare const GroqSymbol = "_groq"; | ||
declare const TypeSymbol = "_type"; | ||
declare const SliceSymbol = "_slice"; | ||
declare const FilterSymbol = "_filter"; | ||
declare const ExpandSymbol = "_expand"; | ||
declare const ConditionsSymbol = "_conditions"; | ||
declare const NeedsIntersectUnwrapSymbol = "_needsIntersectUnwrap"; | ||
/** | ||
* Symbol used to cache GROQ string on a schema. | ||
*/ | ||
declare const QueryCacheSymbol = "_queryCache"; | ||
/** | ||
* Make query cache optionally available on all schemas. | ||
*/ | ||
declare module "@sinclair/typebox" { | ||
interface TSchema { | ||
[QueryCacheSymbol]?: string; | ||
} | ||
} | ||
/** | ||
* Additional attributes added to underlying schema. | ||
*/ | ||
type AdditionalAttributes$4 = { | ||
[TypeSymbol]: "Nullable"; | ||
}; | ||
/** | ||
* Allow the given schema to be null. | ||
*/ | ||
type TNullable<T extends TSchema = TSchema> = TUnion<[T, TNull]> & AdditionalAttributes$4; | ||
type TNullable<T extends TSchema = TSchema> = TUnion<[T, TNull]>; | ||
/** | ||
@@ -65,11 +30,2 @@ * Allow the given schema to be null. | ||
/** | ||
* Additional attributes added to underlying schema. | ||
*/ | ||
type AdditionalAttributes$3 = { | ||
[TypeSymbol]: "Collection"; | ||
[NeedsIntersectUnwrapSymbol]: boolean; | ||
[SliceSymbol]: TCollectionOptions["slice"]; | ||
[FilterSymbol]: TCollectionOptions["filter"]; | ||
}; | ||
/** | ||
* Fetch an array of items with optional filter and slicing. | ||
@@ -79,3 +35,3 @@ */ | ||
_key: TNullable<TString>; | ||
}>]> : T> & AdditionalAttributes$3; | ||
}>]> : T>; | ||
/** | ||
@@ -118,11 +74,2 @@ * Fetch an array of items with optional filter and slicing. | ||
/** | ||
* Additional attributes added to underlying schema. | ||
*/ | ||
type AdditionalAttributes$2 = { | ||
/** Array of conditions in order of the schemas added to the union */ | ||
[ConditionsSymbol]: string[]; | ||
[TypeSymbol]: "ConditionalUnion"; | ||
[ExpandSymbol]: TConditionalUnionOptions["expand"]; | ||
}; | ||
/** | ||
* Given a string keyed record of conditions extract array of schemas. | ||
@@ -134,3 +81,3 @@ */ | ||
*/ | ||
type TConditionalUnion<T extends Record<string, TSchema> = Record<string, TSchema>> = TUnion<SchemaArrayFromConditions<T>> & AdditionalAttributes$2; | ||
type TConditionalUnion<T extends Record<string, TSchema> = Record<string, TSchema>> = TUnion<SchemaArrayFromConditions<T>>; | ||
/** | ||
@@ -162,14 +109,5 @@ * Fetch a union of schemas based on conditions. | ||
/** | ||
* Additional attributes added to underlying schema. | ||
*/ | ||
type AdditionalAttributes$1 = { | ||
[TypeSymbol]: "Projection"; | ||
[SliceSymbol]: TProjectionOptions["slice"]; | ||
[FilterSymbol]: TProjectionOptions["filter"]; | ||
[ExpandSymbol]: TProjectionOptions["expand"]; | ||
}; | ||
/** | ||
* Fetch a single object projection. | ||
*/ | ||
type TProjection<T extends TProperties = TProperties> = TObject<T> & AdditionalAttributes$1; | ||
type TProjection<T extends TProperties = TProperties> = TObject<T>; | ||
/** | ||
@@ -201,12 +139,5 @@ * Fetch a single object projection. | ||
/** | ||
* Additional attributes added to underlying schema. | ||
*/ | ||
type AdditionalAttributes = { | ||
[TypeSymbol]: "Raw"; | ||
[GroqSymbol]: string; | ||
}; | ||
/** | ||
* Output raw GROQ. | ||
*/ | ||
type TRaw<T extends TSchema = TSchema> = T & AdditionalAttributes; | ||
type TRaw<T extends TSchema = TSchema> = T; | ||
/** | ||
@@ -270,2 +201,15 @@ * Output raw GROQ. | ||
/** | ||
* Symbol used to cache GROQ string on a schema. | ||
*/ | ||
declare const QueryCacheSymbol = "_queryCache"; | ||
/** | ||
* Make query cache optionally available on all schemas. | ||
*/ | ||
declare module "@sinclair/typebox" { | ||
interface TSchema { | ||
[QueryCacheSymbol]?: string; | ||
} | ||
} | ||
/** | ||
* Serialize the given schema to a GROQ string. | ||
@@ -272,0 +216,0 @@ */ |
@@ -35,3 +35,4 @@ // src/schemas/Collection.ts | ||
function serializeRaw(schema) { | ||
return schema[GroqSymbol]; | ||
const attributes = schema; | ||
return attributes[GroqSymbol]; | ||
} | ||
@@ -62,3 +63,4 @@ | ||
function serializeProjection(schema) { | ||
const filter = schema[FilterSymbol]?.startsWith("*") ? schema[FilterSymbol].substring(1) : schema[FilterSymbol]; | ||
const attributes = schema; | ||
const filter = attributes[FilterSymbol]?.startsWith("*") ? attributes[FilterSymbol].substring(1) : attributes[FilterSymbol]; | ||
const groq = []; | ||
@@ -72,4 +74,4 @@ if (filter) { | ||
const alreadySliced = filter ? /\[\d+\]$/.test(filter) : false; | ||
if (!alreadySliced && (filter || "undefined" !== typeof schema[SliceSymbol])) { | ||
groq.push(`[${schema[SliceSymbol] ?? 0}]`); | ||
if (!alreadySliced && (filter || "undefined" !== typeof attributes[SliceSymbol])) { | ||
groq.push(`[${attributes[SliceSymbol] ?? 0}]`); | ||
} | ||
@@ -85,7 +87,7 @@ const projection = Object.entries(schema.properties).map(([key, value]) => { | ||
}).join(","); | ||
if (true === schema[ExpandSymbol]) { | ||
if (true === attributes[ExpandSymbol]) { | ||
groq.push(`{...@->{${projection}}}`); | ||
} else if ("string" === typeof schema[ExpandSymbol]) { | ||
} else if ("string" === typeof attributes[ExpandSymbol]) { | ||
groq.push( | ||
`{_type == "${schema[ExpandSymbol]}" => @->{${projection}},_type != "${schema[ExpandSymbol]}" => @{${projection}}}` | ||
`{_type == "${attributes[ExpandSymbol]}" => @->{${projection}},_type != "${attributes[ExpandSymbol]}" => @{${projection}}}` | ||
); | ||
@@ -126,13 +128,16 @@ } else { | ||
function serializeConditionalUnion(schema) { | ||
const attributes = schema; | ||
const groq = []; | ||
const selectConditions = schema[ConditionsSymbol].map((condition, key) => { | ||
if ("default" == condition) | ||
return null; | ||
const conditionSchema = schema.anyOf[key]; | ||
if (!conditionSchema) | ||
return null; | ||
const conditionGroq = serializeQuery(conditionSchema) || "..."; | ||
return `${condition} => ${conditionGroq}`; | ||
}).filter(Boolean); | ||
const defaultConditionIndex = schema[ConditionsSymbol].indexOf("default"); | ||
const selectConditions = attributes[ConditionsSymbol].map( | ||
(condition, key) => { | ||
if ("default" == condition) | ||
return null; | ||
const conditionSchema = schema.anyOf[key]; | ||
if (!conditionSchema) | ||
return null; | ||
const conditionGroq = serializeQuery(conditionSchema) || "..."; | ||
return `${condition} => ${conditionGroq}`; | ||
} | ||
).filter(Boolean); | ||
const defaultConditionIndex = attributes[ConditionsSymbol].indexOf("default"); | ||
const defaultConditionSchema = 0 <= defaultConditionIndex ? schema.anyOf[defaultConditionIndex] : null; | ||
@@ -144,7 +149,7 @@ if (defaultConditionSchema) { | ||
const projection = `...select(${selectConditions.join(",")})`; | ||
if (true === schema[ExpandSymbol]) { | ||
if (true === attributes[ExpandSymbol]) { | ||
groq.push(`{...@->{${projection}}}`); | ||
} else if ("string" === typeof schema[ExpandSymbol]) { | ||
} else if ("string" === typeof attributes[ExpandSymbol]) { | ||
groq.push( | ||
`{_type == "${schema[ExpandSymbol]}" => @->{${projection}},_type != "${schema[ExpandSymbol]}" => @{${projection}}}` | ||
`{_type == "${attributes[ExpandSymbol]}" => @->{${projection}},_type != "${attributes[ExpandSymbol]}" => @{${projection}}}` | ||
); | ||
@@ -220,3 +225,4 @@ } else { | ||
function serializeCollection(schema) { | ||
const filter = schema[FilterSymbol]?.startsWith("*") ? schema[FilterSymbol].substring(1) : schema[FilterSymbol]; | ||
const attributes = schema; | ||
const filter = attributes[FilterSymbol]?.startsWith("*") ? attributes[FilterSymbol].substring(1) : attributes[FilterSymbol]; | ||
const groq = []; | ||
@@ -229,10 +235,12 @@ if (filter) { | ||
} | ||
if (schema[SliceSymbol]) { | ||
groq.push(`[${schema[SliceSymbol][0]}...${schema[SliceSymbol][1]}]`); | ||
if (attributes[SliceSymbol]) { | ||
groq.push( | ||
`[${attributes[SliceSymbol][0]}...${attributes[SliceSymbol][1]}]` | ||
); | ||
} | ||
if (!filter && !schema[SliceSymbol]) { | ||
if (!filter && !attributes[SliceSymbol]) { | ||
groq.push("[]"); | ||
} | ||
let innerSchema = schema.items; | ||
if (schema[NeedsIntersectUnwrapSymbol]) { | ||
if (attributes[NeedsIntersectUnwrapSymbol]) { | ||
innerSchema = schema.items.allOf[0]; | ||
@@ -239,0 +247,0 @@ } |
{ | ||
"name": "@dangreaves/groq-query-builder", | ||
"version": "0.18.0", | ||
"version": "0.18.1", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "author": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
46752
949