phecda-server 7.0.0-alpha.9 → 7.0.1

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.
Files changed (99) hide show
  1. package/assets/schema.json +12 -9
  2. package/bin/cli.mjs +95 -36
  3. package/dist/{chunk-5RBTN33A.js → chunk-4LLLQOMF.js} +10 -5
  4. package/dist/{chunk-7ZGYJ5OW.mjs → chunk-AIAO6SV6.mjs} +10 -34
  5. package/dist/{chunk-V5EYXVJT.js → chunk-DPPDWBYO.js} +53 -25
  6. package/dist/{chunk-CVPZWDXU.mjs → chunk-E7EAPAGM.mjs} +10 -20
  7. package/dist/{chunk-ODVWOXVB.mjs → chunk-MKRHYZCL.mjs} +30 -2
  8. package/dist/{chunk-FXTJ3BJ6.mjs → chunk-NQ55PA2X.mjs} +9 -4
  9. package/dist/{chunk-FX3LDQII.js → chunk-XKK2SQ7W.js} +60 -70
  10. package/dist/{chunk-KJUD2BKE.js → chunk-ZWPOWMZP.js} +25 -49
  11. package/dist/{core-D_cz0tKa.d.ts → core-DbqWh47p.d.mts} +3 -2
  12. package/dist/{core-BDkhrEyf.d.mts → core-Rq7BhPHE.d.ts} +3 -2
  13. package/dist/helper.d.mts +3 -5
  14. package/dist/helper.d.ts +3 -5
  15. package/dist/helper.js +3 -5
  16. package/dist/helper.mjs +2 -4
  17. package/dist/http/elysia/index.d.mts +4 -4
  18. package/dist/http/elysia/index.d.ts +4 -4
  19. package/dist/http/elysia/index.js +41 -40
  20. package/dist/http/elysia/index.mjs +4 -3
  21. package/dist/http/express/index.d.mts +3 -3
  22. package/dist/http/express/index.d.ts +3 -3
  23. package/dist/http/express/index.js +38 -37
  24. package/dist/http/express/index.mjs +3 -2
  25. package/dist/http/fastify/index.d.mts +3 -3
  26. package/dist/http/fastify/index.d.ts +3 -3
  27. package/dist/http/fastify/index.js +39 -38
  28. package/dist/http/fastify/index.mjs +4 -3
  29. package/dist/http/h3/index.d.mts +3 -3
  30. package/dist/http/h3/index.d.ts +3 -3
  31. package/dist/http/h3/index.js +39 -38
  32. package/dist/http/h3/index.mjs +3 -2
  33. package/dist/http/hono/index.d.mts +3 -3
  34. package/dist/http/hono/index.d.ts +3 -3
  35. package/dist/http/hono/index.js +35 -34
  36. package/dist/http/hono/index.mjs +3 -2
  37. package/dist/http/hyper-express/index.d.mts +3 -3
  38. package/dist/http/hyper-express/index.d.ts +3 -3
  39. package/dist/http/hyper-express/index.js +36 -35
  40. package/dist/http/hyper-express/index.mjs +3 -2
  41. package/dist/http/koa/index.d.mts +3 -3
  42. package/dist/http/koa/index.d.ts +3 -3
  43. package/dist/http/koa/index.js +38 -37
  44. package/dist/http/koa/index.mjs +3 -2
  45. package/dist/index.d.mts +76 -12
  46. package/dist/index.d.ts +76 -12
  47. package/dist/index.js +102 -49
  48. package/dist/index.mjs +66 -13
  49. package/dist/{meta-BX5jhe4Z.d.mts → meta-BoS1E-Nz.d.mts} +6 -23
  50. package/dist/{meta-BX5jhe4Z.d.ts → meta-BoS1E-Nz.d.ts} +6 -23
  51. package/dist/rpc/bullmq/index.d.mts +4 -6
  52. package/dist/rpc/bullmq/index.d.ts +4 -6
  53. package/dist/rpc/bullmq/index.js +12 -80
  54. package/dist/rpc/bullmq/index.mjs +4 -72
  55. package/dist/rpc/electron/index.d.mts +13 -0
  56. package/dist/rpc/electron/index.d.ts +13 -0
  57. package/dist/rpc/electron/index.js +72 -0
  58. package/dist/rpc/electron/index.mjs +72 -0
  59. package/dist/rpc/kafka/index.d.mts +4 -9
  60. package/dist/rpc/kafka/index.d.ts +4 -9
  61. package/dist/rpc/kafka/index.js +11 -90
  62. package/dist/rpc/kafka/index.mjs +4 -83
  63. package/dist/rpc/nats/index.d.mts +4 -6
  64. package/dist/rpc/nats/index.d.ts +4 -6
  65. package/dist/rpc/nats/index.js +12 -72
  66. package/dist/rpc/nats/index.mjs +3 -63
  67. package/dist/rpc/rabbitmq/index.d.mts +4 -6
  68. package/dist/rpc/rabbitmq/index.d.ts +4 -6
  69. package/dist/rpc/rabbitmq/index.js +13 -79
  70. package/dist/rpc/rabbitmq/index.mjs +4 -70
  71. package/dist/rpc/redis/index.d.mts +4 -9
  72. package/dist/rpc/redis/index.d.ts +4 -9
  73. package/dist/rpc/redis/index.js +11 -78
  74. package/dist/rpc/redis/index.mjs +4 -71
  75. package/dist/rpc/web-ext/index.d.mts +2 -0
  76. package/dist/rpc/web-ext/index.d.ts +2 -0
  77. package/dist/rpc/web-ext/index.js +1 -0
  78. package/dist/rpc/web-ext/index.mjs +0 -0
  79. package/dist/rpc/ws/index.d.mts +14 -0
  80. package/dist/rpc/ws/index.d.ts +14 -0
  81. package/dist/rpc/ws/index.js +73 -0
  82. package/dist/rpc/ws/index.mjs +73 -0
  83. package/dist/test.d.mts +7 -3
  84. package/dist/test.d.ts +7 -3
  85. package/dist/test.js +6 -6
  86. package/dist/test.mjs +2 -2
  87. package/dist/types-CInz3bD0.d.ts +14 -0
  88. package/dist/types-E-rqlg3-.d.mts +14 -0
  89. package/dist/{types-DKVhyZk_.d.mts → types-SCJZFCYt.d.mts} +1 -1
  90. package/dist/{types-CMeuFoyd.d.ts → types-xruyYmyu.d.ts} +1 -1
  91. package/package.json +24 -8
  92. package/register/export.mjs +30 -0
  93. package/register/index.mjs +2 -3
  94. package/register/loader.mjs +83 -90
  95. package/register/utils.mjs +36 -6
  96. package/assets/ps.json +0 -24
  97. package/assets/tsconfig.json +0 -21
  98. package/dist/types-B-rUM9Fm.d.mts +0 -19
  99. package/dist/types-MxxtkZXw.d.ts +0 -19
