@instantdb/core 0.22.163 → 0.22.164
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/__tests__/src/queryValidation.test.ts +40 -0
- package/dist/commonjs/queryTypes.d.ts +5 -1
- package/dist/commonjs/queryTypes.d.ts.map +1 -1
- package/dist/commonjs/queryTypes.js.map +1 -1
- package/dist/commonjs/queryValidation.d.ts.map +1 -1
- package/dist/commonjs/queryValidation.js +4 -0
- package/dist/commonjs/queryValidation.js.map +1 -1
- package/dist/esm/queryTypes.d.ts +5 -1
- package/dist/esm/queryTypes.d.ts.map +1 -1
- package/dist/esm/queryTypes.js.map +1 -1
- package/dist/esm/queryValidation.d.ts.map +1 -1
- package/dist/esm/queryValidation.js +4 -0
- package/dist/esm/queryValidation.js.map +1 -1
- package/dist/standalone/index.js +5 -1
- package/dist/standalone/index.umd.cjs +1 -1
- package/package.json +2 -2
- package/src/queryTypes.ts +7 -1
- package/src/queryValidation.ts +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryTypes.js","sourceRoot":"","sources":["../../src/queryTypes.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,QAAQ","sourcesContent":["// Query\n// -----\n\nimport type {\n EntitiesDef,\n IContainEntitiesAndLinks,\n InstantGraph,\n LinkAttrDef,\n RuleParams,\n ResolveAttrs,\n ResolveEntityAttrs,\n DataAttrDef,\n AttrsDefs,\n EntityDefFromSchema,\n InstantUnknownSchemaDef,\n} from './schemaTypes.ts';\n\ntype BuiltIn = Date | Function | Error | RegExp;\n\ntype Primitive = string | number | boolean | symbol | null | undefined;\n\nexport type Expand<T> = T extends BuiltIn | Primitive\n ? T\n : T extends object\n ? T extends infer O\n ? { [K in keyof O]: Expand<O[K]> }\n : never\n : T;\n\n// NonEmpty disallows {}, so that you must provide at least one field\nexport type NonEmpty<T> = {\n [K in keyof T]-?: Required<Pick<T, K>>;\n}[keyof T];\n\ntype BaseWhereClauseValueComplex<V> = {\n /** @deprecated use `$in` instead of `in` */\n in?: V[];\n $in?: V[];\n /** @deprecated use `$ne` instead of `not` */\n $not?: V;\n $ne?: V;\n $gt?: V;\n $lt?: V;\n $gte?: V;\n $lte?: V;\n};\n\ntype IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;\n\ntype WhereClauseValueComplex<V, R, I> = BaseWhereClauseValueComplex<V> &\n (IsAny<V> extends true\n ? {\n $ilike?: string;\n $like?: string;\n $isNull?: boolean;\n }\n : (V extends string\n ? {\n $like?: string;\n }\n : {}) &\n (R extends false\n ? {\n $isNull?: boolean;\n }\n : {}) &\n (I extends true\n ? {\n $ilike?: string;\n }\n : {}));\n\n// Make type display better\ntype WhereClauseValue<\n D extends DataAttrDef<string | number | boolean, boolean, boolean, boolean>,\n> =\n D extends DataAttrDef<infer V, infer R, infer I, boolean>\n ?\n | (IsAny<V> extends true ? string | number | boolean : V)\n | NonEmpty<WhereClauseValueComplex<V, R, I>>\n : never;\n\ntype WhereClauseColumnEntries<\n T extends {\n [key: string]: DataAttrDef<any, boolean, boolean, boolean>;\n },\n> = {\n [key in keyof T]?: WhereClauseValue<T[key]>;\n};\n\ntype WhereClauseComboEntries<\n T extends Record<any, DataAttrDef<any, boolean, boolean, boolean>>,\n> = {\n or?:\n | WhereClauses<T>[]\n | WhereClauseValue<DataAttrDef<any, false, true, boolean>>;\n and?:\n | WhereClauses<T>[]\n | WhereClauseValue<DataAttrDef<any, false, true, boolean>>;\n};\n\ntype WhereClauses<\n T extends Record<any, DataAttrDef<any, boolean, boolean, boolean>>,\n> = (\n | WhereClauseComboEntries<T>\n | (WhereClauseComboEntries<T> & WhereClauseColumnEntries<T>)\n) & {\n id?: WhereClauseValue<DataAttrDef<string, false, true, boolean>>;\n [key: `${string}.${string}`]: WhereClauseValue<\n DataAttrDef<any, false, true, boolean>\n >;\n};\n\n/**\n * A tuple representing a cursor.\n * These should not be constructed manually. The current format\n * is an implementation detail that may change in the future.\n * Use the `endCursor` or `startCursor` from the PageInfoResponse as the\n * `before` or `after` field in the query options.\n */\ntype Cursor = [string, string, any, number];\n\ntype Direction = 'asc' | 'desc';\n\ntype IndexedKeys<Attrs extends AttrsDefs> = {\n [K in keyof Attrs]: Attrs[K] extends DataAttrDef<\n any,\n any,\n infer IsIndexed,\n boolean\n >\n ? IsIndexed extends true\n ? K\n : never\n : never;\n}[keyof Attrs];\n\nexport type Order<\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> =\n IndexedKeys<Schema['entities'][EntityName]['attrs']> extends never\n ? {\n serverCreatedAt?: Direction;\n }\n : {\n [K in IndexedKeys<Schema['entities'][EntityName]['attrs']>]?: Direction;\n } & {\n serverCreatedAt?: Direction;\n };\n\ntype $Option<\n S extends IContainEntitiesAndLinks<any, any>,\n K extends keyof S['entities'],\n> = {\n $?: {\n where?: WhereClauses<EntityDefFromSchema<S, K>>;\n order?: Order<S, K>;\n limit?: number;\n last?: number;\n first?: number;\n offset?: number;\n after?: Cursor;\n before?: Cursor;\n fields?: InstaQLFields<S, K>;\n };\n};\n\ntype NamespaceVal =\n | $Option<IContainEntitiesAndLinks<any, any>, keyof EntitiesDef>\n | ($Option<IContainEntitiesAndLinks<any, any>, keyof EntitiesDef> & Subquery);\n\ntype Subquery = { [namespace: string]: NamespaceVal };\n\ninterface Query {\n [namespace: string]: NamespaceVal;\n}\n\ntype InstantObject = {\n id: string;\n [prop: string]: any;\n};\n\ntype ResponseObject<K, Schema> = K extends keyof Schema\n ? { id: string } & Schema[K]\n : InstantObject;\n\ntype IsEmptyObject<T> = T extends Record<string, never> ? true : false;\n\ntype ResponseOf<Q, Schema> = {\n [K in keyof Q]: IsEmptyObject<Q[K]> extends true\n ? ResponseObject<K, Schema>[]\n : (ResponseOf<Q[K], Schema> & ResponseObject<K, Schema>)[];\n};\n\ntype Remove$<T> = T extends object\n ? { [K in keyof T as Exclude<K, '$'>]: Remove$<T[K]> }\n : T;\n\ntype Remove$NonRecursive<T> = T extends object\n ? { [K in keyof T as Exclude<K, '$'>]: T[K] }\n : T;\n\ntype QueryResponse<\n Q,\n Schema,\n WithCardinalityInference extends boolean = false,\n UseDates extends boolean = false,\n> =\n Schema extends InstantGraph<infer E, any>\n ? InstaQLQueryResult<E, Q, WithCardinalityInference, UseDates>\n : ResponseOf<{ [K in keyof Q]: Remove$<Q[K]> }, Schema>;\n\ntype InstaQLResponse<Schema, Q, UseDates extends boolean = false> =\n Schema extends IContainEntitiesAndLinks<any, any>\n ? Q extends InstaQLParams<Schema> | undefined\n ? InstaQLResult<Schema, Q, UseDates>\n : never\n : never;\n\ntype PageInfoResponse<T> = {\n [K in keyof T]: {\n startCursor: Cursor;\n endCursor: Cursor;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n };\n};\n\n/**\n * (XXX)\n * https://github.com/microsoft/TypeScript/issues/26051\n *\n * TypeScript can permit extra keys when a generic extends a type.\n *\n * For some reason, it makes it possible to write a query like so:\n *\n * dummyQuery({\n * users: {\n * $: { where: { \"foo\": 1 } },\n * posts: {\n * $: { \"far\": {} }\n * }\n * }\n *\n * The problem: $: { \"far\": {} }\n *\n * This passes, when it should in reality fail. I don't know why\n * adding `Exactly` fixes this, but it does.\n *\n * */\ntype Exactly<Parent, Child> = Parent & {\n [K in keyof Child]: K extends keyof Parent ? Child[K] : never;\n};\n\n// SafeLookup<T, ['A', 'B', number]> is like doing\n// T['A']['B'][number], but it will merge with undefined if any\n// of the intermediates are undefined\ntype SafeLookup<T, K extends readonly PropertyKey[]> = K extends [\n infer First,\n ...infer Rest extends readonly PropertyKey[],\n]\n ? First extends keyof NonNullable<T>\n ?\n | SafeLookup<NonNullable<T>[First], Rest>\n | (T extends null | undefined ? undefined : never)\n : undefined\n : T;\n\n// ==========\n// InstaQL helpers\n\ntype InstaQLEntitySubqueryResult<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n Query extends InstaQLEntitySubquery<Schema, EntityName> | undefined = {},\n UseDates extends boolean = false,\n> = {\n [QueryPropName in keyof Query]: Schema['entities'][EntityName]['links'][QueryPropName] extends LinkAttrDef<\n infer Cardinality,\n infer LinkedEntityName\n >\n ? LinkedEntityName extends keyof Schema['entities']\n ? Cardinality extends 'one'\n ?\n | InstaQLEntity<\n Schema,\n LinkedEntityName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >\n | undefined\n : InstaQLEntity<\n Schema,\n LinkedEntityName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >[]\n : never\n : never;\n};\n\ntype InstaQLQueryEntityLinksResult<\n Entities extends EntitiesDef,\n EntityName extends keyof Entities,\n Query extends {\n [LinkAttrName in keyof Entities[EntityName]['links']]?: any;\n },\n WithCardinalityInference extends boolean,\n UseDates extends boolean = false,\n> = {\n [QueryPropName in keyof Query]: Entities[EntityName]['links'][QueryPropName] extends LinkAttrDef<\n infer Cardinality,\n infer LinkedEntityName\n >\n ? LinkedEntityName extends keyof Entities\n ? WithCardinalityInference extends true\n ? Cardinality extends 'one'\n ?\n | InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >\n | undefined\n : InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : never\n : never;\n};\n\n// Pick, but applies the pick to each union\ntype DistributePick<T, K extends string> = T extends any\n ? { [P in K]: P extends keyof T ? T[P] : never }\n : never;\n\ntype InstaQLFields<\n S extends IContainEntitiesAndLinks<any, any>,\n K extends keyof S['entities'],\n> = (Extract<keyof ResolveEntityAttrs<S['entities'][K]>, string> | 'id')[];\n\ntype ComputeAttrs<\n AllAttrs,\n Fields extends readonly string[] | undefined,\n> = Fields extends readonly string[]\n ? DistributePick<AllAttrs, Exclude<Fields[number], 'id'>>\n : AllAttrs;\n\ntype InstaQLEntity<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n Subquery extends InstaQLEntitySubquery<Schema, EntityName> | undefined = {},\n Fields extends InstaQLFields<Schema, EntityName> | undefined = undefined,\n UseDates extends boolean = false,\n> = Expand<\n { id: string } & ComputeAttrs<\n ResolveEntityAttrs<Schema['entities'][EntityName], UseDates>,\n Fields\n > &\n InstaQLEntitySubqueryResult<Schema, EntityName, Subquery, UseDates>\n>;\n\ntype InstaQLQueryEntityResult<\n Entities extends EntitiesDef,\n EntityName extends keyof Entities,\n Query extends {\n [QueryPropName in keyof Entities[EntityName]['links']]?: any;\n },\n WithCardinalityInference extends boolean,\n UseDates extends boolean,\n> = { id: string } & ResolveAttrs<Entities, EntityName, UseDates> &\n InstaQLQueryEntityLinksResult<\n Entities,\n EntityName,\n Query,\n WithCardinalityInference,\n UseDates\n >;\n\ntype InstaQLQueryResult<\n Entities extends EntitiesDef,\n Query,\n WithCardinalityInference extends boolean,\n UseDates extends boolean,\n> = {\n [QueryPropName in keyof Query]: QueryPropName extends keyof Entities\n ? InstaQLQueryEntityResult<\n Entities,\n QueryPropName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : never;\n};\n\ntype InstaQLResult<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n Query extends InstaQLParams<Schema> | undefined,\n UseDates extends boolean = false,\n> = Expand<{\n [QueryPropName in keyof Query]: QueryPropName extends keyof Schema['entities']\n ? InstaQLEntity<\n Schema,\n QueryPropName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >[]\n : never;\n}>;\n\ntype InstaQLEntitySubquery<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n> = {\n [QueryPropName in keyof Schema['entities'][EntityName]['links']]?:\n | $Option<Schema, EntityName>\n | ($Option<Schema, EntityName> &\n InstaQLEntitySubquery<\n Schema,\n Schema['entities'][EntityName]['links'][QueryPropName]['entityName']\n >);\n};\n\ntype InstaQLQuerySubqueryParams<\n S extends IContainEntitiesAndLinks<any, any>,\n E extends keyof S['entities'],\n> = {\n [K in keyof S['entities'][E]['links']]?:\n | $Option<S, S['entities'][E]['links'][K]['entityName']>\n | ($Option<S, S['entities'][E]['links'][K]['entityName']> &\n InstaQLQuerySubqueryParams<\n S,\n S['entities'][E]['links'][K]['entityName']\n >);\n};\n\ntype InstaQLParams<S extends IContainEntitiesAndLinks<any, any>> = {\n [K in keyof S['entities']]?:\n | $Option<S, K>\n | ($Option<S, K> & InstaQLQuerySubqueryParams<S, K>);\n};\n\n/**\n * @deprecated\n * `InstaQLQueryParams` is deprecated. Use `InstaQLParams` instead.\n *\n * @example\n * // Before\n * const myQuery = {...} satisfies InstaQLQueryParams<Schema>\n * // After\n * const myQuery = {...} satisfies InstaQLParams<Schema>\n */\ntype InstaQLQueryParams<S extends IContainEntitiesAndLinks<any, any>> =\n InstaQLParams<S>;\n\ntype InstaQLOptions = {\n ruleParams: RuleParams;\n};\n\n// Start of new types\n\ntype ValidQueryObject<\n T extends Record<string, any>,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n TopLevel extends boolean,\n> = keyof T extends keyof Schema['entities'][EntityName]['links'] | '$'\n ? {\n [K in keyof Schema['entities'][EntityName]['links']]?: ValidQueryObject<\n T[K],\n Schema,\n Schema['entities'][EntityName]['links'][K]['entityName'],\n false\n >;\n } & {\n $?: ValidDollarSignQuery<T['$'], Schema, EntityName, TopLevel>;\n }\n : never;\n\ntype PaginationKeys =\n | 'limit'\n | 'last'\n | 'first'\n | 'offset'\n | 'after'\n | 'before';\n\ntype AllowedDollarSignKeys<TopLevel extends boolean> = TopLevel extends true\n ? PaginationKeys | 'where' | 'fields' | 'order'\n : 'where' | 'fields' | 'order' | 'limit';\n\ntype ValidFieldNames<\n S extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof S['entities'],\n> = Extract<keyof ResolveEntityAttrs<S['entities'][EntityName]>, string> | 'id';\n\ntype ValidDollarSignQuery<\n Input extends { [key: string]: any },\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n TopLevel extends boolean,\n> =\n keyof Input extends AllowedDollarSignKeys<TopLevel>\n ? {\n where?: ValidWhereObject<Input['where'], Schema, EntityName>;\n fields?: ValidFieldNames<Schema, EntityName>[];\n order?: Order<Schema, EntityName>;\n limit?: number;\n } & (TopLevel extends true\n ? {\n last?: number;\n first?: number;\n offset?: number;\n after?: Cursor;\n before?: Cursor;\n }\n : {})\n : never;\n\ntype StringifiableKey<T> = Extract<T, string | number | bigint | boolean>;\n\ntype ValidWhereNestedPath<\n T,\n K extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n> = T extends object\n ? K extends keyof T\n ? K // Allow link names as valid paths (they'll default to id)\n : K extends `${infer K0}.${infer KR}`\n ? K0 extends keyof T\n ? T[K0] extends keyof Schema['entities']\n ? `${K0}.${\n | ValidWhereNestedPath<\n {\n [K in keyof Schema['entities'][T[K0]]['links']]: Schema['entities'][T[K0]]['links'][K]['entityName'];\n },\n KR,\n Schema\n >\n | StringifiableKey<keyof Schema['entities'][T[K0]]['attrs']>\n | 'id'}`\n : string & keyof T\n : string & keyof T\n : string & keyof T\n : never;\n\ntype ValidDotPath<\n Input extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = ValidWhereNestedPath<\n {\n [K in keyof Schema['entities'][EntityName]['links']]: Schema['entities'][EntityName]['links'][K]['entityName'];\n },\n Input,\n Schema\n>;\n\ntype WhereOperatorObject<Input, V, R, I> = keyof Input extends\n | keyof BaseWhereClauseValueComplex<V>\n | '$ilike'\n | '$like'\n | '$isNull'\n ? BaseWhereClauseValueComplex<V> &\n (IsAny<V> extends true\n ? {\n $ilike?: string;\n $like?: string;\n $isNull?: boolean;\n }\n : (V extends string\n ? {\n $like?: string;\n }\n : {}) &\n (R extends false\n ? {\n $isNull?: boolean;\n }\n : {}) &\n (I extends true\n ? {\n $ilike?: string;\n }\n : {}))\n : never;\n\ntype ValidWhereValue<\n Input,\n AttrDef extends DataAttrDef<any, any, any, boolean>,\n> =\n AttrDef extends DataAttrDef<infer V, infer R, infer I, boolean>\n ? Input extends V\n ? V\n : NonEmpty<WhereOperatorObject<Input, V, R, I>>\n : never;\n\ntype NoDistribute<T> = [T] extends [any] ? T : never;\n\ntype ValidWhereObject<\n Input extends { [key: string]: any } | undefined,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = Input extends undefined\n ? undefined\n : keyof Input extends\n | ValidDotPath<keyof Input, Schema, EntityName>\n | keyof Schema['entities'][EntityName]['attrs']\n | 'and'\n | 'or'\n | 'id'\n ? {\n [K in ValidDotPath<keyof Input, Schema, EntityName>]?: ValidWhereValue<\n Input[K],\n ExtractAttrFromDotPath<K, Schema, EntityName>\n >;\n } & {\n [K in keyof Schema['entities'][EntityName]['attrs']]?: ValidWhereValue<\n Input[K],\n Schema['entities'][EntityName]['attrs'][K]\n >;\n } & {\n and?: Input extends {\n and: Array<infer Item extends { [key: string]: any } | undefined>;\n }\n ? ValidWhereObject<NoDistribute<Item>, Schema, EntityName>[]\n : never;\n or?: Input extends {\n or: Array<infer Item extends { [key: string]: any } | undefined>;\n }\n ? ValidWhereObject<NoDistribute<Item>, Schema, EntityName>[]\n : never;\n } & {\n // Special case for id\n id?: ValidWhereValue<\n SafeLookup<Input, ['id']>,\n DataAttrDef<string, false, false, boolean>\n >;\n }\n : never;\n\n/**\n * Extracts the attribute definition from a valid dot path.\n * Given a dot path like \"user.posts.title\", this will resolve to the type of the \"title\" attribute.\n * If the path is just a link name (e.g., \"posts\"), it defaults to the id field.\n * Returns DataAttrDef or never\n */\ntype ExtractAttrFromDotPath<\n Path extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = Path extends keyof Schema['entities'][EntityName]['attrs']\n ? Schema['entities'][EntityName]['attrs'][Path]\n : Path extends 'id'\n ? DataAttrDef<string, false, false, boolean>\n : Path extends `${infer LinkName}.${infer RestPath}`\n ? LinkName extends keyof Schema['entities'][EntityName]['links']\n ? ExtractAttrFromDotPath<\n RestPath,\n Schema,\n Schema['entities'][EntityName]['links'][LinkName]['entityName']\n >\n : never\n : Path extends keyof Schema['entities'][EntityName]['links']\n ? DataAttrDef<string, false, false, boolean>\n : never;\n\ntype ValidQuery<\n Q extends Record<string, any>,\n S extends IContainEntitiesAndLinks<any, any>,\n> = S extends InstantUnknownSchemaDef\n ? InstaQLParams<S>\n : keyof Q extends keyof S['entities']\n ? {\n [K in keyof S['entities']]?: ValidQueryObject<Q[K], S, K, true>;\n }\n : never;\n\nexport {\n Query,\n QueryResponse,\n InstaQLResponse,\n PageInfoResponse,\n InstantObject,\n Exactly,\n Remove$,\n ValidQuery,\n InstaQLQueryResult,\n InstaQLParams,\n InstaQLOptions,\n InstaQLQueryEntityResult,\n InstaQLEntitySubquery,\n InstaQLEntity,\n InstaQLResult,\n InstaQLFields,\n Cursor,\n InstaQLQueryParams,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"queryTypes.js","sourceRoot":"","sources":["../../src/queryTypes.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,QAAQ","sourcesContent":["// Query\n// -----\n\nimport type {\n EntitiesDef,\n IContainEntitiesAndLinks,\n InstantGraph,\n LinkAttrDef,\n RuleParams,\n ResolveAttrs,\n ResolveEntityAttrs,\n DataAttrDef,\n AttrsDefs,\n EntityDefFromSchema,\n InstantUnknownSchemaDef,\n} from './schemaTypes.ts';\n\ntype BuiltIn = Date | Function | Error | RegExp;\n\ntype Primitive = string | number | boolean | symbol | null | undefined;\n\nexport type Expand<T> = T extends BuiltIn | Primitive\n ? T\n : T extends object\n ? T extends infer O\n ? { [K in keyof O]: Expand<O[K]> }\n : never\n : T;\n\n// NonEmpty disallows {}, so that you must provide at least one field\nexport type NonEmpty<T> = {\n [K in keyof T]-?: Required<Pick<T, K>>;\n}[keyof T];\n\ntype BaseWhereClauseValueComplex<V> = {\n /** @deprecated use `$in` instead of `in` */\n in?: V[];\n $in?: V[];\n /** @deprecated use `$ne` instead of `not` */\n $not?: V;\n $ne?: V;\n $gt?: V;\n $lt?: V;\n $gte?: V;\n $lte?: V;\n};\n\ntype IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;\n\ntype WhereClauseValueComplex<V, R, I> = BaseWhereClauseValueComplex<V> &\n (IsAny<V> extends true\n ? {\n $ilike?: string;\n $like?: string;\n $isNull?: boolean;\n }\n : (V extends string\n ? {\n $like?: string;\n }\n : {}) &\n (R extends false\n ? {\n $isNull?: boolean;\n }\n : {}) &\n (I extends true\n ? {\n $ilike?: string;\n }\n : {}));\n\n// Make type display better\ntype WhereClauseValue<\n D extends DataAttrDef<string | number | boolean, boolean, boolean, boolean>,\n> =\n D extends DataAttrDef<infer V, infer R, infer I, boolean>\n ?\n | (IsAny<V> extends true ? string | number | boolean : V)\n | NonEmpty<WhereClauseValueComplex<V, R, I>>\n : never;\n\ntype WhereClauseColumnEntries<\n T extends {\n [key: string]: DataAttrDef<any, boolean, boolean, boolean>;\n },\n> = {\n [key in keyof T]?: WhereClauseValue<T[key]>;\n};\n\ntype WhereClauseComboEntries<\n T extends Record<any, DataAttrDef<any, boolean, boolean, boolean>>,\n> = {\n or?:\n | WhereClauses<T>[]\n | WhereClauseValue<DataAttrDef<any, false, true, boolean>>;\n and?:\n | WhereClauses<T>[]\n | WhereClauseValue<DataAttrDef<any, false, true, boolean>>;\n};\n\ntype WhereClauses<\n T extends Record<any, DataAttrDef<any, boolean, boolean, boolean>>,\n> = (\n | WhereClauseComboEntries<T>\n | (WhereClauseComboEntries<T> & WhereClauseColumnEntries<T>)\n) & {\n id?: WhereClauseValue<DataAttrDef<string, false, true, boolean>>;\n [key: `${string}.${string}`]: WhereClauseValue<\n DataAttrDef<any, false, true, boolean>\n >;\n};\n\n/**\n * A tuple representing a cursor.\n * These should not be constructed manually. The current format\n * is an implementation detail that may change in the future.\n * Use the `endCursor` or `startCursor` from the PageInfoResponse as the\n * `before` or `after` field in the query options.\n */\ntype Cursor = [string, string, any, number];\n\ntype Direction = 'asc' | 'desc';\n\ntype IndexedKeys<Attrs extends AttrsDefs> = {\n [K in keyof Attrs]: Attrs[K] extends DataAttrDef<\n any,\n any,\n infer IsIndexed,\n boolean\n >\n ? IsIndexed extends true\n ? K\n : never\n : never;\n}[keyof Attrs];\n\nexport type Order<\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> =\n IndexedKeys<Schema['entities'][EntityName]['attrs']> extends never\n ? {\n serverCreatedAt?: Direction;\n }\n : {\n [K in IndexedKeys<Schema['entities'][EntityName]['attrs']>]?: Direction;\n } & {\n serverCreatedAt?: Direction;\n };\n\ntype $Option<\n S extends IContainEntitiesAndLinks<any, any>,\n K extends keyof S['entities'],\n> = {\n $?: {\n where?: WhereClauses<EntityDefFromSchema<S, K>>;\n order?: Order<S, K>;\n limit?: number;\n last?: number;\n first?: number;\n offset?: number;\n after?: Cursor;\n afterInclusive?: boolean;\n before?: Cursor;\n beforeInclusive?: boolean;\n fields?: InstaQLFields<S, K>;\n };\n};\n\ntype NamespaceVal =\n | $Option<IContainEntitiesAndLinks<any, any>, keyof EntitiesDef>\n | ($Option<IContainEntitiesAndLinks<any, any>, keyof EntitiesDef> & Subquery);\n\ntype Subquery = { [namespace: string]: NamespaceVal };\n\ninterface Query {\n [namespace: string]: NamespaceVal;\n}\n\ntype InstantObject = {\n id: string;\n [prop: string]: any;\n};\n\ntype ResponseObject<K, Schema> = K extends keyof Schema\n ? { id: string } & Schema[K]\n : InstantObject;\n\ntype IsEmptyObject<T> = T extends Record<string, never> ? true : false;\n\ntype ResponseOf<Q, Schema> = {\n [K in keyof Q]: IsEmptyObject<Q[K]> extends true\n ? ResponseObject<K, Schema>[]\n : (ResponseOf<Q[K], Schema> & ResponseObject<K, Schema>)[];\n};\n\ntype Remove$<T> = T extends object\n ? { [K in keyof T as Exclude<K, '$'>]: Remove$<T[K]> }\n : T;\n\ntype Remove$NonRecursive<T> = T extends object\n ? { [K in keyof T as Exclude<K, '$'>]: T[K] }\n : T;\n\ntype QueryResponse<\n Q,\n Schema,\n WithCardinalityInference extends boolean = false,\n UseDates extends boolean = false,\n> =\n Schema extends InstantGraph<infer E, any>\n ? InstaQLQueryResult<E, Q, WithCardinalityInference, UseDates>\n : ResponseOf<{ [K in keyof Q]: Remove$<Q[K]> }, Schema>;\n\ntype InstaQLResponse<Schema, Q, UseDates extends boolean = false> =\n Schema extends IContainEntitiesAndLinks<any, any>\n ? Q extends InstaQLParams<Schema> | undefined\n ? InstaQLResult<Schema, Q, UseDates>\n : never\n : never;\n\ntype PageInfoResponse<T> = {\n [K in keyof T]: {\n startCursor: Cursor;\n endCursor: Cursor;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n };\n};\n\n/**\n * (XXX)\n * https://github.com/microsoft/TypeScript/issues/26051\n *\n * TypeScript can permit extra keys when a generic extends a type.\n *\n * For some reason, it makes it possible to write a query like so:\n *\n * dummyQuery({\n * users: {\n * $: { where: { \"foo\": 1 } },\n * posts: {\n * $: { \"far\": {} }\n * }\n * }\n *\n * The problem: $: { \"far\": {} }\n *\n * This passes, when it should in reality fail. I don't know why\n * adding `Exactly` fixes this, but it does.\n *\n * */\ntype Exactly<Parent, Child> = Parent & {\n [K in keyof Child]: K extends keyof Parent ? Child[K] : never;\n};\n\n// SafeLookup<T, ['A', 'B', number]> is like doing\n// T['A']['B'][number], but it will merge with undefined if any\n// of the intermediates are undefined\ntype SafeLookup<T, K extends readonly PropertyKey[]> = K extends [\n infer First,\n ...infer Rest extends readonly PropertyKey[],\n]\n ? First extends keyof NonNullable<T>\n ?\n | SafeLookup<NonNullable<T>[First], Rest>\n | (T extends null | undefined ? undefined : never)\n : undefined\n : T;\n\n// ==========\n// InstaQL helpers\n\ntype InstaQLEntitySubqueryResult<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n Query extends InstaQLEntitySubquery<Schema, EntityName> | undefined = {},\n UseDates extends boolean = false,\n> = {\n [QueryPropName in keyof Query]: Schema['entities'][EntityName]['links'][QueryPropName] extends LinkAttrDef<\n infer Cardinality,\n infer LinkedEntityName\n >\n ? LinkedEntityName extends keyof Schema['entities']\n ? Cardinality extends 'one'\n ?\n | InstaQLEntity<\n Schema,\n LinkedEntityName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >\n | undefined\n : InstaQLEntity<\n Schema,\n LinkedEntityName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >[]\n : never\n : never;\n};\n\ntype InstaQLQueryEntityLinksResult<\n Entities extends EntitiesDef,\n EntityName extends keyof Entities,\n Query extends {\n [LinkAttrName in keyof Entities[EntityName]['links']]?: any;\n },\n WithCardinalityInference extends boolean,\n UseDates extends boolean = false,\n> = {\n [QueryPropName in keyof Query]: Entities[EntityName]['links'][QueryPropName] extends LinkAttrDef<\n infer Cardinality,\n infer LinkedEntityName\n >\n ? LinkedEntityName extends keyof Entities\n ? WithCardinalityInference extends true\n ? Cardinality extends 'one'\n ?\n | InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >\n | undefined\n : InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : InstaQLQueryEntityResult<\n Entities,\n LinkedEntityName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : never\n : never;\n};\n\n// Pick, but applies the pick to each union\ntype DistributePick<T, K extends string> = T extends any\n ? { [P in K]: P extends keyof T ? T[P] : never }\n : never;\n\ntype InstaQLFields<\n S extends IContainEntitiesAndLinks<any, any>,\n K extends keyof S['entities'],\n> = (Extract<keyof ResolveEntityAttrs<S['entities'][K]>, string> | 'id')[];\n\ntype ComputeAttrs<\n AllAttrs,\n Fields extends readonly string[] | undefined,\n> = Fields extends readonly string[]\n ? DistributePick<AllAttrs, Exclude<Fields[number], 'id'>>\n : AllAttrs;\n\ntype InstaQLEntity<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n Subquery extends InstaQLEntitySubquery<Schema, EntityName> | undefined = {},\n Fields extends InstaQLFields<Schema, EntityName> | undefined = undefined,\n UseDates extends boolean = false,\n> = Expand<\n { id: string } & ComputeAttrs<\n ResolveEntityAttrs<Schema['entities'][EntityName], UseDates>,\n Fields\n > &\n InstaQLEntitySubqueryResult<Schema, EntityName, Subquery, UseDates>\n>;\n\ntype InstaQLQueryEntityResult<\n Entities extends EntitiesDef,\n EntityName extends keyof Entities,\n Query extends {\n [QueryPropName in keyof Entities[EntityName]['links']]?: any;\n },\n WithCardinalityInference extends boolean,\n UseDates extends boolean,\n> = { id: string } & ResolveAttrs<Entities, EntityName, UseDates> &\n InstaQLQueryEntityLinksResult<\n Entities,\n EntityName,\n Query,\n WithCardinalityInference,\n UseDates\n >;\n\ntype InstaQLQueryResult<\n Entities extends EntitiesDef,\n Query,\n WithCardinalityInference extends boolean,\n UseDates extends boolean,\n> = {\n [QueryPropName in keyof Query]: QueryPropName extends keyof Entities\n ? InstaQLQueryEntityResult<\n Entities,\n QueryPropName,\n Query[QueryPropName],\n WithCardinalityInference,\n UseDates\n >[]\n : never;\n};\n\ntype InstaQLResult<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n Query extends InstaQLParams<Schema> | undefined,\n UseDates extends boolean = false,\n> = Expand<{\n [QueryPropName in keyof Query]: QueryPropName extends keyof Schema['entities']\n ? InstaQLEntity<\n Schema,\n QueryPropName,\n Remove$NonRecursive<SafeLookup<Query, [QueryPropName]>>,\n SafeLookup<Query, [QueryPropName, '$', 'fields']>,\n UseDates\n >[]\n : never;\n}>;\n\ntype InstaQLEntitySubquery<\n Schema extends IContainEntitiesAndLinks<EntitiesDef, any>,\n EntityName extends keyof Schema['entities'],\n> = {\n [QueryPropName in keyof Schema['entities'][EntityName]['links']]?:\n | $Option<Schema, EntityName>\n | ($Option<Schema, EntityName> &\n InstaQLEntitySubquery<\n Schema,\n Schema['entities'][EntityName]['links'][QueryPropName]['entityName']\n >);\n};\n\ntype InstaQLQuerySubqueryParams<\n S extends IContainEntitiesAndLinks<any, any>,\n E extends keyof S['entities'],\n> = {\n [K in keyof S['entities'][E]['links']]?:\n | $Option<S, S['entities'][E]['links'][K]['entityName']>\n | ($Option<S, S['entities'][E]['links'][K]['entityName']> &\n InstaQLQuerySubqueryParams<\n S,\n S['entities'][E]['links'][K]['entityName']\n >);\n};\n\ntype InstaQLParams<S extends IContainEntitiesAndLinks<any, any>> = {\n [K in keyof S['entities']]?:\n | $Option<S, K>\n | ($Option<S, K> & InstaQLQuerySubqueryParams<S, K>);\n};\n\n/**\n * @deprecated\n * `InstaQLQueryParams` is deprecated. Use `InstaQLParams` instead.\n *\n * @example\n * // Before\n * const myQuery = {...} satisfies InstaQLQueryParams<Schema>\n * // After\n * const myQuery = {...} satisfies InstaQLParams<Schema>\n */\ntype InstaQLQueryParams<S extends IContainEntitiesAndLinks<any, any>> =\n InstaQLParams<S>;\n\ntype InstaQLOptions = {\n ruleParams: RuleParams;\n};\n\n// Start of new types\n\ntype ValidQueryObject<\n T extends Record<string, any>,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n TopLevel extends boolean,\n> = keyof T extends keyof Schema['entities'][EntityName]['links'] | '$'\n ? {\n [K in keyof Schema['entities'][EntityName]['links']]?: ValidQueryObject<\n T[K],\n Schema,\n Schema['entities'][EntityName]['links'][K]['entityName'],\n false\n >;\n } & {\n $?: ValidDollarSignQuery<T['$'], Schema, EntityName, TopLevel>;\n }\n : never;\n\ntype PaginationKeys =\n | 'limit'\n | 'last'\n | 'first'\n | 'offset'\n | 'after'\n | 'afterInclusive'\n | 'before'\n | 'beforeInclusive';\n\ntype AllowedDollarSignKeys<TopLevel extends boolean> = TopLevel extends true\n ? PaginationKeys | 'where' | 'fields' | 'order'\n : 'where' | 'fields' | 'order' | 'limit';\n\ntype ValidFieldNames<\n S extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof S['entities'],\n> = Extract<keyof ResolveEntityAttrs<S['entities'][EntityName]>, string> | 'id';\n\ntype ValidDollarSignQuery<\n Input extends { [key: string]: any },\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n TopLevel extends boolean,\n> =\n keyof Input extends AllowedDollarSignKeys<TopLevel>\n ? {\n where?: ValidWhereObject<Input['where'], Schema, EntityName>;\n fields?: ValidFieldNames<Schema, EntityName>[];\n order?: Order<Schema, EntityName>;\n limit?: number;\n } & (TopLevel extends true\n ? {\n last?: number;\n first?: number;\n offset?: number;\n after?: Cursor;\n afterInclusive?: boolean;\n before?: Cursor;\n beforeInclusive?: boolean;\n }\n : {})\n : never;\n\ntype StringifiableKey<T> = Extract<T, string | number | bigint | boolean>;\n\ntype ValidWhereNestedPath<\n T,\n K extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n> = T extends object\n ? K extends keyof T\n ? K // Allow link names as valid paths (they'll default to id)\n : K extends `${infer K0}.${infer KR}`\n ? K0 extends keyof T\n ? T[K0] extends keyof Schema['entities']\n ? `${K0}.${\n | ValidWhereNestedPath<\n {\n [K in keyof Schema['entities'][T[K0]]['links']]: Schema['entities'][T[K0]]['links'][K]['entityName'];\n },\n KR,\n Schema\n >\n | StringifiableKey<keyof Schema['entities'][T[K0]]['attrs']>\n | 'id'}`\n : string & keyof T\n : string & keyof T\n : string & keyof T\n : never;\n\ntype ValidDotPath<\n Input extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = ValidWhereNestedPath<\n {\n [K in keyof Schema['entities'][EntityName]['links']]: Schema['entities'][EntityName]['links'][K]['entityName'];\n },\n Input,\n Schema\n>;\n\ntype WhereOperatorObject<Input, V, R, I> = keyof Input extends\n | keyof BaseWhereClauseValueComplex<V>\n | '$ilike'\n | '$like'\n | '$isNull'\n ? BaseWhereClauseValueComplex<V> &\n (IsAny<V> extends true\n ? {\n $ilike?: string;\n $like?: string;\n $isNull?: boolean;\n }\n : (V extends string\n ? {\n $like?: string;\n }\n : {}) &\n (R extends false\n ? {\n $isNull?: boolean;\n }\n : {}) &\n (I extends true\n ? {\n $ilike?: string;\n }\n : {}))\n : never;\n\ntype ValidWhereValue<\n Input,\n AttrDef extends DataAttrDef<any, any, any, boolean>,\n> =\n AttrDef extends DataAttrDef<infer V, infer R, infer I, boolean>\n ? Input extends V\n ? V\n : NonEmpty<WhereOperatorObject<Input, V, R, I>>\n : never;\n\ntype NoDistribute<T> = [T] extends [any] ? T : never;\n\ntype ValidWhereObject<\n Input extends { [key: string]: any } | undefined,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = Input extends undefined\n ? undefined\n : keyof Input extends\n | ValidDotPath<keyof Input, Schema, EntityName>\n | keyof Schema['entities'][EntityName]['attrs']\n | 'and'\n | 'or'\n | 'id'\n ? {\n [K in ValidDotPath<keyof Input, Schema, EntityName>]?: ValidWhereValue<\n Input[K],\n ExtractAttrFromDotPath<K, Schema, EntityName>\n >;\n } & {\n [K in keyof Schema['entities'][EntityName]['attrs']]?: ValidWhereValue<\n Input[K],\n Schema['entities'][EntityName]['attrs'][K]\n >;\n } & {\n and?: Input extends {\n and: Array<infer Item extends { [key: string]: any } | undefined>;\n }\n ? ValidWhereObject<NoDistribute<Item>, Schema, EntityName>[]\n : never;\n or?: Input extends {\n or: Array<infer Item extends { [key: string]: any } | undefined>;\n }\n ? ValidWhereObject<NoDistribute<Item>, Schema, EntityName>[]\n : never;\n } & {\n // Special case for id\n id?: ValidWhereValue<\n SafeLookup<Input, ['id']>,\n DataAttrDef<string, false, false, boolean>\n >;\n }\n : never;\n\n/**\n * Extracts the attribute definition from a valid dot path.\n * Given a dot path like \"user.posts.title\", this will resolve to the type of the \"title\" attribute.\n * If the path is just a link name (e.g., \"posts\"), it defaults to the id field.\n * Returns DataAttrDef or never\n */\ntype ExtractAttrFromDotPath<\n Path extends string | number | symbol,\n Schema extends IContainEntitiesAndLinks<any, any>,\n EntityName extends keyof Schema['entities'],\n> = Path extends keyof Schema['entities'][EntityName]['attrs']\n ? Schema['entities'][EntityName]['attrs'][Path]\n : Path extends 'id'\n ? DataAttrDef<string, false, false, boolean>\n : Path extends `${infer LinkName}.${infer RestPath}`\n ? LinkName extends keyof Schema['entities'][EntityName]['links']\n ? ExtractAttrFromDotPath<\n RestPath,\n Schema,\n Schema['entities'][EntityName]['links'][LinkName]['entityName']\n >\n : never\n : Path extends keyof Schema['entities'][EntityName]['links']\n ? DataAttrDef<string, false, false, boolean>\n : never;\n\ntype ValidQuery<\n Q extends Record<string, any>,\n S extends IContainEntitiesAndLinks<any, any>,\n> = S extends InstantUnknownSchemaDef\n ? InstaQLParams<S>\n : keyof Q extends keyof S['entities']\n ? {\n [K in keyof S['entities']]?: ValidQueryObject<Q[K], S, K, true>;\n }\n : never;\n\nexport {\n Query,\n QueryResponse,\n InstaQLResponse,\n PageInfoResponse,\n InstantObject,\n Exactly,\n Remove$,\n ValidQuery,\n InstaQLQueryResult,\n InstaQLParams,\n InstaQLOptions,\n InstaQLQueryEntityResult,\n InstaQLEntitySubquery,\n InstaQLEntity,\n InstaQLResult,\n InstaQLFields,\n Cursor,\n InstaQLQueryParams,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryValidation.d.ts","sourceRoot":"","sources":["../../src/queryValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EAGzB,MAAM,kBAAkB,CAAC;AAG1B,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAK3C;
|
|
1
|
+
{"version":3,"file":"queryValidation.d.ts","sourceRoot":"","sources":["../../src/queryValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EAGzB,MAAM,kBAAkB,CAAC;AAG1B,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAK3C;AAidD,eAAO,MAAM,aAAa,GACxB,GAAG,OAAO,EACV,SAAS,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,KAC1C,IAqDF,CAAC"}
|
|
@@ -15,7 +15,9 @@ const dollarSignKeys = [
|
|
|
15
15
|
'first',
|
|
16
16
|
'offset',
|
|
17
17
|
'after',
|
|
18
|
+
'afterInclusive',
|
|
18
19
|
'before',
|
|
20
|
+
'beforeInclusive',
|
|
19
21
|
'fields',
|
|
20
22
|
'aggregate',
|
|
21
23
|
];
|
|
@@ -207,7 +209,9 @@ const validateDollarObject = (dollarObj, entityName, schema, path, depth = 0) =>
|
|
|
207
209
|
// 'limit', // only supported client side
|
|
208
210
|
'offset',
|
|
209
211
|
'before',
|
|
212
|
+
'beforeInclusive',
|
|
210
213
|
'after',
|
|
214
|
+
'afterInclusive',
|
|
211
215
|
'first',
|
|
212
216
|
'last',
|
|
213
217
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryValidation.js","sourceRoot":"","sources":["../../src/queryValidation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n IContainEntitiesAndLinks,\n DataAttrDef,\n ValueTypes,\n} from './schemaTypes.ts';\nimport { validate as validateUUID } from 'uuid';\n\nexport class QueryValidationError extends Error {\n constructor(message: string, path?: string) {\n const fullMessage = path ? `At path '${path}': ${message}` : message;\n super(fullMessage);\n this.name = 'QueryValidationError';\n }\n}\n\nconst dollarSignKeys = [\n 'where',\n 'order',\n 'limit',\n 'last',\n 'first',\n 'offset',\n 'after',\n 'before',\n 'fields',\n 'aggregate',\n];\n\ntype PossibleAttrTypes = ValueTypes | 'unknown';\n\nconst getAttrType = (\n attrDef: DataAttrDef<any, any, any>,\n): PossibleAttrTypes => {\n return attrDef.valueType || 'unknown';\n};\n\nconst isValidValueForType = (\n value: unknown,\n expectedType: PossibleAttrTypes,\n isAnyType: boolean = false,\n): boolean => {\n if (isAnyType) return true;\n if (value === null || value === undefined) return true;\n\n switch (expectedType) {\n case 'string':\n return typeof value === 'string';\n case 'number':\n return typeof value === 'number' && !isNaN(value);\n case 'boolean':\n return typeof value === 'boolean';\n case 'date':\n return (\n value instanceof Date ||\n typeof value === 'string' ||\n typeof value === 'number'\n );\n default:\n return true;\n }\n};\n\nconst validateOperator = (\n op: string,\n opValue: unknown,\n expectedType: PossibleAttrTypes,\n attrName: string,\n entityName: string,\n attrDef: DataAttrDef<any, any, any>,\n path: string,\n) => {\n const isAnyType = attrDef.valueType === 'json';\n const assertValidValue = (\n op: string,\n expectedType: PossibleAttrTypes,\n opValue: unknown,\n ) => {\n if (!isValidValueForType(opValue, expectedType, isAnyType)) {\n throw new QueryValidationError(\n `Invalid value for operator '${op}' on attribute '${attrName}' in entity '${entityName}'. Expected ${expectedType}, but received: ${typeof opValue}`,\n path,\n );\n }\n };\n\n switch (op) {\n case 'in':\n case '$in':\n if (!Array.isArray(opValue)) {\n throw new QueryValidationError(\n `Operator '${op}' for attribute '${attrName}' in entity '${entityName}' must be an array, but received: ${typeof opValue}`,\n path,\n );\n }\n for (const item of opValue) {\n assertValidValue(op, expectedType, item);\n }\n break;\n case '$not':\n case '$ne':\n case '$gt':\n case '$lt':\n case '$gte':\n case '$lte':\n assertValidValue(op, expectedType, opValue);\n break;\n case '$like':\n case '$ilike':\n assertValidValue(op, 'string', opValue);\n\n if (op === '$ilike') {\n if (!attrDef.isIndexed) {\n throw new QueryValidationError(\n `Operator '${op}' can only be used with indexed attributes, but '${attrName}' in entity '${entityName}' is not indexed`,\n path,\n );\n }\n }\n\n break;\n case '$isNull':\n assertValidValue(op, 'boolean', opValue);\n break;\n default:\n throw new QueryValidationError(\n `Unknown operator '${op}' for attribute '${attrName}' in entity '${entityName}'`,\n path,\n );\n }\n};\n\nconst validateWhereClauseValue = (\n value: unknown,\n attrName: string,\n attrDef: DataAttrDef<any, any, any>,\n entityName: string,\n path: string,\n): void => {\n const expectedType = getAttrType(attrDef);\n const isAnyType = attrDef.valueType === 'json';\n\n const isComplexObject =\n typeof value === 'object' && value !== null && !Array.isArray(value);\n if (isComplexObject) {\n // For any type, allow complex objects without treating them as operators\n if (isAnyType) {\n return; // Any type accepts any value, including complex objects\n }\n\n const operators = value as Record<string, unknown>;\n\n for (const [op, opValue] of Object.entries(operators)) {\n validateOperator(\n op,\n opValue,\n expectedType,\n attrName,\n entityName,\n attrDef,\n `${path}.${op}`,\n );\n }\n } else {\n if (!isValidValueForType(value, expectedType, isAnyType)) {\n throw new QueryValidationError(\n `Invalid value for attribute '${attrName}' in entity '${entityName}'. Expected ${expectedType}, but received: ${typeof value}`,\n path,\n );\n }\n }\n};\n\nconst validateDotNotationAttribute = (\n dotPath: string,\n value: unknown,\n startEntityName: string,\n schema: IContainEntitiesAndLinks<any, any>,\n path: string,\n): void => {\n const pathParts = dotPath.split('.');\n if (pathParts.length < 2) {\n throw new QueryValidationError(\n `Invalid dot notation path '${dotPath}'. Must contain at least one dot.`,\n path,\n );\n }\n\n let currentEntityName = startEntityName;\n\n // Traverse all path parts except the last one (which should be an attribute)\n for (let i = 0; i < pathParts.length - 1; i++) {\n const linkName = pathParts[i];\n const currentEntity = schema.entities[currentEntityName];\n\n if (!currentEntity) {\n throw new QueryValidationError(\n `Entity '${currentEntityName}' does not exist in schema while traversing dot notation path '${dotPath}'.`,\n path,\n );\n }\n\n const link = currentEntity.links[linkName];\n if (!link) {\n const availableLinks = Object.keys(currentEntity.links);\n throw new QueryValidationError(\n `Link '${linkName}' does not exist on entity '${currentEntityName}' in dot notation path '${dotPath}'. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n path,\n );\n }\n\n currentEntityName = link.entityName;\n }\n\n // Validate the final attribute\n const finalAttrName = pathParts[pathParts.length - 1];\n const finalEntity = schema.entities[currentEntityName];\n\n if (!finalEntity) {\n throw new QueryValidationError(\n `Target entity '${currentEntityName}' does not exist in schema for dot notation path '${dotPath}'.`,\n path,\n );\n }\n\n // Handle 'id' field specially - every entity has an id field\n if (finalAttrName === 'id') {\n if (typeof value == 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for id field in entity '${currentEntityName}'. Expected a UUID, but received: ${value}`,\n path,\n );\n }\n validateWhereClauseValue(\n value,\n dotPath,\n new DataAttrDef('string', false, true),\n startEntityName,\n path,\n );\n return;\n }\n\n const attrDef = finalEntity.attrs[finalAttrName];\n\n if (Object.keys(finalEntity.links).includes(finalAttrName)) {\n if (typeof value === 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for link '${finalAttrName}' in entity '${currentEntityName}'. Expected a UUID, but received: ${value}`,\n path,\n );\n }\n\n validateWhereClauseValue(\n value,\n dotPath,\n new DataAttrDef('string', false, true),\n startEntityName,\n path,\n );\n return;\n }\n\n if (!attrDef) {\n const availableAttrs = Object.keys(finalEntity.attrs);\n throw new QueryValidationError(\n `Attribute '${finalAttrName}' does not exist on entity '${currentEntityName}' in dot notation path '${dotPath}'. Available attributes: ${availableAttrs.length > 0 ? availableAttrs.join(', ') + ', id' : 'id'}`,\n path,\n );\n }\n\n // Validate the value against the attribute type\n validateWhereClauseValue(value, dotPath, attrDef, startEntityName, path);\n};\n\nconst validateWhereClause = (\n whereClause: Record<string, unknown>,\n entityName: string,\n schema: IContainEntitiesAndLinks<any, any>,\n path: string,\n): void => {\n for (const [key, value] of Object.entries(whereClause)) {\n if (key === 'or' || key === 'and') {\n if (Array.isArray(value)) {\n for (const clause of value) {\n if (typeof clause === 'object' && clause !== null) {\n validateWhereClause(\n clause as Record<string, unknown>,\n entityName,\n schema,\n `${path}.${key}[${clause}]`,\n );\n }\n }\n }\n continue;\n }\n\n if (key === 'id') {\n validateWhereClauseValue(\n value,\n 'id',\n new DataAttrDef('string', false, true),\n entityName,\n `${path}.id`,\n );\n continue;\n }\n\n if (key.includes('.')) {\n validateDotNotationAttribute(\n key,\n value,\n entityName,\n schema,\n `${path}.${key}`,\n );\n continue;\n }\n\n const entityDef = schema.entities[entityName];\n if (!entityDef) continue;\n\n const attrDef = entityDef.attrs[key];\n const linkDef = entityDef.links[key];\n\n if (!attrDef && !linkDef) {\n const availableAttrs = Object.keys(entityDef.attrs);\n const availableLinks = Object.keys(entityDef.links);\n throw new QueryValidationError(\n `Attribute or link '${key}' does not exist on entity '${entityName}'. Available attributes: ${availableAttrs.length > 0 ? availableAttrs.join(', ') : 'none'}. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n `${path}.${key}`,\n );\n }\n\n if (attrDef) {\n validateWhereClauseValue(\n value,\n key,\n attrDef,\n entityName,\n `${path}.${key}`,\n );\n } else if (linkDef) {\n // For links, we expect the value to be a string (ID of the linked entity)\n // Create a synthetic string attribute definition for validation\n if (typeof value === 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for link '${key}' in entity '${entityName}'. Expected a UUID, but received: ${value}`,\n `${path}.${key}`,\n );\n }\n const syntheticAttrDef = new DataAttrDef('string', false, true);\n validateWhereClauseValue(\n value,\n key,\n syntheticAttrDef,\n entityName,\n `${path}.${key}`,\n );\n }\n }\n};\n\nconst validateDollarObject = (\n dollarObj: Record<string, unknown>,\n entityName: string,\n schema?: IContainEntitiesAndLinks<any, any> | null | undefined,\n path?: string,\n depth: number = 0,\n): void => {\n for (const key of Object.keys(dollarObj)) {\n if (!dollarSignKeys.includes(key)) {\n throw new QueryValidationError(\n `Invalid query parameter '${key}' in $ object. Valid parameters are: ${dollarSignKeys.join(', ')}. Found: ${key}`,\n path,\n );\n }\n }\n\n // Validate that pagination parameters are only used at top-level\n const paginationParams = [\n // 'limit', // only supported client side\n 'offset',\n 'before',\n 'after',\n 'first',\n 'last',\n ];\n for (const param of paginationParams) {\n if (dollarObj[param] !== undefined && depth > 0) {\n throw new QueryValidationError(\n `'${param}' can only be used on top-level namespaces. It cannot be used in nested queries.`,\n path,\n );\n }\n }\n\n if (dollarObj.where && schema) {\n if (typeof dollarObj.where !== 'object' || dollarObj.where === null) {\n throw new QueryValidationError(\n `'where' clause must be an object in entity '${entityName}', but received: ${typeof dollarObj.where}`,\n path ? `${path}.where` : undefined,\n );\n }\n validateWhereClause(\n dollarObj.where as Record<string, unknown>,\n entityName,\n schema,\n path ? `${path}.where` : 'where',\n );\n }\n};\n\nconst validateEntityInQuery = (\n queryPart: Record<string, unknown>,\n entityName: string,\n schema: IContainEntitiesAndLinks<any, any> | null | undefined,\n path: string,\n depth: number = 0,\n): void => {\n if (!queryPart || typeof queryPart !== 'object') {\n throw new QueryValidationError(\n `Query part for entity '${entityName}' must be an object, but received: ${typeof queryPart}`,\n path,\n );\n }\n\n for (const key of Object.keys(queryPart)) {\n if (key !== '$') {\n // Validate link exists\n if (schema && !(key in schema.entities[entityName].links)) {\n const availableLinks = Object.keys(schema.entities[entityName].links);\n throw new QueryValidationError(\n `Link '${key}' does not exist on entity '${entityName}'. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n `${path}.${key}`,\n );\n }\n\n // Recursively validate nested query\n const nestedQuery = queryPart[key];\n if (typeof nestedQuery === 'object' && nestedQuery !== null) {\n const linkedEntityName =\n schema?.entities[entityName].links[key]?.entityName;\n if (linkedEntityName) {\n validateEntityInQuery(\n nestedQuery as Record<string, unknown>,\n linkedEntityName,\n schema,\n `${path}.${key}`,\n depth + 1,\n );\n }\n }\n } else {\n // Validate $ object\n const dollarObj = queryPart[key];\n if (typeof dollarObj !== 'object' || dollarObj === null) {\n throw new QueryValidationError(\n `Query parameter '$' must be an object in entity '${entityName}', but received: ${typeof dollarObj}`,\n `${path}.$`,\n );\n }\n\n validateDollarObject(\n dollarObj as Record<string, unknown>,\n entityName,\n schema,\n `${path}.$`,\n depth,\n );\n }\n }\n};\n\nexport const validateQuery = (\n q: unknown,\n schema?: IContainEntitiesAndLinks<any, any>,\n): void => {\n if (typeof q !== 'object' || q === null) {\n throw new QueryValidationError(\n `Query must be an object, but received: ${typeof q}${q === null ? ' (null)' : ''}`,\n );\n }\n\n if (Array.isArray(q)) {\n throw new QueryValidationError(\n `Query must be an object, but received: ${typeof q}`,\n );\n }\n\n const queryObj = q as Record<string, unknown>;\n\n for (const topLevelKey of Object.keys(queryObj)) {\n if (Array.isArray(q[topLevelKey])) {\n throw new QueryValidationError(\n `Query keys must be strings, but found key of type: ${typeof topLevelKey}`,\n topLevelKey,\n );\n }\n\n if (typeof topLevelKey !== 'string') {\n throw new QueryValidationError(\n `Query keys must be strings, but found key of type: ${typeof topLevelKey}`,\n topLevelKey,\n );\n }\n\n if (topLevelKey === '$$ruleParams') {\n continue;\n }\n\n // Check if the key is top level entity\n if (schema) {\n if (!schema.entities[topLevelKey]) {\n const availableEntities = Object.keys(schema.entities);\n throw new QueryValidationError(\n `Entity '${topLevelKey}' does not exist in schema. Available entities: ${availableEntities.length > 0 ? availableEntities.join(', ') : 'none'}`,\n topLevelKey,\n );\n }\n }\n\n validateEntityInQuery(\n queryObj[topLevelKey] as Record<string, unknown>,\n topLevelKey,\n schema,\n topLevelKey,\n 0, // Start at depth 0 for top-level entities\n );\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"queryValidation.js","sourceRoot":"","sources":["../../src/queryValidation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n IContainEntitiesAndLinks,\n DataAttrDef,\n ValueTypes,\n} from './schemaTypes.ts';\nimport { validate as validateUUID } from 'uuid';\n\nexport class QueryValidationError extends Error {\n constructor(message: string, path?: string) {\n const fullMessage = path ? `At path '${path}': ${message}` : message;\n super(fullMessage);\n this.name = 'QueryValidationError';\n }\n}\n\nconst dollarSignKeys = [\n 'where',\n 'order',\n 'limit',\n 'last',\n 'first',\n 'offset',\n 'after',\n 'afterInclusive',\n 'before',\n 'beforeInclusive',\n 'fields',\n 'aggregate',\n];\n\ntype PossibleAttrTypes = ValueTypes | 'unknown';\n\nconst getAttrType = (\n attrDef: DataAttrDef<any, any, any>,\n): PossibleAttrTypes => {\n return attrDef.valueType || 'unknown';\n};\n\nconst isValidValueForType = (\n value: unknown,\n expectedType: PossibleAttrTypes,\n isAnyType: boolean = false,\n): boolean => {\n if (isAnyType) return true;\n if (value === null || value === undefined) return true;\n\n switch (expectedType) {\n case 'string':\n return typeof value === 'string';\n case 'number':\n return typeof value === 'number' && !isNaN(value);\n case 'boolean':\n return typeof value === 'boolean';\n case 'date':\n return (\n value instanceof Date ||\n typeof value === 'string' ||\n typeof value === 'number'\n );\n default:\n return true;\n }\n};\n\nconst validateOperator = (\n op: string,\n opValue: unknown,\n expectedType: PossibleAttrTypes,\n attrName: string,\n entityName: string,\n attrDef: DataAttrDef<any, any, any>,\n path: string,\n) => {\n const isAnyType = attrDef.valueType === 'json';\n const assertValidValue = (\n op: string,\n expectedType: PossibleAttrTypes,\n opValue: unknown,\n ) => {\n if (!isValidValueForType(opValue, expectedType, isAnyType)) {\n throw new QueryValidationError(\n `Invalid value for operator '${op}' on attribute '${attrName}' in entity '${entityName}'. Expected ${expectedType}, but received: ${typeof opValue}`,\n path,\n );\n }\n };\n\n switch (op) {\n case 'in':\n case '$in':\n if (!Array.isArray(opValue)) {\n throw new QueryValidationError(\n `Operator '${op}' for attribute '${attrName}' in entity '${entityName}' must be an array, but received: ${typeof opValue}`,\n path,\n );\n }\n for (const item of opValue) {\n assertValidValue(op, expectedType, item);\n }\n break;\n case '$not':\n case '$ne':\n case '$gt':\n case '$lt':\n case '$gte':\n case '$lte':\n assertValidValue(op, expectedType, opValue);\n break;\n case '$like':\n case '$ilike':\n assertValidValue(op, 'string', opValue);\n\n if (op === '$ilike') {\n if (!attrDef.isIndexed) {\n throw new QueryValidationError(\n `Operator '${op}' can only be used with indexed attributes, but '${attrName}' in entity '${entityName}' is not indexed`,\n path,\n );\n }\n }\n\n break;\n case '$isNull':\n assertValidValue(op, 'boolean', opValue);\n break;\n default:\n throw new QueryValidationError(\n `Unknown operator '${op}' for attribute '${attrName}' in entity '${entityName}'`,\n path,\n );\n }\n};\n\nconst validateWhereClauseValue = (\n value: unknown,\n attrName: string,\n attrDef: DataAttrDef<any, any, any>,\n entityName: string,\n path: string,\n): void => {\n const expectedType = getAttrType(attrDef);\n const isAnyType = attrDef.valueType === 'json';\n\n const isComplexObject =\n typeof value === 'object' && value !== null && !Array.isArray(value);\n if (isComplexObject) {\n // For any type, allow complex objects without treating them as operators\n if (isAnyType) {\n return; // Any type accepts any value, including complex objects\n }\n\n const operators = value as Record<string, unknown>;\n\n for (const [op, opValue] of Object.entries(operators)) {\n validateOperator(\n op,\n opValue,\n expectedType,\n attrName,\n entityName,\n attrDef,\n `${path}.${op}`,\n );\n }\n } else {\n if (!isValidValueForType(value, expectedType, isAnyType)) {\n throw new QueryValidationError(\n `Invalid value for attribute '${attrName}' in entity '${entityName}'. Expected ${expectedType}, but received: ${typeof value}`,\n path,\n );\n }\n }\n};\n\nconst validateDotNotationAttribute = (\n dotPath: string,\n value: unknown,\n startEntityName: string,\n schema: IContainEntitiesAndLinks<any, any>,\n path: string,\n): void => {\n const pathParts = dotPath.split('.');\n if (pathParts.length < 2) {\n throw new QueryValidationError(\n `Invalid dot notation path '${dotPath}'. Must contain at least one dot.`,\n path,\n );\n }\n\n let currentEntityName = startEntityName;\n\n // Traverse all path parts except the last one (which should be an attribute)\n for (let i = 0; i < pathParts.length - 1; i++) {\n const linkName = pathParts[i];\n const currentEntity = schema.entities[currentEntityName];\n\n if (!currentEntity) {\n throw new QueryValidationError(\n `Entity '${currentEntityName}' does not exist in schema while traversing dot notation path '${dotPath}'.`,\n path,\n );\n }\n\n const link = currentEntity.links[linkName];\n if (!link) {\n const availableLinks = Object.keys(currentEntity.links);\n throw new QueryValidationError(\n `Link '${linkName}' does not exist on entity '${currentEntityName}' in dot notation path '${dotPath}'. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n path,\n );\n }\n\n currentEntityName = link.entityName;\n }\n\n // Validate the final attribute\n const finalAttrName = pathParts[pathParts.length - 1];\n const finalEntity = schema.entities[currentEntityName];\n\n if (!finalEntity) {\n throw new QueryValidationError(\n `Target entity '${currentEntityName}' does not exist in schema for dot notation path '${dotPath}'.`,\n path,\n );\n }\n\n // Handle 'id' field specially - every entity has an id field\n if (finalAttrName === 'id') {\n if (typeof value == 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for id field in entity '${currentEntityName}'. Expected a UUID, but received: ${value}`,\n path,\n );\n }\n validateWhereClauseValue(\n value,\n dotPath,\n new DataAttrDef('string', false, true),\n startEntityName,\n path,\n );\n return;\n }\n\n const attrDef = finalEntity.attrs[finalAttrName];\n\n if (Object.keys(finalEntity.links).includes(finalAttrName)) {\n if (typeof value === 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for link '${finalAttrName}' in entity '${currentEntityName}'. Expected a UUID, but received: ${value}`,\n path,\n );\n }\n\n validateWhereClauseValue(\n value,\n dotPath,\n new DataAttrDef('string', false, true),\n startEntityName,\n path,\n );\n return;\n }\n\n if (!attrDef) {\n const availableAttrs = Object.keys(finalEntity.attrs);\n throw new QueryValidationError(\n `Attribute '${finalAttrName}' does not exist on entity '${currentEntityName}' in dot notation path '${dotPath}'. Available attributes: ${availableAttrs.length > 0 ? availableAttrs.join(', ') + ', id' : 'id'}`,\n path,\n );\n }\n\n // Validate the value against the attribute type\n validateWhereClauseValue(value, dotPath, attrDef, startEntityName, path);\n};\n\nconst validateWhereClause = (\n whereClause: Record<string, unknown>,\n entityName: string,\n schema: IContainEntitiesAndLinks<any, any>,\n path: string,\n): void => {\n for (const [key, value] of Object.entries(whereClause)) {\n if (key === 'or' || key === 'and') {\n if (Array.isArray(value)) {\n for (const clause of value) {\n if (typeof clause === 'object' && clause !== null) {\n validateWhereClause(\n clause as Record<string, unknown>,\n entityName,\n schema,\n `${path}.${key}[${clause}]`,\n );\n }\n }\n }\n continue;\n }\n\n if (key === 'id') {\n validateWhereClauseValue(\n value,\n 'id',\n new DataAttrDef('string', false, true),\n entityName,\n `${path}.id`,\n );\n continue;\n }\n\n if (key.includes('.')) {\n validateDotNotationAttribute(\n key,\n value,\n entityName,\n schema,\n `${path}.${key}`,\n );\n continue;\n }\n\n const entityDef = schema.entities[entityName];\n if (!entityDef) continue;\n\n const attrDef = entityDef.attrs[key];\n const linkDef = entityDef.links[key];\n\n if (!attrDef && !linkDef) {\n const availableAttrs = Object.keys(entityDef.attrs);\n const availableLinks = Object.keys(entityDef.links);\n throw new QueryValidationError(\n `Attribute or link '${key}' does not exist on entity '${entityName}'. Available attributes: ${availableAttrs.length > 0 ? availableAttrs.join(', ') : 'none'}. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n `${path}.${key}`,\n );\n }\n\n if (attrDef) {\n validateWhereClauseValue(\n value,\n key,\n attrDef,\n entityName,\n `${path}.${key}`,\n );\n } else if (linkDef) {\n // For links, we expect the value to be a string (ID of the linked entity)\n // Create a synthetic string attribute definition for validation\n if (typeof value === 'string' && !validateUUID(value)) {\n throw new QueryValidationError(\n `Invalid value for link '${key}' in entity '${entityName}'. Expected a UUID, but received: ${value}`,\n `${path}.${key}`,\n );\n }\n const syntheticAttrDef = new DataAttrDef('string', false, true);\n validateWhereClauseValue(\n value,\n key,\n syntheticAttrDef,\n entityName,\n `${path}.${key}`,\n );\n }\n }\n};\n\nconst validateDollarObject = (\n dollarObj: Record<string, unknown>,\n entityName: string,\n schema?: IContainEntitiesAndLinks<any, any> | null | undefined,\n path?: string,\n depth: number = 0,\n): void => {\n for (const key of Object.keys(dollarObj)) {\n if (!dollarSignKeys.includes(key)) {\n throw new QueryValidationError(\n `Invalid query parameter '${key}' in $ object. Valid parameters are: ${dollarSignKeys.join(', ')}. Found: ${key}`,\n path,\n );\n }\n }\n\n // Validate that pagination parameters are only used at top-level\n const paginationParams = [\n // 'limit', // only supported client side\n 'offset',\n 'before',\n 'beforeInclusive',\n 'after',\n 'afterInclusive',\n 'first',\n 'last',\n ];\n for (const param of paginationParams) {\n if (dollarObj[param] !== undefined && depth > 0) {\n throw new QueryValidationError(\n `'${param}' can only be used on top-level namespaces. It cannot be used in nested queries.`,\n path,\n );\n }\n }\n\n if (dollarObj.where && schema) {\n if (typeof dollarObj.where !== 'object' || dollarObj.where === null) {\n throw new QueryValidationError(\n `'where' clause must be an object in entity '${entityName}', but received: ${typeof dollarObj.where}`,\n path ? `${path}.where` : undefined,\n );\n }\n validateWhereClause(\n dollarObj.where as Record<string, unknown>,\n entityName,\n schema,\n path ? `${path}.where` : 'where',\n );\n }\n};\n\nconst validateEntityInQuery = (\n queryPart: Record<string, unknown>,\n entityName: string,\n schema: IContainEntitiesAndLinks<any, any> | null | undefined,\n path: string,\n depth: number = 0,\n): void => {\n if (!queryPart || typeof queryPart !== 'object') {\n throw new QueryValidationError(\n `Query part for entity '${entityName}' must be an object, but received: ${typeof queryPart}`,\n path,\n );\n }\n\n for (const key of Object.keys(queryPart)) {\n if (key !== '$') {\n // Validate link exists\n if (schema && !(key in schema.entities[entityName].links)) {\n const availableLinks = Object.keys(schema.entities[entityName].links);\n throw new QueryValidationError(\n `Link '${key}' does not exist on entity '${entityName}'. Available links: ${availableLinks.length > 0 ? availableLinks.join(', ') : 'none'}`,\n `${path}.${key}`,\n );\n }\n\n // Recursively validate nested query\n const nestedQuery = queryPart[key];\n if (typeof nestedQuery === 'object' && nestedQuery !== null) {\n const linkedEntityName =\n schema?.entities[entityName].links[key]?.entityName;\n if (linkedEntityName) {\n validateEntityInQuery(\n nestedQuery as Record<string, unknown>,\n linkedEntityName,\n schema,\n `${path}.${key}`,\n depth + 1,\n );\n }\n }\n } else {\n // Validate $ object\n const dollarObj = queryPart[key];\n if (typeof dollarObj !== 'object' || dollarObj === null) {\n throw new QueryValidationError(\n `Query parameter '$' must be an object in entity '${entityName}', but received: ${typeof dollarObj}`,\n `${path}.$`,\n );\n }\n\n validateDollarObject(\n dollarObj as Record<string, unknown>,\n entityName,\n schema,\n `${path}.$`,\n depth,\n );\n }\n }\n};\n\nexport const validateQuery = (\n q: unknown,\n schema?: IContainEntitiesAndLinks<any, any>,\n): void => {\n if (typeof q !== 'object' || q === null) {\n throw new QueryValidationError(\n `Query must be an object, but received: ${typeof q}${q === null ? ' (null)' : ''}`,\n );\n }\n\n if (Array.isArray(q)) {\n throw new QueryValidationError(\n `Query must be an object, but received: ${typeof q}`,\n );\n }\n\n const queryObj = q as Record<string, unknown>;\n\n for (const topLevelKey of Object.keys(queryObj)) {\n if (Array.isArray(q[topLevelKey])) {\n throw new QueryValidationError(\n `Query keys must be strings, but found key of type: ${typeof topLevelKey}`,\n topLevelKey,\n );\n }\n\n if (typeof topLevelKey !== 'string') {\n throw new QueryValidationError(\n `Query keys must be strings, but found key of type: ${typeof topLevelKey}`,\n topLevelKey,\n );\n }\n\n if (topLevelKey === '$$ruleParams') {\n continue;\n }\n\n // Check if the key is top level entity\n if (schema) {\n if (!schema.entities[topLevelKey]) {\n const availableEntities = Object.keys(schema.entities);\n throw new QueryValidationError(\n `Entity '${topLevelKey}' does not exist in schema. Available entities: ${availableEntities.length > 0 ? availableEntities.join(', ') : 'none'}`,\n topLevelKey,\n );\n }\n }\n\n validateEntityInQuery(\n queryObj[topLevelKey] as Record<string, unknown>,\n topLevelKey,\n schema,\n topLevelKey,\n 0, // Start at depth 0 for top-level entities\n );\n }\n};\n"]}
|
package/dist/standalone/index.js
CHANGED
|
@@ -3640,7 +3640,7 @@ function mt(n) {
|
|
|
3640
3640
|
link: t
|
|
3641
3641
|
}, e), {});
|
|
3642
3642
|
}
|
|
3643
|
-
const Hn = "v0.22.
|
|
3643
|
+
const Hn = "v0.22.164";
|
|
3644
3644
|
function Ni(n, e) {
|
|
3645
3645
|
return {
|
|
3646
3646
|
info: n ? (...t) => console.info(...t, e()) : () => {
|
|
@@ -3759,7 +3759,9 @@ const nn = [
|
|
|
3759
3759
|
"first",
|
|
3760
3760
|
"offset",
|
|
3761
3761
|
"after",
|
|
3762
|
+
"afterInclusive",
|
|
3762
3763
|
"before",
|
|
3764
|
+
"beforeInclusive",
|
|
3763
3765
|
"fields",
|
|
3764
3766
|
"aggregate"
|
|
3765
3767
|
], qi = (n) => n.valueType || "unknown", Jn = (n, e, t = !1) => {
|
|
@@ -3989,7 +3991,9 @@ const nn = [
|
|
|
3989
3991
|
// 'limit', // only supported client side
|
|
3990
3992
|
"offset",
|
|
3991
3993
|
"before",
|
|
3994
|
+
"beforeInclusive",
|
|
3992
3995
|
"after",
|
|
3996
|
+
"afterInclusive",
|
|
3993
3997
|
"first",
|
|
3994
3998
|
"last"
|
|
3995
3999
|
];
|