Skip to content

Commit 4d18244

Browse files
author
Corentin Mors
authored
Packaging optimization (#250)
This PR aims to improve how dependencies are bundled and benefit from ESM builds of some packages. It also improves how pkg is used after esbuild to prevent packaging some dependencies twice.
1 parent 85337ac commit 4d18244

File tree

19 files changed

+510
-797
lines changed

19 files changed

+510
-797
lines changed

.github/workflows/manual-test-release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
- run: yarn workspaces focus --all --production
3636
# package final binaries
3737
- run: |
38-
yarn dlx @yao-pkg/pkg@5.11.1 . -t node18-${{ matrix.settings.target }} -o bundle/dcli-${{ matrix.settings.target }}${{ matrix.settings.extension }} -C GZip "--public" "--public-packages" "tslib,thirty-two,node-hkdf-sync,vows" "--no-bytecode"
38+
yarn dlx @yao-pkg/pkg@5.11.1 ./dist -t node18-${{ matrix.settings.target }} -o bundle/dcli-${{ matrix.settings.target }}${{ matrix.settings.extension }} -C GZip "--public" "--public-packages" "tslib,thirty-two,node-hkdf-sync,vows" "--no-bytecode"
3939
4040
- name: Archive binary artifact
4141
uses: actions/upload-artifact@v4

.github/workflows/release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
- run: yarn workspaces focus --all --production
3939
# package final binaries
4040
- run: |
41-
yarn dlx @yao-pkg/pkg@5.11.1 . -t node18-${{ matrix.settings.target }} -o bundle/dcli-${{ matrix.settings.target }}${{ matrix.settings.extension }} -C GZip "--public" "--public-packages" "tslib,thirty-two,node-hkdf-sync,vows" "--no-bytecode"
41+
yarn dlx @yao-pkg/pkg@5.11.1 ./dist -t node18-${{ matrix.settings.target }} -o bundle/dcli-${{ matrix.settings.target }}${{ matrix.settings.extension }} -C GZip "--public" "--public-packages" "tslib,thirty-two,node-hkdf-sync,vows" "--no-bytecode"
4242
4343
- name: Archive binary artifact
4444
uses: actions/upload-artifact@v4

package.json

+18-19
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
},
1010
"pkg": {
1111
"assets": [
12-
"node_modules/better-sqlite3/build/Release/better_sqlite3.node",
13-
"node_modules/@json2csv/plainjs/dist/**/*",
14-
"node_modules/@json2csv/formatters/dist/**/*",
15-
"node_modules/@json2csv/transforms/dist/**/*",
16-
"node_modules/@streamparser/json/dist/**/*",
17-
"node_modules/node-mac-auth/build/Release/auth.node"
12+
"../node_modules/better-sqlite3/build/Release/better_sqlite3.node",
13+
"../node_modules/@json2csv/plainjs/dist/**/*",
14+
"../node_modules/@json2csv/formatters/dist/**/*",
15+
"../node_modules/@json2csv/transforms/dist/**/*",
16+
"../node_modules/@streamparser/json/dist/**/*",
17+
"../node_modules/node-mac-auth/build/Release/auth.node"
1818
]
1919
},
2020
"scripts": {
@@ -24,10 +24,10 @@
2424
"format": "prettier --write src && eslint --fix src",
2525
"start": "node dist/index.cjs",
2626
"start:dev": "node build/index.js",
27-
"pkg:linux": "pkg . -t node18-linux-x64 -o bundle/dcli-linux -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
28-
"pkg:macos": "pkg . -t node18-macos-x64 -o bundle/dcli-macos -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
29-
"pkg:macos-arm": "pkg . -t node18-macos-arm64 -o bundle/dcli-macos-arm -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
30-
"pkg:win": "pkg . -t node18-win-x64 -o bundle/dcli-win.exe -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
27+
"pkg:linux": "pkg ./dist -t node18-linux-x64 -o bundle/dcli-linux -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
28+
"pkg:macos": "pkg ./dist -t node18-macos-x64 -o bundle/dcli-macos -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
29+
"pkg:macos-arm": "pkg ./dist -t node18-macos-arm64 -o bundle/dcli-macos-arm -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode --no-native-build",
30+
"pkg:win": "pkg ./dist -t node18-win-x64 -o bundle/dcli-win.exe -C GZip --public --public-packages tslib,thirty-two,node-hkdf-sync,vows --no-bytecode",
3131
"pkg": "yarn run build && yarn run pkg:linux && yarn run pkg:macos && yarn run pkg:win",
3232
"version:bump": "yarn run build && node ./build/bumpVersion.js",
3333
"prepare": "husky",
@@ -56,14 +56,14 @@
5656
"@types/better-sqlite3": "^7.6.10",
5757
"@types/chai": "^4.3.16",
5858
"@types/inquirer": "^9.0.7",
59-
"@types/libsodium-wrappers": "^0",
59+
"@types/libsodium-wrappers": "^0.7.14",
6060
"@types/mocha": "^10.0.6",
6161
"@types/node": "^18.19.33",
6262
"@typescript-eslint/eslint-plugin": "^7.8.0",
6363
"@typescript-eslint/parser": "^7.8.0",
6464
"@yao-pkg/pkg": "^5.11.5",
6565
"chai": "^5.1.1",
66-
"esbuild": "^0.21.2",
66+
"esbuild": "^0.21.4",
6767
"eslint": "^8.57.0",
6868
"eslint-config-prettier": "^9.1.0",
6969
"eslint-plugin-import": "^2.29.1",
@@ -75,23 +75,22 @@
7575
},
7676
"dependencies": {
7777
"@dashlane/nsm-attestation": "^1.0.1",
78+
"@inquirer/prompts": "^5.0.4",
7879
"@json2csv/plainjs": "^7.0.6",
7980
"@json2csv/transforms": "^7.0.6",
8081
"@napi-rs/clipboard": "^1.1.2",
8182
"@napi-rs/keyring": "^1.1.6",
8283
"@node-rs/argon2": "^1.8.3",
83-
"ajv": "^8.13.0",
84+
"ajv": "^8.14.0",
8485
"ajv-formats": "^3.0.1",
85-
"better-sqlite3": "^10.0.0",
86-
"commander": "^12.0.0",
87-
"got": "^14.2.1",
88-
"inquirer": "^9.2.21",
89-
"inquirer-search-list": "^1.2.6",
86+
"better-sqlite3": "^11.0.0",
87+
"commander": "^12.1.0",
88+
"got": "^14.3.0",
9089
"jsonpath-plus": "^9.0.0",
9190
"libsodium-wrappers": "^0.7.13",
9291
"node-mac-auth": "^1.0.0",
9392
"otplib": "^12.0.1",
94-
"playwright-core": "^1.44.0",
93+
"playwright-core": "^1.44.1",
9594
"winston": "^3.13.0",
9695
"xml-js": "^1.6.11",
9796
"zlib": "^1.0.5"

scripts/build.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import os from 'os';
44
import fs from 'fs';
5-
import path, { format } from 'path';
5+
import path from 'path';
66
import process from 'process';
77
import childProcess from 'child_process';
88
import esbuild from 'esbuild';
@@ -73,11 +73,36 @@ async function main(argv = process.argv) {
7373
// Minify and keep the original names
7474
minify: true,
7575
keepNames: true,
76-
outfile: path.join(distPath, 'index.cjs')
76+
outfile: path.join(distPath, 'index.cjs'),
77+
metafile: true
7778
};
7879
console.error('Running esbuild:');
7980
console.error(esbuildOptions);
80-
await esbuild.build(esbuildOptions);
81+
const result = await esbuild.build(esbuildOptions);
82+
fs.writeFileSync(path.join(distPath, 'index.meta.json'), JSON.stringify(result.metafile, null, 2));
83+
84+
// Copy package.json
85+
const pkgJson = cleanPkgJson(packageJSON);
86+
fs.writeFileSync(path.join(distPath, 'package.json'), JSON.stringify(pkgJson, null, 2));
8187
}
8288

