Skip to content

Commit

Permalink
feat: Strip external schemas from standalone compiled code (#704)
Browse files Browse the repository at this point in the history
  • Loading branch information
remidewitte authored May 21, 2024
1 parent c873689 commit a2e4ef9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 9 deletions.
6 changes: 5 additions & 1 deletion lib/standalone.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,15 @@ function buildStandaloneCode (contextFunc, context, serializer, validator) {
ajvDependencyCode += 'const validator = null\n'
}

// Don't need to keep external schemas once compiled
// validatorState will hold external schemas if it needs them
const { schema, ...serializerState } = serializer.getState()

return `
'use strict'
const Serializer = require('fast-json-stringify/lib/serializer')
const serializerState = ${JSON.stringify(serializer.getState())}
const serializerState = ${JSON.stringify(serializerState)}
const serializer = Serializer.restoreFromState(serializerState)
${ajvDependencyCode}
Expand Down
111 changes: 103 additions & 8 deletions test/standalone-mode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ test('activate standalone mode', async (t) => {
t.type(code, 'string')
t.equal(code.indexOf('ajv'), -1)

const destionation = path.resolve(tmpDir, 'standalone.js')
const destination = path.resolve(tmpDir, 'standalone.js')

t.teardown(async () => {
await fs.promises.rm(destionation, { force: true })
await fs.promises.rm(destination, { force: true })
})

await fs.promises.writeFile(destionation, code)
const standalone = require(destionation)
await fs.promises.writeFile(destination, code)
const standalone = require(destination)
t.same(standalone({ firstName: 'Foo', surname: 'bar' }), JSON.stringify({ firstName: 'Foo' }), 'surname evicted')
})

Expand Down Expand Up @@ -89,14 +89,14 @@ test('test ajv schema', async (t) => {
t.type(code, 'string')
t.equal(code.indexOf('ajv') > 0, true)

const destionation = path.resolve(tmpDir, 'standalone2.js')
const destination = path.resolve(tmpDir, 'standalone2.js')

t.teardown(async () => {
await fs.promises.rm(destionation, { force: true })
await fs.promises.rm(destination, { force: true })
})

await fs.promises.writeFile(destionation, code)
const standalone = require(destionation)
await fs.promises.writeFile(destination, code)
const standalone = require(destination)
t.same(standalone({
kind: 'foobar',
foo: 'FOO',
Expand All @@ -119,3 +119,98 @@ test('test ajv schema', async (t) => {
}]
}))
})

test('no need to keep external schemas once compiled', async (t) => {
t.plan(1)
const externalSchema = {
first: {
definitions: {
id1: {
type: 'object',
properties: {
id1: {
type: 'integer'
}
}
}
}
}
}
const code = fjs({
$ref: 'first#/definitions/id1'
}, {
mode: 'standalone',
schema: externalSchema
})

const destination = path.resolve(tmpDir, 'standalone3.js')

t.teardown(async () => {
await fs.promises.rm(destination, { force: true })
})

await fs.promises.writeFile(destination, code)
const standalone = require(destination)

t.same(standalone({ id1: 5 }), JSON.stringify({ id1: 5 }), 'serialization works with external schemas')
})

test('no need to keep external schemas once compiled - with oneOf validator', async (t) => {
t.plan(2)

const externalSchema = {
ext: {
definitions: {
oBaz: {
type: 'object',
properties: {
baz: { type: 'number' }
},
required: ['baz']
},
oBar: {
type: 'object',
properties: {
bar: { type: 'string' }
},
required: ['bar']
},
other: {
type: 'string',
const: 'other'
}
}
}
}

const schema = {
title: 'object with oneOf property value containing refs to external schema',
type: 'object',
properties: {
oneOfSchema: {
oneOf: [
{ $ref: 'ext#/definitions/oBaz' },
{ $ref: 'ext#/definitions/oBar' }
]
}
},
required: ['oneOfSchema']
}

const code = fjs(schema, {
mode: 'standalone',
schema: externalSchema
})

const destination = path.resolve(tmpDir, 'standalone-oneOf-ref.js')

t.teardown(async () => {
await fs.promises.rm(destination, { force: true })
})

await fs.promises.writeFile(destination, code)
const stringify = require(destination)

t.equal(stringify({ oneOfSchema: { baz: 5 } }), '{"oneOfSchema":{"baz":5}}')
t.equal(stringify({ oneOfSchema: { bar: 'foo' } }), '{"oneOfSchema":{"bar":"foo"}}')
})

0 comments on commit a2e4ef9

Please sign in to comment.