@companion-module/tools 2.7.1 → 3.0.0
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/CHANGELOG.md +15 -0
- package/dist/build-config.d.ts +26 -0
- package/dist/build-config.js +1 -0
- package/dist/eslint/config.d.mts +9 -0
- package/dist/eslint/config.mjs +123 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/scripts/build-connection.d.ts +2 -0
- package/dist/scripts/build-connection.js +19 -0
- package/dist/scripts/build-surface.d.ts +2 -0
- package/dist/scripts/build-surface.js +17 -0
- package/dist/scripts/check-connection.d.ts +2 -0
- package/dist/scripts/check-connection.js +25 -0
- package/dist/scripts/check-surface.d.ts +2 -0
- package/dist/scripts/check-surface.js +23 -0
- package/dist/scripts/lib/build-util.d.ts +6 -0
- package/dist/scripts/lib/build-util.js +222 -0
- package/package.json +35 -23
- package/tsconfig/node22/recommended-esm.json +0 -3
- package/tsconfig/node22/recommended.json +0 -3
- package/eslint/config.mjs +0 -155
- package/index.js +0 -1
- package/scripts/build-connection.js +0 -27
- package/scripts/build-surface.js +0 -22
- package/scripts/check-connection.js +0 -40
- package/scripts/check-surface.js +0 -40
- package/scripts/generate-connection-manifest.js +0 -83
- package/scripts/lib/build-util.js +0 -254
- package/tsconfig/node18/recommended.json +0 -30
- package/webpack.config.cjs +0 -82
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.0.0](https://github.com/bitfocus/companion-module-tools/compare/v2.7.1...v3.0.0) (2026-03-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* simplify and remove support for module api v1
|
|
9
|
+
* require node22 and module-base 2.0
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* Add type declarations for `@companion-module/tools/eslint/config.mjs` by converting the repository code to TypeScript. ([f4220e8](https://github.com/bitfocus/companion-module-tools/commit/f4220e8c0ec8a3418d68483fbd562bfb2d767a12))
|
|
14
|
+
* replace webpack with esbuild ([395d28d](https://github.com/bitfocus/companion-module-tools/commit/395d28d39c7b31e4ca28cc8e0468c14e4733952e))
|
|
15
|
+
* require node22 and module-base 2.0 ([bb3fadc](https://github.com/bitfocus/companion-module-tools/commit/bb3fadc9474cdbd77e4ade34e4f8964de1e17db3))
|
|
16
|
+
* simplify and remove support for module api v1 ([6648b13](https://github.com/bitfocus/companion-module-tools/commit/6648b132a1af12e0fe0d0e300b5bc4bfee201f45))
|
|
17
|
+
|
|
3
18
|
## [2.7.1](https://github.com/bitfocus/companion-module-tools/compare/v2.7.0...v2.7.1) (2026-02-22)
|
|
4
19
|
|
|
5
20
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface ModuleBuildConfig {
|
|
2
|
+
/**
|
|
3
|
+
* Disable the minification of the code bundle
|
|
4
|
+
* Some libraries can break when names are mangled as part of minification
|
|
5
|
+
*/
|
|
6
|
+
disableMinifier?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Extra files to include in the module package
|
|
9
|
+
*/
|
|
10
|
+
extraFiles?: string[];
|
|
11
|
+
/**
|
|
12
|
+
* If the module uses any native libraries, that utilise `pkg-prebuilds`
|
|
13
|
+
* specify their names here instead of in externals, to efficiently pack the prebuilt binaries
|
|
14
|
+
*/
|
|
15
|
+
prebuilds?: string[];
|
|
16
|
+
/**
|
|
17
|
+
* If any used libraries do not like being bundled, you can name them here to preserve them on disk
|
|
18
|
+
* Warning: This is discouraged as it can really bloat modules, and cause installation problems in some scenarios
|
|
19
|
+
*/
|
|
20
|
+
externals?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* Prepare bundles of additional entrypoints
|
|
23
|
+
* This is typically useful when using worker-threads
|
|
24
|
+
*/
|
|
25
|
+
additionalEntrypoints?: Record<string, string>;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Linter } from 'eslint';
|
|
2
|
+
type ConfigOptions = {
|
|
3
|
+
enableTypescript?: boolean;
|
|
4
|
+
ignores?: string[];
|
|
5
|
+
commonRules?: Readonly<Linter.RulesRecord>;
|
|
6
|
+
typescriptRules?: Readonly<Linter.RulesRecord>;
|
|
7
|
+
};
|
|
8
|
+
export declare function generateEslintConfig(options?: ConfigOptions): Promise<Linter.Config[]>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
2
|
+
import eslint from '@eslint/js';
|
|
3
|
+
import neslint from 'eslint-plugin-n';
|
|
4
|
+
function compactObj(obj) {
|
|
5
|
+
const result = {};
|
|
6
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
7
|
+
if (value)
|
|
8
|
+
result[key] = value;
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
export async function generateEslintConfig(options = {}) {
|
|
13
|
+
const tseslint = options.enableTypescript ? await import('typescript-eslint') : null;
|
|
14
|
+
const result = {
|
|
15
|
+
// extends: commonExtends,
|
|
16
|
+
plugins: compactObj({
|
|
17
|
+
'@typescript-eslint': tseslint ? tseslint.plugin : null,
|
|
18
|
+
}),
|
|
19
|
+
rules: {
|
|
20
|
+
// Default rules to be applied everywhere
|
|
21
|
+
'prettier/prettier': 'error',
|
|
22
|
+
...eslint.configs.recommended.rules,
|
|
23
|
+
'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_(.+)' }],
|
|
24
|
+
'no-extra-semi': 'off',
|
|
25
|
+
// 'n/no-unsupported-features/es-syntax': ['error', { ignores: ['modules'] }],
|
|
26
|
+
'no-use-before-define': 'off',
|
|
27
|
+
'no-warning-comments': ['error', { terms: ['nocommit', '@nocommit', '@no-commit'] }],
|
|
28
|
+
// 'jest/no-mocks-import': 'off',
|
|
29
|
+
...(options.commonRules || {}),
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
return [
|
|
33
|
+
// setup the parser first
|
|
34
|
+
tseslint
|
|
35
|
+
? {
|
|
36
|
+
languageOptions: {
|
|
37
|
+
parser: tseslint.parser,
|
|
38
|
+
parserOptions: {
|
|
39
|
+
project: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
: null,
|
|
44
|
+
neslint.configs['flat/recommended-script'],
|
|
45
|
+
result,
|
|
46
|
+
...(tseslint ? tseslint.configs.recommendedTypeChecked : []),
|
|
47
|
+
{
|
|
48
|
+
// disable type-aware linting on JS files
|
|
49
|
+
files: ['**/*.js', '**/*.cjs', '**/*.mjs'],
|
|
50
|
+
...(tseslint ? tseslint.configs.disableTypeChecked : {}),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
files: ['*.mjs'],
|
|
54
|
+
languageOptions: {
|
|
55
|
+
sourceType: 'module',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
tseslint
|
|
59
|
+
? {
|
|
60
|
+
files: ['**/*.ts', '**/*.cts', '**/*.mts'],
|
|
61
|
+
rules: {
|
|
62
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
63
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
64
|
+
'@typescript-eslint/no-unused-vars': [
|
|
65
|
+
'error',
|
|
66
|
+
{ argsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_', varsIgnorePattern: '^_(.+)' },
|
|
67
|
+
],
|
|
68
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
69
|
+
'@typescript-eslint/explicit-module-boundary-types': ['error'],
|
|
70
|
+
'@typescript-eslint/promise-function-async': 'error',
|
|
71
|
+
'@typescript-eslint/require-await': 'off', // conflicts with 'promise-function-async'
|
|
72
|
+
/** Disable some annoyingly strict rules from the 'recommended-requiring-type-checking' pack */
|
|
73
|
+
'@typescript-eslint/no-unsafe-assignment': 0,
|
|
74
|
+
'@typescript-eslint/no-unsafe-member-access': 0,
|
|
75
|
+
'@typescript-eslint/no-unsafe-argument': 0,
|
|
76
|
+
'@typescript-eslint/no-unsafe-return': 0,
|
|
77
|
+
'@typescript-eslint/no-unsafe-call': 0,
|
|
78
|
+
'@typescript-eslint/restrict-template-expressions': 0,
|
|
79
|
+
'@typescript-eslint/restrict-plus-operands': 0,
|
|
80
|
+
'@typescript-eslint/no-redundant-type-constituents': 0,
|
|
81
|
+
/** End 'recommended-requiring-type-checking' overrides */
|
|
82
|
+
...(options.typescriptRules || {}),
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
: null,
|
|
86
|
+
tseslint
|
|
87
|
+
? {
|
|
88
|
+
files: ['**/__tests__/**/*', 'test/**/*'],
|
|
89
|
+
rules: {
|
|
90
|
+
'@typescript-eslint/ban-ts-ignore': 'off',
|
|
91
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
92
|
+
},
|
|
93
|
+
}
|
|
94
|
+
: null,
|
|
95
|
+
{
|
|
96
|
+
// disable type-aware linting on JS files
|
|
97
|
+
files: [
|
|
98
|
+
'examples/**/*.js',
|
|
99
|
+
'examples/**/*.cjs',
|
|
100
|
+
'examples/**/*.mjs',
|
|
101
|
+
'examples/**/*.ts',
|
|
102
|
+
'examples/**/*.cts',
|
|
103
|
+
'examples/**/*.mts',
|
|
104
|
+
],
|
|
105
|
+
rules: {
|
|
106
|
+
'no-process-exit': 'off',
|
|
107
|
+
'n/no-missing-import': 'off',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
// Add prettier at the end to give it final say on formatting
|
|
111
|
+
eslintPluginPrettierRecommended,
|
|
112
|
+
{
|
|
113
|
+
// But lastly, ensure that we ignore certain paths
|
|
114
|
+
ignores: ['**/dist/*', '/dist', '**/pkg/*', '**/docs/*', '**/generated/*', ...(options.ignores || [])],
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
files: ['eslint.config.*'],
|
|
118
|
+
rules: {
|
|
119
|
+
'n/no-unpublished-import': 'off',
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
].filter((v) => !!v);
|
|
123
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The zx shebang doesn't resolve dependencies correctly
|
|
3
|
+
import 'zx/globals';
|
|
4
|
+
import { buildPackage } from './lib/build-util.js';
|
|
5
|
+
if (process.platform === 'win32') {
|
|
6
|
+
usePowerShell(); // to enable powershell
|
|
7
|
+
}
|
|
8
|
+
if (argv.help) {
|
|
9
|
+
console.log('Usage: companion-module-build [--dev] [--prerelease]');
|
|
10
|
+
console.log('Builds the companion connection module');
|
|
11
|
+
console.log(' --dev: Build in development mode. This will not minify the code, making it easier to debug.');
|
|
12
|
+
console.log(' --prerelease: Build in prerelease mode. This gets added as metadata to the manifest');
|
|
13
|
+
console.log(' --output <filename>: Output to a specific filename, without a file extension');
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
const { validateManifest } = await import('@companion-module/base/manifest').catch((e) => {
|
|
17
|
+
throw new Error(`Failed to load @companion-module/base. Have you installed a compatible version?: ${e?.message ?? e}`);
|
|
18
|
+
});
|
|
19
|
+
await buildPackage('@companion-module/base', validateManifest, 'connection', '>=1.4.0 <3.0.0');
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The zx shebang doesn't resolve dependencies correctly
|
|
3
|
+
import 'zx/globals';
|
|
4
|
+
import { buildPackage } from './lib/build-util.js';
|
|
5
|
+
if (process.platform === 'win32') {
|
|
6
|
+
usePowerShell(); // to enable powershell
|
|
7
|
+
}
|
|
8
|
+
if (argv.help) {
|
|
9
|
+
console.log('Usage: companion-module-build [--dev] [--prerelease]');
|
|
10
|
+
console.log('Builds the companion connection module');
|
|
11
|
+
console.log(' --dev: Build in development mode. This will not minify the code, making it easier to debug.');
|
|
12
|
+
console.log(' --prerelease: Build in prerelease mode. This gets added as metadata to the manifest');
|
|
13
|
+
console.log(' --output <filename>: Output to a specific filename, without a file extension');
|
|
14
|
+
process.exit(0);
|
|
15
|
+
}
|
|
16
|
+
const { validateSurfaceManifest } = await import('@companion-surface/base');
|
|
17
|
+
await buildPackage('@companion-surface/base', validateSurfaceManifest, 'surface', '>=1.0.0 <2.0.0');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The zx shebang doesn't resolve dependencies correctly
|
|
3
|
+
import 'zx/globals';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { findModuleDir, readUTF8File } from './lib/build-util.js';
|
|
6
|
+
if (process.platform === 'win32') {
|
|
7
|
+
usePowerShell(); // to enable powershell
|
|
8
|
+
}
|
|
9
|
+
const { validateManifest } = await import('@companion-module/base/manifest').catch((e) => {
|
|
10
|
+
throw new Error(`Failed to load @companion-module/base. Have you installed a compatible version?: ${e?.message ?? e}`);
|
|
11
|
+
});
|
|
12
|
+
// const toolsDir = path.join(__dirname, '..')
|
|
13
|
+
const toolsDir = await findModuleDir(import.meta.resolve('@companion-module/tools'));
|
|
14
|
+
const frameworkDir = await findModuleDir(import.meta.resolve('@companion-module/base'));
|
|
15
|
+
console.log(`Checking for: ${process.cwd()}`);
|
|
16
|
+
console.log(`Tools path: ${toolsDir}`);
|
|
17
|
+
console.log(`Framework path: ${frameworkDir}`);
|
|
18
|
+
const manifestJson = JSON.parse(await readUTF8File(path.resolve('./companion/manifest.json')));
|
|
19
|
+
try {
|
|
20
|
+
validateManifest(manifestJson, false);
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.error('Manifest validation failed', e);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The zx shebang doesn't resolve dependencies correctly
|
|
3
|
+
import 'zx/globals';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { validateSurfaceManifest } from '@companion-surface/base';
|
|
6
|
+
import { findModuleDir, readUTF8File } from './lib/build-util.js';
|
|
7
|
+
if (process.platform === 'win32') {
|
|
8
|
+
usePowerShell(); // to enable powershell
|
|
9
|
+
}
|
|
10
|
+
// const toolsDir = path.join(__dirname, '..')
|
|
11
|
+
const toolsDir = await findModuleDir(import.meta.resolve('@companion-module/tools'));
|
|
12
|
+
const frameworkDir = await findModuleDir(import.meta.resolve('@companion-surface/base'));
|
|
13
|
+
console.log(`Checking for: ${process.cwd()}`);
|
|
14
|
+
console.log(`Tools path: ${toolsDir}`);
|
|
15
|
+
console.log(`Framework path: ${frameworkDir}`);
|
|
16
|
+
const manifestJson = JSON.parse(await readUTF8File(path.resolve('./companion/manifest.json')));
|
|
17
|
+
try {
|
|
18
|
+
validateSurfaceManifest(manifestJson, false);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
console.error('Manifest validation failed', e);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import 'zx/globals';
|
|
2
|
+
export declare function readUTF8File(filePath: string): Promise<string>;
|
|
3
|
+
export declare function findModuleDir(cwd: string): Promise<string>;
|
|
4
|
+
type ModuleType = 'connection' | 'surface';
|
|
5
|
+
export declare function buildPackage<M>(frameworkPackageName: string, validateManifest: (manifest: M, looseChecks: boolean) => void, moduleType: ModuleType, versionRange: string): Promise<void>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import 'zx/globals';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fs } from 'zx';
|
|
4
|
+
import { findUp } from 'find-up';
|
|
5
|
+
import * as tar from 'tar';
|
|
6
|
+
import { createRequire } from 'module';
|
|
7
|
+
import * as semver from 'semver';
|
|
8
|
+
import * as esbuild from 'esbuild';
|
|
9
|
+
function toSanitizedDirname(name) {
|
|
10
|
+
return name.replace(/[^a-zA-Z0-9-\.]/g, '-').replace(/[-+]/g, '-');
|
|
11
|
+
}
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
export async function readUTF8File(filePath) {
|
|
14
|
+
return fs.readFile(filePath, { encoding: 'utf8' });
|
|
15
|
+
}
|
|
16
|
+
export async function findModuleDir(cwd) {
|
|
17
|
+
const stat = await fs.stat(cwd);
|
|
18
|
+
if (stat.isFile())
|
|
19
|
+
cwd = path.dirname(cwd);
|
|
20
|
+
const pkgJsonPath = await findUp('package.json', { cwd });
|
|
21
|
+
if (pkgJsonPath === undefined) {
|
|
22
|
+
throw new Error('No package.json file found in an enclosing directory');
|
|
23
|
+
}
|
|
24
|
+
return path.dirname(pkgJsonPath);
|
|
25
|
+
}
|
|
26
|
+
export async function buildPackage(frameworkPackageName, validateManifest, moduleType, versionRange) {
|
|
27
|
+
// const toolsDir = path.join(__dirname, '..')
|
|
28
|
+
const moduleDir = process.cwd();
|
|
29
|
+
const moduleRequire = createRequire(path.join(moduleDir, 'package.json'));
|
|
30
|
+
const toolsDir = await findModuleDir(require.resolve('@companion-module/tools'));
|
|
31
|
+
const frameworkDir = await findModuleDir(require.resolve(frameworkPackageName));
|
|
32
|
+
console.log(`Building for: ${process.cwd()}`);
|
|
33
|
+
console.log(`Tools path: ${toolsDir}`);
|
|
34
|
+
console.log(`Framework path: ${frameworkDir}`);
|
|
35
|
+
// Check for Yarn PnP
|
|
36
|
+
const pnpFile = path.join(moduleDir, '.pnp.cjs');
|
|
37
|
+
const pnpFileAlt = path.join(moduleDir, '.pnp.js');
|
|
38
|
+
if ((await fs.pathExists(pnpFile)) || (await fs.pathExists(pnpFileAlt))) {
|
|
39
|
+
console.error("❌ Error: Yarn PnP (Plug'n'Play) is not supported.");
|
|
40
|
+
console.error(' The companion module build process requires a traditional node_modules structure.');
|
|
41
|
+
console.error(' Please add "nodeLinker: node-modules" to your .yarnrc.yml file and run "yarn install".');
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const srcPackageJson = JSON.parse(await readUTF8File(path.resolve('./package.json')));
|
|
45
|
+
const frameworkPackageJson = JSON.parse(await readUTF8File(path.join(frameworkDir, 'package.json')));
|
|
46
|
+
// Check framework version if range is specified
|
|
47
|
+
if (versionRange && !semver.satisfies(frameworkPackageJson.version, versionRange, { includePrerelease: true })) {
|
|
48
|
+
console.error(`Error: ${frameworkPackageName} version ${frameworkPackageJson.version} is not supported.`);
|
|
49
|
+
console.error(`Required version range: ${versionRange}`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const manifestJson = JSON.parse(await readUTF8File(path.resolve('./companion/manifest.json')));
|
|
53
|
+
// clean old
|
|
54
|
+
await fs.remove('pkg');
|
|
55
|
+
const innerFolderName = toSanitizedDirname(manifestJson.id);
|
|
56
|
+
const packageBaseDir = path.join('pkg', innerFolderName);
|
|
57
|
+
// create new
|
|
58
|
+
await fs.mkdir(packageBaseDir, { recursive: true });
|
|
59
|
+
const isDev = !!(argv.dev || argv.debug);
|
|
60
|
+
// Load optional build config from the module directory
|
|
61
|
+
let buildConfig = {};
|
|
62
|
+
const buildConfigPath = path.resolve('build-config.cjs');
|
|
63
|
+
if (fs.existsSync(buildConfigPath)) {
|
|
64
|
+
buildConfig = require(buildConfigPath);
|
|
65
|
+
console.log('Found additional build configuration');
|
|
66
|
+
}
|
|
67
|
+
// Flatten externals to a string array for esbuild
|
|
68
|
+
const externalsRaw = Array.isArray(buildConfig.externals)
|
|
69
|
+
? buildConfig.externals
|
|
70
|
+
: buildConfig.externals
|
|
71
|
+
? [buildConfig.externals]
|
|
72
|
+
: [];
|
|
73
|
+
// Build entry points map
|
|
74
|
+
const entryPoints = {
|
|
75
|
+
main: './' + srcPackageJson.main,
|
|
76
|
+
...buildConfig.additionalEntrypoints,
|
|
77
|
+
};
|
|
78
|
+
// build the code
|
|
79
|
+
const esbuildOptions = {
|
|
80
|
+
entryPoints,
|
|
81
|
+
outdir: path.resolve(moduleDir, packageBaseDir),
|
|
82
|
+
bundle: true,
|
|
83
|
+
platform: 'node',
|
|
84
|
+
format: 'esm',
|
|
85
|
+
minify: isDev ? false : !buildConfig.disableMinifier,
|
|
86
|
+
sourcemap: isDev ? 'inline' : false,
|
|
87
|
+
target: 'node22',
|
|
88
|
+
external: externalsRaw,
|
|
89
|
+
// When bundling to ESM, `require`, `__dirname`, and `__filename` are not defined.
|
|
90
|
+
// Many CJS transitive dependencies call require() for Node built-ins (e.g. `require('events')`).
|
|
91
|
+
// Inject a small header that recreates them with ESM-native APIs so they work at runtime.
|
|
92
|
+
banner: {
|
|
93
|
+
js: [
|
|
94
|
+
`import { createRequire as __esbuild_createRequire } from 'module';`,
|
|
95
|
+
`import { fileURLToPath as __esbuild_fileURLToPath } from 'url';`,
|
|
96
|
+
`import { dirname as __esbuild_dirname } from 'path';`,
|
|
97
|
+
`const require = __esbuild_createRequire(import.meta.url);`,
|
|
98
|
+
`const __filename = __esbuild_fileURLToPath(import.meta.url);`,
|
|
99
|
+
`const __dirname = __esbuild_dirname(__filename);`,
|
|
100
|
+
].join('\n'),
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
await esbuild.build(esbuildOptions);
|
|
104
|
+
// copy in the metadata
|
|
105
|
+
await fs.copy('companion', path.join(packageBaseDir, 'companion'));
|
|
106
|
+
// Copy the manifest, overriding some properties
|
|
107
|
+
manifestJson.runtime.entrypoint = '../main.js';
|
|
108
|
+
manifestJson.version = srcPackageJson.version;
|
|
109
|
+
manifestJson.runtime.api = 'nodejs-ipc';
|
|
110
|
+
manifestJson.runtime.apiVersion = frameworkPackageJson.version;
|
|
111
|
+
// Bake in the prerelease flag if using module-base which is new enough
|
|
112
|
+
if (semver.gt(manifestJson.runtime.apiVersion, '1.12.0-0')) {
|
|
113
|
+
manifestJson.isPrerelease = !!argv.prerelease;
|
|
114
|
+
}
|
|
115
|
+
await fs.writeFile(path.join(packageBaseDir, 'companion/manifest.json'), JSON.stringify(manifestJson));
|
|
116
|
+
// Make sure the manifest is valid
|
|
117
|
+
try {
|
|
118
|
+
validateManifest(manifestJson, false);
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
console.error('Manifest validation failed', e);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
// Generate a minimal package.json
|
|
125
|
+
const packageJson = {
|
|
126
|
+
name: moduleType === 'connection' ? manifestJson.name : manifestJson.id,
|
|
127
|
+
version: manifestJson.version,
|
|
128
|
+
license: manifestJson.license,
|
|
129
|
+
// Minimal content
|
|
130
|
+
type: 'module',
|
|
131
|
+
dependencies: {},
|
|
132
|
+
};
|
|
133
|
+
// Ensure that any externals are added as dependencies
|
|
134
|
+
if (externalsRaw.length) {
|
|
135
|
+
// Add any external dependencies with versions matching what is currently installed.
|
|
136
|
+
// Externals are plain package-name strings when using esbuild.
|
|
137
|
+
for (const external of externalsRaw) {
|
|
138
|
+
const extPath = await findUp('package.json', { cwd: moduleRequire.resolve(external) });
|
|
139
|
+
if (extPath) {
|
|
140
|
+
const extJson = JSON.parse(await readUTF8File(extPath));
|
|
141
|
+
packageJson.dependencies[extJson.name] = extJson.version;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Ensure node-gyp is excluded from the installed deps in the output package
|
|
145
|
+
packageJson.resolutions = {
|
|
146
|
+
'node-gyp': 'npm:empty-npm-package@1.0.0',
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
// Copy across any prebuilds that can be loaded correctly
|
|
150
|
+
if (buildConfig.prebuilds) {
|
|
151
|
+
await fs.mkdir(path.join(packageBaseDir, 'prebuilds'));
|
|
152
|
+
for (const lib of buildConfig.prebuilds) {
|
|
153
|
+
const srcDir = await findModuleDir(moduleRequire.resolve(lib));
|
|
154
|
+
const filesOrDirs = await fs.readdir(path.join(srcDir, 'prebuilds'));
|
|
155
|
+
for (const fileOrDir of filesOrDirs) {
|
|
156
|
+
await fs.copy(path.join(srcDir, 'prebuilds', fileOrDir), path.join(packageBaseDir, 'prebuilds', fileOrDir));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// copy extra files
|
|
161
|
+
if (Array.isArray(buildConfig.extraFiles)) {
|
|
162
|
+
const files = await globby(buildConfig.extraFiles, {
|
|
163
|
+
expandDirectories: false,
|
|
164
|
+
onlyFiles: false,
|
|
165
|
+
});
|
|
166
|
+
for (const file of files) {
|
|
167
|
+
await fs.copy(file, path.join(packageBaseDir, path.basename(file)), {
|
|
168
|
+
overwrite: false,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Write the package.json
|
|
173
|
+
// packageJson.bundleDependencies = Object.keys(packageJson.dependencies)
|
|
174
|
+
await fs.writeFile(path.join(packageBaseDir, 'package.json'), JSON.stringify(packageJson));
|
|
175
|
+
// If we found any depenendencies for the pkg, install them
|
|
176
|
+
if (Object.keys(packageJson.dependencies).length) {
|
|
177
|
+
await fs.writeFile(path.join(packageBaseDir, 'yarn.lock'), '');
|
|
178
|
+
await $ `yarn --cwd ${packageBaseDir} install --no-immutable`;
|
|
179
|
+
}
|
|
180
|
+
// Prune any excessive prebuilds
|
|
181
|
+
const prebuildDirName = path.join(packageBaseDir, 'prebuilds');
|
|
182
|
+
if (fs.existsSync(prebuildDirName)) {
|
|
183
|
+
const prebuildDirs = await fs.readdir(prebuildDirName);
|
|
184
|
+
for (const dir of prebuildDirs) {
|
|
185
|
+
let keepDir = true;
|
|
186
|
+
if (dir.match(/freebsd/) || dir.match(/android/)) {
|
|
187
|
+
// Unsupported platforms
|
|
188
|
+
keepDir = false;
|
|
189
|
+
}
|
|
190
|
+
else if (dir.match(/win32-ia32/)) {
|
|
191
|
+
// 32bit windows is not supported
|
|
192
|
+
keepDir = false;
|
|
193
|
+
}
|
|
194
|
+
else if (dir.match(/linux(.+)musl/)) {
|
|
195
|
+
// linux musl is not supported
|
|
196
|
+
keepDir = false;
|
|
197
|
+
}
|
|
198
|
+
else if (dir.match(/linux-arm$/) || dir.match(/linux-arm-gnueabihf/)) {
|
|
199
|
+
// linux arm (non arm64) is not supported
|
|
200
|
+
keepDir = false;
|
|
201
|
+
}
|
|
202
|
+
if (!keepDir) {
|
|
203
|
+
console.log('Removing unneeded prebuild dir:', dir);
|
|
204
|
+
await fs.rm(path.join(prebuildDirName, dir), { recursive: true, force: true });
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Create tgz of the build
|
|
209
|
+
let tgzFile = toSanitizedDirname(`${manifestJson.id}-${manifestJson.version}`);
|
|
210
|
+
if (typeof argv['output'] === 'string') {
|
|
211
|
+
// -o flag, to allow legacy behaviour creating pkg.tgz output
|
|
212
|
+
tgzFile = argv['output'];
|
|
213
|
+
}
|
|
214
|
+
tgzFile += '.tgz';
|
|
215
|
+
console.log('Writing compressed package output to', tgzFile);
|
|
216
|
+
await tar
|
|
217
|
+
.create({
|
|
218
|
+
gzip: true,
|
|
219
|
+
cwd: 'pkg',
|
|
220
|
+
}, [innerFolderName])
|
|
221
|
+
.pipe(fs.createWriteStream(tgzFile));
|
|
222
|
+
}
|
package/package.json
CHANGED
|
@@ -1,51 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@companion-module/tools",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"main": "index.js",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
"repository": {
|
|
8
7
|
"type": "git",
|
|
9
8
|
"url": "git+https://github.com/bitfocus/companion-module-tools.git"
|
|
10
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "rimraf dist && tsc -p tsconfig.json"
|
|
12
|
+
},
|
|
11
13
|
"bin": {
|
|
12
|
-
"companion-
|
|
13
|
-
"companion-module-
|
|
14
|
-
"companion-
|
|
15
|
-
"companion-surface-
|
|
16
|
-
"companion-surface-check": "scripts/check-surface.js"
|
|
14
|
+
"companion-module-build": "./dist/scripts/build-connection.js",
|
|
15
|
+
"companion-module-check": "./dist/scripts/check-connection.js",
|
|
16
|
+
"companion-surface-build": "./dist/scripts/build-surface.js",
|
|
17
|
+
"companion-surface-check": "./dist/scripts/check-surface.js"
|
|
17
18
|
},
|
|
18
19
|
"engines": {
|
|
19
|
-
"node": "^
|
|
20
|
+
"node": "^22.18"
|
|
21
|
+
},
|
|
22
|
+
"exports": {
|
|
23
|
+
".": "./dist/index.js",
|
|
24
|
+
"./eslint/config.mjs": "./dist/eslint/config.mjs",
|
|
25
|
+
"./scripts/*.js": "./dist/scripts/*.js",
|
|
26
|
+
"./tsconfig/node22/recommended.json": "./tsconfig/node22/recommended.json",
|
|
27
|
+
"./tsconfig/node22/recommended-esm.json": "./tsconfig/node22/recommended-esm.json",
|
|
28
|
+
"./.prettierrc.json": "./.prettierrc.json",
|
|
29
|
+
"./build-config": "./dist/build-config.js"
|
|
20
30
|
},
|
|
21
31
|
"files": [
|
|
22
|
-
"eslint",
|
|
23
|
-
"scripts",
|
|
24
|
-
"tsconfig",
|
|
25
|
-
".prettierrc.json",
|
|
26
|
-
"index.js",
|
|
27
32
|
"CHANGELOG.md",
|
|
28
|
-
"
|
|
33
|
+
"dist",
|
|
34
|
+
".prettierrc.json",
|
|
35
|
+
"tsconfig"
|
|
29
36
|
],
|
|
30
37
|
"dependencies": {
|
|
31
38
|
"@eslint/js": "^9.39.3",
|
|
39
|
+
"esbuild": "^0.27.3",
|
|
32
40
|
"eslint-config-prettier": "^10.1.8",
|
|
33
41
|
"eslint-plugin-n": "^17.24.0",
|
|
34
42
|
"eslint-plugin-prettier": "^5.5.5",
|
|
35
|
-
"find-up": "^
|
|
36
|
-
"parse-author": "^2.0.0",
|
|
43
|
+
"find-up": "^8.0.0",
|
|
37
44
|
"semver": "^7.7.4",
|
|
38
45
|
"tar": "^7.5.9",
|
|
39
|
-
"webpack": "^5.105.2",
|
|
40
|
-
"webpack-cli": "^6.0.1",
|
|
41
46
|
"zx": "^8.8.5"
|
|
42
47
|
},
|
|
43
48
|
"peerDependencies": {
|
|
44
|
-
"@companion-module/base": "^
|
|
49
|
+
"@companion-module/base": "^2.0.0",
|
|
45
50
|
"@companion-surface/base": "^1.0.0",
|
|
46
|
-
"eslint": "^9.
|
|
47
|
-
"prettier": "^3.
|
|
48
|
-
"typescript-eslint": "^8.
|
|
51
|
+
"eslint": "^9.39.3",
|
|
52
|
+
"prettier": "^3.8.1",
|
|
53
|
+
"typescript-eslint": "^8.56.1"
|
|
49
54
|
},
|
|
50
55
|
"peerDependenciesMeta": {
|
|
51
56
|
"@companion-module/base": {
|
|
@@ -65,10 +70,17 @@
|
|
|
65
70
|
}
|
|
66
71
|
},
|
|
67
72
|
"devDependencies": {
|
|
73
|
+
"@companion-module/base": "2.0.0-alpha.0",
|
|
74
|
+
"@companion-surface/base": "^1.1.0",
|
|
68
75
|
"@types/eslint": "^9.6.1",
|
|
76
|
+
"@types/fs-extra": "^11.0.4",
|
|
77
|
+
"@types/node": "^22.19.13",
|
|
78
|
+
"@types/semver": "^7.7.1",
|
|
69
79
|
"eslint": "^9.39.3",
|
|
70
80
|
"prettier": "^3.8.1",
|
|
71
|
-
"
|
|
81
|
+
"rimraf": "^6.1.3",
|
|
82
|
+
"typescript": "^5.9.3",
|
|
83
|
+
"typescript-eslint": "^8.56.1"
|
|
72
84
|
},
|
|
73
85
|
"packageManager": "yarn@4.12.0"
|
|
74
86
|
}
|