@jayfong/x-server 2.103.0 → 2.105.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.
@@ -4,7 +4,7 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
4
4
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
5
  exports.__esModule = true;
6
6
  exports.ApiGenerator = void 0;
7
- var _path = _interopRequireDefault(require("path"));
7
+ var _nodePath = _interopRequireDefault(require("node:path"));
8
8
  var _debug = _interopRequireDefault(require("debug"));
9
9
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
10
10
  var _tsMorph = _interopRequireWildcard(require("ts-morph"));
@@ -32,9 +32,9 @@ class ApiGenerator {
32
32
  }
33
33
  async start() {
34
34
  this.debug('启动项目...');
35
- const tsConfigPath = _path.default.join(this.cwd, 'tsconfig.json');
36
- const handlersPath = _path.default.join(this.cwd, 'node_modules/.x/handlers.ts');
37
- const entryFile = _path.default.join(this.cwd, 'src/generated/handlers.ts');
35
+ const tsConfigPath = _nodePath.default.join(this.cwd, 'tsconfig.json');
36
+ const handlersPath = _nodePath.default.join(this.cwd, 'node_modules/.x/handlers.ts');
37
+ const entryFile = _nodePath.default.join(this.cwd, 'src/generated/handlers.ts');
38
38
 
39
39
  // 仅使用 ts-morph 初始化项目
40
40
  const moProject = new _tsMorph.default.Project({
@@ -62,7 +62,7 @@ class ApiGenerator {
62
62
  const categorySourceFilePath = categorySourceFile.fileName;
63
63
 
64
64
  // 忽略仅开发时生效的路由
65
- if (/@dev[\/\.]/.test(categorySourceFilePath)) continue;
65
+ if (/@dev[/.]/.test(categorySourceFilePath)) continue;
66
66
 
67
67
  // 支持 include, exclude
68
68
  if (this.options.include?.length) {
@@ -148,11 +148,11 @@ class ApiGenerator {
148
148
  }
149
149
  this.debug('写入文件...');
150
150
  const prefix = this.options.name ? `${this.options.name}_` : '';
151
- await Promise.all([_fsExtra.default.outputJSON(_path.default.join(this.cwd, `temp/${prefix}api.json`), apiData, {
151
+ await Promise.all([_fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, `temp/${prefix}api.json`), apiData, {
152
152
  spaces: 2
153
- }), _fsExtra.default.outputJSON(_path.default.join(this.cwd, `temp/${prefix}yapi.json`), this.apiDataToYApiData(apiData), {
153
+ }), _fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, `temp/${prefix}yapi.json`), this.apiDataToYApiData(apiData), {
154
154
  spaces: 2
155
- }), _fsExtra.default.outputJSON(_path.default.join(this.cwd, `temp/${prefix}openapi31.json`), this.apiDataToOpenAPI31Data(apiData), {
155
+ }), _fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, `temp/${prefix}openapi31.json`), this.apiDataToOpenAPI31Data(apiData), {
156
156
  spaces: 2
157
157
  })]);
158
158
  }
@@ -9,7 +9,6 @@ var _compressing = _interopRequireDefault(require("compressing"));
9
9
  var esbuild = _interopRequireWildcard(require("esbuild"));
10
10
  var _execa = _interopRequireDefault(require("execa"));
11
11
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
12
- var _globby = _interopRequireDefault(require("globby"));
13
12
  var _vtils = require("vtils");
14
13
  class BuildUtil {
15
14
  static async build(options) {
@@ -132,7 +131,7 @@ class BuildUtil {
132
131
 
133
132
  // 支持仅开发时生效的路由
134
133
  build.onLoad({
135
- filter: /@dev[\/\.]/
134
+ filter: /@dev[/.]/
136
135
  }, async () => {
137
136
  return {
138
137
  contents: 'module.exports = {}',
@@ -156,9 +155,7 @@ class BuildUtil {
156
155
  });
157
156
  }
158
157
  }
159
- },
160
- // @ts-ignore
161
- macrosPlugin()],
158
+ }, macrosPlugin()],
162
159
  loader: {
163
160
  // 兼容 x-text-render 在服务端使用
164
161
  // dev 时用 css_register 兼容
@@ -180,30 +177,6 @@ class BuildUtil {
180
177
  const distMultipleSchemaDir = _nodePath.default.join(distDir, _nodePath.default.basename(multipleSchemaDir));
181
178
  await _fsExtra.default.copy(multipleSchemaDir, distMultipleSchemaDir);
182
179
  }
183
- if (options.noPrismaEngine) {
184
- const prismaEngineFiles = await (0, _globby.default)('libquery_engine-*', {
185
- cwd: distDir,
186
- onlyFiles: true,
187
- absolute: true
188
- });
189
- await Promise.all(prismaEngineFiles.map(file => _fsExtra.default.remove(file)));
190
- } else {
191
- // 复制查询引擎
192
- const libqueryEngineFiles = await (0, _globby.default)('libquery_engine-*', {
193
- cwd: _nodePath.default.join(options.cwd, 'node_modules/.prisma/client'),
194
- ignore: ['libquery_engine-{darwin,windows}*'],
195
- onlyFiles: true,
196
- absolute: true
197
- });
198
- const prismaCliBinaryTargets = options.prismaCliBinaryTargets?.split(',') || [];
199
- for (const libqueryEngineFile of libqueryEngineFiles) {
200
- const libqueryEngineFileBaseName = _nodePath.default.basename(libqueryEngineFile);
201
- if (prismaCliBinaryTargets.length && prismaCliBinaryTargets.every(prismaCliBinaryTarget => !libqueryEngineFile.includes(prismaCliBinaryTarget))) {
202
- continue;
203
- }
204
- await _fsExtra.default.copyFile(libqueryEngineFile, _nodePath.default.join(distDir, libqueryEngineFileBaseName));
205
- }
206
- }
207
180
  }
208
181
 
209
182
  // 写入 pkg
@@ -232,9 +205,9 @@ class BuildUtil {
232
205
  {
233
206
  name: ${JSON.stringify(distPkgContent.name)},
234
207
  script: './main.js',
208
+ interpreter: 'node',
209
+ interpreter_args: ${JSON.stringify(options.pm2NodeArgs || [])},
235
210
  ${hasNvmrc ? `
236
- interpreter: 'node',
237
- interpreter_args: [],
238
211
  env: {
239
212
  PATH: \`\${require('child_process').execSync('fnm exec which node').toString().trim().replace(/\\/node$/, '')}:\${process.env.PATH}\`,
240
213
  },
@@ -3,7 +3,7 @@
3
3
 
4
4
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
5
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
6
- var _path = _interopRequireDefault(require("path"));
6
+ var _nodePath = _interopRequireDefault(require("node:path"));
7
7
  var _chokidar = _interopRequireDefault(require("chokidar"));
8
8
  var _execa = _interopRequireDefault(require("execa"));
9
9
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
@@ -96,7 +96,7 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
96
96
  });
97
97
  }
98
98
  await _template_util.TemplateUtil.init(process.cwd());
99
- const xsignoreFile = _path.default.join(process.cwd(), '.xsignore');
99
+ const xsignoreFile = _nodePath.default.join(process.cwd(), '.xsignore');
100
100
  const xsignoreContent = (await _fsExtra.default.pathExists(xsignoreFile)) ? (await _fsExtra.default.readFile(xsignoreFile, 'utf-8')).trim().split(/[\r\n]+/g).filter(v => v && !v.startsWith('#')) : [];
101
101
  const watcher = _chokidar.default.watch(['src', '.env', '.env*'], {
102
102
  cwd: process.cwd(),
@@ -167,12 +167,6 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
167
167
  describe: '构建时排除的文件',
168
168
  type: 'string',
169
169
  array: true
170
- })
171
- // 注意:不要加 no 前缀,其会自动处理
172
- .positional('prisma-engine', {
173
- describe: '是否包含 Prisma 引擎',
174
- type: 'boolean',
175
- default: true
176
170
  }).positional('empty-dist-dir', {
177
171
  describe: '是否清空构建目录',
178
172
  type: 'boolean',
@@ -225,11 +219,10 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
225
219
  onlyCode: true
226
220
  });
227
221
  }),
228
- prismaCliBinaryTargets: envMap.PRISMA_CLI_BINARY_TARGETS,
229
- noPrismaEngine: argv['prisma-engine'] === false,
230
222
  noEmptyDistDir: argv['empty-dist-dir'] === false,
231
223
  pm2MaxMemoryRestart: deployEnv.MEMORY,
232
- pm2CronRestart: deployEnv.CRON
224
+ pm2CronRestart: deployEnv.CRON,
225
+ pm2NodeArgs: deployEnv.NODE_ARGS
233
226
  });
234
227
  console.log('构建成功');
235
228
  if (argv.deploy) {
@@ -305,7 +298,7 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
305
298
 
306
299
  // 多 schema 文件兼容
307
300
  // https://www.prisma.io/docs/orm/prisma-schema/overview/location#how-to-use-existing-prisma-cli-commands-with-multiple-prisma-schema-files
308
- const schemaDir = _path.default.join(process.cwd(), 'src/db/schema');
301
+ const schemaDir = _nodePath.default.join(process.cwd(), 'src/db/schema');
309
302
  const isMultipleFiles = await _fsExtra.default.pathExists(schemaDir);
310
303
  const schemaArg = isMultipleFiles ? 'src/db' : 'src/db/schema.prisma';
311
304
  await (0, _execa.default)('tnpx', ['prisma', ...argv._.slice(1), '--schema', schemaArg], {
@@ -376,7 +369,7 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
376
369
  channel: '_',
377
370
  cb: async channel => {
378
371
  if (channel && argv.file) {
379
- await _fsExtra.default.writeFile(_path.default.join(process.cwd(), argv.file), channel);
372
+ await _fsExtra.default.writeFile(_nodePath.default.join(process.cwd(), argv.file), channel);
380
373
  }
381
374
  console.log(channel || '');
382
375
  }
@@ -3,14 +3,14 @@
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
4
  exports.__esModule = true;
5
5
  exports.DeployUtil = void 0;
6
- var _path = _interopRequireDefault(require("path"));
6
+ var _nodePath = _interopRequireDefault(require("node:path"));
7
7
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
8
8
  var _nodeSsh = require("node-ssh");
9
9
  var _vtils = require("vtils");
10
10
  class DeployUtil {
11
11
  static async deploy(options) {
12
- const pkgContent = await _fsExtra.default.readJson(_path.default.join(options.cwd, 'package.json'));
13
- const appFile = _path.default.join(options.cwd, `temp${options.channel ? `/${options.channel}` : ''}/app.${pkgContent.version}.tgz`);
12
+ const pkgContent = await _fsExtra.default.readJson(_nodePath.default.join(options.cwd, 'package.json'));
13
+ const appFile = _nodePath.default.join(options.cwd, `temp${options.channel ? `/${options.channel}` : ''}/app.${pkgContent.version}.tgz`);
14
14
  if (!(await _fsExtra.default.pathExists(appFile))) {
15
15
  throw new Error('请先构建');
16
16
  }
@@ -32,7 +32,7 @@ class DeployUtil {
32
32
  onStdout: buf => console.log(buf.toString()),
33
33
  onStderr: buf => console.log(buf.toString())
34
34
  });
35
- const remoteAppFile = `${options.dir}/app_files/${appName}/${options.channel || 'dist'}/${_path.default.basename(appFile)}`;
35
+ const remoteAppFile = `${options.dir}/app_files/${appName}/${options.channel || 'dist'}/${_nodePath.default.basename(appFile)}`;
36
36
  await ssh.putFile(appFile, remoteAppFile);
37
37
  await ssh.execCommand((0, _vtils.dedent)`
38
38
  set -ex
@@ -206,7 +206,6 @@ class EnvUtil {
206
206
  process.env[env.key] = env.value;
207
207
  }
208
208
  process.env.X_SERVER_ENVS = JSON.stringify({
209
- // @ts-ignore
210
209
  ...JSON.parse(process.env.X_SERVER_ENVS || '{}'),
211
210
  ...envsObj
212
211
  });
@@ -3,9 +3,9 @@
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
4
  exports.__esModule = true;
5
5
  exports.TemplateUtil = void 0;
6
+ var _nodePath = _interopRequireDefault(require("node:path"));
6
7
  var _fsExtra = _interopRequireDefault(require("fs-extra"));
7
8
  var _globby = _interopRequireDefault(require("globby"));
8
- var _path = _interopRequireDefault(require("path"));
9
9
  var _vscodeGenerateIndexStandalone = require("vscode-generate-index-standalone");
10
10
  var _vtils = require("vtils");
11
11
  class TemplateUtil {
@@ -20,10 +20,9 @@ class TemplateUtil {
20
20
  * 初始化辅助包。
21
21
  */
22
22
  static async initHelperPackage(cwd) {
23
- const prismaClientFile = TemplateUtil.getPrismaClientTypeFile();
24
- const fromDir = _path.default.join(__dirname, 'templates');
25
- const toDir = _path.default.join(cwd, 'node_modules/.x');
26
- const hasDb = await _fsExtra.default.pathExists(_path.default.join(cwd, 'src/db/schema.prisma'));
23
+ const fromDir = _nodePath.default.join(__dirname, 'templates');
24
+ const toDir = _nodePath.default.join(cwd, 'node_modules/.x');
25
+ const hasDb = await _fsExtra.default.pathExists(_nodePath.default.join(cwd, 'src/db/schema.prisma'));
27
26
  const fromFiles = await (0, _globby.default)('*', {
28
27
  cwd: fromDir,
29
28
  onlyFiles: true,
@@ -37,7 +36,7 @@ class TemplateUtil {
37
36
  await _fsExtra.default.writeFile(toFile, 'export {}');
38
37
  } else {
39
38
  let fromFileContent = await _fsExtra.default.readFile(fromFile, 'utf-8');
40
- fromFileContent = fromFileContent.replaceAll('../.prisma/client/index.d.ts', _path.default.relative(toDir, prismaClientFile)).replaceAll('../../src', _path.default.relative(toDir, `${cwd}/src`));
39
+ fromFileContent = fromFileContent.replaceAll('../../src', _nodePath.default.relative(toDir, `${cwd}/src`));
41
40
  await _fsExtra.default.writeFile(toFile, fromFileContent);
42
41
  }
43
42
  }));
@@ -52,8 +51,8 @@ class TemplateUtil {
52
51
  * 初始化任务。
53
52
  */
54
53
  static async initTasks(cwd) {
55
- const tasksDir = _path.default.join(cwd, 'src/tasks');
56
- const tasksIndexFile = _path.default.join(tasksDir, 'index.ts');
54
+ const tasksDir = _nodePath.default.join(cwd, 'src/tasks');
55
+ const tasksIndexFile = _nodePath.default.join(tasksDir, 'index.ts');
57
56
  if (!(await _fsExtra.default.pathExists(tasksIndexFile))) {
58
57
  await _fsExtra.default.outputFile(tasksIndexFile, (0, _vtils.dedent)`
59
58
  // @index(['./**/*.ts', '!**/*.test.ts', '!**/_*'], f => \`export * from '\${f.path}'\`)
@@ -66,16 +65,16 @@ class TemplateUtil {
66
65
  * 初始化模型。
67
66
  */
68
67
  static async initModels(cwd) {
69
- const modelsDir = _path.default.join(cwd, 'src/models');
70
- const indexFile = _path.default.join(modelsDir, 'index.ts');
71
- const indexFile2 = _path.default.join(cwd, 'node_modules/.x/models.ts');
72
- const prismaClientFile = TemplateUtil.getPrismaClientTypeFile();
68
+ const modelsDir = _nodePath.default.join(cwd, 'src/models');
69
+ const indexFile = _nodePath.default.join(modelsDir, 'index.ts');
70
+ const indexFile2 = _nodePath.default.join(cwd, 'node_modules/.x/models.ts');
71
+ const prismaClientFile = _nodePath.default.join(cwd, 'node_modules/.x/prisma/internal/prismaNamespace.ts');
73
72
  const prismaClientFileContent = await _fsExtra.default.readFile(prismaClientFile, 'utf8');
74
- const modelNames = [...prismaClientFileContent.match(/(?<=const ModelName:).+?(?=\})/s)[0].matchAll(/(\S+?):/g)].map(match => (0, _vtils.camelCase)(match[1]));
73
+ const modelNames = [...prismaClientFileContent.match(/(?<=const ModelName).+?(?=\})/s)[0].matchAll(/(\S+?):/g)].map(match => (0, _vtils.camelCase)(match[1]));
75
74
  await Promise.all(modelNames.map(async modelName => {
76
75
  const model_name = (0, _vtils.snakeCase)(modelName);
77
76
  const ModelName = (0, _vtils.upperFirst)(modelName);
78
- const modelFile = _path.default.join(modelsDir, `${model_name}.ts`);
77
+ const modelFile = _nodePath.default.join(modelsDir, `${model_name}.ts`);
79
78
  if (!(await _fsExtra.default.pathExists(modelFile))) {
80
79
  await _fsExtra.default.outputFile(modelFile, (0, _vtils.dedent)`
81
80
  import { ${ModelName}BaseModel } from '@jayfong/x-server'
@@ -98,14 +97,5 @@ class TemplateUtil {
98
97
  replaceFile: true
99
98
  });
100
99
  }
101
- static getPrismaClientTypeFile() {
102
- // const prismaClientFile = path.join(
103
- // cwd,
104
- // 'node_modules/.prisma/client/index.d.ts',
105
- // )
106
- // 用 require.resolve 以兼容 pnpm
107
- const prismaClientFile = require.resolve('@prisma/client/package.json').replace('@prisma/client/package.json', '.prisma/client/index.d.ts');
108
- return prismaClientFile;
109
- }
110
100
  }
111
101
  exports.TemplateUtil = TemplateUtil;
@@ -1,23 +1,33 @@
1
+ import { URL } from 'node:url';
1
2
  import { x } from '@jayfong/x-server';
2
- import { Prisma, PrismaClient } from '@prisma/client';
3
+ import { PrismaMariaDb } from '@prisma/adapter-mariadb';
4
+ import { type Prisma, PrismaClient } from './prisma/client';
3
5
 
4
- export const prismaClient = new PrismaClient();
6
+ const dbUri = new URL(process.env.DATABASE_URL!);
7
+ const adapter = new PrismaMariaDb({
8
+ host: dbUri.hostname,
9
+ port: +dbUri.port,
10
+ user: dbUri.username,
11
+ password: dbUri.password,
12
+ database: dbUri.pathname.slice(1),
13
+ });
14
+ export const prismaClient = new PrismaClient({ adapter });
5
15
 
6
16
  x.dispose.add(() => prismaClient.$disconnect());
7
17
 
8
18
  type ModelName =
9
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
19
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
10
20
  '';
11
21
  // @endindex
12
22
 
13
- function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
23
+ function _makeBaseModel<TModelName extends ModelName>(name: TModelName) {
14
24
  return class BaseModel {
15
25
  public query = prismaClient[name];
16
26
 
17
27
  public transactionClient: Prisma.TransactionClient | null = null;
18
28
 
19
29
  public transactionify = (tx: Prisma.TransactionClient) => {
20
- // @ts-ignore
30
+ // @ts-expect-error
21
31
  return new (class extends this.constructor {
22
32
  public query = tx[name];
23
33
 
@@ -37,10 +47,10 @@ function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
37
47
  };
38
48
  }
39
49
 
40
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = makeBaseModel('${_.camel(m[1])}')`)
50
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = _makeBaseModel('${_.camel(m[1])}')`)
41
51
  // @endindex
42
52
 
43
- export * from '@prisma/client';
53
+ export * from './prisma/client';
44
54
 
45
55
  export const startTransaction = <T>(
46
56
  cb: (
@@ -49,11 +59,11 @@ export const startTransaction = <T>(
49
59
  },
50
60
  ) => Promise<T>,
51
61
  ): Promise<T> => {
52
- return prismaClient.$transaction(async tx => {
62
+ return prismaClient.$transaction(async _tx => {
53
63
  const _models = require('../../src/models');
54
- const cache = Object.create(null);
64
+ const _cache = Object.create(null);
55
65
  return cb({
56
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return cache.${_.camel(m[1])} || (cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(tx)) }, `)
66
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return _cache.${_.camel(m[1])} || (_cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(_tx)) }, `)
57
67
  // @endindex
58
68
  });
59
69
  });
@@ -1,9 +1,9 @@
1
1
  import createDebug from 'debug';
2
- import { type JSONSchema4 } from 'json-schema';
3
- import { type OpenAPIV3_1 } from 'openapi-types';
2
+ import type { JSONSchema4 } from 'json-schema';
3
+ import type { OpenAPIV3_1 } from 'openapi-types';
4
4
  import { ts } from 'ts-morph';
5
- import { LiteralUnion } from 'vtils/types';
6
- import { type XHandler } from '../core/types';
5
+ import type { LiteralUnion } from 'vtils/types';
6
+ import type { XHandler } from '../core/types';
7
7
  /** 注释 */
8
8
  type Comment = {
9
9
  existing: boolean;
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import createDebug from 'debug';
3
3
  import fs from 'fs-extra';
4
4
  import mo, { ts } from 'ts-morph';
@@ -57,7 +57,7 @@ export class ApiGenerator {
57
57
  const categorySourceFilePath = categorySourceFile.fileName;
58
58
 
59
59
  // 忽略仅开发时生效的路由
60
- if (/@dev[\/\.]/.test(categorySourceFilePath)) continue;
60
+ if (/@dev[/.]/.test(categorySourceFilePath)) continue;
61
61
 
62
62
  // 支持 include, exclude
63
63
  if (this.options.include?.length) {
@@ -7,11 +7,10 @@ export interface BuildOptions {
7
7
  noInstall?: boolean;
8
8
  channel?: string;
9
9
  excludeFiles?: string[];
10
- prismaCliBinaryTargets?: string;
11
- noPrismaEngine?: boolean;
12
10
  noEmptyDistDir?: boolean;
13
11
  pm2MaxMemoryRestart?: string;
14
12
  pm2CronRestart?: string;
13
+ pm2NodeArgs?: string | string[];
15
14
  }
16
15
  export declare class BuildUtil {
17
16
  static build(options: BuildOptions): Promise<void>;
@@ -3,7 +3,6 @@ import compressing from 'compressing';
3
3
  import * as esbuild from 'esbuild';
4
4
  import exec from 'execa';
5
5
  import fs from 'fs-extra';
6
- import globby from 'globby';
7
6
  import { dedent, uniq } from 'vtils';
8
7
  export class BuildUtil {
9
8
  static async build(options) {
@@ -126,7 +125,7 @@ export class BuildUtil {
126
125
 
127
126
  // 支持仅开发时生效的路由
128
127
  build.onLoad({
129
- filter: /@dev[\/\.]/
128
+ filter: /@dev[/.]/
130
129
  }, async () => {
131
130
  return {
132
131
  contents: 'module.exports = {}',
@@ -150,9 +149,7 @@ export class BuildUtil {
150
149
  });
151
150
  }
152
151
  }
153
- },
154
- // @ts-ignore
155
- macrosPlugin()],
152
+ }, macrosPlugin()],
156
153
  loader: {
157
154
  // 兼容 x-text-render 在服务端使用
158
155
  // dev 时用 css_register 兼容
@@ -174,30 +171,6 @@ export class BuildUtil {
174
171
  const distMultipleSchemaDir = path.join(distDir, path.basename(multipleSchemaDir));
175
172
  await fs.copy(multipleSchemaDir, distMultipleSchemaDir);
176
173
  }
177
- if (options.noPrismaEngine) {
178
- const prismaEngineFiles = await globby('libquery_engine-*', {
179
- cwd: distDir,
180
- onlyFiles: true,
181
- absolute: true
182
- });
183
- await Promise.all(prismaEngineFiles.map(file => fs.remove(file)));
184
- } else {
185
- // 复制查询引擎
186
- const libqueryEngineFiles = await globby('libquery_engine-*', {
187
- cwd: path.join(options.cwd, 'node_modules/.prisma/client'),
188
- ignore: ['libquery_engine-{darwin,windows}*'],
189
- onlyFiles: true,
190
- absolute: true
191
- });
192
- const prismaCliBinaryTargets = options.prismaCliBinaryTargets?.split(',') || [];
193
- for (const libqueryEngineFile of libqueryEngineFiles) {
194
- const libqueryEngineFileBaseName = path.basename(libqueryEngineFile);
195
- if (prismaCliBinaryTargets.length && prismaCliBinaryTargets.every(prismaCliBinaryTarget => !libqueryEngineFile.includes(prismaCliBinaryTarget))) {
196
- continue;
197
- }
198
- await fs.copyFile(libqueryEngineFile, path.join(distDir, libqueryEngineFileBaseName));
199
- }
200
- }
201
174
  }
202
175
 
203
176
  // 写入 pkg
@@ -226,9 +199,9 @@ export class BuildUtil {
226
199
  {
227
200
  name: ${JSON.stringify(distPkgContent.name)},
228
201
  script: './main.js',
202
+ interpreter: 'node',
203
+ interpreter_args: ${JSON.stringify(options.pm2NodeArgs || [])},
229
204
  ${hasNvmrc ? `
230
- interpreter: 'node',
231
- interpreter_args: [],
232
205
  env: {
233
206
  PATH: \`\${require('child_process').execSync('fnm exec which node').toString().trim().replace(/\\/node$/, '')}:\${process.env.PATH}\`,
234
207
  },
package/lib/cli/cli.js CHANGED
@@ -1,12 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import path from 'path';
2
+ import path from 'node:path';
3
3
  import chokidar from 'chokidar';
4
4
  import execa from 'execa';
5
5
  import fs from 'fs-extra';
6
6
  import { generateManyIndex } from 'vscode-generate-index-standalone';
7
- import { castArray, debounce } from 'vtils';
8
- import { StringTemplate } from 'vtils';
9
7
  import * as vtils from 'vtils';
8
+ import { castArray, debounce, StringTemplate } from 'vtils';
10
9
  import yargs from 'yargs';
11
10
  import { ApiGenerator } from "./api_generator";
12
11
  import { BuildUtil } from "./build_util";
@@ -164,12 +163,6 @@ yargs.command('dev', '开始开发', _ => _.positional('index', {
164
163
  describe: '构建时排除的文件',
165
164
  type: 'string',
166
165
  array: true
167
- })
168
- // 注意:不要加 no 前缀,其会自动处理
169
- .positional('prisma-engine', {
170
- describe: '是否包含 Prisma 引擎',
171
- type: 'boolean',
172
- default: true
173
166
  }).positional('empty-dist-dir', {
174
167
  describe: '是否清空构建目录',
175
168
  type: 'boolean',
@@ -222,11 +215,10 @@ yargs.command('dev', '开始开发', _ => _.positional('index', {
222
215
  onlyCode: true
223
216
  });
224
217
  }),
225
- prismaCliBinaryTargets: envMap.PRISMA_CLI_BINARY_TARGETS,
226
- noPrismaEngine: argv['prisma-engine'] === false,
227
218
  noEmptyDistDir: argv['empty-dist-dir'] === false,
228
219
  pm2MaxMemoryRestart: deployEnv.MEMORY,
229
- pm2CronRestart: deployEnv.CRON
220
+ pm2CronRestart: deployEnv.CRON,
221
+ pm2NodeArgs: deployEnv.NODE_ARGS
230
222
  });
231
223
  console.log('构建成功');
232
224
  if (argv.deploy) {
@@ -1,4 +1,4 @@
1
- import path from 'path';
1
+ import path from 'node:path';
2
2
  import fs from 'fs-extra';
3
3
  import { NodeSSH } from 'node-ssh';
4
4
  import { dedent } from 'vtils';
@@ -201,7 +201,6 @@ export class EnvUtil {
201
201
  process.env[env.key] = env.value;
202
202
  }
203
203
  process.env.X_SERVER_ENVS = JSON.stringify({
204
- // @ts-ignore
205
204
  ...JSON.parse(process.env.X_SERVER_ENVS || '{}'),
206
205
  ...envsObj
207
206
  });
@@ -15,5 +15,4 @@ export declare class TemplateUtil {
15
15
  * 初始化模型。
16
16
  */
17
17
  static initModels(cwd: string): Promise<void>;
18
- static getPrismaClientTypeFile(): string;
19
18
  }
@@ -1,6 +1,6 @@
1
+ import path from 'node:path';
1
2
  import fs from 'fs-extra';
2
3
  import globby from 'globby';
3
- import path from 'path';
4
4
  import { generateManyIndex } from 'vscode-generate-index-standalone';
5
5
  import { camelCase, dedent, snakeCase, upperFirst } from 'vtils';
6
6
  export class TemplateUtil {
@@ -15,7 +15,6 @@ export class TemplateUtil {
15
15
  * 初始化辅助包。
16
16
  */
17
17
  static async initHelperPackage(cwd) {
18
- const prismaClientFile = TemplateUtil.getPrismaClientTypeFile();
19
18
  const fromDir = path.join(__dirname, 'templates');
20
19
  const toDir = path.join(cwd, 'node_modules/.x');
21
20
  const hasDb = await fs.pathExists(path.join(cwd, 'src/db/schema.prisma'));
@@ -32,7 +31,7 @@ export class TemplateUtil {
32
31
  await fs.writeFile(toFile, 'export {}');
33
32
  } else {
34
33
  let fromFileContent = await fs.readFile(fromFile, 'utf-8');
35
- fromFileContent = fromFileContent.replaceAll('../.prisma/client/index.d.ts', path.relative(toDir, prismaClientFile)).replaceAll('../../src', path.relative(toDir, `${cwd}/src`));
34
+ fromFileContent = fromFileContent.replaceAll('../../src', path.relative(toDir, `${cwd}/src`));
36
35
  await fs.writeFile(toFile, fromFileContent);
37
36
  }
38
37
  }));
@@ -64,9 +63,9 @@ export class TemplateUtil {
64
63
  const modelsDir = path.join(cwd, 'src/models');
65
64
  const indexFile = path.join(modelsDir, 'index.ts');
66
65
  const indexFile2 = path.join(cwd, 'node_modules/.x/models.ts');
67
- const prismaClientFile = TemplateUtil.getPrismaClientTypeFile();
66
+ const prismaClientFile = path.join(cwd, 'node_modules/.x/prisma/internal/prismaNamespace.ts');
68
67
  const prismaClientFileContent = await fs.readFile(prismaClientFile, 'utf8');
69
- const modelNames = [...prismaClientFileContent.match(/(?<=const ModelName:).+?(?=\})/s)[0].matchAll(/(\S+?):/g)].map(match => camelCase(match[1]));
68
+ const modelNames = [...prismaClientFileContent.match(/(?<=const ModelName).+?(?=\})/s)[0].matchAll(/(\S+?):/g)].map(match => camelCase(match[1]));
70
69
  await Promise.all(modelNames.map(async modelName => {
71
70
  const model_name = snakeCase(modelName);
72
71
  const ModelName = upperFirst(modelName);
@@ -93,13 +92,4 @@ export class TemplateUtil {
93
92
  replaceFile: true
94
93
  });
95
94
  }
96
- static getPrismaClientTypeFile() {
97
- // const prismaClientFile = path.join(
98
- // cwd,
99
- // 'node_modules/.prisma/client/index.d.ts',
100
- // )
101
- // 用 require.resolve 以兼容 pnpm
102
- const prismaClientFile = require.resolve('@prisma/client/package.json').replace('@prisma/client/package.json', '.prisma/client/index.d.ts');
103
- return prismaClientFile;
104
- }
105
95
  }
@@ -1,23 +1,33 @@
1
+ import { URL } from 'node:url';
1
2
  import { x } from '@jayfong/x-server';
2
- import { Prisma, PrismaClient } from '@prisma/client';
3
+ import { PrismaMariaDb } from '@prisma/adapter-mariadb';
4
+ import { type Prisma, PrismaClient } from './prisma/client';
3
5
 
4
- export const prismaClient = new PrismaClient();
6
+ const dbUri = new URL(process.env.DATABASE_URL!);
7
+ const adapter = new PrismaMariaDb({
8
+ host: dbUri.hostname,
9
+ port: +dbUri.port,
10
+ user: dbUri.username,
11
+ password: dbUri.password,
12
+ database: dbUri.pathname.slice(1),
13
+ });
14
+ export const prismaClient = new PrismaClient({ adapter });
5
15
 
6
16
  x.dispose.add(() => prismaClient.$disconnect());
7
17
 
8
18
  type ModelName =
9
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
19
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
10
20
  '';
11
21
  // @endindex
12
22
 
13
- function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
23
+ function _makeBaseModel<TModelName extends ModelName>(name: TModelName) {
14
24
  return class BaseModel {
15
25
  public query = prismaClient[name];
16
26
 
17
27
  public transactionClient: Prisma.TransactionClient | null = null;
18
28
 
19
29
  public transactionify = (tx: Prisma.TransactionClient) => {
20
- // @ts-ignore
30
+ // @ts-expect-error
21
31
  return new (class extends this.constructor {
22
32
  public query = tx[name];
23
33
 
@@ -37,10 +47,10 @@ function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
37
47
  };
38
48
  }
39
49
 
40
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = makeBaseModel('${_.camel(m[1])}')`)
50
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = _makeBaseModel('${_.camel(m[1])}')`)
41
51
  // @endindex
42
52
 
43
- export * from '@prisma/client';
53
+ export * from './prisma/client';
44
54
 
45
55
  export const startTransaction = <T>(
46
56
  cb: (
@@ -49,11 +59,11 @@ export const startTransaction = <T>(
49
59
  },
50
60
  ) => Promise<T>,
51
61
  ): Promise<T> => {
52
- return prismaClient.$transaction(async tx => {
62
+ return prismaClient.$transaction(async _tx => {
53
63
  const _models = require('../../src/models');
54
- const cache = Object.create(null);
64
+ const _cache = Object.create(null);
55
65
  return cb({
56
- // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return cache.${_.camel(m[1])} || (cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(tx)) }, `)
66
+ // @index('./prisma/internal/prismaNamespace.ts', /(?<=const ModelName).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return _cache.${_.camel(m[1])} || (_cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(_tx)) }, `)
57
67
  // @endindex
58
68
  });
59
69
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayfong/x-server",
3
- "version": "2.103.0",
3
+ "version": "2.105.0",
4
4
  "license": "ISC",
5
5
  "sideEffects": false,
6
6
  "main": "lib/_cjs/index.js",
@@ -27,7 +27,8 @@
27
27
  "@fastify/formbody": "^7.4.0",
28
28
  "@fastify/multipart": "^7.7.0",
29
29
  "@fastify/websocket": "^8.1.0",
30
- "@prisma/client": "^6.3.1",
30
+ "@prisma/adapter-mariadb": "^6.17.0",
31
+ "@prisma/client": "^6.17.0",
31
32
  "@types/busboy": "^0.3.2",
32
33
  "@types/http-errors": "^1.8.2",
33
34
  "@types/jsonwebtoken": "^8.5.8",
@@ -65,7 +66,7 @@
65
66
  "pino-pretty": "^10.0.1",
66
67
  "pinyin-pro": "^3.26.0",
67
68
  "pirates": "^4.0.6",
68
- "prisma": "^6.3.1",
69
+ "prisma": "^6.17.0",
69
70
  "select-run": "^1.1.2",
70
71
  "supports-color": "^8",
71
72
  "svg-captcha": "^1.4.0",