89+
const cleanPkgJson = (json) => {
90+
delete json.devDependencies;
91+
delete json.optionalDependencies;
92+
const oldDependencies = json.dependencies;
93+
delete json.dependencies;
94+
json.dependencies = {};
95+
96+
for (const [name, version] of Object.entries(oldDependencies)) {
97+
if (Object.keys(json.nativeDependencies).includes(name)) {
98+
json.dependencies[name] = version;
99+
}
100+
}
101+
delete json.nativeDependencies;
102+
delete json.scripts;
103+
json.bin.dcli = 'index.cjs';
104+
json.main = 'index.cjs';
105+
return json;
106+
};
107+
83108
void main();

src/command-handlers/lock.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import * as winston from 'winston';
21
import { deleteLocalKey } from '../modules/crypto/keychainManager.js';
32
import { connectAndPrepare } from '../modules/database/index.js';
3+
import { logger } from '../logger.js';
44

55
export const runLock = async () => {
66
const { db, localConfiguration } = await connectAndPrepare({
@@ -18,7 +18,7 @@ export const runLock = async () => {
1818
if (error instanceof Error) {
1919
errorMessage = error.message;
2020
}
21-
winston.warn(`Unable to lock the vault: ${errorMessage}`);
21+
logger.warn(`Unable to lock the vault: ${errorMessage}`);
2222
}
2323

2424
db.prepare('UPDATE device SET masterPasswordEncrypted = ? WHERE login = ?')

src/modules/api-connect/signRequest.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as crypto from 'crypto';
1+
import crypto from 'crypto';
22
import { makeCanonicalRequest } from './makeCanonicalRequest.js';
33
import { Authentication, SignRequestParams } from './types.js';
44
import { logger } from '../../logger.js';

src/modules/crypto/decrypt.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import * as argon2 from '@node-rs/argon2';
2-
import * as xmlJs from 'xml-js';
1+
import argon2 from '@node-rs/argon2';
2+
import xmlJs from 'xml-js';
33
import crypto from 'crypto';
44
import { promisify } from 'util';
55
import zlib from 'zlib';

src/modules/crypto/hash.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as crypto from 'crypto';
1+
import crypto from 'crypto';
22

33
const toBuffer = (data: Buffer | string): Buffer => {
44
return Buffer.isBuffer(data) ? data : Buffer.from(data);

src/modules/tunnel-api-connect/apiconnect.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as sodium from 'libsodium-wrappers';
1+
import sodium from 'libsodium-wrappers';
22
import { clientHello, terminateHello, SendSecureContentParams, sendSecureContent } from './steps/index.js';
33
import { ApiConnectParams, ApiConnect, ApiData, ApiRequestsDefault } from './types.js';
44
import { makeClientKeyPair, makeOrRefreshSession } from './utils/index.js';

src/modules/tunnel-api-connect/steps/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type * as sodium from 'libsodium-wrappers';
1+
import type sodium from 'libsodium-wrappers';
22
import { ApiRequestsDefault } from '../types.js';
33

44
export interface ApiEndpointResponse<T> {

src/modules/tunnel-api-connect/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { EnclavePcr } from '@dashlane/nsm-attestation';
2-
import type * as sodium from 'libsodium-wrappers';
2+
import type sodium from 'libsodium-wrappers';
33
import type { ClientHelloParsedResponse, SendSecureContentParams, TerminateHelloResponse } from './steps/index.js';
44

55
export interface ApiRequestsDefault {

src/modules/typecheck/customize_ajv.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
1-
import Ajv, { SchemaObjCxt } from 'ajv';
2-
import {
3-
AnySchemaObject,
4-
DataValidateFunction,
5-
DataValidationCxt,
6-
ErrorObject,
7-
KeywordDefinition,
8-
} from 'ajv/dist/types';
1+
import Ajv, { SchemaObjCxt, AnySchemaObject, ErrorObject, KeywordDefinition } from 'ajv';
2+
import type { DataValidateFunction, DataValidationCxt } from 'ajv/dist/types';
93

104
// https://github.com/ajv-validator/ajv-formats/blob/master/src/formats.ts#L237
115
const BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;

src/modules/typecheck/index.ts

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import * as Ajv from 'ajv';
2-
import addFormats from 'ajv-formats';
1+
import Ajv, { ErrorObject, ValidateFunction } from 'ajv';
32
import Ajv2020 from 'ajv/dist/2020.js';
3+
import addFormats from 'ajv-formats';
44
import { customizeAjv } from './customize_ajv.js';
55

66
export class TypeCheckError extends Error {
@@ -22,7 +22,7 @@ export class JSONParsingError extends TypeCheckError {
2222

2323
export class JSONValidationError extends TypeCheckError {
2424
constructor(
25-
readonly reasonAjv: Ajv.ErrorObject,
25+
readonly reasonAjv: ErrorObject,
2626
details?: string
2727
) {
2828
super(
@@ -34,11 +34,11 @@ export class JSONValidationError extends TypeCheckError {
3434
}
3535
}
3636

37-
export type DetailedAjvErrorObject = { errors: Ajv.ErrorObject[]; details: string };
37+
export type DetailedAjvErrorObject = { errors: ErrorObject[]; details: string };
3838

39-
export const detailedErrorReportingOverride = (errors: Ajv.ErrorObject[]): DetailedAjvErrorObject => {
39+
export const detailedErrorReportingOverride = (errors: ErrorObject[]): DetailedAjvErrorObject => {
4040
const details = errors
41-
.map((obj: Ajv.ErrorObject) => `[${obj.schemaPath}] [${JSON.stringify(obj.params)}] ${obj.message ?? ''}`)
41+
.map((obj: ErrorObject) => `[${obj.schemaPath}] [${JSON.stringify(obj.params)}] ${obj.message ?? ''}`)
4242
.join('\n')
4343
.trim();
4444
return { errors, details };
@@ -47,11 +47,11 @@ export const detailedErrorReportingOverride = (errors: Ajv.ErrorObject[]): Detai
4747
type JSONSchema = Record<string, unknown>;
4848

4949
export class TypeCheck<T> {
50-
private validator: Ajv.ValidateFunction;
50+
private validator: ValidateFunction;
5151

5252
constructor(
5353
schema: JSONSchema,
54-
readonly errorReportingOverride?: (errors: Ajv.ErrorObject[]) => DetailedAjvErrorObject,
54+
readonly errorReportingOverride?: (errors: ErrorObject[]) => DetailedAjvErrorObject,
5555
openApiValidation?: boolean
5656
) {
5757
if (openApiValidation) {
@@ -61,6 +61,7 @@ export class TypeCheck<T> {
6161
strictTypes: false,
6262
strictRequired: false,
6363
allowMatchingProperties: true,
64+
code: { esm: true },
6465
});
6566
ajv.addFormat('media-range', true); // used in OpenAPI 3.1
6667

@@ -69,7 +70,7 @@ export class TypeCheck<T> {
6970

7071
this.validator = ajv.compile(schema);
7172
} else {
72-
const ajv = new Ajv.default({ allErrors: true });
73+
const ajv = new Ajv({ allErrors: true, code: { esm: true } });
7374
addFormats(ajv);
7475
customizeAjv(ajv);
7576
this.validator = ajv.compile(schema);

src/requestApi.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Response, HTTPError } from 'got';
2-
import * as apiConnect from './modules/api-connect/index.js';
2+
import { Authentication, postRequestAPI } from './modules/api-connect/index.js';
33
import { CLI_VERSION, cliVersionToString } from './cliVersion.js';
44
import { gotImplementation } from './utils/index.js';
55

66
interface RequestApi {
77
payload: Record<string, unknown>;
88
path: string;
9-
authentication: apiConnect.Authentication;
9+
authentication: Authentication;
1010
isNitroEncryptionService?: boolean;
1111
}
1212

@@ -46,7 +46,7 @@ const requestApi = async <T>(params: RequestApi): Promise<T> => {
4646

4747
let response: Response<string>;
4848
try {
49-
response = await apiConnect.postRequestAPI<Response<string>>({
49+
response = await postRequestAPI<Response<string>>({
5050
requestFunction: gotImplementation,
5151
authentication,
5252
path: (isNitroEncryptionService ? 'v1-nitro-encryption-service/' : 'v1/') + path,

0 commit comments

Comments
 (0)