mirror of
https://github.com/lowdefy/lowdefy.git
synced 2025-04-06 15:30:30 +08:00
chore: update from develop
This commit is contained in:
commit
efbb840a59
1
.github/workflows/test.yml
vendored
1
.github/workflows/test.yml
vendored
@ -17,6 +17,7 @@ jobs:
|
||||
node-version: '12.x'
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# needed for yarn version check, checks out entire repo
|
||||
fetch-depth: 0
|
||||
- name: Check yarn cache integrity
|
||||
run: yarn install --immutable --immutable-cache --check-cache
|
||||
|
BIN
.yarn/cache/@lowdefy-block-tools-npm-1.0.1-alpha.9-4588a99901-1283256de9.zip
vendored
Normal file
BIN
.yarn/cache/@lowdefy-block-tools-npm-1.0.1-alpha.9-4588a99901-1283256de9.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/@lowdefy-engine-npm-0.0.0-alpha.1-004c11a426-096f56708e.zip
vendored
Normal file
BIN
.yarn/cache/@lowdefy-engine-npm-0.0.0-alpha.1-004c11a426-096f56708e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/@lowdefy-graphql-npm-0.0.0-alpha.1-ae7035028f-877635c0c9.zip
vendored
Normal file
BIN
.yarn/cache/@lowdefy-graphql-npm-0.0.0-alpha.1-ae7035028f-877635c0c9.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@types-cookies-npm-0.7.5-45cb7b9bb5-913d972d89.zip
vendored
Normal file
BIN
.yarn/cache/@types-cookies-npm-0.7.5-45cb7b9bb5-913d972d89.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@types-uglify-js-npm-3.11.1-911509ddc2-75f1c06245.zip
vendored
Normal file
BIN
.yarn/cache/@types-uglify-js-npm-3.11.1-911509ddc2-75f1c06245.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@types-ws-npm-7.2.9-65a5cae19f-77532ad73c.zip
vendored
Normal file
BIN
.yarn/cache/@types-ws-npm-7.2.9-65a5cae19f-77532ad73c.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/camelcase-npm-6.2.0-69f8c130ac-654700600a.zip
vendored
Normal file
BIN
.yarn/cache/camelcase-npm-6.2.0-69f8c130ac-654700600a.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/caniuse-lite-npm-1.0.30001154-2944c2dcaf-7e087e61d0.zip
vendored
Normal file
BIN
.yarn/cache/caniuse-lite-npm-1.0.30001154-2944c2dcaf-7e087e61d0.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/clean-webpack-plugin-npm-3.0.0-21f4eeb4fb-fc0fbd1c8e.zip
vendored
Normal file
BIN
.yarn/cache/clean-webpack-plugin-npm-3.0.0-21f4eeb4fb-fc0fbd1c8e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/cli-color-npm-2.0.0-9f10b21e11-6a8824e7f1.zip
vendored
Normal file
BIN
.yarn/cache/cli-color-npm-2.0.0-9f10b21e11-6a8824e7f1.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/d-npm-1.0.1-64afbbc689-cf9b770965.zip
vendored
Normal file
BIN
.yarn/cache/d-npm-1.0.1-64afbbc689-cf9b770965.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/es5-ext-npm-0.10.53-18c0039c41-99e8115c2f.zip
vendored
Normal file
BIN
.yarn/cache/es5-ext-npm-0.10.53-18c0039c41-99e8115c2f.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/es6-iterator-npm-2.0.3-4dadb0ccc1-1880ce3121.zip
vendored
Normal file
BIN
.yarn/cache/es6-iterator-npm-2.0.3-4dadb0ccc1-1880ce3121.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/es6-symbol-npm-3.1.3-34d72f2a23-0915d72de8.zip
vendored
Normal file
BIN
.yarn/cache/es6-symbol-npm-3.1.3-34d72f2a23-0915d72de8.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/es6-weak-map-npm-2.0.3-5e57e0b4e6-8dfd50b291.zip
vendored
Normal file
BIN
.yarn/cache/es6-weak-map-npm-2.0.3-5e57e0b4e6-8dfd50b291.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/event-emitter-npm-0.3.5-f1e8b8edb5-92107b8970.zip
vendored
Normal file
BIN
.yarn/cache/event-emitter-npm-0.3.5-f1e8b8edb5-92107b8970.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/execa-npm-4.1.0-cc675b4189-79bd736acd.zip
vendored
Normal file
BIN
.yarn/cache/execa-npm-4.1.0-cc675b4189-79bd736acd.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/ext-npm-1.4.0-4190310122-c94102371f.zip
vendored
Normal file
BIN
.yarn/cache/ext-npm-1.4.0-4190310122-c94102371f.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/fastq-npm-1.9.0-11e58b198d-e9b46ea899.zip
vendored
Normal file
BIN
.yarn/cache/fastq-npm-1.9.0-11e58b198d-e9b46ea899.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/flow-parser-npm-0.137.0-2e0024a61a-054a1a4c49.zip
vendored
Normal file
BIN
.yarn/cache/flow-parser-npm-0.137.0-2e0024a61a-054a1a4c49.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-d523437689.zip
vendored
Normal file
BIN
.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-d523437689.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/ieee754-npm-1.2.1-fb63b3caeb-6c1cfab995.zip
vendored
Normal file
BIN
.yarn/cache/ieee754-npm-1.2.1-fb63b3caeb-6c1cfab995.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/is-promise-npm-2.2.2-afbf94db67-6fe84293b8.zip
vendored
Normal file
BIN
.yarn/cache/is-promise-npm-2.2.2-afbf94db67-6fe84293b8.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/lru-queue-npm-0.1.0-8e1c90dde8-2eab98cdfb.zip
vendored
Normal file
BIN
.yarn/cache/lru-queue-npm-0.1.0-8e1c90dde8-2eab98cdfb.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/memoizee-npm-0.4.14-a62a033531-89530bbed2.zip
vendored
Normal file
BIN
.yarn/cache/memoizee-npm-0.4.14-a62a033531-89530bbed2.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/next-tick-npm-1.0.0-0c0dd4bec1-18db63c447.zip
vendored
Normal file
BIN
.yarn/cache/next-tick-npm-1.0.0-0c0dd4bec1-18db63c447.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/next-tick-npm-1.1.0-e0eb60d6a4-586cc85dcd.zip
vendored
Normal file
BIN
.yarn/cache/next-tick-npm-1.1.0-e0eb60d6a4-586cc85dcd.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/node-releases-npm-1.1.65-fff441f5a5-7b8b1c118e.zip
vendored
Normal file
BIN
.yarn/cache/node-releases-npm-1.1.65-fff441f5a5-7b8b1c118e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/open-npm-7.3.0-d582d8b42e-a212fc9cf6.zip
vendored
Normal file
BIN
.yarn/cache/open-npm-7.3.0-d582d8b42e-a212fc9cf6.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/opener-npm-1.5.2-7a1aa69f14-855420de4f.zip
vendored
Normal file
BIN
.yarn/cache/opener-npm-1.5.2-7a1aa69f14-855420de4f.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/reload-npm-3.1.1-c7ae64f9ae-3401eedb3e.zip
vendored
Normal file
BIN
.yarn/cache/reload-npm-3.1.1-c7ae64f9ae-3401eedb3e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/supervisor-npm-0.12.0-86eb2f0732-b06597a97c.zip
vendored
Normal file
BIN
.yarn/cache/supervisor-npm-0.12.0-86eb2f0732-b06597a97c.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/timers-ext-npm-0.1.7-7edcefbfb5-4593b57c39.zip
vendored
Normal file
BIN
.yarn/cache/timers-ext-npm-0.1.7-7edcefbfb5-4593b57c39.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/type-npm-1.2.0-e67311c4b2-1589416fd9.zip
vendored
Normal file
BIN
.yarn/cache/type-npm-1.2.0-e67311c4b2-1589416fd9.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/type-npm-2.1.0-065c3f492a-c58a014169.zip
vendored
Normal file
BIN
.yarn/cache/type-npm-2.1.0-065c3f492a-c58a014169.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/unist-util-is-npm-4.0.3-df0a79ea11-661a7fbf5f.zip
vendored
Normal file
BIN
.yarn/cache/unist-util-is-npm-4.0.3-df0a79ea11-661a7fbf5f.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/v8-compile-cache-npm-2.2.0-b4d8f03dca-1efc994640.zip
vendored
Normal file
BIN
.yarn/cache/v8-compile-cache-npm-2.2.0-b4d8f03dca-1efc994640.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
2
.yarn/versions/aaab972e.yml
vendored
2
.yarn/versions/aaab972e.yml
vendored
@ -4,7 +4,6 @@ releases:
|
||||
"@lowdefy/cli": patch
|
||||
"@lowdefy/color": patch
|
||||
"@lowdefy/engine": patch
|
||||
"@lowdefy/express": patch
|
||||
"@lowdefy/format": patch
|
||||
"@lowdefy/graphql": patch
|
||||
"@lowdefy/helpers": patch
|
||||
@ -14,3 +13,4 @@ releases:
|
||||
"@lowdefy/nunjucks": patch
|
||||
"@lowdefy/operators": patch
|
||||
"@lowdefy/renderer": patch
|
||||
"@lowdefy/server": patch
|
||||
|
@ -30,7 +30,8 @@
|
||||
"clean": "lerna run clean",
|
||||
"prepare": "lerna run prepare",
|
||||
"prettier": "prettier --config .prettierrc --write **/*.js",
|
||||
"test": "lerna run test"
|
||||
"test": "lerna run test",
|
||||
"test:ci": "yarn install --immutable --immutable-cache --check-cache && yarn version check && yarn build && yarn test --ignore='@lowdefy/format'"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@yarnpkg/pnpify": "2.3.3",
|
||||
|
@ -57,6 +57,7 @@
|
||||
"babel-loader": "8.1.0",
|
||||
"babel-plugin-import": "1.13.1",
|
||||
"buffer": "5.7.0",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.0.0",
|
||||
"enzyme": "3.11.0",
|
||||
"html-webpack-plugin": "4.5.0",
|
||||
|
@ -1,4 +1,5 @@
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
@ -55,6 +56,7 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './public/index.html',
|
||||
}),
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@lowdefy/build",
|
||||
"version": "0.0.0-experimental.0",
|
||||
"version": "0.0.0-alpha.2",
|
||||
"licence": "Apache-2.0",
|
||||
"description": "",
|
||||
"homepage": "https://lowdefy.com",
|
||||
@ -55,6 +55,7 @@
|
||||
"@babel/preset-env": "7.12.1",
|
||||
"babel-jest": "26.6.1",
|
||||
"babel-loader": "8.1.0",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"jest": "26.6.1",
|
||||
"webpack": "5.3.2",
|
||||
"webpack-cli": "4.1.0"
|
||||
|
@ -15,11 +15,17 @@
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const build = require('./dist/index.js').default;
|
||||
|
||||
build({
|
||||
logger: console,
|
||||
cacheDirectory: path.resolve(process.cwd(), '.lowdefy/.cache'),
|
||||
configDirectory: process.cwd(),
|
||||
outputDirectory: path.resolve(process.cwd(), '.lowdefy/build'),
|
||||
});
|
||||
async function run() {
|
||||
// Doing weird things for webpack module federation.
|
||||
// Webpack needs an async import to resolve shared dependencies.
|
||||
const build = await require('./dist/index.js').default.then((module) => module.default);
|
||||
await build({
|
||||
logger: console,
|
||||
cacheDirectory: path.resolve(process.cwd(), '.lowdefy/.cache'),
|
||||
configDirectory: process.cwd(),
|
||||
outputDirectory: path.resolve(process.cwd(), '.lowdefy/build'),
|
||||
});
|
||||
}
|
||||
|
||||
run();
|
||||
|
70
packages/build/src/build.js
Normal file
70
packages/build/src/build.js
Normal file
@ -0,0 +1,70 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
/*
|
||||
Copyright 2020 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 createFileLoader from './loaders/fileLoader';
|
||||
import createFileSetter from './loaders/fileSetter';
|
||||
import createMetaLoader from './loaders/metaLoader';
|
||||
|
||||
import buildConnections from './build/buildConnections';
|
||||
import buildMenu from './build/buildMenu';
|
||||
import buildPages from './build/buildPages';
|
||||
import buildRefs from './build/buildRefs';
|
||||
import cleanOutputDirectory from './build/cleanOutputDirectory';
|
||||
import testSchema from './build/testSchema';
|
||||
import writeConnections from './build/writeConnections';
|
||||
import writeGlobal from './build/writeGlobal';
|
||||
import writeMenus from './build/writeMenus';
|
||||
import writePages from './build/writePages';
|
||||
import writeRequests from './build/writeRequests';
|
||||
|
||||
function createContext(options) {
|
||||
const { logger, cacheDirectory, configDirectory, outputDirectory } = options;
|
||||
const context = {
|
||||
logger,
|
||||
configLoader: createFileLoader({ baseDirectory: configDirectory }),
|
||||
artifactSetter: createFileSetter({ baseDirectory: outputDirectory }),
|
||||
outputDirectory,
|
||||
cacheDirectory,
|
||||
};
|
||||
return context;
|
||||
}
|
||||
|
||||
async function build(options) {
|
||||
const context = createContext(options);
|
||||
try {
|
||||
let components = await buildRefs({ context });
|
||||
await testSchema({ components, context });
|
||||
context.metaLoader = createMetaLoader({ components, context });
|
||||
await buildConnections({ components, context });
|
||||
await buildPages({ components, context });
|
||||
await buildMenu({ components, context });
|
||||
await cleanOutputDirectory({ context });
|
||||
await writeConnections({ components, context });
|
||||
await writeRequests({ components, context });
|
||||
await writePages({ components, context });
|
||||
await writeGlobal({ components, context });
|
||||
await writeMenus({ components, context });
|
||||
} catch (error) {
|
||||
context.logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export { createContext };
|
||||
|
||||
export default build;
|
@ -26,7 +26,6 @@ async function writeConnections({ components, context }) {
|
||||
filePath: `connections/${connection.connectionId}.json`,
|
||||
content: JSON.stringify(connection, null, 2),
|
||||
});
|
||||
await context.logger.info(`Updated connection ${connection.connectionId}`);
|
||||
});
|
||||
return Promise.all(writePromises);
|
||||
}
|
||||
|
@ -17,21 +17,15 @@
|
||||
import writeConnections from './writeConnections';
|
||||
import testContext from '../test/testContext';
|
||||
|
||||
const mockLogInfo = jest.fn();
|
||||
const mockSet = jest.fn();
|
||||
|
||||
const logger = {
|
||||
info: mockLogInfo,
|
||||
};
|
||||
|
||||
const artifactSetter = {
|
||||
set: mockSet,
|
||||
};
|
||||
|
||||
const context = testContext({ logger, artifactSetter });
|
||||
const context = testContext({ artifactSetter });
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogInfo.mockReset();
|
||||
mockSet.mockReset();
|
||||
});
|
||||
|
||||
@ -62,7 +56,6 @@ test('writeConnections write connection', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated connection connection1']]);
|
||||
});
|
||||
|
||||
test('writeConnections multiple connection', async () => {
|
||||
@ -99,10 +92,6 @@ test('writeConnections multiple connection', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([
|
||||
['Updated connection connection1'],
|
||||
['Updated connection connection2'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('writeConnections no connections', async () => {
|
||||
@ -111,14 +100,12 @@ test('writeConnections no connections', async () => {
|
||||
};
|
||||
await writeConnections({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writeConnections connections undefined', async () => {
|
||||
const components = {};
|
||||
await writeConnections({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writeConnections connections not an array', async () => {
|
||||
|
@ -27,7 +27,6 @@ async function writeGlobal({ components, context }) {
|
||||
filePath: 'global.json',
|
||||
content: JSON.stringify(components.global, null, 2),
|
||||
});
|
||||
await context.logger.info('Updated global');
|
||||
}
|
||||
|
||||
export default writeGlobal;
|
||||
|
@ -17,21 +17,15 @@
|
||||
import writeGlobal from './writeGlobal';
|
||||
import testContext from '../test/testContext';
|
||||
|
||||
const mockLogInfo = jest.fn();
|
||||
const mockSet = jest.fn();
|
||||
|
||||
const logger = {
|
||||
info: mockLogInfo,
|
||||
};
|
||||
|
||||
const artifactSetter = {
|
||||
set: mockSet,
|
||||
};
|
||||
|
||||
const context = testContext({ logger, artifactSetter });
|
||||
const context = testContext({ artifactSetter });
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogInfo.mockReset();
|
||||
mockSet.mockReset();
|
||||
});
|
||||
|
||||
@ -52,7 +46,6 @@ test('writeGlobal', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated global']]);
|
||||
});
|
||||
|
||||
test('writeGlobal empty global', async () => {
|
||||
@ -68,7 +61,6 @@ test('writeGlobal empty global', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated global']]);
|
||||
});
|
||||
|
||||
test('writeGlobal global undefined', async () => {
|
||||
@ -82,7 +74,6 @@ test('writeGlobal global undefined', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated global']]);
|
||||
});
|
||||
|
||||
test('writeGlobal global not an object', async () => {
|
||||
|
@ -24,7 +24,6 @@ async function writeMenus({ components, context }) {
|
||||
filePath: 'menus.json',
|
||||
content: JSON.stringify(components.menus, null, 2),
|
||||
});
|
||||
await context.logger.info('Updated menus');
|
||||
}
|
||||
|
||||
export default writeMenus;
|
||||
|
@ -17,21 +17,15 @@
|
||||
import writeMenus from './writeMenus';
|
||||
import testContext from '../test/testContext';
|
||||
|
||||
const mockLogInfo = jest.fn();
|
||||
const mockSet = jest.fn();
|
||||
|
||||
const logger = {
|
||||
info: mockLogInfo,
|
||||
};
|
||||
|
||||
const artifactSetter = {
|
||||
set: mockSet,
|
||||
};
|
||||
|
||||
const context = testContext({ logger, artifactSetter });
|
||||
const context = testContext({ artifactSetter });
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogInfo.mockReset();
|
||||
mockSet.mockReset();
|
||||
});
|
||||
|
||||
@ -60,7 +54,6 @@ test('writeMenus', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated menus']]);
|
||||
});
|
||||
|
||||
test('writeMenus empty menus', async () => {
|
||||
@ -76,7 +69,6 @@ test('writeMenus empty menus', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated menus']]);
|
||||
});
|
||||
|
||||
test('writeMenus menus undefined', async () => {
|
||||
|
@ -24,7 +24,6 @@ async function writePage({ page, context }) {
|
||||
filePath: `pages/${page.pageId}/${page.pageId}.json`,
|
||||
content: JSON.stringify(page, null, 2),
|
||||
});
|
||||
await context.logger.info(`Updated page ${page.pageId}`);
|
||||
}
|
||||
|
||||
async function writePages({ components, context }) {
|
||||
|
@ -17,21 +17,15 @@
|
||||
import writePages from './writePages';
|
||||
import testContext from '../test/testContext';
|
||||
|
||||
const mockLogInfo = jest.fn();
|
||||
const mockSet = jest.fn();
|
||||
|
||||
const logger = {
|
||||
info: mockLogInfo,
|
||||
};
|
||||
|
||||
const artifactSetter = {
|
||||
set: mockSet,
|
||||
};
|
||||
|
||||
const context = testContext({ logger, artifactSetter });
|
||||
const context = testContext({ artifactSetter });
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogInfo.mockReset();
|
||||
mockSet.mockReset();
|
||||
});
|
||||
|
||||
@ -62,7 +56,6 @@ test('writePages write page', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated page page1']]);
|
||||
});
|
||||
|
||||
test('writePages multiple pages', async () => {
|
||||
@ -111,7 +104,6 @@ test('writePages multiple pages', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated page page1'], ['Updated page page2']]);
|
||||
});
|
||||
|
||||
test('writePages no pages', async () => {
|
||||
@ -120,14 +112,12 @@ test('writePages no pages', async () => {
|
||||
};
|
||||
await writePages({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writePages pages undefined', async () => {
|
||||
const components = {};
|
||||
await writePages({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writePages pages not an array', async () => {
|
||||
|
@ -65,14 +65,15 @@ async function updateRequestsOnPage({ page, context }) {
|
||||
filePath: `pages/${page.pageId}/requests/${request.requestId}.json`,
|
||||
content: JSON.stringify(request, null, 2),
|
||||
});
|
||||
await context.logger.info(`Updated request ${request.requestId} on page ${page.pageId}`);
|
||||
});
|
||||
const writeMutationPromises = mutations.map(async (mutation) => {
|
||||
await context.artifactSetter.set({
|
||||
filePath: `pages/${page.pageId}/mutations/${mutation.mutationId}.json`,
|
||||
content: JSON.stringify(mutation, null, 2),
|
||||
});
|
||||
await context.logger.info(`Updated mutation ${mutation.mutationId} on page ${page.pageId}`);
|
||||
await context.logger.info(
|
||||
`Updated mutation "${mutation.mutationId}" on page "${page.pageId}".`
|
||||
);
|
||||
});
|
||||
|
||||
return Promise.all([...writeRequestPromises, ...writeMutationPromises]);
|
||||
|
@ -17,21 +17,15 @@
|
||||
import writeRequests from './writeRequests';
|
||||
import testContext from '../test/testContext';
|
||||
|
||||
const mockLogInfo = jest.fn();
|
||||
const mockSet = jest.fn();
|
||||
|
||||
const logger = {
|
||||
info: mockLogInfo,
|
||||
};
|
||||
|
||||
const artifactSetter = {
|
||||
set: mockSet,
|
||||
};
|
||||
|
||||
const context = testContext({ logger, artifactSetter });
|
||||
const context = testContext({ artifactSetter });
|
||||
|
||||
beforeEach(() => {
|
||||
mockLogInfo.mockReset();
|
||||
mockSet.mockReset();
|
||||
});
|
||||
|
||||
@ -69,7 +63,6 @@ test('writeRequests write request', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated request request1 on page page1']]);
|
||||
});
|
||||
|
||||
test('writeRequests write nested request', async () => {
|
||||
@ -116,7 +109,6 @@ test('writeRequests write nested request', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated request request1 on page page1']]);
|
||||
});
|
||||
|
||||
test('writeRequests add mutation', async () => {
|
||||
@ -153,7 +145,6 @@ test('writeRequests add mutation', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated mutation mutation1 on page page1']]);
|
||||
});
|
||||
|
||||
test('writeRequests add nested mutation', async () => {
|
||||
@ -199,7 +190,6 @@ test('writeRequests add nested mutation', async () => {
|
||||
},
|
||||
],
|
||||
]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([['Updated mutation mutation1 on page page1']]);
|
||||
});
|
||||
|
||||
test('writeRequests requests is not an array', async () => {
|
||||
@ -238,14 +228,12 @@ test('writeRequests empty pages array', async () => {
|
||||
};
|
||||
await writeRequests({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writeRequests no pages array', async () => {
|
||||
const components = {};
|
||||
await writeRequests({ components, context });
|
||||
expect(mockSet.mock.calls).toEqual([]);
|
||||
expect(mockLogInfo.mock.calls).toEqual([]);
|
||||
});
|
||||
|
||||
test('writeRequests pages not an array', async () => {
|
||||
|
@ -1,5 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
/*
|
||||
Copyright 2020 Lowdefy, Inc
|
||||
|
||||
@ -16,57 +14,6 @@
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { type } from '@lowdefy/helpers';
|
||||
|
||||
import createFileLoader from './loaders/fileLoader';
|
||||
import createFileSetter from './loaders/fileSetter';
|
||||
import createMetaLoader from './loaders/metaLoader';
|
||||
|
||||
import buildConnections from './build/buildConnections';
|
||||
import buildMenu from './build/buildMenu';
|
||||
import buildPages from './build/buildPages';
|
||||
import buildRefs from './build/buildRefs';
|
||||
import cleanOutputDirectory from './build/cleanOutputDirectory';
|
||||
import testSchema from './build/testSchema';
|
||||
import writeConnections from './build/writeConnections';
|
||||
import writeGlobal from './build/writeGlobal';
|
||||
import writeMenus from './build/writeMenus';
|
||||
import writePages from './build/writePages';
|
||||
import writeRequests from './build/writeRequests';
|
||||
|
||||
function createContext(options) {
|
||||
const { logger, cacheDirectory, configDirectory, outputDirectory } = options;
|
||||
const context = {
|
||||
logger,
|
||||
configLoader: createFileLoader({ baseDirectory: configDirectory }),
|
||||
artifactSetter: createFileSetter({ baseDirectory: outputDirectory }),
|
||||
outputDirectory,
|
||||
cacheDirectory,
|
||||
};
|
||||
return context;
|
||||
}
|
||||
|
||||
async function build(options) {
|
||||
const context = createContext(options);
|
||||
try {
|
||||
let components = await buildRefs({ context });
|
||||
await testSchema({ components, context });
|
||||
context.metaLoader = createMetaLoader({ components, context });
|
||||
await buildConnections({ components, context });
|
||||
await buildPages({ components, context });
|
||||
await buildMenu({ components, context });
|
||||
await cleanOutputDirectory({ context });
|
||||
await writeConnections({ components, context });
|
||||
await writeRequests({ components, context });
|
||||
await writePages({ components, context });
|
||||
await writeGlobal({ components, context });
|
||||
await writeMenus({ components, context });
|
||||
} catch (error) {
|
||||
context.logger.error(error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export { createContext };
|
||||
const build = import('./build');
|
||||
|
||||
export default build;
|
||||
|
@ -1,5 +1,6 @@
|
||||
const path = require('path');
|
||||
const { ModuleFederationPlugin } = require('webpack').container;
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const { dependencies } = require('./package.json');
|
||||
|
||||
module.exports = {
|
||||
@ -37,12 +38,13 @@ module.exports = {
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(),
|
||||
new ModuleFederationPlugin({
|
||||
name: 'build',
|
||||
library: { type: 'commonjs' },
|
||||
filename: 'remoteEntry.js',
|
||||
exposes: {
|
||||
'./build': './src/index.js',
|
||||
'./build': './src/build.js',
|
||||
},
|
||||
shared: dependencies,
|
||||
}),
|
||||
|
@ -7,6 +7,7 @@
|
||||
"node": "12"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"@babel/preset-react"
|
||||
]
|
||||
}
|
||||
|
@ -3,7 +3,13 @@ module.exports = {
|
||||
collectCoverage: true,
|
||||
collectCoverageFrom: ['src/**/*.js'],
|
||||
coverageDirectory: 'coverage',
|
||||
coveragePathIgnorePatterns: ['<rootDir>/dist/', '<rootDir>/src/test'],
|
||||
coveragePathIgnorePatterns: [
|
||||
'<rootDir>/dist/',
|
||||
'<rootDir>/src/test',
|
||||
'<rootDir>/src/index.js',
|
||||
'<rootDir>/src/index.js',
|
||||
'<rootDir>/src/commands/dev/shell/*',
|
||||
],
|
||||
coverageReporters: [['lcov', { projectRoot: '../..' }], 'text', 'clover'],
|
||||
errorOnDeprecated: true,
|
||||
testEnvironment: 'node',
|
||||
|
@ -1,22 +0,0 @@
|
||||
version: '1.0.1-experimental.1'
|
||||
|
||||
types:
|
||||
Context:
|
||||
url: http://localhost:3002/meta/Context.json
|
||||
Button:
|
||||
url: http://localhost:3002/meta/Button.json
|
||||
|
||||
connections:
|
||||
- id: con1
|
||||
type: AxiosHttp
|
||||
|
||||
pages:
|
||||
- id: page1
|
||||
type: Context
|
||||
requests:
|
||||
- id: req1
|
||||
type: AxiosHttp
|
||||
connectionId: con1
|
||||
blocks:
|
||||
- id: button
|
||||
type: Button
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@lowdefy/cli",
|
||||
"version": "3.0.0-experimental.1",
|
||||
"version": "3.0.0-alpha.3",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Lowdefy CLI",
|
||||
"homepage": "https://lowdefy.com",
|
||||
@ -36,7 +36,7 @@
|
||||
"npm-publish": "npm publish --access public",
|
||||
"prepare": "yarn build",
|
||||
"prepublishOnly": "yarn build",
|
||||
"test": "jest --coverage --passWithNoTests",
|
||||
"test": "FORCE_COLOR=3 jest --coverage",
|
||||
"webpack": "webpack --config webpack.config.js",
|
||||
"version:prerelease": "yarn version prerelease",
|
||||
"version:patch": "yarn version patch -d",
|
||||
@ -44,25 +44,37 @@
|
||||
"version:major": "yarn version major -d"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lowdefy/build": "0.0.0-experimental.0",
|
||||
"@lowdefy/block-tools": "1.0.1-alpha.9",
|
||||
"@lowdefy/helpers": "1.1.0",
|
||||
"@lowdefy/node-utils": "1.0.0",
|
||||
"apollo-server-express": "2.18.2",
|
||||
"axios": "0.21.0",
|
||||
"chalk": "4.1.0",
|
||||
"chokidar": "3.4.3",
|
||||
"commander": "6.2.0",
|
||||
"decompress": "4.2.1",
|
||||
"decompress-targz": "4.1.1",
|
||||
"express": "4.17.1",
|
||||
"graphql": "15.4.0",
|
||||
"inquirer": "7.3.3",
|
||||
"js-yaml": "3.14.0"
|
||||
"js-yaml": "3.14.0",
|
||||
"opener": "1.5.2",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"reload": "3.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.12.1",
|
||||
"@babel/core": "7.12.3",
|
||||
"@babel/preset-env": "7.12.1",
|
||||
"@babel/preset-react": "7.12.1",
|
||||
"babel-jest": "26.5.2",
|
||||
"babel-loader": "8.1.0",
|
||||
"clean-webpack-plugin": "3.0.0",
|
||||
"css-loader": "5.0.0",
|
||||
"html-webpack-plugin": "4.5.0",
|
||||
"jest": "26.5.3",
|
||||
"style-loader": "2.0.0",
|
||||
"webpack": "5.3.2",
|
||||
"webpack-cli": "4.0.0"
|
||||
}
|
||||
|
@ -16,25 +16,21 @@
|
||||
|
||||
import path from 'path';
|
||||
import getBuildScript from './getBuildScript';
|
||||
import getLowdefyVersion from '../../utils/getLowdefyVersion';
|
||||
import createPrint from '../../utils/print';
|
||||
import { cacheDirectoryPath, outputDirectoryPath } from '../../utils/directories';
|
||||
import createContext from '../../utils/context';
|
||||
import { outputDirectoryPath } from '../../utils/directories';
|
||||
|
||||
async function build(program) {
|
||||
let baseDirectory = process.cwd();
|
||||
if (program.baseDirectory) {
|
||||
baseDirectory = path.resolve(program.baseDirectory);
|
||||
}
|
||||
const version = await getLowdefyVersion(program.baseDirectory);
|
||||
const cacheDirectory = path.resolve(baseDirectory, cacheDirectoryPath);
|
||||
const buildScript = await getBuildScript(version, cacheDirectory);
|
||||
|
||||
buildScript({
|
||||
logger: createPrint({ timestamp: true }),
|
||||
cacheDirectory,
|
||||
configDirectory: baseDirectory,
|
||||
outputDirectory: path.resolve(baseDirectory, outputDirectoryPath),
|
||||
async function build(options) {
|
||||
const context = await createContext(options);
|
||||
await getBuildScript(context);
|
||||
const outputDirectory = path.resolve(context.baseDirectory, outputDirectoryPath);
|
||||
context.print.info('Starting build.');
|
||||
await context.buildScript({
|
||||
logger: context.print,
|
||||
cacheDirectory: context.cacheDirectory,
|
||||
configDirectory: context.baseDirectory,
|
||||
outputDirectory,
|
||||
});
|
||||
context.print.info(`Build artifacts saved at ${outputDirectory}.`);
|
||||
}
|
||||
|
||||
export default build;
|
||||
|
80
packages/cli/src/commands/build/build.test.js
Normal file
80
packages/cli/src/commands/build/build.test.js
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright 2020 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 path from 'path';
|
||||
import build from './build';
|
||||
import getBuildScript from './getBuildScript';
|
||||
import createContext from '../../utils/context';
|
||||
|
||||
const info = jest.fn();
|
||||
|
||||
jest.mock('./getBuildScript', () => {
|
||||
const buildScript = jest.fn();
|
||||
return (context) => {
|
||||
context.buildScript = buildScript;
|
||||
return context;
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../utils/context', () => {
|
||||
const createContext = jest.fn();
|
||||
return createContext;
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
createContext.mockReset();
|
||||
});
|
||||
|
||||
test('build', async () => {
|
||||
const baseDirectory = process.cwd();
|
||||
const cacheDirectory = path.resolve(process.cwd(), '.lowdefy/.cache');
|
||||
const outputDirectory = path.resolve(process.cwd(), '.lowdefy/build');
|
||||
createContext.mockImplementation(() => ({
|
||||
print: {
|
||||
info,
|
||||
},
|
||||
baseDirectory,
|
||||
cacheDirectory,
|
||||
}));
|
||||
await build({});
|
||||
const context = createContext.mock.results[0].value;
|
||||
const { buildScript } = context;
|
||||
expect(createContext).toHaveBeenCalledTimes(1);
|
||||
expect(buildScript).toHaveBeenCalledTimes(1);
|
||||
expect(buildScript.mock.calls[0][0].outputDirectory).toEqual(outputDirectory);
|
||||
expect(buildScript.mock.calls[0][0].cacheDirectory).toEqual(cacheDirectory);
|
||||
expect(buildScript.mock.calls[0][0].outputDirectory).toEqual(outputDirectory);
|
||||
});
|
||||
|
||||
test('build with base directory', async () => {
|
||||
const baseDirectory = path.resolve(process.cwd(), 'baseDirectory');
|
||||
const cacheDirectory = path.resolve(process.cwd(), 'baseDirectory/.lowdefy/.cache');
|
||||
const outputDirectory = path.resolve(process.cwd(), 'baseDirectory/.lowdefy/build');
|
||||
createContext.mockImplementation(() => ({
|
||||
print: {
|
||||
info,
|
||||
},
|
||||
baseDirectory,
|
||||
cacheDirectory,
|
||||
}));
|
||||
await build({ baseDirectory: 'baseDirectory' });
|
||||
const context = createContext.mock.results[0].value;
|
||||
const { buildScript } = context;
|
||||
expect(createContext).toHaveBeenCalledTimes(1);
|
||||
expect(buildScript).toHaveBeenCalledTimes(1);
|
||||
expect(buildScript.mock.calls[0][0].outputDirectory).toEqual(outputDirectory);
|
||||
expect(buildScript.mock.calls[0][0].cacheDirectory).toEqual(cacheDirectory);
|
||||
expect(buildScript.mock.calls[0][0].outputDirectory).toEqual(outputDirectory);
|
||||
});
|
@ -19,15 +19,15 @@ import path from 'path';
|
||||
import loadBuildScriptToCache from './loadBuildScriptToCache';
|
||||
import loadModule from '../../utils/loadModule';
|
||||
|
||||
async function getBuildScript(version, cacheDirectory) {
|
||||
let buildScript;
|
||||
const cleanVersion = version.replace(/[-.]/g, '_');
|
||||
const cachePath = path.resolve(cacheDirectory, `scripts/build_${cleanVersion}`);
|
||||
async function getBuildScript(context) {
|
||||
const cleanVersion = context.version.replace(/[-.]/g, '_');
|
||||
const cachePath = path.resolve(context.cacheDirectory, `scripts/build_${cleanVersion}`);
|
||||
if (!fs.existsSync(path.resolve(cachePath, 'package/dist/remoteEntry.js'))) {
|
||||
await loadBuildScriptToCache(version, cachePath);
|
||||
await loadBuildScriptToCache(context, cachePath);
|
||||
}
|
||||
buildScript = await loadModule(cachePath, './build');
|
||||
return buildScript.default;
|
||||
const buildScript = await loadModule(path.resolve(cachePath, 'package/dist'), './build');
|
||||
context.buildScript = buildScript.default;
|
||||
return context;
|
||||
}
|
||||
|
||||
export default getBuildScript;
|
||||
|
@ -18,7 +18,7 @@ import axios from 'axios';
|
||||
import decompress from 'decompress';
|
||||
import decompressTargz from 'decompress-targz';
|
||||
|
||||
async function loadBuildScriptToCache(version, cachePath) {
|
||||
async function loadBuildScriptToCache(context, cachePath) {
|
||||
const registryUrl = 'https://registry.npmjs.org/@lowdefy/build';
|
||||
const packageInfo = await axios.get(registryUrl);
|
||||
if (!packageInfo || !packageInfo.data) {
|
||||
@ -27,16 +27,18 @@ async function loadBuildScriptToCache(version, cachePath) {
|
||||
`Build package could not be found at ${registryUrl}. Check internet connection.`
|
||||
);
|
||||
}
|
||||
if (!packageInfo.data.versions[version]) {
|
||||
throw new Error(`Invalid Lowdefy version. Version "${version}" does not exist.`);
|
||||
if (!packageInfo.data.versions[context.version]) {
|
||||
throw new Error(`Invalid Lowdefy version. Version "${context.version}" does not exist.`);
|
||||
}
|
||||
const tarball = await axios.get(packageInfo.data.versions[version].dist.tarball, {
|
||||
const tarball = await axios.get(packageInfo.data.versions[context.version].dist.tarball, {
|
||||
responseType: 'arraybuffer',
|
||||
});
|
||||
if (!tarball || !tarball.data) {
|
||||
/// TODO: Check if user has internet connection.
|
||||
throw new Error(
|
||||
`Build script could not be fetched from ${packageInfo.data.versions[version].dist.tarball}. Check internet connection.`
|
||||
`Build script could not be fetched from ${
|
||||
packageInfo.data.versions[context.version].dist.tarball
|
||||
}. Check internet connection.`
|
||||
);
|
||||
}
|
||||
await decompress(tarball.data, cachePath, {
|
||||
|
57
packages/cli/src/commands/cleanCache/cleanCache.test.js
Normal file
57
packages/cli/src/commands/cleanCache/cleanCache.test.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
Copyright 2020 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 path from 'path';
|
||||
import { cleanDirectory } from '@lowdefy/node-utils';
|
||||
import cleanCache from './cleanCache';
|
||||
import createPrint from '../../utils/print';
|
||||
|
||||
jest.mock('@lowdefy/node-utils', () => {
|
||||
const cleanDirectory = jest.fn();
|
||||
return { cleanDirectory };
|
||||
});
|
||||
|
||||
jest.mock('../../utils/print', () => {
|
||||
const info = jest.fn();
|
||||
return () => ({
|
||||
info,
|
||||
});
|
||||
});
|
||||
|
||||
const print = createPrint();
|
||||
|
||||
beforeEach(() => {
|
||||
cleanDirectory.mockReset();
|
||||
});
|
||||
|
||||
test('cleanCache', async () => {
|
||||
await cleanCache({});
|
||||
const cachePath = path.resolve(process.cwd(), './.lowdefy/.cache');
|
||||
expect(cleanDirectory.mock.calls).toEqual([[cachePath]]);
|
||||
expect(print.info.mock.calls).toEqual([
|
||||
[`Cleaning cache at "${cachePath}".`],
|
||||
['Cache cleaned.'],
|
||||
]);
|
||||
});
|
||||
|
||||
test('cleanCache baseDir', async () => {
|
||||
await cleanCache({ baseDirectory: 'baseDir' });
|
||||
const cachePath = path.resolve(process.cwd(), 'baseDir/.lowdefy/.cache');
|
||||
expect(cleanDirectory.mock.calls).toEqual([[cachePath]]);
|
||||
expect(print.info.mock.calls).toEqual([
|
||||
[`Cleaning cache at "${cachePath}".`],
|
||||
['Cache cleaned.'],
|
||||
]);
|
||||
});
|
96
packages/cli/src/commands/dev/dev.js
Normal file
96
packages/cli/src/commands/dev/dev.js
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2020 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 path from 'path';
|
||||
import chokidar from 'chokidar';
|
||||
import express from 'express';
|
||||
import reload from 'reload';
|
||||
import opener from 'opener';
|
||||
import { ApolloServer } from 'apollo-server-express';
|
||||
|
||||
import BatchChanges from '../../utils/BatchChanges';
|
||||
import createContext from '../../utils/context';
|
||||
import getBuildScript from '../build/getBuildScript';
|
||||
import getGraphql from './getGraphql';
|
||||
import { outputDirectoryPath } from '../../utils/directories';
|
||||
|
||||
async function dev(options) {
|
||||
// Setup
|
||||
if (!options.port) options.port = 3000;
|
||||
const context = await createContext(options);
|
||||
await getBuildScript(context);
|
||||
await getGraphql(context);
|
||||
|
||||
context.print.info('Starting development server.');
|
||||
|
||||
//Graphql
|
||||
const config = {
|
||||
DEPLOYMENT_ID: 'DEPLOYMENT_ID',
|
||||
DEPLOYMENT_NAME: 'DEPLOYMENT_NAME',
|
||||
DOMAIN_NAME: 'DOMAIN_NAME',
|
||||
CONFIGURATION_BASE_PATH: path.resolve(process.cwd(), './.lowdefy/build'),
|
||||
logger: console,
|
||||
getHeadersFromInput: ({ req }) => req.headers,
|
||||
getSecrets: () => ({
|
||||
CONNECTION_SECRETS: {},
|
||||
}),
|
||||
};
|
||||
const { typeDefs, resolvers, createContext: createGqlContext } = context.graphql;
|
||||
const gqlContext = createGqlContext(config);
|
||||
const server = new ApolloServer({ typeDefs, resolvers, context: gqlContext });
|
||||
|
||||
// Express
|
||||
const app = express();
|
||||
app.set('port', options.port);
|
||||
server.applyMiddleware({ app, path: '/api/graphql' });
|
||||
const reloadReturned = await reload(app, { route: '/api/dev/reload.js' });
|
||||
app.use(express.static(path.join(__dirname, 'shell')));
|
||||
app.use('/api/dev/version', (req, res) => {
|
||||
res.json(context.version);
|
||||
});
|
||||
app.use((req, res) => {
|
||||
res.sendFile(path.resolve(__dirname, 'shell/index.html'));
|
||||
});
|
||||
|
||||
// File watcher
|
||||
const fn = async () => {
|
||||
context.print.info('Building configuration.');
|
||||
await context.buildScript({
|
||||
logger: context.print,
|
||||
cacheDirectory: context.cacheDirectory,
|
||||
configDirectory: context.baseDirectory,
|
||||
outputDirectory: path.resolve(context.baseDirectory, outputDirectoryPath),
|
||||
});
|
||||
reloadReturned.reload();
|
||||
};
|
||||
const batchChanges = new BatchChanges({ fn, context });
|
||||
|
||||
const watcher = chokidar.watch('.', {
|
||||
ignored: /(^|[/\\])\../, // ignore dotfiles
|
||||
persistent: true,
|
||||
});
|
||||
watcher.on('add', () => batchChanges.newChange());
|
||||
watcher.on('change', () => batchChanges.newChange());
|
||||
watcher.on('unlink', () => batchChanges.newChange());
|
||||
|
||||
// Start server
|
||||
app.listen(app.get('port'), function () {
|
||||
context.print.log(`Development server listening on port ${options.port}`);
|
||||
});
|
||||
opener(`http://localhost:${options.port}`);
|
||||
}
|
||||
|
||||
export default dev;
|
35
packages/cli/src/commands/dev/getGraphql.js
Normal file
35
packages/cli/src/commands/dev/getGraphql.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright 2020 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 fs from 'fs';
|
||||
import path from 'path';
|
||||
import loadGraphqlToCache from './loadGraphqlToCache';
|
||||
import loadModule from '../../utils/loadModule';
|
||||
|
||||
async function getGraphql(context) {
|
||||
const cleanVersion = context.version.replace(/[-.]/g, '_');
|
||||
const cachePath = path.resolve(context.cacheDirectory, `scripts/graphql_${cleanVersion}`);
|
||||
if (!fs.existsSync(path.resolve(cachePath, 'package/dist/remoteEntry.js'))) {
|
||||
await loadGraphqlToCache(context, cachePath);
|
||||
}
|
||||
context.graphql = await loadModule(
|
||||
path.resolve(cachePath, 'package/dist/moduleFederation'),
|
||||
'./graphql'
|
||||
);
|
||||
return context;
|
||||
}
|
||||
|
||||
export default getGraphql;
|
49
packages/cli/src/commands/dev/loadGraphqlToCache.js
Normal file
49
packages/cli/src/commands/dev/loadGraphqlToCache.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2020 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 axios from 'axios';
|
||||
import decompress from 'decompress';
|
||||
import decompressTargz from 'decompress-targz';
|
||||
|
||||
async function loadGraphqlToCache(context, cachePath) {
|
||||
const registryUrl = 'https://registry.npmjs.org/@lowdefy/graphql';
|
||||
const packageInfo = await axios.get(registryUrl);
|
||||
if (!packageInfo || !packageInfo.data) {
|
||||
// TODO: Check if user has internet connection.
|
||||
throw new Error(
|
||||
`Graphql package could not be found at ${registryUrl}. Check internet connection.`
|
||||
);
|
||||
}
|
||||
if (!packageInfo.data.versions[context.version]) {
|
||||
throw new Error(`Invalid Lowdefy version. Version "${context.version}" does not exist.`);
|
||||
}
|
||||
const tarball = await axios.get(packageInfo.data.versions[context.version].dist.tarball, {
|
||||
responseType: 'arraybuffer',
|
||||
});
|
||||
if (!tarball || !tarball.data) {
|
||||
/// TODO: Check if user has internet connection.
|
||||
throw new Error(
|
||||
`Graphql could not be fetched from ${
|
||||
packageInfo.data.versions[context.version].dist.tarball
|
||||
}. Check internet connection.`
|
||||
);
|
||||
}
|
||||
await decompress(tarball.data, cachePath, {
|
||||
plugins: [decompressTargz()],
|
||||
});
|
||||
}
|
||||
|
||||
export default loadGraphqlToCache;
|
107
packages/cli/src/commands/dev/shell/bootstrap.js
vendored
Normal file
107
packages/cli/src/commands/dev/shell/bootstrap.js
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2020 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.
|
||||
*/
|
||||
|
||||
/*global __webpack_share_scopes__, __webpack_init_sharing__*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Loading } from '@lowdefy/block-tools';
|
||||
|
||||
function loadComponent(scope, module) {
|
||||
return async () => {
|
||||
// Initializes the share scope. This fills it with known provided modules from this build and all remotes
|
||||
await __webpack_init_sharing__('default');
|
||||
const container = window[scope]; // or get the container somewhere else
|
||||
// Initialize the container, it may provide shared modules
|
||||
await container.init(__webpack_share_scopes__.default);
|
||||
const factory = await window[scope].get(`./${module}`);
|
||||
const Module = factory();
|
||||
return Module;
|
||||
};
|
||||
}
|
||||
|
||||
const useDynamicScript = (args) => {
|
||||
const [ready, setReady] = React.useState(false);
|
||||
const [failed, setFailed] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!args.url) {
|
||||
return;
|
||||
}
|
||||
|
||||
const element = document.createElement('script');
|
||||
|
||||
element.src = args.url;
|
||||
element.type = 'text/javascript';
|
||||
element.async = true;
|
||||
|
||||
setReady(false);
|
||||
setFailed(false);
|
||||
|
||||
element.onload = () => {
|
||||
console.log(`Dynamic Script Loaded: ${args.url}`);
|
||||
setReady(true);
|
||||
};
|
||||
|
||||
element.onerror = () => {
|
||||
console.error(`Dynamic Script Error: ${args.url}`);
|
||||
setReady(false);
|
||||
setFailed(true);
|
||||
};
|
||||
|
||||
document.head.appendChild(element);
|
||||
|
||||
return () => {
|
||||
console.log(`Dynamic Script Removed: ${args.url}`);
|
||||
document.head.removeChild(element);
|
||||
};
|
||||
}, [args.url]);
|
||||
|
||||
return {
|
||||
ready,
|
||||
failed,
|
||||
};
|
||||
};
|
||||
|
||||
function Shell({ version }) {
|
||||
const { ready, failed } = useDynamicScript({
|
||||
url: `http://unpkg.com/@lowdefy/renderer@${version}/dist/remoteEntry.js`,
|
||||
});
|
||||
|
||||
if (!ready) {
|
||||
return <Loading type="Spinner" properties={{ height: '100vh' }} />;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
return <h2>Failed to load dynamic script</h2>;
|
||||
}
|
||||
|
||||
const Component = React.lazy(loadComponent('lowdefy_renderer', 'Renderer'));
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<Loading type="Spinner" properties={{ height: '100vh' }} />}>
|
||||
<Component />
|
||||
</React.Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
const getVersion = async () => {
|
||||
return (await fetch(`api/dev/version`)).json();
|
||||
};
|
||||
|
||||
getVersion().then((version) => {
|
||||
ReactDOM.render(<Shell version={version} />, document.getElementById('root'));
|
||||
});
|
29
packages/cli/src/commands/dev/shell/index.html
Normal file
29
packages/cli/src/commands/dev/shell/index.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!--
|
||||
Copyright 2020 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. -->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Lowdefy App</title>
|
||||
<script src="/api/dev/reload.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="emotion"></div>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user