@@ -0,0 +1,73 @@
1
+ import {
2
+ Context,
3
+ createControllerMetaMap,
4
+ detectAopDep
5
+ } from "../../chunk-E7EAPAGM.mjs";
6
+ import {
7
+ __name
8
+ } from "../../chunk-NQ55PA2X.mjs";
9
+
10
+ // src/rpc/ws/bind.ts
11
+ import Debug from "debug";
12
+ var debug = Debug("phecda-server/ws");
13
+ function bind(wss, data, opts = {}) {
14
+ const { globalGuards, globalAddons, globalFilter, globalPipe } = opts;
15
+ const { moduleMap, meta } = data;
16
+ const metaMap = createControllerMetaMap(meta, (meta2) => {
17
+ const { controller, rpc, func, tag } = meta2.data;
18
+ if (controller === "rpc" && rpc?.queue !== void 0) {
19
+ debug(`register method "${func}" in module "${tag}"`);
20
+ return true;
21
+ }
22
+ });
23
+ detectAopDep(meta, {
24
+ guards: globalGuards,
25
+ addons: globalAddons
26
+ }, "rpc");
27
+ wss.on("connection", (ws) => {
28
+ ws.on("message", async (raw) => {
29
+ try {
30
+ const data2 = JSON.parse(raw.toString());
31
+ const { func, id, tag, _ps, args, queue } = data2;
32
+ if (_ps !== 1) return;
33
+ const meta2 = metaMap.get(tag)[func];
34
+ const { data: { rpc: { isEvent } = {} } } = meta2;
35
+ const aop = Context.getAop(meta2, {
36
+ globalFilter,
37
+ globalGuards,
38
+ globalPipe
39
+ });
40
+ const context = new Context({
41
+ type: "ws",
42
+ category: "rpc",
43
+ meta: meta2,
44
+ moduleMap,
45
+ tag,
46
+ func,
47
+ args,
48
+ id,
49
+ queue,
50
+ wss,
51
+ ws
52
+ });
53
+ return await context.run(aop, (returnData) => {
54
+ if (!isEvent) ws.send(JSON.stringify({
55
+ id,
56
+ data: returnData
57
+ }));
58
+ }, (err) => {
59
+ if (!isEvent) ws.send(JSON.stringify({
60
+ id,
61
+ data: err,
62
+ error: true
63
+ }));
64
+ });
65
+ } catch (e) {
66
+ }
67
+ });
68
+ });
69
+ }
70
+ __name(bind, "bind");
71
+ export {
72
+ bind
73
+ };
package/dist/test.d.mts CHANGED
@@ -2,9 +2,13 @@ import * as supertest from 'supertest';
2
2
  import { Test } from 'supertest';
