@pushwoosh/frontend-builder-engine 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # Pushwoosh Frontend Engine
package/bin/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../lib/pushwoosh-engine.js');
@@ -0,0 +1,39 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const babel = require('@babel/core');
4
+ const { listFilesInDirectoryRecursively, PromiseQueue } = require('./helpers');
5
+
6
+ async function buildStyledComponents(
7
+ sourceDir,
8
+ targetDir,
9
+ ) {
10
+ const files = await listFilesInDirectoryRecursively(sourceDir);
11
+ const options = {
12
+ babelrc: false,
13
+ configFile: false,
14
+ plugins: [
15
+ [
16
+ 'babel-plugin-styled-components',
17
+ {
18
+ fileName: false,
19
+ minify: true,
20
+ transpileTemplateLiterals: true,
21
+ },
22
+ ],
23
+ ],
24
+ };
25
+ const jsFiles = files.filter((file) => file.endsWith('.js'));
26
+ const queue = new PromiseQueue(10);
27
+ await Promise.all(jsFiles.map((file) => queue.add(async () => {
28
+ const fullSourcePath = path.join(sourceDir, file);
29
+ const fullTargetPath = path.join(targetDir, file);
30
+ const beforeDate = new Date();
31
+ const result = await babel.transformFileAsync(fullSourcePath, options);
32
+ console.log(`Writing ${fullTargetPath} ${new Date() - beforeDate}ms`);
33
+ await fs.promises.mkdir(path.dirname(fullTargetPath), { recursive: true });
34
+ await fs.promises.writeFile(fullTargetPath, result.code);
35
+ })));
36
+ }
37
+ module.exports = {
38
+ buildStyledComponents,
39
+ };
@@ -0,0 +1,42 @@
1
+ const ts = require('typescript');
2
+
3
+ async function buildTs(basePath, configFile) {
4
+ // const configFile = ts.readConfigFile(configFilePath, ts.sys.readFile);
5
+ // console.log(configFile);
6
+ const parsedCommandLine = ts.parseJsonConfigFileContent(
7
+ configFile,
8
+ ts.sys,
9
+ basePath,
10
+ );
11
+
12
+ const program = ts.createProgram(parsedCommandLine.fileNames, parsedCommandLine.options);
13
+ const emitResult = program.emit();
14
+
15
+ const allDiagnostics = ts
16
+ .getPreEmitDiagnostics(program)
17
+ .concat(emitResult.diagnostics);
18
+
19
+ allDiagnostics.forEach((diagnostic) => {
20
+ if (diagnostic.file) {
21
+ const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
22
+ diagnostic.start,
23
+ );
24
+ const message = ts.flattenDiagnosticMessageText(
25
+ diagnostic.messageText,
26
+ '\n',
27
+ );
28
+ console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
29
+ } else {
30
+ console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
31
+ }
32
+ });
33
+
34
+ if (allDiagnostics.length > 0) {
35
+ return 1;
36
+ }
37
+ return 0;
38
+ }
39
+
40
+ module.exports = {
41
+ buildTs,
42
+ };
package/lib/helpers.js ADDED
@@ -0,0 +1,77 @@
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+
4
+ async function listFilesInDirectoryRecursively(directory, baseDirectory = directory) {
5
+ let files = [];
6
+
7
+ const items = await fs.readdir(directory, { withFileTypes: true });
8
+ for (const item of items) {
9
+ const fullPath = path.join(directory, item.name);
10
+ if (item.isDirectory()) {
11
+ files = files.concat(await listFilesInDirectoryRecursively(fullPath, baseDirectory));
12
+ } else {
13
+ files.push(path.relative(baseDirectory, fullPath));
14
+ }
15
+ }
16
+
17
+ return files;
18
+ }
19
+
20
+ class PromiseQueue {
21
+ constructor(maxPendingPromises) {
22
+ this.queue = [];
23
+ this.pendingPromises = 0;
24
+ this.maxPendingPromises = maxPendingPromises;
25
+ }
26
+
27
+ add(promiseGenerator) {
28
+ return new Promise((resolve, reject) => {
29
+ this.queue.push({
30
+ promiseGenerator,
31
+ resolve,
32
+ reject,
33
+ });
34
+
35
+ this.dequeue();
36
+ });
37
+ }
38
+
39
+ dequeue() {
40
+ if (this.pendingPromises >= this.maxPendingPromises) {
41
+ return false;
42
+ }
43
+
44
+ const item = this.queue.shift();
45
+ if (!item) {
46
+ return false;
47
+ }
48
+ try {
49
+ this.pendingPromises++;
50
+
51
+ item.promiseGenerator()
52
+ .then(
53
+ (value) => {
54
+ this.pendingPromises--;
55
+ item.resolve(value);
56
+ this.dequeue();
57
+ },
58
+ (err) => {
59
+ this.pendingPromises--;
60
+ item.reject(err);
61
+ this.dequeue();
62
+ },
63
+ );
64
+ } catch (err) {
65
+ this.pendingPromises--;
66
+ item.reject(err);
67
+ this.dequeue();
68
+ }
69
+
70
+ return true;
71
+ }
72
+ }
73
+
74
+ module.exports = {
75
+ listFilesInDirectoryRecursively,
76
+ PromiseQueue,
77
+ };
@@ -0,0 +1,42 @@
1
+ const path = require('path');
2
+ const { mapValues, isPlainObject } = require('lodash');
3
+ const ts = require('typescript');
4
+
5
+ function smartMerge(obj, extend) {
6
+ const result = mapValues(obj, (value, key) => {
7
+ if (key in extend) {
8
+ const newValue = extend[key];
9
+ if (
10
+ typeof newValue === 'string'
11
+ || typeof newValue === 'boolean'
12
+ || typeof newValue === 'number'
13
+ || Array.isArray(newValue)
14
+ ) {
15
+ return newValue;
16
+ }
17
+ if (typeof newValue === 'function') {
18
+ return newValue(value);
19
+ }
20
+ if (isPlainObject(newValue)) {
21
+ return smartMerge(value, newValue);
22
+ }
23
+ }
24
+ return value;
25
+ });
26
+ const extendsUniqueKeys = Object.keys(extend).filter((key) => !(key in obj));
27
+ for (const key of extendsUniqueKeys) {
28
+ const newValue = extend[key];
29
+ result[key] = typeof newValue === 'function' ? newValue() : newValue;
30
+ }
31
+ return result;
32
+ }
33
+
34
+ function loadTsConfig(extend) {
35
+ const tsConfigPath = path.resolve(__dirname, 'tsconfig.json');
36
+ const { config } = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
37
+ return smartMerge(config, extend);
38
+ }
39
+
40
+ module.exports = {
41
+ loadTsConfig,
42
+ };
@@ -0,0 +1,44 @@
1
+ const { program, Command } = require('commander');
2
+
3
+ const { buildTs } = require('./build-ts');
4
+ const { buildStyledComponents } = require('./build-babel');
5
+ const { loadTsConfig } = require('./lib-build-tsconfig');
6
+
7
+ program
8
+ .version('1.0.0')
9
+ .description('An example CLI tool with commander')
10
+ .option('-n, --name <type>', 'Your name')
11
+ .option('-a, --age <type>', 'Your age')
12
+ .command('lib:build')
13
+ .action(async () => {
14
+ const curDir = process.cwd();
15
+ const targetDir = `${curDir}/dist`;
16
+ const tsConfig = loadTsConfig({});
17
+ await buildTs(curDir, tsConfig);
18
+ await buildStyledComponents(targetDir, targetDir);
19
+ })
20
+ .option('-s, --ss <type>', 'output extra debugging');
21
+
22
+ program
23
+ .addCommand(
24
+ new Command('lib:check-types')
25
+ .description('Check types in the project')
26
+ .action(async () => {
27
+ const curDir = process.cwd();
28
+ const tsConfig = loadTsConfig({ compilerOptions: { noEmit: true } });
29
+ const code = await buildTs(curDir, tsConfig);
30
+ if (code !== 0) {
31
+ process.exit(code);
32
+ }
33
+ }),
34
+ );
35
+
36
+ program.parse(process.argv);
37
+ /*
38
+
39
+ const options = program.opts();
40
+ console.log(options, process.cwd());
41
+ if (options.name && options.age) {
42
+ console.log(`Hello ${options.name}, you are ${options.age} years old.`);
43
+ }
44
+ */
@@ -0,0 +1,53 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* ----- Base Options ----- */
4
+ "target": "ES2022",
5
+ "module": "ESNext",
6
+ "lib": [
7
+ "ESNext",
8
+ "DOM"
9
+ ],
10
+ "outDir": "./dist",
11
+ "rootDir": "./src",
12
+ "jsx": "react",
13
+ "importHelpers": true,
14
+ "declaration": true,
15
+ "sourceMap": false,
16
+ /* ----- Strict Type-Checking Options ----- */
17
+ "strict": true,
18
+ "noImplicitAny": true,
19
+ "strictNullChecks": true,
20
+ "strictFunctionTypes": true,
21
+ "strictBindCallApply": true,
22
+ "strictPropertyInitialization": true,
23
+ "noImplicitThis": true,
24
+ "alwaysStrict": true,
25
+ /* ----- Additional Checks ----- */
26
+ "forceConsistentCasingInFileNames": true,
27
+ "noUnusedLocals": false,
28
+ "noUnusedParameters": true,
29
+ "noImplicitReturns": true,
30
+ "noFallthroughCasesInSwitch": true,
31
+ /* ----- More ----- */
32
+ "allowSyntheticDefaultImports": true,
33
+ "esModuleInterop": true,
34
+ "isolatedModules": true,
35
+ /* ----- Experimental Options ----- */
36
+ "experimentalDecorators": true,
37
+ "emitDecoratorMetadata": true,
38
+ /* ----- Module Resolution Options ----- */
39
+ "moduleResolution": "node",
40
+ "baseUrl": "./",
41
+ "paths": {
42
+ "~/src": [
43
+ "./src"
44
+ ],
45
+ "~/src/*": [
46
+ "./src/*"
47
+ ]
48
+ }
49
+ },
50
+ "include": [
51
+ "./src/**/*",
52
+ ]
53
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "compilerOptions": {
4
+ "skipLibCheck": true,
5
+ "baseUrl": "./scripts",
6
+ "paths": {
7
+ "~/src": ["../src"],
8
+ "~/src/*": ["../src/*"]
9
+ //"*": ["node_modules/*"]
10
+ }
11
+ },
12
+ //"include": ["../playground/**/*"]
13
+ }
@@ -0,0 +1,59 @@
1
+ const path = require('path');
2
+
3
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
4
+ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
5
+ // const { loadTsConfig } = require('./lib-build-tsconfig');
6
+
7
+ function getConfig() {
8
+ const projectPath = process.cwd();
9
+ return {
10
+ target: 'web',
11
+ mode: 'development',
12
+ entry: './playground/index.tsx',
13
+ output: {
14
+ path: path.resolve(projectPath, 'dist'),
15
+ filename: 'bundle.js',
16
+ },
17
+ resolve: {
18
+ extensions: ['.tsx', '.ts', 'jsx', '.js'],
19
+ alias: {
20
+ '~src': path.resolve(projectPath, 'src/'),
21
+ },
22
+ plugins: [
23
+ new TsconfigPathsPlugin({
24
+ context: path.join(projectPath, './playground'),
25
+ configFile: path.join(projectPath, './playground/tsconfig.json'),
26
+ }),
27
+ ],
28
+ },
29
+ module: {
30
+ rules: [
31
+ {
32
+ test: /\.tsx?$/,
33
+ use: {
34
+ loader: 'ts-loader',
35
+ options: {
36
+ context: path.join(projectPath, './playground'),
37
+ configFile: path.join(projectPath, './playground/tsconfig.json'),
38
+ },
39
+ },
40
+ exclude: /node_modules/,
41
+ },
42
+ ],
43
+ },
44
+ plugins: [
45
+ new HtmlWebpackPlugin({
46
+ template: './playground/index.html',
47
+ }),
48
+ ],
49
+ devServer: {
50
+ static: {
51
+ directory: path.join(projectPath, 'dist'),
52
+ },
53
+ // compress: true,
54
+ port: 8080,
55
+ },
56
+ };
57
+ }
58
+
59
+ module.exports = getConfig;
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@pushwoosh/frontend-builder-engine",
3
+ "version": "0.0.1",
4
+ "description": "Pushwoosh frontend builder engine",
5
+ "main": "./lib/pushwoosh-frontend-builder-engine.js",
6
+ "scripts": {
7
+ "test": "echo test"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "lib",
12
+ "README.md"
13
+ ],
14
+ "dependencies": {
15
+ "@babel/core": "^7.24.3",
16
+ "commander": "^12.0.0",
17
+ "html-webpack-plugin": "^5.6.0",
18
+ "ts-loader": "^9.5.1",
19
+ "tsconfig-paths-webpack-plugin": "^4.1.0",
20
+ "typescript": "^5.4.3",
21
+ "webpack": "^5.91.0",
22
+ "webpack-dev-server": "^5.0.4"
23
+ },
24
+ "peerDependencies": {
25
+ "lodash": "^4.0.0",
26
+ "typescript": "^5.0.0"
27
+ }
28
+ }