mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-08 15:09:27 +08:00
feat: support commerical plugin server inject
This commit is contained in:
parent
a7301b5e47
commit
1a3d11f94e
@ -26,12 +26,14 @@
|
||||
"@vercel/ncc": "0.36.1",
|
||||
"babel-loader": "^9.2.1",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"bundle-require": "^5.1.0",
|
||||
"chalk": "2.4.2",
|
||||
"css-loader": "^6.8.1",
|
||||
"esbuild-register": "^3.4.2",
|
||||
"fast-glob": "^3.3.1",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-typescript": "6.0.0-alpha.1",
|
||||
"javascript-obfuscator": "^4.1.1",
|
||||
"less": "^4.2.0",
|
||||
"less-loader": "^12.2.0",
|
||||
"postcss": "^8.4.29",
|
||||
@ -40,7 +42,7 @@
|
||||
"react-imported-component": "^6.5.4",
|
||||
"style-loader": "^3.3.3",
|
||||
"tar": "^6.2.0",
|
||||
"tsup": "8.2.4",
|
||||
"tsup": "^8.4.0",
|
||||
"typescript": "5.1.3",
|
||||
"update-notifier": "3.0.0",
|
||||
"vite-plugin-css-injected-by-js": "^3.2.1",
|
||||
@ -49,7 +51,8 @@
|
||||
},
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
"build": "tsup"
|
||||
"build": "tsup",
|
||||
"build:watch": "tsup --watch"
|
||||
},
|
||||
"gitHead": "d0b4efe4be55f8c79a98a331d99d9f8cf99021a1"
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import fg from 'fast-glob';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { build as tsupBuild } from 'tsup';
|
||||
|
||||
import * as bundleRequire from 'bundle-require';
|
||||
import { EsbuildSupportExts, globExcludeFiles } from './constant';
|
||||
import { PkgLog, UserConfig, getPackageJson } from './utils';
|
||||
import {
|
||||
@ -27,6 +27,8 @@ import {
|
||||
} from './utils/buildPluginUtils';
|
||||
import { getDepPkgPath, getDepsConfig } from './utils/getDepsConfig';
|
||||
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin';
|
||||
import { obfuscate } from './utils/obfuscationResult';
|
||||
import pluginEsbuildCommercialInject from './plugins/pluginEsbuildCommercialInject';
|
||||
|
||||
const validExts = ['.ts', '.tsx', '.js', '.jsx', '.mjs'];
|
||||
const serverGlobalFiles: string[] = ['src/**', '!src/client/**', ...globExcludeFiles];
|
||||
@ -307,6 +309,83 @@ export async function buildPluginServer(cwd: string, userConfig: UserConfig, sou
|
||||
await buildServerDeps(cwd, serverFiles, log);
|
||||
}
|
||||
|
||||
export async function buildProPluginServer(cwd: string, userConfig: UserConfig, sourcemap: boolean, log: PkgLog) {
|
||||
log('build pro plugin server source');
|
||||
const packageJson = getPackageJson(cwd);
|
||||
const serverFiles = fg.globSync(serverGlobalFiles, { cwd, absolute: true });
|
||||
buildCheck({ cwd, packageJson, entry: 'server', files: serverFiles, log });
|
||||
const otherExts = Array.from(
|
||||
new Set(serverFiles.map((item) => path.extname(item)).filter((item) => !EsbuildSupportExts.includes(item))),
|
||||
);
|
||||
if (otherExts.length) {
|
||||
log('%s will not be processed, only be copied to the dist directory.', chalk.yellow(otherExts.join(',')));
|
||||
}
|
||||
|
||||
deleteServerFiles(cwd, log);
|
||||
|
||||
// remove compilerOptions.paths in tsconfig.json
|
||||
let tsconfig = bundleRequire.loadTsConfig(path.join(cwd, 'tsconfig.json'));
|
||||
fs.writeFileSync(path.join(cwd, 'tsconfig.json'), JSON.stringify({
|
||||
...tsconfig.data,
|
||||
compilerOptions: { ...tsconfig.data.compilerOptions, paths: [] }
|
||||
}, null, 2));
|
||||
tsconfig = bundleRequire.loadTsConfig(path.join(cwd, 'tsconfig.json'));
|
||||
|
||||
// convert all ts to js, some files may not be referenced by the entry file
|
||||
await tsupBuild(
|
||||
userConfig.modifyTsupConfig({
|
||||
entry: serverFiles,
|
||||
splitting: false,
|
||||
clean: false,
|
||||
bundle: false,
|
||||
silent: true,
|
||||
treeshake: false,
|
||||
target: 'node16',
|
||||
sourcemap,
|
||||
outDir: path.join(cwd, target_dir),
|
||||
format: 'cjs',
|
||||
skipNodeModulesBundle: true,
|
||||
loader: {
|
||||
...otherExts.reduce((prev, cur) => ({ ...prev, [cur]: 'copy' }), {}),
|
||||
'.json': 'copy',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const entryFile = path.join(cwd, 'src/index.ts');
|
||||
// bundle all files、inject commercial code and obfuscate
|
||||
await tsupBuild(
|
||||
userConfig.modifyTsupConfig({
|
||||
entry: [entryFile],
|
||||
splitting: false,
|
||||
clean: false,
|
||||
bundle: true,
|
||||
silent: true,
|
||||
treeshake: false,
|
||||
target: 'node16',
|
||||
sourcemap,
|
||||
outDir: path.join(cwd, target_dir),
|
||||
format: 'cjs',
|
||||
skipNodeModulesBundle: true,
|
||||
tsconfig: tsconfig.path,
|
||||
loader: {
|
||||
...otherExts.reduce((prev, cur) => ({ ...prev, [cur]: 'copy' }), {}),
|
||||
'.json': 'copy',
|
||||
},
|
||||
esbuildPlugins: [pluginEsbuildCommercialInject],
|
||||
onSuccess: async () => {
|
||||
const serverFiles = [path.join(cwd, target_dir, 'index.js')];
|
||||
serverFiles.forEach((file) => {
|
||||
obfuscate(file);
|
||||
});
|
||||
},
|
||||
}),
|
||||
);
|
||||
fs.removeSync(tsconfig.path);
|
||||
|
||||
await buildServerDeps(cwd, serverFiles, log);
|
||||
}
|
||||
|
||||
export async function buildPluginClient(cwd: string, userConfig: UserConfig, sourcemap: boolean, log: PkgLog) {
|
||||
log('build plugin client');
|
||||
const packageJson = getPackageJson(cwd);
|
||||
@ -567,6 +646,10 @@ __webpack_require__.p = (function() {
|
||||
|
||||
export async function buildPlugin(cwd: string, userConfig: UserConfig, sourcemap: boolean, log: PkgLog) {
|
||||
await buildPluginClient(cwd, userConfig, sourcemap, log);
|
||||
await buildPluginServer(cwd, userConfig, sourcemap, log);
|
||||
if (cwd.includes('/pro-plugins') && !cwd.includes('plugin-commercial')) {
|
||||
await buildProPluginServer(cwd, userConfig, sourcemap, log);
|
||||
} else {
|
||||
await buildPluginServer(cwd, userConfig, sourcemap, log);
|
||||
}
|
||||
writeExternalPackageVersion(cwd, log);
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { transform } from 'esbuild';
|
||||
import * as path from 'path';
|
||||
import fs from 'node:fs'
|
||||
|
||||
const pluginEsbuildCommercialInject = {
|
||||
name: 'plugin-esbuild-commercial-inject',
|
||||
setup(build) {
|
||||
|
||||
build.onLoad({ filter: /src\/index\.ts$/ }, async (args) => {
|
||||
let text = fs.readFileSync(args.path, 'utf8');
|
||||
const regex = /export\s*\{\s*default\s*\}\s*from\s*(?:'([^']*)'|"([^"]*)");?/; // match: export { default } from './plugin';
|
||||
const match = text.match(regex);
|
||||
if (match) {
|
||||
text = text.replace(regex, ``);
|
||||
const moduleName = match[1] || match[2];
|
||||
text =
|
||||
`
|
||||
import { withCommercial } from '@nocobase/plugin-for-commercial/server';
|
||||
import _plugin from '${moduleName}';
|
||||
export default withCommercial(_plugin);
|
||||
${text}
|
||||
`;
|
||||
console.log(`${args.path} insert commercial server code`);
|
||||
} else {
|
||||
console.error(`${args.path} can't insert commercial code`);
|
||||
}
|
||||
|
||||
return {
|
||||
contents: text,
|
||||
loader: 'ts',
|
||||
}
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
export default pluginEsbuildCommercialInject
|
48
packages/core/build/src/utils/obfuscationResult.ts
Normal file
48
packages/core/build/src/utils/obfuscationResult.ts
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import * as JavaScriptObfuscator from 'javascript-obfuscator';
|
||||
|
||||
export const obfuscate = (filePath: string) => {
|
||||
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||
const obfuscationResult = JavaScriptObfuscator.obfuscate(fileContent, {
|
||||
compact: true,
|
||||
controlFlowFlattening: true,
|
||||
controlFlowFlatteningThreshold: 0.75,
|
||||
deadCodeInjection: true,
|
||||
deadCodeInjectionThreshold: 0.4,
|
||||
debugProtection: false,
|
||||
debugProtectionInterval: 0,
|
||||
disableConsoleOutput: true,
|
||||
identifierNamesGenerator: 'hexadecimal',
|
||||
log: false,
|
||||
numbersToExpressions: true,
|
||||
renameGlobals: false,
|
||||
selfDefending: true,
|
||||
simplify: true,
|
||||
splitStrings: true,
|
||||
splitStringsChunkLength: 10,
|
||||
stringArray: true,
|
||||
stringArrayCallsTransform: true,
|
||||
stringArrayCallsTransformThreshold: 0.75,
|
||||
stringArrayEncoding: ['base64'],
|
||||
stringArrayIndexShift: true,
|
||||
stringArrayRotate: true,
|
||||
stringArrayShuffle: true,
|
||||
stringArrayWrappersCount: 2,
|
||||
stringArrayWrappersChainedCalls: true,
|
||||
stringArrayWrappersParametersMaxCount: 4,
|
||||
stringArrayWrappersType: 'function',
|
||||
stringArrayThreshold: 0.75,
|
||||
transformObjectKeys: true,
|
||||
unicodeEscapeSequence: false
|
||||
});
|
||||
fs.writeFileSync(filePath, obfuscationResult.getObfuscatedCode(), 'utf8');
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user