mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-21 17:12:43 +00:00
refactor: remove pack
This commit is contained in:
@@ -18,10 +18,8 @@ import {Logger} from '@openstapps/logger';
|
|||||||
import {asyncPool} from 'async-pool-native/dist/async-pool';
|
import {asyncPool} from 'async-pool-native/dist/async-pool';
|
||||||
import {readFile, unlink, writeFile} from 'fs';
|
import {readFile, unlink, writeFile} from 'fs';
|
||||||
import * as glob from 'glob';
|
import * as glob from 'glob';
|
||||||
import {basename} from 'path';
|
|
||||||
import {promisify} from 'util';
|
import {promisify} from 'util';
|
||||||
import {PACK_IDENTIFIER} from './configuration';
|
import {PACK_IDENTIFIER} from './configuration';
|
||||||
import {JavaScriptModule} from './pack/types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiated logger
|
* Instantiated logger
|
||||||
@@ -129,33 +127,3 @@ export function getAllInternalDependecies(moduleContent: string): string[] {
|
|||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort modules by their dependencies
|
|
||||||
*
|
|
||||||
* @param modules Modules to sort
|
|
||||||
*/
|
|
||||||
export function topologicalSort(modules: JavaScriptModule[]): JavaScriptModule[] {
|
|
||||||
const topoSort = require('toposort');
|
|
||||||
|
|
||||||
// vertices are modules, an edge from a to b means that b depends on a
|
|
||||||
const edges: string[][] = [];
|
|
||||||
const nodes: string[] = [];
|
|
||||||
|
|
||||||
// add all edges
|
|
||||||
modules.forEach((module) => {
|
|
||||||
module.dependencies.forEach((dependenciePath) => {
|
|
||||||
// add edge from dependency to our module
|
|
||||||
edges.push([basename(dependenciePath), module.name]);
|
|
||||||
});
|
|
||||||
|
|
||||||
nodes.push(module.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
// sort graph and return as an array of sorted modules
|
|
||||||
return topoSort.array(nodes, edges).map((moduleName: string) => {
|
|
||||||
return modules.find((module) => {
|
|
||||||
return module.name === moduleName;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
import * as del from 'del';
|
|
||||||
import {logger} from './common';
|
|
||||||
import {packCliJs} from './pack/pack-cli';
|
|
||||||
import {packTypeDefinitions} from './pack/pack-definitions';
|
|
||||||
import {packJavaScriptFiles} from './pack/pack-modules';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack
|
|
||||||
*/
|
|
||||||
async function pack() {
|
|
||||||
logger.log(`Packing project in ${process.cwd()}...`);
|
|
||||||
|
|
||||||
// run all tasks in parallel
|
|
||||||
const promises: Array<Promise<void>> = [
|
|
||||||
packCliJs(),
|
|
||||||
packTypeDefinitions(),
|
|
||||||
packJavaScriptFiles(),
|
|
||||||
];
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
// clean up afterwards
|
|
||||||
logger.info('Deleting extraneous files...');
|
|
||||||
|
|
||||||
await del([
|
|
||||||
// delete all transpiled files
|
|
||||||
'lib/*',
|
|
||||||
|
|
||||||
// keep packed files
|
|
||||||
'!lib/index.d.ts', '!lib/index.js',
|
|
||||||
|
|
||||||
// keep converted schema files
|
|
||||||
'!lib/schema', '!lib/schema/*.json',
|
|
||||||
|
|
||||||
// keep documentation
|
|
||||||
'!lib/doc', '!lib/doc/*', '!lib/doc/**/*',
|
|
||||||
|
|
||||||
// keep cli
|
|
||||||
'!lib/cli.js',
|
|
||||||
|
|
||||||
// keep tests
|
|
||||||
'!lib/test', '!lib/test/*', '!lib/test/**/*',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pack().then(() => {
|
|
||||||
logger.ok('Packed library!');
|
|
||||||
}, (err) => {
|
|
||||||
logger.error(err);
|
|
||||||
process.exit(-1);
|
|
||||||
});
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
import {existsSync} from 'fs';
|
|
||||||
import {join} from 'path';
|
|
||||||
import {cwd} from 'process';
|
|
||||||
import {logger, writeFilePromisified} from '../common';
|
|
||||||
import {readFilePromisified} from '../common';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack cli.js
|
|
||||||
*
|
|
||||||
* This finds all internal requires and replaces the paths with `./index` or internal requires if it has been
|
|
||||||
* required already.
|
|
||||||
*
|
|
||||||
* Furthermore it checks that no shebang line is present and that it does not export anything.
|
|
||||||
*/
|
|
||||||
export async function packCliJs(): Promise<void> {
|
|
||||||
const path = join(cwd(), 'lib', 'cli.js');
|
|
||||||
|
|
||||||
if (!existsSync(path)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info('Adjusting JavaScript CLI...');
|
|
||||||
|
|
||||||
const buffer = await readFilePromisified(path);
|
|
||||||
const content = buffer.toString();
|
|
||||||
|
|
||||||
if (content.indexOf('#!/') === 0) {
|
|
||||||
throw new Error('`cli.js` must not contain a shebang line! It is added by this script.');
|
|
||||||
}
|
|
||||||
|
|
||||||
let internalRequire: string | null = null;
|
|
||||||
|
|
||||||
const adjustedContent = '#!/usr/bin/env node\n\n' + content
|
|
||||||
.split('\n')
|
|
||||||
.map((line, lineNumber) => {
|
|
||||||
|
|
||||||
// check for exports (cli.js is not allowed to export anything)
|
|
||||||
if (Array.isArray(line.match(/^\s*((exports)|(module\.exports))/))) {
|
|
||||||
throw new Error(
|
|
||||||
'Line ' +
|
|
||||||
lineNumber +
|
|
||||||
' in cli.js has a reference to the exports object. cli.js is not for exporting. Line was: "'
|
|
||||||
+ line
|
|
||||||
+ '"',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace lines with internal requires
|
|
||||||
// extract module name from line
|
|
||||||
const match = line.match(/^(\s*)(const|var) ([a-z0-9_]*) = require\(("[^"]+"|'[^']+')\);$/i);
|
|
||||||
|
|
||||||
if (match !== null) {
|
|
||||||
const importedName = match[3];
|
|
||||||
const moduleName = match[4].substring(1, match[4].length - 1);
|
|
||||||
|
|
||||||
// if it begins with '.' and not ends with json
|
|
||||||
if (/^[.]{1,2}\/(?!.*\.json$).*$/i.test(moduleName)) {
|
|
||||||
|
|
||||||
// is the first internal require
|
|
||||||
if (internalRequire !== null) {
|
|
||||||
return 'const ' + importedName + ' = ' + internalRequire + ';';
|
|
||||||
}
|
|
||||||
|
|
||||||
// only the first import needs a require
|
|
||||||
internalRequire = importedName;
|
|
||||||
return 'const ' + importedName + ' = require("./index");';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
})
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
return await writeFilePromisified(path, adjustedContent);
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
import {join} from 'path';
|
|
||||||
import {cwd} from 'process';
|
|
||||||
import {
|
|
||||||
deleteFileIfExistingAndPacked,
|
|
||||||
globPromisified,
|
|
||||||
logger,
|
|
||||||
readFilePromisified,
|
|
||||||
writeFilePromisified,
|
|
||||||
} from '../common';
|
|
||||||
import {PACK_IDENTIFIER} from '../configuration';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list containing the contents of all type definition files
|
|
||||||
*/
|
|
||||||
async function getAllTypeDefinitions(): Promise<string[]> {
|
|
||||||
const fileNames = await globPromisified(join(cwd(), '*(lib|src)', '**', '*.d.ts'), {
|
|
||||||
ignore: [
|
|
||||||
join(cwd(), 'lib', 'doc', '**', '*.d.ts'),
|
|
||||||
join(cwd(), 'lib', 'test', '**', '*.d.ts'),
|
|
||||||
join(cwd(), 'lib', 'cli.d.ts'),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const promises = fileNames.map((fileName) => {
|
|
||||||
return readFilePromisified(fileName, 'utf8');
|
|
||||||
});
|
|
||||||
|
|
||||||
return await Promise.all(promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack a list of type definitions into one file
|
|
||||||
*/
|
|
||||||
export async function packTypeDefinitions(): Promise<void> {
|
|
||||||
logger.info('Packing TypeScript definition files...');
|
|
||||||
|
|
||||||
const path = join(cwd(), 'lib', 'index.d.ts');
|
|
||||||
|
|
||||||
await deleteFileIfExistingAndPacked(path);
|
|
||||||
|
|
||||||
const typeDefinitions = await getAllTypeDefinitions();
|
|
||||||
|
|
||||||
// pack TypeScript definition files
|
|
||||||
const imports: { [k: string]: string[] } = {};
|
|
||||||
|
|
||||||
const referenceLines: string[] = [];
|
|
||||||
|
|
||||||
let allDefinitions = typeDefinitions
|
|
||||||
// concat them separated by new lines
|
|
||||||
.join('\n\n\n\n\n')
|
|
||||||
// split all lines
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => {
|
|
||||||
if (line.indexOf('export =') !== -1) {
|
|
||||||
throw new Error('`export =` is not allowed by pack. Use named imports instead.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (line.indexOf('/// <reference') === 0) {
|
|
||||||
referenceLines.push(line);
|
|
||||||
return '// moved referenced line';
|
|
||||||
}
|
|
||||||
|
|
||||||
// match import lines
|
|
||||||
const match = line.match(/^import {([^}].*)} from '([^'].*)';$/);
|
|
||||||
|
|
||||||
if (match !== null) {
|
|
||||||
// extract module
|
|
||||||
const module = match[2];
|
|
||||||
|
|
||||||
// extract imported objects
|
|
||||||
const importedObjects = match[1].split(',').map((object) => {
|
|
||||||
return object.trim();
|
|
||||||
});
|
|
||||||
|
|
||||||
// add list of already imported objects for module
|
|
||||||
if (typeof imports[module] === 'undefined') {
|
|
||||||
imports[module] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// count already imported objects and objects to import now
|
|
||||||
const objectsToImport: string[] = [];
|
|
||||||
importedObjects.forEach((object) => {
|
|
||||||
if (imports[module].indexOf(object) === -1) {
|
|
||||||
imports[module].push(object);
|
|
||||||
objectsToImport.push(object);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// replace import line
|
|
||||||
if (objectsToImport.length === 0) {
|
|
||||||
return '// extraneous removed import';
|
|
||||||
} else {
|
|
||||||
return 'import { ' + objectsToImport.join(', ') + ' } from \'' + module + '\';';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
})
|
|
||||||
// filter lines which contain "local" imports
|
|
||||||
.filter((line) => {
|
|
||||||
return !line.match(/^import .* from '\./);
|
|
||||||
})
|
|
||||||
// concat all lines separated by new lines
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
if (allDefinitions.length > 0) {
|
|
||||||
if (referenceLines.length > 0) {
|
|
||||||
allDefinitions = referenceLines.join('\n') + '\n\n' + allDefinitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// write packed TypeScript definition files
|
|
||||||
return await writeFilePromisified(path, PACK_IDENTIFIER + '\n\n' + allDefinitions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
import {existsSync} from 'fs';
|
|
||||||
import {basename, dirname, join} from 'path';
|
|
||||||
import {cwd} from 'process';
|
|
||||||
import {
|
|
||||||
deleteFileIfExistingAndPacked,
|
|
||||||
getAllInternalDependecies,
|
|
||||||
globPromisified,
|
|
||||||
logger,
|
|
||||||
readFilePromisified,
|
|
||||||
topologicalSort,
|
|
||||||
writeFilePromisified,
|
|
||||||
} from '../common';
|
|
||||||
import {PACK_IDENTIFIER} from '../configuration';
|
|
||||||
import {JavaScriptModule} from './types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all JavaScript modules
|
|
||||||
*/
|
|
||||||
async function getAllJavaScriptModules(): Promise<JavaScriptModule[]> {
|
|
||||||
const fileNames = await globPromisified(join(cwd(), 'lib', '**', '*.js'), {
|
|
||||||
ignore: [
|
|
||||||
join(cwd(), 'lib', 'doc', '**', '*.js'),
|
|
||||||
join(cwd(), 'lib', 'test', '*.js'),
|
|
||||||
join(cwd(), 'lib', 'cli.js'),
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const promises = fileNames.map(async (fileName) => {
|
|
||||||
const fileContent = await readFilePromisified(fileName, 'utf8');
|
|
||||||
const directory = dirname(fileName).replace(new RegExp('^' + join(cwd(), 'lib')), '');
|
|
||||||
|
|
||||||
return {
|
|
||||||
content: '(function() {\n' + fileContent + '\n})();\n',
|
|
||||||
dependencies: getAllInternalDependecies(fileContent),
|
|
||||||
directory: directory,
|
|
||||||
name: basename(fileName, '.js'),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return await Promise.all(promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pack all javascript files
|
|
||||||
*/
|
|
||||||
export async function packJavaScriptFiles(): Promise<void> {
|
|
||||||
const path = join(cwd(), 'lib', 'index.js');
|
|
||||||
|
|
||||||
logger.info('Packing JavaScript files...');
|
|
||||||
|
|
||||||
await deleteFileIfExistingAndPacked(path);
|
|
||||||
|
|
||||||
// topologically sort the modules (sort by dependencies)
|
|
||||||
const jsModules = topologicalSort(await getAllJavaScriptModules());
|
|
||||||
|
|
||||||
let wholeCode = jsModules
|
|
||||||
// convert modules to strings
|
|
||||||
.map((module) => {
|
|
||||||
module.content = module.content
|
|
||||||
.split('\n')
|
|
||||||
.map((line) => {
|
|
||||||
const match = line.match(
|
|
||||||
/^(\s*)(const|var) ([a-z0-9_]*) = ((require\("([^"]+)"\))|(require\('([^']+)'\)));$/i,
|
|
||||||
);
|
|
||||||
|
|
||||||
// replace lines with internal requires
|
|
||||||
if (match !== null) {
|
|
||||||
// match[6] or match[8] contain the modulePath
|
|
||||||
if (typeof match[6] === 'undefined') {
|
|
||||||
match[6] = match[8];
|
|
||||||
}
|
|
||||||
|
|
||||||
const whiteSpace = match[1] ? match[1] : '';
|
|
||||||
const importedName = match[3];
|
|
||||||
const modulePath = match[6];
|
|
||||||
|
|
||||||
// leave line unchanged if it is a "global" import
|
|
||||||
if (modulePath.match(/^[.]{1,2}\//) === null) {
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
// replace internal requires with `module.exports`
|
|
||||||
if (existsSync(join(cwd(), 'lib', module.directory, modulePath + '.js'))) {
|
|
||||||
return whiteSpace + 'const ' + importedName + ' = module.exports;';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existsSync(join(cwd(), 'src', module.directory, modulePath))) {
|
|
||||||
return whiteSpace + 'const ' + importedName + ' = require(\'../src/' + modulePath + '\');';
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.warn('Import ' + importedName + ' could not be found in module.directory ' + modulePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
})
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
return '// Module: ' + module.name + '\n' + module.content;
|
|
||||||
})
|
|
||||||
// concat them separated by new lines
|
|
||||||
.join('\n\n\n\n\n')
|
|
||||||
// split all lines
|
|
||||||
.split('\n')
|
|
||||||
// filter lines
|
|
||||||
.filter((line) => {
|
|
||||||
// remove strict usage
|
|
||||||
if (line === '"use strict";') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove esModule property
|
|
||||||
if (line === 'Object.defineProperty(exports, "__esModule", { value: true });') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove source map references
|
|
||||||
if (line.indexOf('//# sourceMappingURL=') === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep all other lines
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
// concat all lines separated by new lines
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
if (wholeCode.length > 0) {
|
|
||||||
// add meta lines to the file
|
|
||||||
wholeCode = '"use strict";\nObject.defineProperty(exports, "__esModule", { value: true });\n\n' + wholeCode;
|
|
||||||
|
|
||||||
// write packed JavaScript files
|
|
||||||
return await writeFilePromisified(path, PACK_IDENTIFIER + '\n\n' + wholeCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2018 StApps
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the Free
|
|
||||||
* Software Foundation, version 3.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with
|
|
||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* A JavaScript module representation to sort a list of them by dependencies
|
|
||||||
*/
|
|
||||||
export interface JavaScriptModule {
|
|
||||||
/**
|
|
||||||
* Content of the module
|
|
||||||
*/
|
|
||||||
content: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of names of dependencies
|
|
||||||
*/
|
|
||||||
dependencies: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Directory the module is in
|
|
||||||
*/
|
|
||||||
directory: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the module
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user