@companion-module/tools 0.0.1-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.
@@ -0,0 +1,9 @@
1
+ {
2
+ "arrowParens": "always",
3
+ "bracketSpacing": true,
4
+ "printWidth": 120,
5
+ "semi": false,
6
+ "singleQuote": true,
7
+ "useTabs": true,
8
+ "endOfLine": "lf"
9
+ }
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @companion-module/tools
2
+
3
+ This is a collection of tools, used for developing and verifying Companion modules
4
+
5
+ ## Scripts
6
+
7
+ ### companion-module-build
8
+
9
+ When used, this will build a module ready for distibution
@@ -0,0 +1,64 @@
1
+ const enableJest = false // TODO
2
+
3
+ function compact(arr) {
4
+ return arr.filter((v) => v !== undefined && v !== null)
5
+ }
6
+
7
+ module.exports = {
8
+ enableJest,
9
+
10
+ commonPlugins: compact(['prettier', enableJest ? 'jest' : null]),
11
+ tsPlugins: compact(['@typescript-eslint', 'prettier', enableJest ? 'jest' : null]),
12
+
13
+ commonExtends: ['eslint:recommended', 'plugin:node/recommended', 'plugin:prettier/recommended'],
14
+ tsExtends: compact([
15
+ 'eslint:recommended',
16
+ 'plugin:@typescript-eslint/eslint-recommended',
17
+ 'plugin:@typescript-eslint/recommended',
18
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
19
+ 'plugin:node/recommended',
20
+ enableJest ? 'plugin:jest/recommended' : null,
21
+ 'prettier',
22
+ 'plugin:prettier/recommended',
23
+ ]),
24
+
25
+ commonRules: {
26
+ 'prettier/prettier': 'error',
27
+ 'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_(.+)' }],
28
+ 'no-extra-semi': 'off',
29
+ 'node/no-unsupported-features/es-syntax': ['error', { ignores: ['modules'] }],
30
+ 'no-use-before-define': 'off',
31
+ 'no-warning-comments': ['error', { terms: ['nocommit', '@nocommit', '@no-commit'] }],
32
+ 'jest/no-mocks-import': 'off',
33
+ },
34
+ tsRules: {
35
+ 'no-unused-vars': 'off',
36
+ '@typescript-eslint/no-explicit-any': 'off',
37
+ '@typescript-eslint/interface-name-prefix': 'off',
38
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_(.+)' }],
39
+ '@typescript-eslint/no-floating-promises': 'error',
40
+ '@typescript-eslint/explicit-module-boundary-types': ['error'],
41
+ '@typescript-eslint/promise-function-async': 'error',
42
+ '@typescript-eslint/require-await': 'off', // conflicts with 'promise-function-async'
43
+
44
+ /** Disable some annoyingly strict rules from the 'recommended-requiring-type-checking' pack */
45
+ '@typescript-eslint/no-unsafe-assignment': 0,
46
+ '@typescript-eslint/no-unsafe-member-access': 0,
47
+ '@typescript-eslint/no-unsafe-argument': 0,
48
+ '@typescript-eslint/no-unsafe-return': 0,
49
+ '@typescript-eslint/no-unsafe-call': 0,
50
+ '@typescript-eslint/restrict-template-expressions': 0,
51
+ '@typescript-eslint/restrict-plus-operands': 0,
52
+ /** End 'recommended-requiring-type-checking' overrides */
53
+ },
54
+
55
+ tsParser: {
56
+ parser: '@typescript-eslint/parser',
57
+ parserOptions: { project: './tsconfig.json' },
58
+ settings: {
59
+ node: {
60
+ tryExtensions: ['.js', '.json', '.node', '.ts', '.d.ts'],
61
+ },
62
+ },
63
+ },
64
+ }
@@ -0,0 +1,92 @@
1
+ const {
2
+ commonPlugins,
3
+ tsPlugins,
4
+ commonExtends,
5
+ tsExtends,
6
+ commonRules,
7
+ tsRules,
8
+ tsParser,
9
+ enableJest,
10
+ } = require('./fragments.cjs')
11
+
12
+ const disableJest = enableJest
13
+ ? {
14
+ 'jest/globals': false, // Block jest from this
15
+ }
16
+ : {}
17
+ const allowJest = enableJest
18
+ ? {
19
+ 'jest/globals': true,
20
+ jest: true,
21
+ }
22
+ : {}
23
+
24
+ module.exports = {
25
+ extends: commonExtends,
26
+ plugins: commonPlugins,
27
+ rules: {
28
+ 'prettier/prettier': 'error',
29
+ },
30
+ env: { es2017: true },
31
+ parserOptions: { sourceType: 'module', ecmaVersion: 2018 },
32
+ overrides: [
33
+ // Note: these replace the values defined above, so make sure to extend them if they are needed
34
+ {
35
+ files: ['*.ts'],
36
+ extends: tsExtends,
37
+ plugins: tsPlugins,
38
+ ...tsParser,
39
+ env: {
40
+ ...disableJest,
41
+ },
42
+ rules: {
43
+ ...commonRules,
44
+ ...tsRules,
45
+ },
46
+ },
47
+ {
48
+ files: ['*.js'],
49
+ settings: {
50
+ node: {
51
+ tryExtensions: ['.js', '.json', '.node', '.ts'],
52
+ },
53
+ },
54
+ env: {
55
+ ...disableJest,
56
+ },
57
+ rules: {
58
+ ...commonRules,
59
+ },
60
+ },
61
+ {
62
+ files: ['src/**/__tests__/**/*.ts'],
63
+ extends: tsExtends,
64
+ plugins: tsPlugins,
65
+ ...tsParser,
66
+ env: {
67
+ ...allowJest,
68
+ },
69
+ rules: {
70
+ ...commonRules,
71
+ ...tsRules,
72
+ '@typescript-eslint/ban-ts-ignore': 'off',
73
+ '@typescript-eslint/ban-ts-comment': 'off',
74
+ },
75
+ },
76
+ {
77
+ files: ['examples/**/*.ts'],
78
+ extends: tsExtends,
79
+ plugins: tsPlugins,
80
+ ...tsParser,
81
+ env: {
82
+ ...disableJest,
83
+ },
84
+ rules: {
85
+ ...commonRules,
86
+ ...tsRules,
87
+ 'no-process-exit': 'off',
88
+ 'node/no-missing-import': 'off',
89
+ },
90
+ },
91
+ ],
92
+ }
package/index.js ADDED
@@ -0,0 +1 @@
1
+ throw new Error('Not importable!')
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@companion-module/tools",
3
+ "version": "0.0.1-0",
4
+ "type": "module",
5
+ "main": "index.js",
6
+ "license": "MIT",
7
+ "bin": {
8
+ "companion-module-build": "scripts/build.js",
9
+ "companion-generate-manifest": "scripts/generate-manifest.js"
10
+ },
11
+ "files": [
12
+ "eslint",
13
+ "scripts",
14
+ "tsconfig",
15
+ ".prettierrc.json",
16
+ "index.js",
17
+ "CHANGELOG.md"
18
+ ],
19
+ "dependencies": {
20
+ "@typescript-eslint/eslint-plugin": "^5.30.5",
21
+ "@typescript-eslint/parser": "^5.30.5",
22
+ "eslint": "^8.19.0",
23
+ "eslint-config-prettier": "^8.5.0",
24
+ "eslint-plugin-node": "^11.1.0",
25
+ "eslint-plugin-prettier": "^4.2.1",
26
+ "find-up": "^6.3.0",
27
+ "husky": "^8.0.1",
28
+ "lint-staged": "^13.0.3",
29
+ "parse-author": "^2.0.0",
30
+ "prettier": "^2.7.1",
31
+ "webpack": "^5.73.0",
32
+ "webpack-cli": "^4.10.0",
33
+ "zx": "^4.3.0"
34
+ },
35
+ "peerDependencies": {
36
+ "@companion-module/base": "^0.0.3"
37
+ }
38
+ }
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import path from 'path'
4
+ import { fs } from 'zx'
5
+ import { findUp } from 'find-up'
6
+ import * as tar from 'tar'
7
+
8
+ async function findModuleDir(cwd) {
9
+ const stat = await fs.stat(cwd)
10
+ if (stat.isFile()) cwd = path.dirname(cwd)
11
+
12
+ const pkgJsonPath = await findUp('package.json', { cwd })
13
+ return path.dirname(pkgJsonPath)
14
+ }
15
+
16
+ // const toolsDir = path.join(__dirname, '..')
17
+ const toolsDir = await findModuleDir(require.resolve('@companion-module/tools'))
18
+ const frameworkDir = await findModuleDir(require.resolve('@companion-module/base'))
19
+ console.log(`Building for: ${process.cwd()}`)
20
+
21
+ console.log(`Tools path: ${toolsDir}`)
22
+ console.log(`Framework path: ${frameworkDir}`)
23
+
24
+ // clean old
25
+ await fs.remove('pkg')
26
+
27
+ // build the code
28
+ const webpackConfig = path.join(toolsDir, 'webpack.config.cjs')
29
+ await $`yarn webpack -c ${webpackConfig}`
30
+
31
+ // copy in the metadata
32
+ await fs.copy('companion', 'pkg/companion')
33
+
34
+ const manifestJson = JSON.parse(await fs.readFile(path.resolve('./companion/manifest.json')))
35
+ manifestJson.runtime.entrypoint = '../main.js'
36
+ await fs.writeFile(path.resolve('./pkg/companion/manifest.json'), JSON.stringify(manifestJson))
37
+
38
+ // Generate a minimal package.json
39
+ const packageJson = {
40
+ name: manifestJson.name,
41
+ version: manifestJson.version,
42
+ license: manifestJson.license,
43
+ // Minimal content
44
+ type: 'commonjs',
45
+ dependencies: {},
46
+ }
47
+
48
+ // Ensure that any externals are added as dependencies
49
+ const webpackExtPath = path.resolve('webpack-ext.cjs')
50
+ if (fs.existsSync(webpackExtPath)) {
51
+ const webpackExt = require(webpackExtPath)
52
+ if (webpackExt.externals) {
53
+ const extArray = Array.isArray(webpackExt.externals) ? webpackExt.externals : [webpackExt.externals]
54
+ for (const extGroup of extArray) {
55
+ if (typeof extGroup === 'object') {
56
+ // TODO - does this need to be a stricter object check?
57
+
58
+ for (const external of Object.keys(extGroup)) {
59
+ const extPath = await findUp('package.json', { cwd: require.resolve(external) })
60
+ const extJson = JSON.parse(await fs.readFile(extPath))
61
+ packageJson.dependencies[external] = extJson.version
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ // Write the package.json
69
+ // packageJson.bundleDependencies = Object.keys(packageJson.dependencies)
70
+ await fs.writeFile('pkg/package.json', JSON.stringify(packageJson))
71
+
72
+ if (Object.keys(packageJson.dependencies).length) {
73
+ await $`yarn --cwd pkg`
74
+ }
75
+
76
+ // Create tgz of the build
77
+ // await $`yarn --cwd pkg pack --filename pkg/package.tgz`
78
+
79
+ await tar
80
+ .c(
81
+ // or tar.create
82
+ {
83
+ gzip: true,
84
+ },
85
+ ['pkg']
86
+ )
87
+ .pipe(fs.createWriteStream('pkg.tgz'))
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env zx
2
+
3
+ import { fs, path, $ } from 'zx'
4
+ import parseAuthor from 'parse-author'
5
+
6
+ if (await fs.pathExists('companion/manifest.json')) {
7
+ throw new Error('Manifest has already been created')
8
+ }
9
+
10
+ const pkgJsonStr = await fs.readFile('package.json')
11
+ const pkgJson = JSON.parse(pkgJsonStr.toString())
12
+
13
+ const maintainers = []
14
+
15
+ function tryParsePerson(person) {
16
+ try {
17
+ if (person) {
18
+ const rawAuthor = typeof person === 'string' ? parseAuthor(person) : person
19
+ if (rawAuthor.name) {
20
+ maintainers.push({
21
+ name: rawAuthor.name,
22
+ email: rawAuthor.email,
23
+ })
24
+ }
25
+ }
26
+ } catch (e) {
27
+ // Ignore
28
+ }
29
+ }
30
+
31
+ tryParsePerson(pkgJson.author)
32
+ if (Array.isArray(pkgJson.contributors)) {
33
+ for (const person of pkgJson.contributors) {
34
+ tryParsePerson(person)
35
+ }
36
+ }
37
+
38
+ const manifest = {
39
+ id: `bitfocus.${pkgJson.name}`,
40
+ name: pkgJson.name,
41
+ shortname: pkgJson.shortname ?? pkgJson.name,
42
+ description: pkgJson.description ?? pkgJson.name,
43
+ version: pkgJson.version ?? '0.0.0',
44
+ license: pkgJson.license,
45
+ repository: pkgJson.repository?.url ?? `https://github.com/bitfocus/companion-module-${pkgJson.name}.git`,
46
+ bugs: pkgJson.bugs?.url ?? `https://github.com/bitfocus/companion-module-${pkgJson.name}/issues`,
47
+ maintainers: maintainers,
48
+ legacyIds: [...(pkgJson.legacy || []), pkgJson.name],
49
+
50
+ runtime: {
51
+ type: 'node14',
52
+ api: 'socket.io',
53
+
54
+ entrypoint: path.join('../', pkgJson.main || 'index.js'),
55
+ // universal: boolean
56
+ },
57
+
58
+ manufacturer: pkgJson.manufacturer ?? '',
59
+ products: pkgJson.products ?? (pkgJson.product ? [pkgJson.product] : []),
60
+ keywords: pkgJson.keywords || [],
61
+ }
62
+
63
+ const manifestDir = './companion'
64
+ await fs.mkdirp(manifestDir)
65
+ await fs.writeFile(path.join(manifestDir, 'manifest.json'), JSON.stringify(manifest, undefined, '\t'))
66
+
67
+ if (await fs.pathExists('HELP.md')) {
68
+ await fs.move('HELP.md', path.join(manifestDir, 'HELP.md'))
69
+
70
+ // guess at what images might be needed by the help
71
+ if (await fs.pathExists('images')) await fs.move('images', path.join(manifestDir, 'images'))
72
+ if (await fs.pathExists('documentation')) await fs.move('documentation', path.join(manifestDir, 'documentation'))
73
+ }
74
+
75
+ // for (const folder of dirs) {
76
+ // if (folder.match(/companion-module-/) && !ignoreNames.includes(folder)) {
77
+ // const moduleDir = path.join(outerDir, folder)
78
+ // const moduleNewDir = path.join(outerManifest, folder)
79
+ // const manifestDir = path.join(moduleNewDir, 'companion')
80
+
81
+ //
82
+ // await fs.mkdirp(manifestDir)
83
+ // await fs.writeFile(path.join(manifestDir, 'manifest.json'), JSON.stringify(manifest, undefined, '\t'))
84
+
85
+ // if (await fs.pathExists(( 'HELP.md'))) {
86
+ // await fs.copy(( 'HELP.md'), path.join(manifestDir, 'HELP.md'))
87
+
88
+ // // guess at what images might be needed by the help
89
+ // if (await fs.pathExists(( 'images')))
90
+ // await fs.copy(( 'images'), path.join(manifestDir, 'images'))
91
+ // if (await fs.pathExists(( 'documentation')))
92
+ // await fs.copy(( 'documentation'), path.join(manifestDir, 'documentation'))
93
+ // }
94
+
95
+ // await fs.writeFile(
96
+ // path.join(outerEntrypoints, `${pkgJson.name}.cjs`),
97
+ // `
98
+ // global.modulePkg = require('companion-module-${pkgJson.name}/package.json')
99
+ // global.moduleFactory = require('companion-module-${pkgJson.name}')
100
+ // global.moduleName = "${pkgJson.name}"
101
+ // import('../../dist/index.js')
102
+ // `
103
+ // )
104
+ // }
105
+ // }
106
+
107
+ // console.log('Bundling code. This will take a couple of minutes')
108
+ // await $`yarn webpack`
109
+
110
+ // // trick node into treating them all as cjs
111
+ // await fs.writeFile(`manifests/package.json`, '')
112
+
113
+ // // const useDir = await fs.pathExists('./module/legacy')
114
+ // // const baseDir = useDir ? './module/legacy' : './node_modules/companion-wrapped-module'
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "es2020",
4
+ "target": "es2018",
5
+ "noImplicitAny": true,
6
+ "moduleResolution": "node",
7
+ "sourceMap": true,
8
+ "paths": {
9
+ "*": ["../node_modules/*"]
10
+ },
11
+ "declaration": false,
12
+ "importHelpers": true,
13
+ "listFiles": false,
14
+ "traceResolution": false,
15
+ "pretty": true,
16
+ "lib": ["es2018"],
17
+ "types": ["node"],
18
+ "strict": true,
19
+ "alwaysStrict": false,
20
+ "forceConsistentCasingInFileNames": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "noImplicitReturns": true,
23
+ "noUnusedLocals": true,
24
+ "noUnusedParameters": true,
25
+ "skipLibCheck": true,
26
+ "allowSyntheticDefaultImports": true
27
+ },
28
+ "compileOnSave": false
29
+ }