Skip to content

Commit b1bcc6c

Browse files
committed
WIP
1 parent 7ba545b commit b1bcc6c

3 files changed

Lines changed: 196 additions & 1 deletion

File tree

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"install": "node-gyp-build",
1717
"prebuild": "node ./scripts/prebuild.js",
1818
"build": "shx rm -rf ./dist && tsc -p ./tsconfig.build.json",
19-
"postversion": "npm install --package-lock-only --ignore-scripts --silent",
19+
"version": "node ./scripts/version.js",
20+
"prepublishOnly": "node ./scripts/prepublishOnly.js",
2021
"ts-node": "ts-node",
2122
"test": "jest",
2223
"lint": "eslint '{src,tests,scripts,benches}/**/*.{js,ts}'",
@@ -37,6 +38,12 @@
3738
"node-gyp-build": "4.4.0",
3839
"threads": "^1.6.5"
3940
},
41+
"optionalDependencies": {
42+
"@matrixai/db-darwin-arm64": "5.1.0",
43+
"@matrixai/db-darwin-x64": "5.1.0",
44+
"@matrixai/db-linux-x64": "5.1.0",
45+
"@matrixai/db-win32-x64": "5.1.0"
46+
},
4047
"devDependencies": {
4148
"@swc/core": "^1.3.62",
4249
"@swc/jest": "^0.2.26",

scripts/prepublishOnly.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* This runs before `npm publish` command.
5+
* This will take the native objects in `prebuild/`
6+
* and create native packages under `prepublishOnly/`.
7+
*
8+
* For example:
9+
*
10+
* /prepublishOnly
11+
* /@org
12+
* /name-linux-x64
13+
* /package.json
14+
* /node.napi.node
15+
* /README.md
16+
*/
17+
18+
const os = require('os');
19+
const fs = require('fs');
20+
const path = require('path');
21+
const process = require('process');
22+
const childProcess = require('child_process');
23+
const packageJSON = require('../package.json');
24+
25+
const platform = os.platform();
26+
27+
/* eslint-disable no-console */
28+
async function main(argv = process.argv) {
29+
argv = argv.slice(2);
30+
let tag;
31+
let dryRun = false;
32+
const restArgs = [];
33+
while (argv.length > 0) {
34+
const option = argv.shift();
35+
let match;
36+
if ((match = option.match(/--tag(?:=(.+)|$)/))) {
37+
tag = match[1] ?? argv.shift();
38+
} else if ((match = option.match(/--dry-run$/))) {
39+
dryRun = true;
40+
} else {
41+
restArgs.push(option);
42+
}
43+
}
44+
if (tag == null) {
45+
tag = process.env.npm_config_tag;
46+
}
47+
const projectRoot = path.join(__dirname, '..');
48+
const prebuildPath = path.join(projectRoot, 'prebuild');
49+
const prepublishOnlyPath = path.join(projectRoot, 'prepublishOnly');
50+
const buildNames = (await fs.promises.readdir(prebuildPath)).filter(
51+
(filename) => /^(?:[^-]+)-(?:[^-]+)-(?:[^-]+)$/.test(filename),
52+
);
53+
if (buildNames.length < 1) {
54+
console.error(
55+
'You must prebuild at least 1 native object with the filename of `name-platform-arch` before prepublish',
56+
);
57+
process.exitCode = 1;
58+
return process.exitCode;
59+
}
60+
// Extract out the org name, this may be undefined
61+
const orgName = packageJSON.name.match(/^@[^/]+/)?.[0];
62+
for (const buildName of buildNames) {
63+
// This is `name-platform-arch`
64+
const name = path.basename(buildName, '.node');
65+
// This is `@org/name-platform-arch`, uses `posix` to force usage of `/`
66+
const packageName = path.posix.join(orgName ?? '', name);
67+
const constraints = name.match(
68+
/^(?:[^-]+)-(?<platform>[^-]+)-(?<arch>[^-]+)$/,
69+
);
70+
// This will be `prebuild/name-platform-arch.node`
71+
const buildPath = path.join(prebuildPath, buildName);
72+
// This will be `prepublishOnly/@org/name-platform-arch`
73+
const packagePath = path.join(prepublishOnlyPath, packageName);
74+
console.error('Packaging:', packagePath);
75+
try {
76+
await fs.promises.rm(packagePath, {
77+
recursive: true,
78+
});
79+
} catch (e) {
80+
if (e.code !== 'ENOENT') throw e;
81+
}
82+
await fs.promises.mkdir(packagePath, { recursive: true });
83+
const nativePackageJSON = {
84+
name: packageName,
85+
version: packageJSON.version,
86+
homepage: packageJSON.homepage,
87+
author: packageJSON.author,
88+
contributors: packageJSON.contributors,
89+
description: packageJSON.description,
90+
keywords: packageJSON.keywords,
91+
license: packageJSON.license,
92+
repository: packageJSON.repository,
93+
main: 'node.napi.node',
94+
os: [constraints.groups.platform],
95+
cpu: [...constraints.groups.arch.split('+')],
96+
};
97+
const packageJSONPath = path.join(packagePath, 'package.json');
98+
console.error(`Writing ${packageJSONPath}`);
99+
const packageJSONString = JSON.stringify(nativePackageJSON, null, 2);
100+
console.error(packageJSONString);
101+
await fs.promises.writeFile(packageJSONPath, packageJSONString, {
102+
encoding: 'utf-8',
103+
});
104+
const packageReadmePath = path.join(packagePath, 'README.md');
105+
console.error(`Writing ${packageReadmePath}`);
106+
const packageReadme = `# ${packageName}\n`;
107+
console.error(packageReadme);
108+
await fs.promises.writeFile(packageReadmePath, packageReadme, {
109+
encoding: 'utf-8',
110+
});
111+
const packageBuildPath = path.join(packagePath, 'node.napi.node');
112+
console.error(`Copying ${buildPath} to ${packageBuildPath}`);
113+
await fs.promises.copyFile(buildPath, packageBuildPath);
114+
const publishArgs = [
115+
'publish',
116+
packagePath,
117+
...(tag != null ? [`--tag=${tag}`] : []),
118+
'--access=public',
119+
...(dryRun ? ['--dry-run'] : []),
120+
];
121+
console.error('Running npm publish:');
122+
console.error(['npm', ...publishArgs].join(' '));
123+
childProcess.execFileSync('npm', publishArgs, {
124+
stdio: ['inherit', 'inherit', 'inherit'],
125+
windowsHide: true,
126+
encoding: 'utf-8',
127+
shell: platform === 'win32' ? true : false,
128+
});
129+
}
130+
}
131+
/* eslint-enable no-console */
132+
133+
void main();

scripts/version.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* This runs after `npm version` command updates the version but before changes are commited.
5+
* This will also update the `package.json` optional native dependencies
6+
* to match the same version as the version of this package.
7+
* This maintains the same version between this master package
8+
* and the optional native dependencies.
9+
* At the same time, the `package-lock.json` is also regenerated.
10+
* Note that at this point, the new optional native dependencies have
11+
* not yet been published, so the `--package-lock-only` flag is used
12+
* to prevent `npm` from attempting to download unpublished packages.
13+
*/
14+
15+
const path = require('path');
16+
const os = require('os');
17+
const childProcess = require('child_process');
18+
const packageJSON = require('../package.json');
19+
20+
const platform = os.platform();
21+
22+
/* eslint-disable no-console */
23+
async function main() {
24+
console.error(
25+
'Updating the package.json with optional native dependencies and package-lock.json',
26+
);
27+
const optionalDepsNative = [];
28+
for (const key in packageJSON.optionalDependencies) {
29+
if (key.startsWith(packageJSON.name)) {
30+
optionalDepsNative.push(`${key}@${packageJSON.version}`);
31+
}
32+
}
33+
if (optionalDepsNative.length > 0) {
34+
const installArgs = [
35+
'install',
36+
'--ignore-scripts',
37+
'--silent',
38+
'--package-lock-only',
39+
'--save-optional',
40+
'--save-exact',
41+
...optionalDepsNative,
42+
];
43+
console.error('Running npm install:');
44+
console.error(['npm', ...installArgs].join(' '));
45+
childProcess.execFileSync('npm', installArgs, {
46+
stdio: ['inherit', 'inherit', 'inherit'],
47+
windowsHide: true,
48+
encoding: 'utf-8',
49+
shell: platform === 'win32' ? true : false,
50+
});
51+
}
52+
}
53+
/* eslint-enable no-console */
54+
55+
void main();

0 commit comments

Comments
 (0)