@superdesk/build-tools 1.0.19 → 1.2.0-rc1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdesk/build-tools",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0-rc1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"gettext-extractor": "3.5.3",
|
|
15
15
|
"gettext.js": "0.9.0",
|
|
16
16
|
"glob": "7.1.7",
|
|
17
|
-
"lodash": "4.17.19",
|
|
18
17
|
"rimraf": "3.0.2"
|
|
19
18
|
}
|
|
20
19
|
}
|
package/src/dev-link.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dev-link` CLI command. Symlinks one or more local source repos into the
|
|
3
|
+
* current working directory's node_modules so a Superdesk template can be
|
|
4
|
+
* developed against unpublished local checkouts (e.g. superdesk-client-core,
|
|
5
|
+
* superdesk-planning) without using `npm link`.
|
|
6
|
+
*
|
|
7
|
+
* For each source path:
|
|
8
|
+
* 1. Read its package.json to get the package name. The symlink in
|
|
9
|
+
* node_modules uses this name, not the directory name (so
|
|
10
|
+
* superdesk-client-core correctly lands as node_modules/superdesk-core).
|
|
11
|
+
* 2. Run `npm install` in the source root, and also in any client/<subdir>
|
|
12
|
+
* that has its own package.json (covers superdesk-planning's nested
|
|
13
|
+
* client/planning-extension without hard-coding it).
|
|
14
|
+
* 3. Replace whatever is currently at node_modules/<package-name> with a
|
|
15
|
+
* symlink to the source's absolute path.
|
|
16
|
+
*
|
|
17
|
+
* Pre-condition: node_modules must already exist in the cwd. The command
|
|
18
|
+
* errors out otherwise to catch the common mistake of linking before the
|
|
19
|
+
* template's own `npm install` has run.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const path = require('path');
|
|
24
|
+
const {execFileSync} = require('child_process');
|
|
25
|
+
|
|
26
|
+
function readPkg(dir) {
|
|
27
|
+
return JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns every directory inside `sourceRoot` that contains a package.json
|
|
32
|
+
* we need to install. That is the root itself, plus any `client/*` subdir
|
|
33
|
+
* that ships its own package.json (covers the superdesk-planning layout
|
|
34
|
+
* where the host-build-relevant deps live under client/planning-extension).
|
|
35
|
+
*/
|
|
36
|
+
function findInstallTargets(sourceRoot) {
|
|
37
|
+
const targets = [];
|
|
38
|
+
|
|
39
|
+
if (fs.existsSync(path.join(sourceRoot, 'package.json'))) {
|
|
40
|
+
targets.push(sourceRoot);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const clientDir = path.join(sourceRoot, 'client');
|
|
44
|
+
|
|
45
|
+
if (fs.existsSync(clientDir) && fs.statSync(clientDir).isDirectory()) {
|
|
46
|
+
for (const entry of fs.readdirSync(clientDir, {withFileTypes: true})) {
|
|
47
|
+
if (!entry.isDirectory()) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const nestedPkg = path.join(clientDir, entry.name, 'package.json');
|
|
52
|
+
|
|
53
|
+
if (fs.existsSync(nestedPkg)) {
|
|
54
|
+
targets.push(path.join(clientDir, entry.name));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return targets;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function npmInstall(dir) {
|
|
63
|
+
console.info(` installing dependencies in ${dir}`);
|
|
64
|
+
execFileSync('npm', ['install'], {stdio: 'inherit', cwd: dir});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function ensureSymlink(target, linkPath) {
|
|
68
|
+
let existing;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
existing = fs.lstatSync(linkPath);
|
|
72
|
+
} catch (e) {
|
|
73
|
+
if (e.code !== 'ENOENT') {
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (existing != null) {
|
|
79
|
+
if (existing.isSymbolicLink() || !existing.isDirectory()) {
|
|
80
|
+
fs.unlinkSync(linkPath);
|
|
81
|
+
} else {
|
|
82
|
+
fs.rmSync(linkPath, {recursive: true, force: true});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fs.symlinkSync(target, linkPath, 'dir');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function devLink(consumerDir, sources) {
|
|
90
|
+
const consumerNodeModules = path.join(consumerDir, 'node_modules');
|
|
91
|
+
|
|
92
|
+
if (!fs.existsSync(consumerNodeModules)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Consumer node_modules not found at ${consumerNodeModules}. `
|
|
95
|
+
+ 'Run `npm install` in the template first, then re-run dev-link.'
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const source of sources) {
|
|
100
|
+
const sourceAbs = path.resolve(consumerDir, source);
|
|
101
|
+
|
|
102
|
+
if (!fs.existsSync(sourceAbs)) {
|
|
103
|
+
throw new Error(`Source path does not exist: ${sourceAbs}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const pkg = readPkg(sourceAbs);
|
|
107
|
+
const packageName = pkg.name;
|
|
108
|
+
|
|
109
|
+
if (packageName == null) {
|
|
110
|
+
throw new Error(`Source ${sourceAbs} has no name field in package.json`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
console.info(`\n${packageName} <- ${sourceAbs}`);
|
|
114
|
+
|
|
115
|
+
for (const target of findInstallTargets(sourceAbs)) {
|
|
116
|
+
npmInstall(target);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const linkPath = path.join(consumerNodeModules, packageName);
|
|
120
|
+
|
|
121
|
+
ensureSymlink(sourceAbs, linkPath);
|
|
122
|
+
console.info(` linked node_modules/${packageName}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function register(program, currentDir) {
|
|
127
|
+
program.command('dev-link <source...>')
|
|
128
|
+
.description(
|
|
129
|
+
'symlink one or more local source repos into the current node_modules '
|
|
130
|
+
+ 'for local development. Runs `npm install` in each source (and in any '
|
|
131
|
+
+ 'nested client/<extension> packages) before linking.'
|
|
132
|
+
)
|
|
133
|
+
.action((sources) => {
|
|
134
|
+
devLink(currentDir, sources);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {register, devLink};
|
|
@@ -110,7 +110,7 @@ function getExtensionDirectoriesSync(clientPath) {
|
|
|
110
110
|
.then((res) => res.default),
|
|
111
111
|
}
|
|
112
112
|
*/
|
|
113
|
-
var extensionRegistrationPattern = /id:\W*'(.*)',\W*load:\W*import\('(.+?)'/g;
|
|
113
|
+
var extensionRegistrationPattern = /id:\W*['"](.*)['"],\W*load:\W*import\(['"](.+?)['"]/g;
|
|
114
114
|
|
|
115
115
|
const matches = [];
|
|
116
116
|
|
|
@@ -83,6 +83,24 @@ module.exports = function installExtensions(clientDir) {
|
|
|
83
83
|
directories.forEach(({extensionRootPath, extensionSrcPath}) => {
|
|
84
84
|
// if src dir doesn't exist, assume that the extension is already built (e.g. when installed from npm)
|
|
85
85
|
if (fs.existsSync(extensionSrcPath)) {
|
|
86
|
+
const pkgPath = path.join(extensionRootPath, 'package.json');
|
|
87
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
88
|
+
|
|
89
|
+
// Extensions whose `main` points at TypeScript source are consumed
|
|
90
|
+
// directly by webpack's ts-loader. Skip compile and the legacy
|
|
91
|
+
// `correct*` fixups. Still install runtime `dependencies` so webpack
|
|
92
|
+
// can resolve them via the extension's nested node_modules walk.
|
|
93
|
+
// (When workspaces land, this per-extension install goes away.)
|
|
94
|
+
if (typeof pkg.main === 'string' && /\.(ts|tsx)$/.test(pkg.main)) {
|
|
95
|
+
if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
|
|
96
|
+
execSync(
|
|
97
|
+
'npm install --no-audit --omit=dev',
|
|
98
|
+
{stdio: 'inherit', cwd: extensionRootPath}
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
86
104
|
correctApiDefinitionsPath(extensionRootPath, clientDir);
|
|
87
105
|
|
|
88
106
|
execSync(
|
package/src/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const installExtensions = require('./extensions/install-extensions');
|
|
|
9
9
|
const {mergeTranslationsFromExtensions} = require('./extensions/translations');
|
|
10
10
|
const {extractTranslations} = require('./extensions/extract-translations');
|
|
11
11
|
const {namespaceCSS, watchCSS} = require('./extensions/css');
|
|
12
|
+
const devLink = require('./dev-link');
|
|
12
13
|
|
|
13
14
|
const {Command} = require('commander');
|
|
14
15
|
const program = new Command();
|
|
@@ -108,5 +109,7 @@ extensions
|
|
|
108
109
|
|
|
109
110
|
program.addCommand(extensions);
|
|
110
111
|
|
|
112
|
+
devLink.register(program, currentDir);
|
|
113
|
+
|
|
111
114
|
program.version(require('../package.json').version);
|
|
112
115
|
program.parse(process.argv);
|
package/src/po-to-json/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
var fs = require('fs');
|
|
2
2
|
var path = require('path');
|
|
3
3
|
var execSync = require('child_process').execSync;
|
|
4
|
-
var _ = require('lodash');
|
|
5
4
|
const {isDirectory} = require('../utils');
|
|
6
5
|
|
|
7
6
|
function getModuleDir(moduleName) {
|
|
@@ -90,7 +89,7 @@ function compileTranslationsPoToJson(translationsPoDir, translationsJsonDir) {
|
|
|
90
89
|
return;
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
if (
|
|
92
|
+
if (filename.endsWith('.po') !== true) {
|
|
94
93
|
return;
|
|
95
94
|
}
|
|
96
95
|
|