diff --git a/.npmrc b/.npmrc new file mode 100644 index 00000000..2cee8aab --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +strict-peer-dependencies=false +resolution-mode=time-based diff --git a/build/prepare.js b/build/prepare.js index 1c0de4d6..849cbcc5 100644 --- a/build/prepare.js +++ b/build/prepare.js @@ -1,9 +1,11 @@ -const fs = require('fs'); +const fs = require('fs-extra'); const path = require('path'); const child = require('child_process'); -if (fs.existsSync('plugins/patch-package/package.json') && fs.existsSync('node_modules/patch-package/package.json')) { - child.execSync('npx patch-package --patch-dir=plugins/patch-package/patches', { stdio: 'inherit' }); +if (process.env.npm_execpath.includes('yarn')) { + if (fs.existsSync('plugins/patch-package/package.json') && fs.existsSync('node_modules/patch-package/package.json')) { + child.execSync('npx patch-package --patch-dir=plugins/patch-package/patches', { stdio: 'inherit' }); + } } const dir = path.dirname(path.dirname(require.resolve('@types/node/package.json'))); @@ -96,9 +98,23 @@ const UIConfig = { }, }; +const nm = path.resolve(__dirname, '../node_modules'); +fs.ensureDirSync(path.join(nm, '@hydrooj')); +try { + fs.symlinkSync( + path.join(process.cwd(), 'packages/ui-default'), + path.join(nm, '@hydrooj/ui-default'), + 'dir', + ); +} catch (e) { } for (const package of modules) { const basedir = path.resolve(process.cwd(), package); const files = fs.readdirSync(basedir); + try { + // eslint-disable-next-line import/no-dynamic-require + const name = require(path.join(basedir, 'package.json')).name; + fs.symlinkSync(basedir, path.join(nm, name), 'dir'); + } catch (e) { } if (!files.includes('src') && !files.filter((i) => i.endsWith('.ts')).length && package !== 'packages/utils') continue; config.references.push({ path: package }); const expectedConfig = JSON.stringify((files.includes('src') ? configSrc : configFlat)(package)); diff --git a/package.json b/package.json index 7f8a520e..37f4b411 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "build": "node build/prepare.js && tsc -b --verbose", "build:installer": "esbuild ./install/install.js --minify --format=cjs | base64", "build:watch": "node build/prepare.js && tsc -b --watch", - "build:ui": "yarn build:ui:gulp && node packages/ui-default/build", + "build:ui": "node packages/ui-default/build --gulp && node packages/ui-default/build", "build:ui:gulp": "node packages/ui-default/build --gulp", - "build:ui:dev": "yarn build:ui:gulp && node --trace-deprecation packages/ui-default/build --dev", - "build:ui:production": "cross-env NODE_OPTIONS=--max_old_space_size=8192 yarn build:ui:gulp && node packages/ui-default/build --production", + "build:ui:dev": "node packages/ui-default/build --gulp && node --trace-deprecation packages/ui-default/build --dev", + "build:ui:production": "cross-env NODE_OPTIONS=--max_old_space_size=8192 node packages/ui-default/build --gulp && node packages/ui-default/build --production", "build:ui:production:webpack": "cross-env NODE_OPTIONS=--max_old_space_size=8192 node packages/ui-default/build --production", "test": "mocha", "benchmark": "cross-env BENCHMARK=true mocha", diff --git a/packages/hydrooj/bin/hydrooj.js b/packages/hydrooj/bin/hydrooj.js index 49a6f237..ecce3b7a 100755 --- a/packages/hydrooj/bin/hydrooj.js +++ b/packages/hydrooj/bin/hydrooj.js @@ -1,8 +1,9 @@ #!/usr/bin/env node require('@hydrooj/utils/lib/register'); +const packageBasedir = require('path').resolve(__dirname, '..'); const { default: hook } = require('require-resolve-hook'); -const { bypass } = hook(/^(hydrooj|@hydrooj\/utils|cordis|schemastery|lodash|js-yaml)/, (id) => { +const { bypass } = hook(/^(hydrooj|@hydrooj\/utils|cordis|lodash|js-yaml)($|\/)/, (id) => { if (id.startsWith('hydrooj/src')) { console.log('module require via %s is deprecated.', id); if (process.env.DEV) { @@ -13,7 +14,34 @@ const { bypass } = hook(/^(hydrooj|@hydrooj\/utils|cordis|schemastery|lodash|js- ); } } - return bypass(() => require.resolve(id)); + if (id.startsWith('hydrooj')) { + return bypass(() => require.resolve(id, { paths: [packageBasedir] })); + } + return bypass(() => { + try { + return require.resolve(id); + } catch (_) { + try { + return require.resolve(id, { paths: [`${process.cwd()}/node_modules`] }); + } catch (e) { + return id; + } + } + }); }); +// Replace pnpm paths. +// Vscode will try to open a local file for links, so this doesn't work for remote-ssh, etc. +if (process.env.npm_execpath && process.env.npm_execpath.includes('pnpm') && !process.env.SSH_CONNECTION) { + const original = Error.prepareStackTrace; + Error.prepareStackTrace = function capture(...args) { + const res = original.apply(this, args); + if (!res.includes('.pnpm')) return res; + return res.replace( + /([( ])([^( ]+\/\.pnpm\/.+?\/node_modules\/)(.+)(:\d+:[^)\n]+)/g, + '$1\u001B]8;;$2$3$4\u0007pnpm:$3$4\u001B]8;;\u0007', + ); + }; +} + require('./commands'); diff --git a/packages/hydrooj/src/plugin-api.ts b/packages/hydrooj/src/plugin-api.ts index 1181e706..ee998a98 100644 --- a/packages/hydrooj/src/plugin-api.ts +++ b/packages/hydrooj/src/plugin-api.ts @@ -1,4 +1,9 @@ +import serialize from 'serialize-javascript'; import db from './service/db'; + +export { nanoid } from 'nanoid'; +export { serialize }; + export * from './pipelineUtils'; export * from './error'; export * from './libs'; diff --git a/packages/hydrooj/src/service/router.ts b/packages/hydrooj/src/service/router.ts index c4248b41..1a64c612 100644 --- a/packages/hydrooj/src/service/router.ts +++ b/packages/hydrooj/src/service/router.ts @@ -1,6 +1,5 @@ import { IncomingMessage } from 'http'; import KoaRouter from 'koa-router'; -import parseUrl from 'parseurl'; import { pathToRegexp } from 'path-to-regexp'; import type WebSocket from 'ws'; import type { KoaContext } from './server'; @@ -20,7 +19,7 @@ export class WebSocketLayer { } accept(socket: WebSocket, request: IncomingMessage, ctx: KoaContext) { - if (!this.regexp.test(parseUrl(request).pathname)) return false; + if (!this.regexp.test(new URL(request.url, `http://${request.headers.host}`).pathname)) return false; this.clients.add(socket); socket.on('close', () => { this.clients.delete(socket); diff --git a/packages/ui-default/backendlib/misc.ts b/packages/ui-default/backendlib/misc.ts index cdf6a46c..23c599ca 100644 --- a/packages/ui-default/backendlib/misc.ts +++ b/packages/ui-default/backendlib/misc.ts @@ -1,8 +1,7 @@ import AnsiUp from 'ansi_up'; -import moment from 'moment-timezone'; -import { ObjectID } from 'mongodb'; +import { moment, ObjectID } from 'hydrooj'; -export { size, formatSeconds } from '@hydrooj/utils/lib/utils'; +export { size, formatSeconds } from 'hydrooj'; const AU = new AnsiUp(); diff --git a/packages/ui-default/backendlib/template.js b/packages/ui-default/backendlib/template.js index 422a4afe..38541b90 100644 --- a/packages/ui-default/backendlib/template.js +++ b/packages/ui-default/backendlib/template.js @@ -1,7 +1,5 @@ -const fs = require('fs'); const path = require('path'); -const yaml = require('js-yaml'); -const serialize = require('serialize-javascript'); +const { serialize, fs, yaml } = require('hydrooj'); const nunjucks = require('nunjucks'); const jsesc = require('jsesc'); const argv = require('cac')().parse(); diff --git a/packages/ui-default/build/config/webpack.ts b/packages/ui-default/build/config/webpack.ts index 3e327f56..236cbfa8 100644 --- a/packages/ui-default/build/config/webpack.ts +++ b/packages/ui-default/build/config/webpack.ts @@ -128,7 +128,7 @@ export default function (env: { watch?: boolean, production?: boolean, measure?: const p = pathData.module.resource.replace(/\\/g, '/'); const filename = p.split('/').pop(); if (p.includes('node_modules')) { - const extra = p.split('node_modules')[1]; + const extra = p.split('node_modules/').pop(); const moduleName = extra.split('/')[0]; if (extra.includes('@fontsource')) { return `fonts/${filename}?[hash:6]`; @@ -198,7 +198,7 @@ export default function (env: { watch?: boolean, production?: boolean, measure?: test: /[\\/]node_modules[\\/].+\.([jt]sx?|json|yaml)$/, priority: -10, name(module) { - const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]; + const packageName = module.context.replace(/\\/g, '/').split('node_modules/').pop().split('/')[0]; if (packageName === 'monaco-editor-nls') { return `i.monaco.${module.userRequest.split('/').pop().split('.')[0]}`; } diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 9ce6c321..843c38a5 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -90,6 +90,7 @@ "redux-promise-middleware": "^6.1.3", "redux-thunk": "^2.4.2", "rupture": "^0.7.1", + "schemastery": "^3.6.1", "slideout": "^1.0.1", "sticky-kit": "^1.1.3", "tether": "1.4.7", diff --git a/packages/utils/lib/register.js b/packages/utils/lib/register.js index 99a87a35..69101191 100644 --- a/packages/utils/lib/register.js +++ b/packages/utils/lib/register.js @@ -17,7 +17,7 @@ const vm = require('vm'); const fs = require('fs-extra'); const esbuild = require('esbuild'); -if (!process.env.NODE_APP_INSTANCE) process.env.NODE_APP_INSTANCE = '0'; +process.env.NODE_APP_INSTANCE ||= '0'; const major = +process.version.split('.')[0].split('v')[1]; const minor = +process.version.split('.')[1]; @@ -86,4 +86,4 @@ if (argv.options.debug) { console.log('Debug mode enabled'); process.env.NODE_ENV = 'development'; process.env.DEV = 'on'; -} else process.env.NODE_ENV = process.env.NODE_ENV || 'production'; +} else process.env.NODE_ENV ||= 'production'; diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 00000000..8897423b --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +packages: +- packages/* +- plugins/* \ No newline at end of file