3
3
  import { Server } from 'node:http';
4
4
  import { Construct } from 'phecda-core';
5
- import { F as Factory } from './core-BDkhrEyf.mjs';
6
- import { P as PickFunc } from './meta-BX5jhe4Z.mjs';
5
+ import { F as Factory } from './core-DbqWh47p.mjs';
6
+ import { C as CustomResponse } from './meta-BoS1E-Nz.mjs';
7
7
 
8
+ type PickFuncKeys<Type> = {
9
+ [Key in keyof Type]: Type[Key] extends (...args: any) => any ? (ReturnType<Type[Key]> extends CustomResponse<any> ? never : Key) : never;
10
+ }[keyof Type];
11
+ type PickFunc<Instance> = Pick<Instance, PickFuncKeys<Instance>>;
8
12
  declare function TestFactory<T extends Construct[]>(...Modules: T): Promise<{
9
13
  get<C extends T[number]>(Model: C): InstanceType<C>;
10
14
  }>;
@@ -15,4 +19,4 @@ declare function TestHttp(app: Server | any, { moduleMap, meta }: Awaited<Return
15
19
  module: <T extends Construct>(Module: T) => SuperTestRequest<PickFunc<InstanceType<T>>>;
16
20
  }>;
17
21
 
18
- export { type SuperTestRequest, TestFactory, TestHttp };
22
+ export { type PickFunc, type SuperTestRequest, TestFactory, TestHttp };
package/dist/test.d.ts CHANGED
@@ -2,9 +2,13 @@ import * as supertest from 'supertest';
2
2
  import { Test } from 'supertest';
3
3
  import { Server } from 'node:http';
4
4
  import { Construct } from 'phecda-core';
5
- import { F as Factory } from './core-D_cz0tKa.js';
6
- import { P as PickFunc } from './meta-BX5jhe4Z.js';
5
+ import { F as Factory } from './core-Rq7BhPHE.js';
6
+ import { C as CustomResponse } from './meta-BoS1E-Nz.js';
7
7
 
8
+ type PickFuncKeys<Type> = {
9
+ [Key in keyof Type]: Type[Key] extends (...args: any) => any ? (ReturnType<Type[Key]> extends CustomResponse<any> ? never : Key) : never;
10
+ }[keyof Type];
11
+ type PickFunc<Instance> = Pick<Instance, PickFuncKeys<Instance>>;
8
12
  declare function TestFactory<T extends Construct[]>(...Modules: T): Promise<{
9
13
  get<C extends T[number]>(Model: C): InstanceType<C>;
10
14
  }>;
@@ -15,4 +19,4 @@ declare function TestHttp(app: Server | any, { moduleMap, meta }: Awaited<Return
15
19
  module: <T extends Construct>(Module: T) => SuperTestRequest<PickFunc<InstanceType<T>>>;
16
20
  }>;
17
21
 
18
- export { type SuperTestRequest, TestFactory, TestHttp };
22
+ export { type PickFunc, type SuperTestRequest, TestFactory, TestHttp };
package/dist/test.js CHANGED
@@ -1,14 +1,14 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } }
2
2
 
3
- var _chunkKJUD2BKEjs = require('./chunk-KJUD2BKE.js');
3
+ var _chunkZWPOWMZPjs = require('./chunk-ZWPOWMZP.js');
4
4
 
5
5
 
6
- var _chunk5RBTN33Ajs = require('./chunk-5RBTN33A.js');
6
+ var _chunk4LLLQOMFjs = require('./chunk-4LLLQOMF.js');
7
7
 
8
8
  // src/test.ts
9
9
  var _phecdacore = require('phecda-core');
