Skip to content

Commit

Permalink
WIP: pair expression with approriate schema
Browse files Browse the repository at this point in the history
  • Loading branch information
bkeepers committed Jul 14, 2023
1 parent 82cf6ac commit 2390157
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 18 deletions.
2 changes: 1 addition & 1 deletion lib/flipper/gates/expression.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def open?(context)
end

def protects?(thing)
thing.is_a?(Flipper::Expression) || thing.is_a?(Hash)
thing.is_a?(Flipper::Expression) || thing.is_a?(Flipper::Expression::Constant) || thing.is_a?(Hash)
end

def wrap(thing)
Expand Down
8 changes: 8 additions & 0 deletions packages/expressions/examples/Equal.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
"expression": { "Equal": ["a", "a"] },
"result": { "enum": [true] }
},
{
"expression": { "Equal": [null, null] },
"result": { "enum": [true] }
},
{
"expression": { "Equal": [null, false] },
"result": { "enum": [false] }
},
{
"expression": { "Equal": [1, 2] },
"result": { "enum": [false] }
Expand Down
5 changes: 4 additions & 1 deletion packages/expressions/examples/expressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
{
"expression": 1.1,
"result": { "enum": [1.1] }
},
{
"expression": null,
"result": { "enum": [null] }
}
],
"invalid": [
null,
{},
[]
]
Expand Down
2 changes: 1 addition & 1 deletion packages/expressions/lib/constant.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Schema } from './schemas'
//
// Implements the same interface as Expression
export class Constant {
constructor (value, { id = uuidv4(), schema = Schema.resolve('#/definitions/constant') } = {}) {
constructor (value, { id = uuidv4(), schema = Schema.resolve('#') } = {}) {
this.value = value
this.id = id
this.schema = schema
Expand Down
25 changes: 15 additions & 10 deletions packages/expressions/lib/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ import { Constant } from './constant'
import { Schema } from './schemas'

function toArray (arg) {
if (Array.isArray(arg)) {
return arg
} else if (arg === null) {
return []
} else {
return [arg]
}
if (Array.isArray(arg)) return arg
if (arg === null) return []
return [arg]
}

// Simple model to transform this: `{ All: [{ Boolean: [true] }]`
Expand All @@ -20,14 +16,14 @@ export class Expression {
return expression
}

if (typeof expression === 'object') {
if (['number', 'string', 'boolean'].includes(typeof expression) || expression === null) {
return new Constant(expression, { schema })
} else if (typeof expression === 'object') {
if (Object.keys(expression).length !== 1) {
throw new TypeError(`Invalid expression: ${JSON.stringify(expression)}`)
}
const name = Object.keys(expression)[0]
return new Expression({ name, args: expression[name] })
} else if (['number', 'string', 'boolean'].includes(typeof expression)) {
return new Constant(expression, { schema })
} else {
throw new TypeError(`Invalid expression: ${JSON.stringify(expression)}`)
}
Expand All @@ -44,6 +40,15 @@ export class Expression {
return new Expression({ id, name, args })
}

fill () {
const length = Math.max(this.schema.minItems ?? 0, this.args.length)
this.args = Array.from({ ...this.args, length }, (arg, i) => {
return Expression.build(arg ?? null, this.schema.arrayItem(i))
})

return this
}

get value () {
return { [this.name]: this.args.map(arg => arg.value) }
}
Expand Down
3 changes: 3 additions & 0 deletions packages/expressions/schemas/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
"title": "Boolean",
"type": "boolean",
"enum": [true, false]
},
{
"type": "null"
}
]
},
Expand Down
4 changes: 2 additions & 2 deletions packages/expressions/test/constant.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Constant, Schema } from '../lib'

describe('Constant', () => {
describe('schema', () => {
test('defaults to Constant schema', () => {
test('defaults to expression schema', () => {
expect(new Constant('string').schema.title).toEqual('Constant')
})

Expand All @@ -26,7 +26,7 @@ describe('Constant', () => {

test('returns false for invalid value', () => {
expect(new Constant(['array']).validate().valid).toBe(false)
expect(new Constant({Now: []}).validate().valid).toBe(false)
expect(new Constant({ Now: [] }).validate().valid).toBe(false)
})

test('uses provided schema', () => {
Expand Down
7 changes: 6 additions & 1 deletion packages/expressions/test/expression.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@ describe('Expression', () => {
expect(expression.args[1].schema).toEqual(schema.items[1])
})

test('sets schema for constant', () => {
const expression = Expression.build(false)
expect(expression.schema.$id).toEqual(Schema.resolve('#').$id)
})

test('each subexpression uses its own schema', () => {
const expression = Expression.build({ GreaterThan: [ { Now: [] }, { Property: ['released_at'] } ] })
const expression = Expression.build({ GreaterThan: [{ Now: [] }, { Property: ['released_at'] }] })
expect(expression.schema).toEqual(Schema.resolve('GreaterThan.schema.json'))
expect(expression.args[0].schema).toEqual(Schema.resolve('Now.schema.json'))
expect(expression.args[1].schema).toEqual(Schema.resolve('Property.schema.json'))
Expand Down
4 changes: 2 additions & 2 deletions packages/expressions/test/schemas.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ describe('schema.json', () => {
describe('resolveAnyOf', () => {
test('returns nested anyOf', () => {
const ref = Schema.resolve('#')
expect(ref.resolveAnyOf()).toHaveLength(4)
expect(ref.resolveAnyOf()).toHaveLength(5)
})

test('returns array of schemas', () => {
const ref = Schema.resolve('#/definitions/constant')
expect(ref.resolveAnyOf()).toHaveLength(3)
expect(ref.resolveAnyOf()).toHaveLength(4)
expect(ref.resolveAnyOf()).toEqual(ref.anyOf)
})
})
Expand Down

0 comments on commit 2390157

Please sign in to comment.