mirror of
https://github.com/unraid/api.git
synced 2026-01-02 06:30:02 -06:00
Compare commits
3 Commits
renovate/m
...
feat/repkg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
085a74b793 | ||
|
|
cd35af28a4 | ||
|
|
167ef4c659 |
@@ -5,7 +5,7 @@ require:
|
||||
- ts-node/register
|
||||
config:
|
||||
namingConvention:
|
||||
typeNames: './fix-array-type.cjs'
|
||||
typeNames: './configs/fix-array-type.cjs'
|
||||
enumValues: 'change-case#upperCase'
|
||||
useTypeImports: true
|
||||
scalars:
|
||||
5
api/configs/esbuild-shims.js
Normal file
5
api/configs/esbuild-shims.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const __import_meta_url =
|
||||
typeof document === 'undefined'
|
||||
? new (require('url'.replace('', '')).URL)('file:' + __filename).href
|
||||
: (document.currentScript && document.currentScript.src) ||
|
||||
new URL('main.js', document.baseURI).href;
|
||||
177
api/configs/esbuild.js
Normal file
177
api/configs/esbuild.js
Normal file
@@ -0,0 +1,177 @@
|
||||
import { cp, readFile, stat, writeFile } from 'fs/promises';
|
||||
import { createRequire as topLevelCreateRequire } from 'module';
|
||||
import { join } from 'path';
|
||||
|
||||
import esbuild from 'esbuild';
|
||||
import { emptyDir, exists } from 'fs-extra';
|
||||
|
||||
const outputDir = 'deploy/esbuild/';
|
||||
|
||||
function cleanPkgJson(json) {
|
||||
delete json.devDependencies;
|
||||
delete json['release-it'];
|
||||
delete json.optionalDependencies;
|
||||
delete json.dependencies;
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove useless fields from package.json, this is needed mostly for `pkg`
|
||||
* otherwise it will try to bundle dependencies
|
||||
*/
|
||||
async function patchPkgJson(path) {
|
||||
const pkgJsonPath = join(outputDir, path, 'package.json');
|
||||
const pkgJson = require('./' + pkgJsonPath);
|
||||
cleanPkgJson(pkgJson);
|
||||
delete pkgJson.scripts;
|
||||
await writeFile(pkgJsonPath, JSON.stringify(pkgJson, null, 2));
|
||||
}
|
||||
|
||||
// from https://github.com/evanw/esbuild/issues/1051#issuecomment-806325487
|
||||
const nativeNodeModulesPlugin = {
|
||||
name: 'native-node-modules',
|
||||
setup(build) {
|
||||
const require = topLevelCreateRequire(import.meta.url);
|
||||
// If a ".node" file is imported within a module in the "file" namespace, resolve
|
||||
// it to an absolute path and put it into the "node-file" virtual namespace.
|
||||
build.onResolve({ filter: /\.node$/, namespace: 'file' }, (args) => {
|
||||
console.log('args', args);
|
||||
return {
|
||||
path: require.resolve(args.path, { paths: [args.resolveDir] }),
|
||||
namespace: 'node-file',
|
||||
}});
|
||||
|
||||
// Files in the "node-file" virtual namespace call "require()" on the
|
||||
// path from esbuild of the ".node" file in the output directory.
|
||||
build.onLoad({ filter: /.*/, namespace: 'node-file' }, (args) => ({
|
||||
contents: `
|
||||
import path from ${JSON.stringify(args.path)}
|
||||
try { module.exports = require(path) }
|
||||
catch {}
|
||||
`,
|
||||
}));
|
||||
|
||||
// If a ".node" file is imported within a module in the "node-file" namespace, put
|
||||
// it in the "file" namespace where esbuild's default loading behavior will handle
|
||||
// it. It is already an absolute path since we resolved it to one above.
|
||||
build.onResolve({ filter: /\.node$/, namespace: 'node-file' }, (args) => ({
|
||||
path: args.path,
|
||||
namespace: 'file',
|
||||
}));
|
||||
|
||||
// Tell esbuild's default loading behavior to use the "file" loader for
|
||||
// these ".node" files.
|
||||
let opts = build.initialOptions;
|
||||
opts.loader = opts.loader || {};
|
||||
opts.loader['.node'] = 'file';
|
||||
},
|
||||
};
|
||||
|
||||
async function printSize(fileName) {
|
||||
const stats = await stat(fileName);
|
||||
|
||||
// print size in MB
|
||||
console.log(`Bundle size: ${Math.round(stats.size / 10000) / 100}MB\n\n`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const start = Date.now();
|
||||
// clean build folder
|
||||
await emptyDir(outputDir);
|
||||
|
||||
const outfile = `${outputDir}/index.js`;
|
||||
|
||||
const externals = [
|
||||
'@fastify/static',
|
||||
'@fastify/view',
|
||||
'@apollo/gateway',
|
||||
'@nestjs/websockets/socket-module',
|
||||
'@nestjs/microservices/microservices-module',
|
||||
'@nestjs/microservices',
|
||||
'@nestjs/microservices',
|
||||
'@nestjs/platform-express',
|
||||
'@apollo/subgraph',
|
||||
'@apollo/subgraph/package.json',
|
||||
'@apollo/subgraph/dist/directives',
|
||||
'class-transformer/storage',
|
||||
'redlock',
|
||||
'@vmngr/libvirt/build/Release',
|
||||
'ts-invariant/',
|
||||
];
|
||||
|
||||
/** @type { import('esbuild').BuildOptions } */
|
||||
const config = {
|
||||
entryPoints: ['dist/cli.js', 'dist/main.js'],
|
||||
|
||||
logLevel: 'error',
|
||||
plugins: [nativeNodeModulesPlugin],
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
target: 'node20',
|
||||
sourcemap: true,
|
||||
outdir: outputDir,
|
||||
// suppress direct-eval warning
|
||||
logOverride: {
|
||||
'direct-eval': 'silent',
|
||||
},
|
||||
format: 'esm',
|
||||
treeShaking: false,
|
||||
external: externals,
|
||||
// Prevent esbuild from adding a "2" to the names of CC classes for some reason.
|
||||
keepNames: true,
|
||||
};
|
||||
|
||||
await esbuild.build(config);
|
||||
|
||||
console.log(`Build took ${Date.now() - start}ms`);
|
||||
|
||||
/* const content = (await readFile(outfile, 'utf-8'))
|
||||
.replace(/__dirname, "\.\.\/"/g, '__dirname, "./node_modules/@serialport/bindings-cpp"')
|
||||
.replace(`"../../package.json"`, `"./node_modules/@zwave-js/server/package.json"`); */
|
||||
|
||||
// await writeFile(outfile, content);
|
||||
|
||||
|
||||
// copy assets to build folder
|
||||
for (const ext of externals) {
|
||||
const path = ext.startsWith('./') ? ext : `node_modules/${ext}`;
|
||||
if (await exists(path)) {
|
||||
console.log(`Copying "${path}" to "${outputDir}" folder`);
|
||||
await cp(path, `${outputDir}/${path}`, { recursive: true });
|
||||
} else {
|
||||
console.log(`Asset "${path}" does not exist. Skipping...`);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the folder directly into the build directory
|
||||
const folderToCopy = 'node_modules/@vmngr/libvirt/build/Release/libvirt.node';
|
||||
const destination = `${outputDir}/build/libvirt.node`;
|
||||
await cp(folderToCopy, destination, { recursive: true });
|
||||
|
||||
// create main patched packege.json
|
||||
const json = await import('../package.json', { assert: { type: 'json' } });
|
||||
|
||||
const pkgJson = { ...json };
|
||||
cleanPkgJson(pkgJson);
|
||||
|
||||
pkgJson.scripts = {
|
||||
start: 'node index.js',
|
||||
};
|
||||
|
||||
pkgJson.bin = 'index.js';
|
||||
pkgJson.pkg = {
|
||||
assets: ['dist/**', 'snippets/**', 'node_modules/**'],
|
||||
};
|
||||
|
||||
await writeFile(`${outputDir}/package.json`, JSON.stringify(pkgJson, null, 2));
|
||||
|
||||
/*
|
||||
await patchPkgJson('node_modules/@zwave-js/config');
|
||||
await patchPkgJson('node_modules/zwave-js');
|
||||
await patchPkgJson('node_modules/@zwave-js/server'); */
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
19
api/configs/fix-array-type.cjs
Normal file
19
api/configs/fix-array-type.cjs
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* This function wraps constant case, that turns any string into CONSTANT_CASE
|
||||
* However, this function has a bug that, if you pass _ to it it will return an empty
|
||||
* string. This small module fixes that
|
||||
*
|
||||
* @param {string*} str
|
||||
* @return {string}
|
||||
*/
|
||||
function FixArrayType(str) {
|
||||
if (str === 'Array') {
|
||||
return 'ArrayType';
|
||||
}
|
||||
|
||||
// If result is an empty string, just return the original string
|
||||
return str;
|
||||
}
|
||||
|
||||
module.exports = FixArrayType;
|
||||
|
||||
12
api/configs/pkg.config.json
Normal file
12
api/configs/pkg.config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"assets": [
|
||||
"./deploy/esbuild/*",
|
||||
"src/**/*.graphql"
|
||||
],
|
||||
"targets": [
|
||||
"node20-linux-arm64",
|
||||
"node20-linux-x64"
|
||||
],
|
||||
"bin": "deploy/esbuild/index.js",
|
||||
"outputPath": "./deploy/pre-pack"
|
||||
}
|
||||
@@ -18,10 +18,10 @@ x-volumes: &volumes
|
||||
- ./.env.test:/app/.env.test
|
||||
- ./.env.development:/app/.env.development
|
||||
- ./codegen.yml:/app/codegen.yml
|
||||
- ./fix-array-type.cjs:/app/fix-array-type.cjs
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./unraid-api.js:/app/unraid-api.js
|
||||
- ./ecosystem.config.json:/app/ecosystem.config.json
|
||||
- ./configs/:/app/configs/
|
||||
|
||||
services:
|
||||
|
||||
|
||||
13365
api/package-lock.json
generated
13365
api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@unraid/api",
|
||||
"version": "3.11.0",
|
||||
"main": "src/cli/index.ts",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"repository": "git@github.com:unraid/api.git",
|
||||
"author": "Lime Technology, Inc. <unraid.net>",
|
||||
@@ -12,9 +12,11 @@
|
||||
"build": "vite build --mode=production",
|
||||
"postbuild": "chmod +x dist/main.js && chmod +x dist/cli.js",
|
||||
"build-and-pack": "./scripts/build.mjs",
|
||||
"codegen": "MOTHERSHIP_GRAPHQL_LINK='https://staging.mothership.unraid.net/ws' graphql-codegen --config codegen.yml -r dotenv/config './.env.staging'",
|
||||
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen --config codegen.yml --watch -r dotenv/config",
|
||||
"codegen:local": "NODE_TLS_REJECT_UNAUTHORIZED=0 MOTHERSHIP_GRAPHQL_LINK='https://mothership.localhost/ws' graphql-codegen-esm --config codegen.yml --watch",
|
||||
"bundle": "node ./configs/esbuild.js",
|
||||
"build:binary": "pkg --sea --config configs/pkg.config.json deploy/esbuild/index.js",
|
||||
"codegen": "MOTHERSHIP_GRAPHQL_LINK='https://staging.mothership.unraid.net/ws' graphql-codegen --config configs/codegen.yml -r dotenv/config './.env.staging'",
|
||||
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen --config configs/codegen.yml --watch -r dotenv/config",
|
||||
"codegen:local": "NODE_TLS_REJECT_UNAUTHORIZED=0 MOTHERSHIP_GRAPHQL_LINK='https://mothership.localhost/ws' graphql-codegen-esm --config configs/codegen.yml --watch",
|
||||
"tsc": "tsc --noEmit",
|
||||
"lint": "eslint --flag unstable_ts_config --config .eslintrc.ts src/",
|
||||
"lint:fix": "eslint --flag unstable_ts_config --fix --config .eslintrc.ts src/",
|
||||
@@ -109,7 +111,7 @@
|
||||
"pino": "^9.5.0",
|
||||
"pino-http": "^10.3.0",
|
||||
"pino-pretty": "^11.3.0",
|
||||
"pm2": "^5.4.2",
|
||||
"pm2": "^5.4.3",
|
||||
"reflect-metadata": "^0.1.14",
|
||||
"request": "^2.88.2",
|
||||
"semver": "^7.6.3",
|
||||
@@ -162,6 +164,7 @@
|
||||
"@types/wtfnode": "^0.7.3",
|
||||
"@vitest/coverage-v8": "^2.1.4",
|
||||
"@vitest/ui": "^2.1.4",
|
||||
"@yao-pkg/pkg": "^6.1.1",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"eslint": "^9.14.0",
|
||||
"graphql-codegen-typescript-validation-schema": "^0.16.0",
|
||||
@@ -171,8 +174,10 @@
|
||||
"typescript": "^5.6.3",
|
||||
"typescript-eslint": "^8.13.0",
|
||||
"vite": "^5.4.10",
|
||||
"vite-plugin-native": "^2.2.2",
|
||||
"vite-plugin-node": "^4.0.0",
|
||||
"vite-plugin-static-copy": "^2.0.0",
|
||||
"vite-plugin-top-level-await": "^1.4.4",
|
||||
"vite-tsconfig-paths": "^5.1.0",
|
||||
"vitest": "^2.1.4",
|
||||
"zx": "^8.2.0"
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#!/usr/bin/env zx
|
||||
import { exit } from 'process';
|
||||
import { cd, $ } from 'zx';
|
||||
|
||||
|
||||
|
||||
import { $, cd } from 'zx';
|
||||
|
||||
|
||||
|
||||
import { getDeploymentVersion } from './get-deployment-version.mjs';
|
||||
|
||||
|
||||
try {
|
||||
// Enable colours in output
|
||||
process.env.FORCE_COLOR = '1';
|
||||
@@ -15,6 +21,7 @@ try {
|
||||
// Create deployment directories - ignore if they already exist
|
||||
await $`mkdir -p ./deploy/release`;
|
||||
await $`mkdir -p ./deploy/pre-pack`;
|
||||
await $`mkdir -p ./deploy/pre-pack/.configs`;
|
||||
|
||||
await $`rm -rf ./deploy/release/*`;
|
||||
await $`rm -rf ./deploy/pre-pack/*`;
|
||||
@@ -28,23 +35,23 @@ try {
|
||||
await $`cp -r ./dist/ ./deploy/pre-pack/dist/`;
|
||||
|
||||
// Copy environment to deployment directory
|
||||
const files = [
|
||||
'.env.production',
|
||||
'.env.staging',
|
||||
'tsconfig.json',
|
||||
'codegen.yml',
|
||||
'ecosystem.config.json'
|
||||
]
|
||||
const files = ['.env.production', '.env.staging', 'tsconfig.json'];
|
||||
|
||||
for (const file of files) {
|
||||
console.info(`Copying ${file} to deployment directory`);
|
||||
await $`cp ./${file} ./deploy/pre-pack/${file}`;
|
||||
}
|
||||
|
||||
await $`cp ./configs/codegen.yml ./deploy/pre-pack/codegen.yml`;
|
||||
await $`cp ./configs/ecosystem.config.json ./deploy/pre-pack/ecosystem.config.json`;
|
||||
|
||||
// Get package details
|
||||
const { name, version, ...rest } = await import('../package.json', {
|
||||
assert: { type: 'json' },
|
||||
}).then((pkg) => pkg.default);
|
||||
|
||||
console.info(`Building package ${name} v${version}`);
|
||||
|
||||
const deploymentVersion = getDeploymentVersion(process.env, version);
|
||||
|
||||
// Create deployment package.json
|
||||
@@ -58,7 +65,14 @@ try {
|
||||
await $`cp ./README.md ./deploy/pre-pack/`;
|
||||
|
||||
await $`cp -r ./node_modules ./deploy/pre-pack/node_modules`;
|
||||
// Install production dependencies
|
||||
|
||||
// Bundle and Pack for Legacy OS Versions
|
||||
console.info('Bundling app with esbuild');
|
||||
await $`npm run bundle`;
|
||||
console.info('Packing app with pkg');
|
||||
await $`npm run build:binary`;
|
||||
|
||||
// Install production dependencies
|
||||
cd('./deploy/pre-pack');
|
||||
|
||||
await $`npm prune --omit=dev`;
|
||||
@@ -81,4 +95,4 @@ try {
|
||||
}
|
||||
|
||||
exit(error.exitCode);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,6 @@ export const logoutUser = createAsyncThunk<
|
||||
{ state: RootState }
|
||||
>('config/logout-user', async ({ reason }) => {
|
||||
logger.info('Logging out user: %s', reason ?? 'No reason provided');
|
||||
const { pubsub } = await import('@app/core/pubsub');
|
||||
|
||||
// Publish to servers endpoint
|
||||
await pubsub.publish(PUBSUB_CHANNEL.SERVERS, {
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import nodeExternals from 'rollup-plugin-node-externals';
|
||||
import { viteCommonjs } from '@originjs/vite-plugin-commonjs';
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
import nodeResolve from '@rollup/plugin-node-resolve';
|
||||
import nodeExternals from 'rollup-plugin-node-externals';
|
||||
import native from 'vite-plugin-native';
|
||||
import { VitePluginNode } from 'vite-plugin-node';
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||
import topLevelAwait from "vite-plugin-top-level-await";
|
||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
return {
|
||||
plugins: [
|
||||
native({}),
|
||||
topLevelAwait(),
|
||||
tsconfigPaths(),
|
||||
nodeExternals(),
|
||||
nodeResolve(),
|
||||
@@ -51,7 +55,7 @@ export default defineConfig(({ mode }) => {
|
||||
},
|
||||
output: {
|
||||
entryFileNames: '[name].js',
|
||||
format: 'es', // Change the format to 'es' to support top-level await
|
||||
format: 'es',
|
||||
},
|
||||
},
|
||||
modulePreload: false,
|
||||
@@ -73,4 +77,4 @@ export default defineConfig(({ mode }) => {
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user