10
10
  async function TestFactory(...Modules) {
11
- const { moduleMap, modelMap } = await _chunkKJUD2BKEjs.Factory.call(void 0, Modules);
11
+ const { moduleMap, modelMap } = await _chunkZWPOWMZPjs.Factory.call(void 0, Modules);
12
12
  return {
13
13
  get(Model) {
14
14
  const tag = _phecdacore.getTag.call(void 0, Model);
@@ -19,7 +19,7 @@ async function TestFactory(...Modules) {
19
19
  }
20
20
  };
21
21
  }
22
- _chunk5RBTN33Ajs.__name.call(void 0, TestFactory, "TestFactory");
22
+ _chunk4LLLQOMFjs.__name.call(void 0, TestFactory, "TestFactory");
23
23
  async function TestHttp(app, { moduleMap, meta }, isAgent = true) {
24
24
  const { default: request, agent } = await Promise.resolve().then(() => _interopRequireWildcard(require("supertest")));
25
25
  const Agent = agent(app);
@@ -59,11 +59,11 @@ async function TestHttp(app, { moduleMap, meta }, isAgent = true) {
59
59
  }
60
60
  });
61
61
  }
62
- _chunk5RBTN33Ajs.__name.call(void 0, module, "module");
62
+ _chunk4LLLQOMFjs.__name.call(void 0, module, "module");
63
63
  Agent.module = module;
64
64
  return Agent;
65
65
  }
66
- _chunk5RBTN33Ajs.__name.call(void 0, TestHttp, "TestHttp");
66
+ _chunk4LLLQOMFjs.__name.call(void 0, TestHttp, "TestHttp");
67
67
 
68
68
 
69
69
 
package/dist/test.mjs CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Factory
3
- } from "./chunk-7ZGYJ5OW.mjs";
3
+ } from "./chunk-AIAO6SV6.mjs";
4
4
  import {
5
5
  __name
6
- } from "./chunk-FXTJ3BJ6.mjs";
6
+ } from "./chunk-NQ55PA2X.mjs";
7
7
 
8
8
  // src/test.ts
9
9
  import { getTag } from "phecda-core";
@@ -0,0 +1,14 @@
1
+ import { B as BaseCtx, D as DefaultOptions } from './meta-BoS1E-Nz.js';
2
+
3
+ interface RpcServerOptions extends DefaultOptions {
4
+ defaultQueue?: string;
5
+ }
6
+ interface RpcCtx extends BaseCtx {
7
+ args: any[];
8
+ id: string;
9
+ queue: string;
10
+ isEvent?: boolean;
11
+ category: 'rpc';
12
+ }
13
+
14
+ export type { RpcCtx as R, RpcServerOptions as a };
@@ -0,0 +1,14 @@
1
+ import { B as BaseCtx, D as DefaultOptions } from './meta-BoS1E-Nz.mjs';
2
+
3
+ interface RpcServerOptions extends DefaultOptions {
4
+ defaultQueue?: string;
5
+ }
6
+ interface RpcCtx extends BaseCtx {
7
+ args: any[];
8
+ id: string;
9
+ queue: string;
10
+ isEvent?: boolean;
11
+ category: 'rpc';
12
+ }
13
+
14
+ export type { RpcCtx as R, RpcServerOptions as a };
@@ -1,5 +1,5 @@
1
1
  import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
2
- import { D as DefaultOptions, B as BaseCtx } from './meta-BX5jhe4Z.mjs';
2
+ import { B as BaseCtx, D as DefaultOptions } from './meta-BoS1E-Nz.mjs';
3
3
 
