Comparing version 1.5.0-canary.1 to 1.5.0-canary.2
# API | ||
GROQ-JS exposes two functions: | ||
GROQ-JS exposes three functions: | ||
```typescript | ||
import {parse, evaluate} from 'groq-js' | ||
import {parse, evaluate, typeEvaluate} from 'groq-js' | ||
``` | ||
@@ -8,0 +8,0 @@ |
@@ -45,4 +45,7 @@ export declare interface AccessAttributeNode extends BaseNode { | ||
/** Describes a type node for array values. */ | ||
export declare interface ArrayTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'array' */ | ||
type: 'array' | ||
/** the type of the array elements */ | ||
of: T | ||
@@ -63,4 +66,7 @@ } | ||
/** Describes a type node for boolean values, optionally including a value. If a value is provided it will always be the given boolean value. */ | ||
export declare interface BooleanTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'boolean' */ | ||
type: 'boolean' | ||
/** an optional value of the boolean, if provided it will always be the given boolean value */ | ||
value?: boolean | ||
@@ -133,5 +139,9 @@ } | ||
/** Represents a document structure with a fixed type 'document', a name, and a collection of attributes.*/ | ||
export declare interface DocumentSchemaType { | ||
/** can be used to identify the type of the node, in this case it's always 'document' */ | ||
type: 'document' | ||
/** the name of the document */ | ||
name: string | ||
/** ttributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
attributes: Record<string, ObjectAttribute> | ||
@@ -257,4 +267,7 @@ } | ||
/** Describes a type node for inline values, including a name that references another type. */ | ||
export declare interface InlineTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'inline' */ | ||
type: 'inline' | ||
/** the name of the referenced type */ | ||
name: string | ||
@@ -287,3 +300,5 @@ } | ||
/** Describes a type node for null values, always being the null value. */ | ||
export declare interface NullTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'null' */ | ||
type: 'null' | ||
@@ -294,4 +309,7 @@ } | ||
/** Describes a type node for number values, optionally including a value. If a value is provided it will always be the given numeric value.*/ | ||
export declare interface NumberTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'number' */ | ||
type: 'number' | ||
/** an optional value of the number, if provided it will always be the given numeric value */ | ||
value?: number | ||
@@ -302,5 +320,9 @@ } | ||
/** Describes a type node for object attributes, including a type and an optional flag for being optional. */ | ||
export declare interface ObjectAttribute<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'objectAttribute' */ | ||
type: 'objectAttribute' | ||
/** the type of the attribute */ | ||
value: T | ||
/** an optional flag if the attribute is optional set on the object */ | ||
optional?: boolean | ||
@@ -336,5 +358,15 @@ } | ||
/** | ||
* Describes a type node for object values, including a collection of attributes and an optional rest value. | ||
* The rest value can be another ObjectTypeNode, an UnknownTypeNode, or an InlineTypeNode. | ||
* If the rest value is an ObjectTypeNode, it means that the object can have additional attributes. | ||
* If the rest value is an UnknownTypeNode, the entire object is unknown. | ||
* If the rest value is an InlineTypeNode, it means that the object has additional attributes from the referenced type. | ||
*/ | ||
export declare interface ObjectTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'object' */ | ||
type: 'object' | ||
/** a collection of attributes */ | ||
attributes: Record<string, ObjectAttribute<T>> | ||
/** an optional rest value */ | ||
rest?: ObjectTypeNode | UnknownTypeNode | InlineTypeNode | ||
@@ -419,2 +451,3 @@ dereferencesTo?: string | ||
/** Union of any primitive type nodes. */ | ||
export declare type PrimitiveTypeNode = StringTypeNode | NumberTypeNode | BooleanTypeNode | ||
@@ -428,2 +461,3 @@ | ||
/** A schema consisting of a list of Document or TypeDeclaration items, allowing for complex type definitions. */ | ||
export declare type SchemaType = (DocumentSchemaType | TypeDeclarationSchemaType)[] | ||
@@ -495,4 +529,7 @@ | ||
/** Describes a type node for string values, optionally including a value. If a value is provided it will always be the given string value. */ | ||
export declare interface StringTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'string' */ | ||
type: 'string' | ||
/** an optional value of the string, if provided it will always be the given string value */ | ||
value?: string | ||
@@ -519,5 +556,9 @@ } | ||
/** Defines a type declaration with a specific name and a value that describes the structure of the type using a TypeNode. */ | ||
export declare interface TypeDeclarationSchemaType { | ||
/** can be used to identify the type of the node, in this case it's always 'type' */ | ||
type: 'type' | ||
/** the name of the type */ | ||
name: string | ||
/** the value that describes the structure of the type */ | ||
value: TypeNode | ||
@@ -536,2 +577,3 @@ } | ||
/** All possible type nodes. */ | ||
export declare type TypeNode = | ||
@@ -548,8 +590,13 @@ | ObjectTypeNode | ||
/** Describes a type node for union values. */ | ||
export declare interface UnionTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'union' */ | ||
type: 'union' | ||
/** a collection of types */ | ||
of: T[] | ||
} | ||
/** Describes a type node for unknown value. */ | ||
export declare type UnknownTypeNode = { | ||
/** can be used to identify the type of the node, in this case it's always 'unknown' */ | ||
type: 'unknown' | ||
@@ -556,0 +603,0 @@ } |
{ | ||
"name": "groq-js", | ||
"version": "1.5.0-canary.1", | ||
"version": "1.5.0-canary.2", | ||
"keywords": [ | ||
@@ -83,8 +83,8 @@ "sanity", | ||
"devDependencies": { | ||
"@sanity/pkg-utils": "^4.3.1", | ||
"@sanity/pkg-utils": "^5.0.0", | ||
"@sanity/semantic-release-preset": "^4.1.7", | ||
"@types/debug": "^4.1.12", | ||
"@types/tap": "^15.0.11", | ||
"@typescript-eslint/eslint-plugin": "^7.1.0", | ||
"@typescript-eslint/parser": "^7.1.0", | ||
"@typescript-eslint/eslint-plugin": "^7.1.1", | ||
"@typescript-eslint/parser": "^7.1.1", | ||
"eslint": "^8.57.0", | ||
@@ -102,3 +102,3 @@ "eslint-config-prettier": "^9.1.0", | ||
"tsx": "^4.7.1", | ||
"typescript": "^5.3.3" | ||
"typescript": "^5.4.2" | ||
}, | ||
@@ -105,0 +105,0 @@ "engines": { |
@@ -27,2 +27,3 @@ import debug from 'debug' | ||
SelectNode, | ||
SliceNode, | ||
ValueNode, | ||
@@ -48,2 +49,3 @@ } from '../nodeTypes' | ||
} from './types' | ||
import {nullUnion} from './typeHelpers' | ||
@@ -53,3 +55,3 @@ const $trace = debug('typeEvaluator:evaluate:trace') | ||
// log to stdout | ||
const $debug = debug('typeEvaluator:evaluate::debug') | ||
const $debug = debug('typeEvaluator:evaluate:debug') | ||
// log to stdout | ||
@@ -68,2 +70,3 @@ $debug.log = console.log.bind(console) // eslint-disable-line no-console | ||
export function typeEvaluate(ast: ExprNode, schema: Schema): TypeNode { | ||
$debug('evaluateQueryType.ast %O', ast) | ||
const parsed = walk({ | ||
@@ -76,3 +79,3 @@ node: ast, | ||
const optimized = optimizeUnions(parsed) | ||
$trace('evaluateQueryType.optimized %O', optimized) | ||
$debug('evaluateQueryType.optimized %O', optimized) | ||
@@ -140,3 +143,3 @@ return optimized | ||
if (attr.type === 'ObjectAttributeValue') { | ||
const field = optimizeUnions(walk({node: attr.value, scope})) | ||
const field = walk({node: attr.value, scope}) | ||
attributes[attr.name] = { | ||
@@ -185,157 +188,162 @@ type: 'objectAttribute', | ||
// eslint-disable-next-line complexity, max-statements | ||
// eslint-disable-next-line max-statements | ||
function handleOpCallNode(node: OpCallNode, scope: Scope): TypeNode { | ||
const left = walk({node: node.left, scope}) | ||
const right = walk({node: node.right, scope}) | ||
$trace('opCallNode "%s" %O', node.op, {left, right}) | ||
if (left.type === 'unknown' || right.type === 'unknown') { | ||
return {type: 'unknown'} satisfies UnknownTypeNode | ||
} | ||
switch (node.op) { | ||
case '==': | ||
case '!=': { | ||
return { | ||
type: 'boolean', | ||
value: resolveCondition(node, scope), | ||
} satisfies BooleanTypeNode | ||
} | ||
case '>': | ||
case '>=': | ||
case '<': | ||
case '<=': { | ||
if (left.type !== right.type) { | ||
return {type: 'null'} | ||
const lhs = walk({node: node.left, scope}) | ||
const rhs = walk({node: node.right, scope}) | ||
return mapUnion(lhs, (left) => | ||
// eslint-disable-next-line complexity | ||
mapUnion(rhs, (right) => { | ||
$trace('opCallNode "%s" %O', node.op, {left, right}) | ||
if (left.type === 'unknown' || right.type === 'unknown') { | ||
return {type: 'unknown'} satisfies UnknownTypeNode | ||
} | ||
if (isPrimitiveTypeNode(left)) { | ||
const resolved = resolveCondition(node, scope) | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
return {type: 'null'} | ||
} | ||
case 'in': { | ||
if (right.type === 'array') { | ||
const resolved = resolveCondition(node, scope) | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
return {type: 'null'} | ||
} | ||
case 'match': { | ||
const resolved = resolveCondition(node, scope) | ||
switch (node.op) { | ||
case '==': | ||
case '!=': { | ||
return { | ||
type: 'boolean', | ||
value: resolveCondition(node, scope), | ||
} satisfies BooleanTypeNode | ||
} | ||
case '>': | ||
case '>=': | ||
case '<': | ||
case '<=': { | ||
if (left.type !== right.type) { | ||
return {type: 'null'} | ||
} | ||
if (isPrimitiveTypeNode(left)) { | ||
const resolved = resolveCondition(node, scope) | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
case '+': { | ||
if (left.type === 'string' && right.type === 'string') { | ||
return { | ||
type: 'string', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value + right.value | ||
: undefined, | ||
return {type: 'null'} | ||
} | ||
} | ||
case 'in': { | ||
if (right.type === 'array') { | ||
const resolved = resolveCondition(node, scope) | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
return {type: 'null'} | ||
} | ||
case 'match': { | ||
const resolved = resolveCondition(node, scope) | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value + right.value | ||
: undefined, | ||
return { | ||
type: 'boolean', | ||
value: resolved, | ||
} satisfies BooleanTypeNode | ||
} | ||
} | ||
if (left.type === 'array' && right.type === 'array') { | ||
return { | ||
type: 'array', | ||
of: { | ||
type: 'union', | ||
of: [left.of, right.of], | ||
}, | ||
} satisfies ArrayTypeNode | ||
} | ||
if (left.type === 'object' && right.type === 'object') { | ||
return { | ||
type: 'object', | ||
attributes: {...left.attributes, ...right.attributes}, | ||
} satisfies ObjectTypeNode | ||
} | ||
return {type: 'null'} | ||
} | ||
case '-': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value - right.value | ||
: undefined, | ||
case '+': { | ||
if (left.type === 'string' && right.type === 'string') { | ||
return { | ||
type: 'string', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value + right.value | ||
: undefined, | ||
} | ||
} | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value + right.value | ||
: undefined, | ||
} | ||
} | ||
if (left.type === 'array' && right.type === 'array') { | ||
return { | ||
type: 'array', | ||
of: { | ||
type: 'union', | ||
of: [left.of, right.of], | ||
}, | ||
} satisfies ArrayTypeNode | ||
} | ||
if (left.type === 'object' && right.type === 'object') { | ||
return { | ||
type: 'object', | ||
attributes: {...left.attributes, ...right.attributes}, | ||
} satisfies ObjectTypeNode | ||
} | ||
return {type: 'null'} | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
case '*': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value * right.value | ||
: undefined, | ||
case '-': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value - right.value | ||
: undefined, | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
case '/': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value / right.value | ||
: undefined, | ||
case '*': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value * right.value | ||
: undefined, | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
case '**': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value ** right.value | ||
: undefined, | ||
case '/': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value / right.value | ||
: undefined, | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
case '%': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value % right.value | ||
: undefined, | ||
case '**': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value ** right.value | ||
: undefined, | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
case '%': { | ||
if (left.type === 'number' && right.type === 'number') { | ||
return { | ||
type: 'number', | ||
value: | ||
left.value !== undefined && right.value !== undefined | ||
? left.value % right.value | ||
: undefined, | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
default: { | ||
return { | ||
type: 'unknown', | ||
} satisfies UnknownTypeNode | ||
} | ||
} | ||
return {type: 'null'} | ||
} | ||
default: { | ||
return { | ||
type: 'unknown', | ||
} satisfies UnknownTypeNode | ||
} | ||
} | ||
}), | ||
) | ||
} | ||
@@ -397,13 +405,25 @@ | ||
if (base.of.type === 'union') { | ||
const value = walk({node: node.expr, scope: scope.createHidden(base.of.of)}) // re use the current parent, this is a "sub" scope | ||
$trace('map.expr %O', value) | ||
// if this is an inline type we resolve it since we want to map over the actual value. | ||
return maybeResolveInline(base.of, scope, (base) => { | ||
if (base.type === 'union') { | ||
const value = walk({node: node.expr, scope: scope.createHidden(base.of)}) // re use the current parent, this is a "sub" scope | ||
$trace('map.expr %O', value) | ||
return { | ||
type: 'array', | ||
of: value, | ||
} satisfies ArrayTypeNode | ||
} | ||
return { | ||
type: 'array', | ||
of: value, | ||
} satisfies ArrayTypeNode | ||
} | ||
if (base.type === 'object') { | ||
const value = walk({node: node.expr, scope: scope.createHidden([base])}) // re use the current parent, this is a "sub" scope | ||
$trace('map.expr %O', value) | ||
return base | ||
return { | ||
type: 'array', | ||
of: value, | ||
} satisfies ArrayTypeNode | ||
} | ||
return {type: 'unknown'} satisfies UnknownTypeNode | ||
}) | ||
}) | ||
@@ -438,3 +458,2 @@ } | ||
$trace('projection.base %O', base) | ||
$trace('projection.scope %O', scope.value) | ||
@@ -544,2 +563,6 @@ if (base.type === 'unknown' || base.type === 'null') { | ||
$debug(`accessAttribute.attribute found ${node.name} %O`, attribute) | ||
if (attribute.optional) { | ||
return nullUnion(attribute.value) | ||
} | ||
return attribute.value | ||
@@ -639,2 +662,15 @@ } | ||
function handleSlice(node: SliceNode, scope: Scope): TypeNode { | ||
$trace('slice.node %O', node) | ||
const base = walk({node: node.base, scope}) | ||
return mapUnion(base, (base) => { | ||
if (base.type !== 'array') { | ||
return {type: 'null'} satisfies NullTypeNode | ||
} | ||
return base | ||
}) | ||
} | ||
function handleParentNode({n}: ParentNode, scope: Scope): TypeNode { | ||
@@ -791,2 +827,5 @@ let current: Scope = scope | ||
case 'Slice': { | ||
return handleSlice(node, scope) | ||
} | ||
// everything else | ||
@@ -1119,1 +1158,13 @@ case 'Asc': | ||
} | ||
function maybeResolveInline( | ||
node: TypeNode, | ||
scope: Scope, | ||
mapper: (node: TypeNode) => TypeNode, | ||
): TypeNode { | ||
if (node.type === 'inline') { | ||
const resolvedInline = scope.context.lookupTypeDeclaration(node) | ||
return mapper(resolvedInline) | ||
} | ||
return mapper(node) | ||
} |
@@ -1,2 +0,2 @@ | ||
import {ObjectAttribute, ObjectTypeNode} from './types' | ||
import type {ObjectAttribute, ObjectTypeNode, TypeNode, UnionTypeNode} from './types' | ||
@@ -50,1 +50,15 @@ /** | ||
} | ||
export function nullUnion(node: TypeNode): UnionTypeNode { | ||
if (node.type === 'union') { | ||
return { | ||
type: 'union', | ||
of: [...node.of, {type: 'null'}], | ||
} satisfies UnionTypeNode | ||
} | ||
return { | ||
type: 'union', | ||
of: [node, {type: 'null'}], | ||
} satisfies UnionTypeNode | ||
} |
@@ -0,65 +1,116 @@ | ||
/** Represents a document structure with a fixed type 'document', a name, and a collection of attributes.*/ | ||
export interface Document { | ||
/** can be used to identify the type of the node, in this case it's always 'document' */ | ||
type: 'document' | ||
/** the name of the document */ | ||
name: string | ||
/** ttributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
attributes: Record<string, ObjectAttribute> | ||
} | ||
/** Defines a type declaration with a specific name and a value that describes the structure of the type using a TypeNode. */ | ||
export interface TypeDeclaration { | ||
/** can be used to identify the type of the node, in this case it's always 'type' */ | ||
type: 'type' | ||
/** the name of the type */ | ||
name: string | ||
/** the value that describes the structure of the type */ | ||
value: TypeNode | ||
} | ||
/** A schema consisting of a list of Document or TypeDeclaration items, allowing for complex type definitions. */ | ||
export type Schema = (Document | TypeDeclaration)[] | ||
/** Describes a type node for string values, optionally including a value. If a value is provided it will always be the given string value. */ | ||
export interface StringTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'string' */ | ||
type: 'string' | ||
/** an optional value of the string, if provided it will always be the given string value */ | ||
value?: string | ||
} | ||
/** Describes a type node for number values, optionally including a value. If a value is provided it will always be the given numeric value.*/ | ||
export interface NumberTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'number' */ | ||
type: 'number' | ||
/** an optional value of the number, if provided it will always be the given numeric value */ | ||
value?: number | ||
} | ||
/** Describes a type node for boolean values, optionally including a value. If a value is provided it will always be the given boolean value. */ | ||
export interface BooleanTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'boolean' */ | ||
type: 'boolean' | ||
/** an optional value of the boolean, if provided it will always be the given boolean value */ | ||
value?: boolean | ||
} | ||
/** Union of any primitive type nodes. */ | ||
export type PrimitiveTypeNode = StringTypeNode | NumberTypeNode | BooleanTypeNode | ||
/** Describes a type node for null values, always being the null value. */ | ||
export interface NullTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'null' */ | ||
type: 'null' | ||
} | ||
// InlineTypeNode inlines a type from a type declaration | ||
/** Describes a type node for inline values, including a name that references another type. */ | ||
export interface InlineTypeNode { | ||
/** can be used to identify the type of the node, in this case it's always 'inline' */ | ||
type: 'inline' | ||
/** the name of the referenced type */ | ||
name: string | ||
} | ||
/** | ||
* Describes a type node for object values, including a collection of attributes and an optional rest value. | ||
* The rest value can be another ObjectTypeNode, an UnknownTypeNode, or an InlineTypeNode. | ||
* If the rest value is an ObjectTypeNode, it means that the object can have additional attributes. | ||
* If the rest value is an UnknownTypeNode, the entire object is unknown. | ||
* If the rest value is an InlineTypeNode, it means that the object has additional attributes from the referenced type. | ||
*/ | ||
export interface ObjectTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'object' */ | ||
type: 'object' | ||
/** a collection of attributes */ | ||
attributes: Record<string, ObjectAttribute<T>> | ||
/** an optional rest value */ | ||
rest?: ObjectTypeNode | UnknownTypeNode | InlineTypeNode | ||
dereferencesTo?: string // the name of the document this object dereferences to | ||
/* an optional reference to the document this object dereferences to */ | ||
dereferencesTo?: string | ||
} | ||
/** Describes a type node for object attributes, including a type and an optional flag for being optional. */ | ||
export interface ObjectAttribute<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'objectAttribute' */ | ||
type: 'objectAttribute' | ||
/** the type of the attribute */ | ||
value: T | ||
/** an optional flag if the attribute is optional set on the object */ | ||
optional?: boolean | ||
} | ||
/** Describes a type node for union values. */ | ||
export interface UnionTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'union' */ | ||
type: 'union' | ||
/** a collection of types */ | ||
of: T[] | ||
} | ||
/** Describes a type node for array values. */ | ||
export interface ArrayTypeNode<T extends TypeNode = TypeNode> { | ||
/** can be used to identify the type of the node, in this case it's always 'array' */ | ||
type: 'array' | ||
/** the type of the array elements */ | ||
of: T | ||
} | ||
export type UnknownTypeNode = {type: 'unknown'} | ||
/** Describes a type node for unknown value. */ | ||
export type UnknownTypeNode = { | ||
/** can be used to identify the type of the node, in this case it's always 'unknown' */ | ||
type: 'unknown' | ||
} | ||
/** All possible type nodes. */ | ||
export type TypeNode = | ||
@@ -66,0 +117,0 @@ | ObjectTypeNode |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
832179
11867
2