mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-02-23 14:39:32 +08:00
feat(build): Add support for resolver functions in _ref operator.
This commit is contained in:
parent
3eb00dc7eb
commit
aa7fddcfc2
File diff suppressed because it is too large
Load Diff
39
packages/build/src/build/buildRefs/getConfigFile.js
Normal file
39
packages/build/src/build/buildRefs/getConfigFile.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type } from '@lowdefy/helpers';
|
||||||
|
|
||||||
|
async function getConfigFile({ context, refDef, referencedFrom }) {
|
||||||
|
if (!type.isString(refDef.path)) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid _ref definition ${JSON.stringify({
|
||||||
|
_ref: refDef.original,
|
||||||
|
})} in file ${referencedFrom}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const content = context.readConfigFile(refDef.path);
|
||||||
|
|
||||||
|
if (content === null) {
|
||||||
|
throw new Error(
|
||||||
|
`Tried to reference file "${refDef.path}" from "${referencedFrom}", but file does not exist.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getConfigFile;
|
@ -14,47 +14,19 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { type } from '@lowdefy/helpers';
|
import getConfigFile from './getConfigFile';
|
||||||
import { getFileExtension, getFileSubExtension } from '@lowdefy/node-utils';
|
import parseRefContent from './parseRefContent';
|
||||||
import JSON5 from 'json5';
|
import runRefResolver from './runRefResolver';
|
||||||
import YAML from 'js-yaml';
|
|
||||||
|
|
||||||
import parseNunjucks from './parseNunjucks';
|
|
||||||
|
|
||||||
function parseRefContent({ content, vars, path }) {
|
|
||||||
let ext = getFileExtension(path);
|
|
||||||
if (ext === 'njk') {
|
|
||||||
content = parseNunjucks(content, vars, path);
|
|
||||||
ext = getFileSubExtension(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ext === 'yaml' || ext === 'yml') {
|
|
||||||
return YAML.load(content);
|
|
||||||
}
|
|
||||||
if (ext === 'json') {
|
|
||||||
return JSON5.parse(content);
|
|
||||||
}
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getRefContent({ context, refDef, referencedFrom }) {
|
async function getRefContent({ context, refDef, referencedFrom }) {
|
||||||
if (!type.isString(refDef.path)) {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid _ref definition ${JSON.stringify({
|
|
||||||
_ref: refDef.original,
|
|
||||||
})} in file ${referencedFrom}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { path, vars } = refDef;
|
|
||||||
let content;
|
let content;
|
||||||
content = await context.readConfigFile(path);
|
if (refDef.resolver) {
|
||||||
|
content = await runRefResolver({ context, refDef, referencedFrom });
|
||||||
if (content === null) {
|
} else {
|
||||||
throw new Error(`Tried to reference file with path "${path}", but file does not exist.`);
|
content = await getConfigFile({ context, refDef, referencedFrom });
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseRefContent({ content, vars, path });
|
return parseRefContent({ content, refDef });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getRefContent;
|
export default getRefContent;
|
||||||
|
@ -22,10 +22,11 @@ import getRefPath from './getRefPath';
|
|||||||
function makeRefDefinition(refDefinition) {
|
function makeRefDefinition(refDefinition) {
|
||||||
return {
|
return {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
path: getRefPath(refDefinition),
|
|
||||||
vars: get(refDefinition, 'vars', { default: {} }),
|
|
||||||
transformer: get(refDefinition, 'transformer'),
|
|
||||||
original: refDefinition,
|
original: refDefinition,
|
||||||
|
path: getRefPath(refDefinition),
|
||||||
|
resolver: get(refDefinition, 'resolver'),
|
||||||
|
transformer: get(refDefinition, 'transformer'),
|
||||||
|
vars: get(refDefinition, 'vars', { default: {} }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
packages/build/src/build/buildRefs/parseRefContent.js
Normal file
43
packages/build/src/build/buildRefs/parseRefContent.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type } from '@lowdefy/helpers';
|
||||||
|
import { getFileExtension, getFileSubExtension } from '@lowdefy/node-utils';
|
||||||
|
import JSON5 from 'json5';
|
||||||
|
import YAML from 'js-yaml';
|
||||||
|
|
||||||
|
import parseNunjucks from './parseNunjucks';
|
||||||
|
|
||||||
|
function parseRefContent({ content, refDef }) {
|
||||||
|
const { path, vars } = refDef;
|
||||||
|
if (type.isString(path)) {
|
||||||
|
let ext = getFileExtension(path);
|
||||||
|
if (ext === 'njk') {
|
||||||
|
content = parseNunjucks(content, vars);
|
||||||
|
ext = getFileSubExtension(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ext === 'yaml' || ext === 'yml') {
|
||||||
|
return YAML.load(content);
|
||||||
|
}
|
||||||
|
if (ext === 'json') {
|
||||||
|
return JSON5.parse(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default parseRefContent;
|
@ -21,7 +21,7 @@ import runTransformer from './runTransformer';
|
|||||||
|
|
||||||
async function recursiveParseFile({ context, refDef, count, referencedFrom }) {
|
async function recursiveParseFile({ context, refDef, count, referencedFrom }) {
|
||||||
// TODO: Maybe it would be better to detect a cycle, since this is the real issue here?
|
// TODO: Maybe it would be better to detect a cycle, since this is the real issue here?
|
||||||
if (count > 20) {
|
if (count > 40) {
|
||||||
throw new Error(`Maximum recursion depth of references exceeded.`);
|
throw new Error(`Maximum recursion depth of references exceeded.`);
|
||||||
}
|
}
|
||||||
let fileContent = await getRefContent({ context, refDef, referencedFrom });
|
let fileContent = await getRefContent({ context, refDef, referencedFrom });
|
||||||
|
41
packages/build/src/build/buildRefs/runRefResolver.js
Normal file
41
packages/build/src/build/buildRefs/runRefResolver.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { type } from '@lowdefy/helpers';
|
||||||
|
import getUserJavascriptFunction from './getUserJavascriptFunction';
|
||||||
|
|
||||||
|
async function runRefResolver({ context, refDef, referencedFrom }) {
|
||||||
|
const resolverFn = await getUserJavascriptFunction({
|
||||||
|
context,
|
||||||
|
filePath: refDef.resolver,
|
||||||
|
});
|
||||||
|
let content;
|
||||||
|
try {
|
||||||
|
content = await resolverFn(refDef.path, refDef.vars, context);
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(
|
||||||
|
`Error calling resolver "${refDef.resolver}" from "${referencedFrom}": ${error.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (type.isNone(content)) {
|
||||||
|
throw new Error(
|
||||||
|
`Tried to reference with resolver "${refDef.resolver}" from "${referencedFrom}", but received "${content}".`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default runRefResolver;
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const wait = (ms) => {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
};
|
||||||
|
|
||||||
|
async function asyncFn() {
|
||||||
|
await wait(20);
|
||||||
|
return { async: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = asyncFn;
|
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function resolver() {
|
||||||
|
throw new Error('Test error');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = resolver;
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function resolver(path) {
|
||||||
|
if (path === 'null') return null;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = resolver;
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function resolver(path) {
|
||||||
|
switch (path) {
|
||||||
|
case 'target.yaml':
|
||||||
|
return `
|
||||||
|
array:
|
||||||
|
- 1
|
||||||
|
- 2`;
|
||||||
|
case 'target.yml':
|
||||||
|
return `
|
||||||
|
array:
|
||||||
|
- 1
|
||||||
|
- 2`;
|
||||||
|
case 'target.json':
|
||||||
|
return `{"a": 42}`;
|
||||||
|
case 'target.yaml.njk':
|
||||||
|
return 'a: {{ var }}';
|
||||||
|
case 'target.yml.njk':
|
||||||
|
return 'a: {{ var }}';
|
||||||
|
case 'target.json.njk':
|
||||||
|
return `{ "a": "{{ var }}" }`;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = resolver;
|
26
packages/build/src/test/buildRefs/testBuildRefsResolver.js
Normal file
26
packages/build/src/test/buildRefs/testBuildRefsResolver.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function resolver(path, vars, context) {
|
||||||
|
return {
|
||||||
|
resolved: true,
|
||||||
|
path,
|
||||||
|
vars,
|
||||||
|
context,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = resolver;
|
29
packages/build/src/test/buildRefs/testBuildRefsTransform.js
Normal file
29
packages/build/src/test/buildRefs/testBuildRefsTransform.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020-2021 Lowdefy, Inc
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function add(a, b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformer(obj, vars) {
|
||||||
|
return {
|
||||||
|
json: JSON.stringify(obj),
|
||||||
|
add: add(obj.a, 42),
|
||||||
|
var: vars.var1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = transformer;
|
@ -1,13 +0,0 @@
|
|||||||
function add(a, b) {
|
|
||||||
return a + b;
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformer(obj, vars) {
|
|
||||||
return {
|
|
||||||
json: JSON.stringify(obj),
|
|
||||||
add: add(obj.a, 42),
|
|
||||||
var: vars.var1,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = transformer;
|
|
Loading…
Reference in New Issue
Block a user