4
4
  interface HttpOptions extends DefaultOptions {
5
5
  /**
@@ -1,5 +1,5 @@
1
1
  import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from 'node:http';
2
- import { D as DefaultOptions, B as BaseCtx } from './meta-BX5jhe4Z.js';
2
+ import { B as BaseCtx, D as DefaultOptions } from './meta-BoS1E-Nz.js';
3
3
 
4
4
  interface HttpOptions extends DefaultOptions {
5
5
  /**
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "phecda-server",
3
- "version": "7.0.0-alpha.9",
3
+ "version": "7.0.1",
4
4
  "description": "server framework that provide IOC/type-reuse/http&rpc-adaptor",
5
5
  "author": "fgsreally",
6
6
  "license": "MIT",
7
7
  "repository": "https://github.com/fgsreally/phecda/tree/main/packages/server",
8
8
  "keywords": [
9
9
  "server",
10
+ "http",
10
11
  "IOC",
11
12
  "rpc",
12
- "types-share"
13
+ "types-safe"
13
14
  ],
14
15
  "exports": {
15
16
  ".": {
16
17
  "require": "./dist/index.js",
17
- "import": "./dist/index.mjs",
18
- "node": "./dist/index.js"
18
+ "import": "./dist/index.mjs"
19
19
  },
20
20
  "./helper": {
21
21
  "require": "./dist/helper.js",
@@ -73,6 +73,18 @@
73
73
  "require": "./dist/rpc/nats/index.js",
74
74
  "import": "./dist/rpc/nats/index.mjs"
75
75
  },
76
+ "./electron": {
77
+ "require": "./dist/rpc/electron/index.js",
78
+ "import": "./dist/rpc/electron/index.mjs"
79
+ },
80
+ "./ws": {
81
+ "require": "./dist/rpc/ws/index.js",
82
+ "import": "./dist/rpc/ws/index.mjs"
83
+ },
84
+ "./web-ext": {
85
+ "require": "./dist/rpc/web-ext/index.js",
86
+ "import": "./dist/rpc/web-ext/index.mjs"
87
+ },
76
88
  "./register": "./register/index.mjs",
77
89
  "./*": "./*"
78
90
  },
@@ -144,27 +156,30 @@
144
156
  "chokidar": "^3.5.3",
145
157
  "debug": "^4.3.4",
146
158
  "fs-extra": "^11.2.0",
147
- "h3": "^1.12.0",
148
159
  "picocolors": "^1.0.0",
149
160
  "reflect-metadata": "^0.1.13",
150
161
  "ts-mixer": "^6.0.4",
151
- "phecda-core": "4.1.0-alpha.0"
162
+ "phecda-core": "4.2.0"
152
163
  },
153
164
  "devDependencies": {
154
165
  "@koa/router": "^12.0.1",
155
166
  "@nucleoidjs/kafkajs-mock": "^0.0.1",
156
167
  "@types/amqplib": "^0.10.1",
168
+ "@types/chrome": "^0.0.309",
157
169
  "@types/debug": "^4.1.12",
158
170
  "@types/express": "^4.17.17",
159
171
  "@types/fs-extra": "^11.0.4",
160
172
  "@types/koa": "^2.13.12",
161
173
  "@types/koa__router": "^12.0.4",
162
174
  "@types/supertest": "^2.0.12",
175
+ "@types/ws": "^8.5.13",
163
176
  "amqplib": "^0.10.3",
164
177
  "bullmq": "^5.7.1",
178
+ "electron": "^33.2.1",
165
179
  "elysia": "^1.0.17",
166
180
  "express": "^4.18.2",
167
181
  "fastify": "^4.25.1",
182
+ "h3": "^1.12.0",
168
183
  "hono": "^4.3.4",
169
184
  "hyper-express": "^6.15.2",
170
185
  "ioredis": "^5.3.2",
@@ -176,8 +191,9 @@
176
191
  "nats": "^2.22.0",
177
192
  "supertest": "^6.3.3",
178
193
  "tsup": "^8.1.0",
179
- "typescript": "^5.4.5",
180
- "unimport": "^3.7.1"
194
+ "typescript": "^5.8.3",
195
+ "unimport": "^3.7.1",
196
+ "ws": "^8.18.0"
181
197
  },
182
198
  "scripts": {
183
199
  "dev": "tsup --watch",
@@ -0,0 +1,30 @@
1
+ export default ['Addon', 'Arg', 'Assign', 'BadGatewayException', 'BadRequestException',
2
+ 'Base', 'Body', 'Clear',
3
+ 'ConflictException', 'Controller',
4
+ 'Ctx', 'CustomResponse',
5
+ 'Delete',
6
+ 'Define',
7
+ 'ERROR_SYMBOL',
8
+ 'Effect', 'Empty', 'Err', 'Exception', 'Expose', 'Factory', 'Filter', 'ForbiddenException',
9
+ 'FrameworkException',
10
+ 'Generator', 'Get', 'Global', 'Guard', 'HTTPGenerator', 'Head', 'Header', 'HttpBase',
11
+ 'If', 'Init', 'Inject', 'Injectable',
12
+ 'InvalidInputException', 'Isolate',
13
+ 'Mixin',
14
+ 'NotFoundException', 'PAddon', 'PExtension', 'PFilter', 'PGuard',
15
+ 'PPipe', 'Param', 'Patch', 'PayloadLargeException', 'Pipe', 'Pipeline', 'Post',
16
+ 'Provide', 'Put', 'Query', 'Queue', 'RPCGenerator', 'Route',
17
+ 'Rpc', 'RpcBase', 'Search', 'ServerBase', 'ServerPhecda', 'ServiceUnavailableException', 'Storage',
18
+ 'Tag', 'TimeoutException', 'TimerException', 'UnauthorizedException', 'UndefinedException',
19
+ 'Unique', 'Unmount', 'UnsupportedMediaTypeException', 'ValidateException',
20
+ 'Watcher', 'WorkerException',
21
+ 'addAddon', 'addDecoToClass',
22
+ 'addFilter', 'addGuard', 'addPipe', 'emitter',
23
+ 'getMergedMeta',
24
+ 'getMeta', 'getMetaKey', 'getMetaParams', 'getOwnMeta', 'getOwnMetaKey', 'getOwnMetaParams',
25
+ 'getTag',
26
+ 'isPhecda', 'log', 'phecdaNamespace', 'runMiddleware',
27
+ 'setInject',
28
+ 'setLogger',
29
+ 'setMeta',
30
+ 'useS', 'wait', 'OneFile', 'ManyFiles']
@@ -16,9 +16,8 @@ const fileModelMap = new Map()
16
16
 
17
17
  port1.on('message', async (data) => {
18
18
  const { type, files } = JSON.parse(data)
19
-
20
- if (!isRunning || type === 'relaunch')
21
- return RELAUNCH()// file change -> relaunch
19
+ if ((!isRunning && type !== 'init') || type === 'relaunch')
20
+ return RELAUNCH()
22
21
 
23
22
  if (type === 'change' || type === 'init') {
24
23
  if (!files.length)
@@ -3,31 +3,45 @@ import { writeFile } from 'fs/promises'
3
3
  import {
4
4
  basename,
5
5
  dirname,
6
- extname,
7
6
  isAbsolute,
8
7
  relative,
9
8
  resolve as resolvePath,
10
9
  } from 'path'
11
10
  import { createRequire } from 'module'
12
- import { existsSync } from 'fs'
13
11
  import ts from 'typescript'
14
12
  import chokidar from 'chokidar'
15
- import { IS_DEV, log } from '../dist/index.mjs'
13
+ import Debug from 'debug'
16
14
  import { compile, genUnImportRet, handleClassTypes, slash } from './utils.mjs'
17
15
 
16
+ const require = createRequire(import.meta.url)
17
+ const debug = Debug('phecda-server/loader')
18
+
19
+ const isLowVersion = parseFloat(process.version.slice(1)) < 18.19
20
+ const IS_DEV = process.env.NODE_ENV === 'development'
18
21
  let port
22
+ let config
23
+ const workdir = process.cwd()
24
+ const configPath = resolvePath(
25
+ workdir,
26
+ process.env.PS_CONFIG_FILE || 'ps.json',
27
+ )
28
+
29
+ // unimport
30
+ let unimportRet, customLoad, customResolve
31
+ const dtsPath = process.env.PS_DTS_PATH || 'ps.d.ts'
32
+
33
+ // graph
34
+ const watchFiles = new Set()
35
+ const filesRecord = new Map()
36
+ const moduleGraph = {}
37
+ // ts
19
38
  let tsconfig = {
20
39
  module: ts.ModuleKind.ESNext,
21
40
  moduleResolution: ts.ModuleResolutionKind.NodeNext,
22
41
  }
23
-
24
- const isLowVersion = parseFloat(process.version.slice(1)) < 18.19
25
- // this part is important or not?
26
42
  const EXTENSIONS = [ts.Extension.Ts, ts.Extension.Tsx, ts.Extension.Mts]
27
-
28
43
  const tsconfigPath = resolvePath(process.cwd(), 'tsconfig.json')
29
44
  const tsRet = ts.readConfigFile(tsconfigPath, ts.sys.readFile)
30
-
31
45
  if (!tsRet.error) {
32
46
  const { error, options } = ts.parseJsonConfigFileContent(
33
47
  tsRet.config,
@@ -48,33 +62,31 @@ const host = {
48
62
  readFile: ts.sys.readFile,
49
63
  }
50
64
 
51
- let unimportRet
52
- const dtsPath = 'ps.d.ts'
53
-
54
65
  if (isLowVersion)
55
66
  await initialize()
56
67
 
57
- let config
58
-
59
- const workdir = process.cwd()
60
-
61
- const configPath = resolvePath(
62
- workdir,
63
- process.env.PS_CONFIG_FILE || 'ps.json',
64
- )
65
-
66
- const require = createRequire(import.meta.url)
67
68
  export async function initialize(data) {
68
69
  if (data)
69
70
  port = data.port
70
- log('read config...')
71
+
72
+ debug('read config...')
71
73
 
72
74
  config = require(configPath)
73
- if (!config.virtualFile)
74
- config.virtualFile = {}
75
+
75
76
  if (!config.paths)
76
77
  config.paths = {}
77
78
 
79
+ const loaderPath = process.env.PS_LOADER_PATH
80
+
81
+ if (loaderPath) {
82
+ const loader = await import(loaderPath.startsWith('.') ? resolvePath(workdir, loaderPath) : loaderPath)
83
+
84
+ if (typeof loader.load === 'function')
85
+ customLoad = loader.load
86
+
87
+ if (typeof loader.resolve === 'function')
88
+ customResolve = loader.resolve
89
+ }
78
90
  if (IS_DEV) {
79
91
  chokidar.watch(configPath, { persistent: true }).on('change', () => {
80
92
  port.postMessage(
@@ -87,19 +99,21 @@ export async function initialize(data) {
87
99
 
88
100
  if (!config.unimport)
89
101
  return
102
+
90
103
  unimportRet = await genUnImportRet(config.unimport)
91
104
  if (unimportRet) {
92
- log('auto import...')
105
+ debug('auto import...')
93
106
  await unimportRet.init()
94
107
 
108
+ const unimportDtsPath = resolvePath(workdir, dtsPath)
95
109
  writeFile(
96
- resolvePath(workdir, config.unimport.dtsPath || dtsPath),
110
+ unimportDtsPath,
97
111
  handleClassTypes(
98
112
  await unimportRet.generateTypeDeclarations({
99
113
  resolvePath: (i) => {
100
114
  if (i.from.startsWith('.') || isAbsolute(i.from)) {
101
115
  const related = slash(
102
- relative(workdir, i.from).replace(/\.ts(x)?$/, ''),
116
+ relative(dirname(unimportDtsPath), i.from).replace(/\.ts(x)?$/, ''),
103
117
  )
104
118
 
105
119
  return !related.startsWith('.') ? `./${related}` : related
@@ -112,12 +126,6 @@ export async function initialize(data) {
112
126
  }
113
127
  }
114
128
 
115
- const watchFiles = new Set()
116
- const filesRecord = new Map()
117
- const moduleGraph = {}
118
-
119
- let entryUrl
120
-
121
129
  function addUrlToGraph(url, parent) {
122
130
  if (!(url in moduleGraph))
123
131
  moduleGraph[url] = new Set()
@@ -129,63 +137,34 @@ function addUrlToGraph(url, parent) {
129
137
  function getFileMid(file) {
130
138
  const filename = basename(file)
131
139
  const ret = filename.split('.')
132
- if (ret.length === 3)
133
- return ret[1]
134
- else return ''
140
+ if (!['js', 'mjs', 'cjs', 'ts', 'tsx', 'mts', 'cts'].includes(ret.pop()))
141
+ return ''
142
+ if (!ret[0])// .dockerfile
143
+ return ''
144
+
145
+ return ret[1]
135
146
  }
136
147
 
137
148
  export const resolve = async (specifier, context, nextResolve) => {
138
- // virtual file
139
- if (config.virtualFile[specifier]) {
140
- return {
141
- format: 'ts',
142
- url: specifier,
143
- shortCircuit: true,
144
- }
145
- }
146
- // entrypoint
147
- if (!context.parentURL) {
148
- if (/^file:\/\/\//.test(specifier) && existsSync(fileURLToPath(specifier))) {
149
- entryUrl = specifier
150
-
149
+ if (customResolve) {
150
+ const url = await customResolve(specifier, context)
151
+ if (url) {
151
152
  return {
152
- format: EXTENSIONS.some(ext => specifier.endsWith(ext))
153
- ? 'ts'
154
- : undefined,
155
- url: specifier,
153
+ format: 'ts',
154
+ url,
156
155
  shortCircuit: true,
157
156
  }
158
157
  }
159
- else {
160
- // won't resolve virtual file as entry in vite
161
- return nextResolve(specifier)
162
- }
163
- }
164
- // url import
165
- // it seems useless
166
- if (/^file:\/\/\//.test(specifier) && extname(specifier) === '.ts') {
167
- const url = addUrlToGraph(specifier, context.parentURL.split('?')[0])
168
- return {
169
- format: 'ts',
170
- url,
171
- shortCircuit: true,
172
- }
173
- }
174
-
175
- // hmr import
176
- if (
177
- context.parentURL.includes('/node_modules/phecda-server')
178
- && isAbsolute(specifier)
179
- ) {
180
- specifier = relative(fileURLToPath(entryUrl), specifier)
181
- .replace(/\.ts$/, '')
182
- .slice(1)
183
- context.parentURL = entryUrl
184
158
  }
185
159
 
186
- // import/require from external library
187
- if (context.parentURL.includes('/node_modules/'))
160
+ // entrypoint
161
+ if (!context.parentURL)
188
162
  return nextResolve(specifier)
163
+
164
+ // @todo skip resolve to improve performance
165
+ // if (context.parentURL.includes('/node_modules/') && specifier.includes('/node_modules/'))
166
+ // return nextResolve(specifier)
167
+
189
168
  const { resolvedModule } = ts.resolveModuleName(
190
169
  specifier,
191
170
  fileURLToPath(context.parentURL),
@@ -194,7 +173,7 @@ export const resolve = async (specifier, context, nextResolve) => {
194
173
  moduleResolutionCache,
195
174
  )
196
175
 
197
- // import between loacl projects
176
+ // import among files in local project
198
177
  if (
199
178
  resolvedModule
200
179
  && !resolvedModule.resolvedFileName.includes('/node_modules/')
@@ -230,23 +209,24 @@ export const resolve = async (specifier, context, nextResolve) => {
230
209
  const resolveRet = await nextResolve(specifier)
231
210
 
232
211
  // ts resolve fail in some cases
233
- if (resolveRet.url && isAbsolute(resolveRet.url))
234
- resolveRet.url = pathToFileURL(resolveRet.url).href
212
+ if (resolveRet.url && isAbsolute(resolveRet.url)) {
213
+ const [path, query] = resolveRet.url.split('?')
214
+ resolveRet.url = pathToFileURL(path).href + (query ? `?${query}` : '')
215
+ }
235
216
 
236
217
  return resolveRet
237
218
  }
238
219
  // @todo the first params may be url or path, need to distinguish
239
220
 
240
221
  export const load = async (url, context, nextLoad) => {
241
- if (config.virtualFile[url]) {
242
- return {
243
- format: 'module',
244
- source: config.virtualFile[url],
245
- shortCircuit: true,
246
- }
222
+ let mode
223
+ if (context.importAttributes.ps) {
224
+ mode = context.importAttributes.ps
225
+ delete context.importAttributes.ps
247
226
  }
248
227
 
249
228
  url = url.split('?')[0]
229
+
250
230
  if (
251
231
  !url.includes('/node_modules/')
252
232
  && url.startsWith('file://')
@@ -255,7 +235,7 @@ export const load = async (url, context, nextLoad) => {
255
235
  ) {
256
236
  watchFiles.add(url)
257
237
 
258
- if (IS_DEV) {
238
+ if (IS_DEV && mode !== 'not-hmr') {
259
239
  if (isModuleFileUrl(url)) {
260
240
  port.postMessage(
261
241
  JSON.stringify({
@@ -289,6 +269,17 @@ export const load = async (url, context, nextLoad) => {
289
269
  )
290
270
  }
291
271
  }
272
+ // after hmr
273
+ if (customLoad) {
274
+ const source = await customLoad(url, context)
275
+ if (source) {
276
+ return {
277
+ format: 'module',
278
+ source,
279
+ shortCircuit: true,
280
+ }
281
+ }
282
+ }
292
283
  // resolveModuleName failed
293
284
  // I don't know why it failed
294
285
  if (!context.format && url.endsWith('.ts'))
@@ -299,10 +290,12 @@ export const load = async (url, context, nextLoad) => {
299
290
 
300
291
  const code
301
292
  = typeof source === 'string' ? source : Buffer.from(source).toString()
293
+
302
294
  const compiled = (await compile(code, url)).replace(/_ts_metadata\(\"design:paramtypes\"\,/g, '_ts_metadata("design:paramtypes",()=>')// handle cycle
303
295
 
304
296
  if (unimportRet) {
305
297
  const { injectImports } = unimportRet
298
+
306
299
  return {
307
300
  format: 'module',
308
301
  source: (