Comparing version 1.8.0 to 1.9.0
@@ -143,3 +143,3 @@ export declare interface AccessAttributeNode extends BaseNode { | ||
name: string | ||
/** ttributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
/** Attributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
attributes: Record<string, ObjectAttribute> | ||
@@ -146,0 +146,0 @@ } |
@@ -143,3 +143,3 @@ export declare interface AccessAttributeNode extends BaseNode { | ||
name: string | ||
/** ttributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
/** Attributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
attributes: Record<string, ObjectAttribute> | ||
@@ -146,0 +146,0 @@ } |
{ | ||
"name": "groq-js", | ||
"version": "1.8.0", | ||
"version": "1.9.0", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "sanity", |
@@ -56,2 +56,7 @@ import type {FuncCallNode} from '../nodeTypes' | ||
} | ||
case 'global.references': { | ||
return {type: 'boolean'} | ||
} | ||
case 'global.string': { | ||
@@ -77,2 +82,63 @@ const arg = walk({node: node.args[0], scope}) | ||
case 'math.sum': { | ||
const values = walk({node: node.args[0], scope}) | ||
// use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union | ||
return mapConcrete(values, scope, (node) => { | ||
// Aggregate functions can only be applied to arrays | ||
if (node.type === 'array') { | ||
// Resolve the concrete type of the array elements | ||
return mapConcrete(node.of, scope, (node) => { | ||
// Math functions can only be applied to numbers, but we should also ignore nulls | ||
if (node.type === 'number' || node.type === 'null') { | ||
return {type: 'number'} | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
case 'math.avg': { | ||
const values = walk({node: node.args[0], scope}) | ||
// use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union | ||
return mapConcrete(values, scope, (node) => { | ||
// Aggregate functions can only be applied to arrays | ||
if (node.type === 'array') { | ||
// Resolve the concrete type of the array elements | ||
return mapConcrete(node.of, scope, (node) => { | ||
// Math functions can only be applied to numbers | ||
if (node.type === 'number') { | ||
return {type: 'number'} | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
case 'math.max': | ||
case 'math.min': { | ||
const values = walk({node: node.args[0], scope}) | ||
// use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union | ||
return mapConcrete(values, scope, (node) => { | ||
// Aggregate functions can only be applied to arrays | ||
if (node.type === 'array') { | ||
// Resolve the concrete type of the array elements | ||
return mapConcrete(node.of, scope, (node) => { | ||
// Math functions can only be applied to numbers | ||
if (node.type === 'number') { | ||
return node | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
return {type: 'null'} | ||
}) | ||
} | ||
case 'pt.text': { | ||
@@ -86,2 +152,36 @@ if (node.args.length === 0) { | ||
} | ||
case 'string.startsWith': { | ||
const strTypeNode = walk({node: node.args[0], scope}) | ||
const prefixTypeNode = walk({node: node.args[1], scope}) | ||
return mapConcrete(strTypeNode, scope, (strNode) => { | ||
if (strNode.type !== 'string') { | ||
return {type: 'null'} | ||
} | ||
return mapConcrete(prefixTypeNode, scope, (prefixNode) => { | ||
if (prefixNode.type !== 'string') { | ||
return {type: 'null'} | ||
} | ||
return {type: 'boolean'} | ||
}) | ||
}) | ||
} | ||
case 'string.split': { | ||
const strTypeNode = walk({node: node.args[0], scope}) | ||
const sepTypeNode = walk({node: node.args[1], scope}) | ||
return mapConcrete(strTypeNode, scope, (strNode) => { | ||
if (strNode.type !== 'string') { | ||
return {type: 'null'} | ||
} | ||
return mapConcrete(sepTypeNode, scope, (sepNode) => { | ||
if (sepNode.type !== 'string') { | ||
return {type: 'null'} | ||
} | ||
return {type: 'array', of: {type: 'string'}} | ||
}) | ||
}) | ||
} | ||
default: { | ||
@@ -88,0 +188,0 @@ return {type: 'unknown'} |
@@ -9,3 +9,3 @@ import type {TypeNode} from './types' | ||
if (field.value !== undefined) { | ||
return `${field.type}:${field.value}` | ||
return `${field.type}(${field.value})` | ||
} | ||
@@ -21,17 +21,17 @@ return `${field.type}` | ||
case 'array': { | ||
return `${field.type}:${hashField(field.of)}` | ||
return `${field.type}(${hashField(field.of)})` | ||
} | ||
case 'object': { | ||
return `${field.type}:ref-${field.dereferencesTo}:${Object.entries(field.attributes) | ||
return `${field.type}:(${Object.entries(field.attributes) | ||
.map(([key, value]) => `${key}:${hashField(value.value)}`) | ||
.join(',')}:${field.rest ? hashField(field.rest) : 'no-rest'}` | ||
.join(',')}):ref-${field.dereferencesTo}:${field.rest ? hashField(field.rest) : 'no-rest'}` | ||
} | ||
case 'union': { | ||
return `${field.type}:${field.of.map(hashField).join(',')}` | ||
return `${field.type}(${field.of.map(hashField).join(',')})` | ||
} | ||
case 'inline': { | ||
return `${field.type}:${field.name}` | ||
return `${field.type}(${field.name})` | ||
} | ||
@@ -38,0 +38,0 @@ |
@@ -199,9 +199,6 @@ import debug from 'debug' | ||
const rhs = walk({node: node.right, scope}) | ||
return mapUnion(lhs, (left) => | ||
return mapConcrete(lhs, scope, (left) => | ||
// eslint-disable-next-line complexity | ||
mapUnion(rhs, (right) => { | ||
mapConcrete(rhs, scope, (right) => { | ||
$trace('opCallNode "%s" %O', node.op, {left, right}) | ||
if (left.type === 'unknown' || right.type === 'unknown') { | ||
return {type: 'unknown'} satisfies UnknownTypeNode | ||
} | ||
@@ -1080,12 +1077,2 @@ switch (node.op) { | ||
function mapUnion(node: TypeNode, mapper: (node: TypeNode) => TypeNode): TypeNode { | ||
if (node.type === 'union') { | ||
return optimizeUnions({ | ||
type: 'union', | ||
of: node.of.map((subNode) => mapUnion(subNode, mapper)), | ||
}) | ||
} | ||
return mapper(node) | ||
} | ||
function mapArray( | ||
@@ -1092,0 +1079,0 @@ node: TypeNode, |
@@ -65,11 +65,12 @@ import {optimizeUnions} from './optimizations' | ||
if (node.type === 'union') { | ||
return { | ||
type: 'union', | ||
of: [...node.of, {type: 'null'}], | ||
} satisfies UnionTypeNode | ||
return unionOf(...node.of, {type: 'null'}) | ||
} | ||
return unionOf(node, {type: 'null'}) | ||
} | ||
export function unionOf(...nodes: TypeNode[]): UnionTypeNode { | ||
return { | ||
type: 'union', | ||
of: [node, {type: 'null'}], | ||
of: nodes, | ||
} satisfies UnionTypeNode | ||
@@ -76,0 +77,0 @@ } |
@@ -7,3 +7,3 @@ /** Represents a document structure with a fixed type 'document', a name, and a collection of attributes.*/ | ||
name: string | ||
/** ttributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
/** Attributes is defined by a key-value pair where the key is a string and the value is an ObjectAttribute. */ | ||
attributes: Record<string, ObjectAttribute> | ||
@@ -10,0 +10,0 @@ } |
Sorry, the diff of this file is not supported yet
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
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
902033
12680