Comparing version 0.3.0-beta.0 to 0.3.0
# Changelog | ||
## v0.3.0 - 2021-06-25 | ||
API changes: | ||
- Introduce `params` parameter on `parse` which is required to properly parse an expression (@judofyr) | ||
GROQ compatibility fixes: | ||
- Preserve nulls in objects (@judofyr, #36) | ||
- Add support for arrays in `length` (@judofyr) | ||
- Use stable sorting in `order` (@judofyr) | ||
- Implement `string` function (@judofyr, @israelroldan) | ||
- Add support for arrays in `references` (@judofyr) | ||
- Implement `dateTime` (@judofyr) | ||
- Implement proper array traversal (@judofyr) | ||
- Implement `score` function (@judofyr) | ||
- Implement namespaced functions (@judofyr) | ||
- Implement `lower` and `upper` (@judofyr) | ||
- Implement `pt::text` (@judofyr) | ||
- Improve `match` behavior (@judofyr) | ||
Private changes: | ||
- Simplify and restructure AST (@judofyr) | ||
- Split up `SyntaxNode` into a special `ExprNode` represent what's returned from `parse` (@judofyr) | ||
Tooling changes: | ||
- Use `tap` for running tests since Jest is too slow (@judofyr) | ||
## v0.2.0 - 2020-10-20 | ||
@@ -4,0 +34,0 @@ |
@@ -7,4 +7,4 @@ import { Value } from '../values'; | ||
parent: Scope | null; | ||
timestamp: string; | ||
isHidden: boolean; | ||
context: Record<string, Value | undefined>; | ||
constructor(params: Record<string, unknown>, source: Value, value: Value, parent: Scope | null); | ||
@@ -11,0 +11,0 @@ createNested(value: Value): Scope; |
@@ -9,5 +9,2 @@ import * as NodeTypes from '../nodeTypes'; | ||
params?: Record<string, unknown>; | ||
timestamp?: Date; | ||
before?: any; | ||
after?: any; | ||
} |
@@ -6,3 +6,3 @@ import { GroqFunction, GroqPipeFunction } from './evaluator/functions'; | ||
/** A node which can be evaluated into a value. */ | ||
export declare type ExprNode = AccessAttributeNode | AccessElementNode | AndNode | ArrayNode | ArrayCoerceNode | AscNode | ContextNode | DerefNode | DescNode | EverythingNode | FilterNode | FlatMapNode | FuncCallNode | GroupNode | InRangeNode | MapNode | NegNode | NotNode | ObjectNode | OpCallNode | OrNode | ParameterNode | ParentNode | PipeFuncCallNode | PosNode | ProjectionNode | SelectNode | SliceNode | ThisNode | ValueNode; | ||
export declare type ExprNode = AccessAttributeNode | AccessElementNode | AndNode | ArrayNode | ArrayCoerceNode | AscNode | DerefNode | DescNode | EverythingNode | FilterNode | FlatMapNode | FuncCallNode | GroupNode | InRangeNode | MapNode | NegNode | NotNode | ObjectNode | OpCallNode | OrNode | ParameterNode | ParentNode | PipeFuncCallNode | PosNode | ProjectionNode | SelectNode | SliceNode | ThisNode | ValueNode; | ||
export declare type OpCall = '==' | '!=' | '>' | '>=' | '<' | '<=' | '+' | '-' | '*' | '/' | '%' | '**' | 'in' | 'match'; | ||
@@ -35,6 +35,2 @@ /** The base interface for SyntaxNode. */ | ||
} | ||
export interface ContextNode extends BaseNode { | ||
type: 'Context'; | ||
key: string; | ||
} | ||
export interface DerefNode extends BaseNode { | ||
@@ -41,0 +37,0 @@ type: 'Deref'; |
export interface ParseOptions { | ||
params?: Record<string, unknown>; | ||
mode?: 'normal' | 'delta'; | ||
} |
{ | ||
"name": "groq-js", | ||
"version": "0.3.0-beta.0", | ||
"version": "0.3.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "author": "Sanity.io <hello@sanity.io>", |
@@ -6,5 +6,3 @@ import * as NodeTypes from '../nodeTypes' | ||
import { | ||
DateTime, | ||
FALSE_VALUE, | ||
fromDateTime, | ||
fromJS, | ||
@@ -65,8 +63,2 @@ fromNumber, | ||
Context({key}, scope) { | ||
const value = scope.context[key] | ||
if (!value) throw new Error(`unknown value: ${key}`) | ||
return value | ||
}, | ||
Parent({n}, scope) { | ||
@@ -458,10 +450,3 @@ let current = scope | ||
const scope = new Scope(params, dataset, root, null) | ||
scope.context.timestamp = fromDateTime(new DateTime(options.timestamp || new Date())) | ||
if (options.before) { | ||
scope.context.before = fromJS(options.before) | ||
} | ||
if (options.after) { | ||
scope.context.after = fromJS(options.after) | ||
} | ||
return evaluate(tree, scope) | ||
} |
@@ -227,7 +227,3 @@ import type {ExprNode} from '../nodeTypes' | ||
global.now = async function now(args, scope) { | ||
const timestamp = scope.context.timestamp | ||
if (timestamp && timestamp.type === 'datetime') { | ||
return fromString(timestamp.data.toString()) | ||
} | ||
return NULL_VALUE | ||
return fromString(scope.timestamp) | ||
} | ||
@@ -234,0 +230,0 @@ global.now.arity = 0 |
@@ -6,25 +6,22 @@ import {NULL_VALUE, Value} from '../values' | ||
return blockText(value.data) | ||
} else if (value.isArray()) { | ||
const texts = await arrayText(value) | ||
if (texts.length > 0) { | ||
return texts.join('\n\n') | ||
} | ||
} | ||
let result = '' | ||
let first = true | ||
return null | ||
} | ||
if (value.isArray()) { | ||
for await (const block of value) { | ||
if (block.type !== 'object') continue | ||
async function arrayText(value: Value, result: string[] = []): Promise<string[]> { | ||
for await (const block of value) { | ||
if (block.type === 'object') { | ||
const text = blockText(block.data) | ||
if (text === null) continue | ||
if (!first) { | ||
result += '\n\n' | ||
} | ||
first = false | ||
result += text | ||
if (text !== null) result.push(text) | ||
} else if (block.isArray()) { | ||
await arrayText(block, result) | ||
} | ||
} | ||
// If there were no blocks => Return null. | ||
if (first) return null | ||
return result | ||
@@ -31,0 +28,0 @@ } |
@@ -8,5 +8,6 @@ import {Value} from '../values' | ||
public parent: Scope | null | ||
public timestamp: string | ||
public isHidden = false | ||
public context: Record<string, Value | undefined> | ||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types | ||
constructor(params: Record<string, unknown>, source: Value, value: Value, parent: Scope | null) { | ||
@@ -17,3 +18,3 @@ this.params = params | ||
this.parent = parent | ||
this.context = parent ? parent.context : {} | ||
this.timestamp = parent ? parent.timestamp : new Date().toISOString() | ||
} | ||
@@ -20,0 +21,0 @@ |
@@ -16,11 +16,2 @@ import * as NodeTypes from '../nodeTypes' | ||
params?: Record<string, unknown> | ||
// The timestamp returned from now() | ||
timestamp?: Date | ||
// The value returned from before() in Delta-mode | ||
before?: any | ||
// The value returned from after() in Delta-mode | ||
after?: any | ||
} |
@@ -19,3 +19,2 @@ import {GroqFunction, GroqPipeFunction} from './evaluator/functions' | ||
| AscNode | ||
| ContextNode | ||
| DerefNode | ||
@@ -93,7 +92,2 @@ | DescNode | ||
export interface ContextNode extends BaseNode { | ||
type: 'Context' | ||
key: string | ||
} | ||
export interface DerefNode extends BaseNode { | ||
@@ -100,0 +94,0 @@ type: 'Deref' |
@@ -352,11 +352,2 @@ /* eslint-disable camelcase */ | ||
if (namespace === 'global' && (name === 'before' || name === 'after')) { | ||
if (p.parseOptions.mode === 'delta') { | ||
return { | ||
type: 'Context', | ||
key: name, | ||
} | ||
} | ||
} | ||
if (namespace === 'global' && name === 'boost' && !p.allowBoost) | ||
@@ -363,0 +354,0 @@ throw new GroqQueryError('unexpected boost') |
export interface ParseOptions { | ||
params?: Record<string, unknown> | ||
mode?: 'normal' | 'delta' | ||
} |
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 too big to display
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
2210872
20144