nmtjs 0.15.0-beta.3 → 0.15.0-beta.5

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 (43) hide show
  1. package/dist/_exports/index.d.ts +9 -6
  2. package/dist/_exports/index.js +7 -6
  3. package/dist/_exports/index.js.map +1 -1
  4. package/dist/vite/server.js +1 -0
  5. package/dist/vite/server.js.map +1 -1
  6. package/package.json +14 -13
  7. package/src/_exports/application.ts +1 -0
  8. package/src/_exports/common.ts +1 -0
  9. package/src/_exports/contract.ts +2 -0
  10. package/src/_exports/core.ts +1 -0
  11. package/src/_exports/gateway.ts +1 -0
  12. package/src/_exports/http-transport/bun.ts +1 -0
  13. package/src/_exports/http-transport/deno.ts +1 -0
  14. package/src/_exports/http-transport/node.ts +1 -0
  15. package/src/_exports/http-transport.ts +1 -0
  16. package/src/_exports/index.ts +75 -0
  17. package/src/_exports/json-format.ts +1 -0
  18. package/src/_exports/protocol/client.ts +1 -0
  19. package/src/_exports/protocol/server.ts +1 -0
  20. package/src/_exports/protocol.ts +1 -0
  21. package/src/_exports/runtime/types.ts +1 -0
  22. package/src/_exports/runtime.ts +1 -0
  23. package/src/_exports/type.ts +2 -0
  24. package/src/_exports/ws-transport/bun.ts +1 -0
  25. package/src/_exports/ws-transport/deno.ts +1 -0
  26. package/src/_exports/ws-transport/node.ts +1 -0
  27. package/src/_exports/ws-transport.ts +1 -0
  28. package/src/cli.ts +139 -0
  29. package/src/command.ts +30 -0
  30. package/src/config.ts +64 -0
  31. package/src/entrypoints/cli.ts +13 -0
  32. package/src/entrypoints/main.ts +111 -0
  33. package/src/entrypoints/thread.ts +69 -0
  34. package/src/entrypoints/worker.ts +48 -0
  35. package/src/resolver.ts +16 -0
  36. package/src/typings.ts +27 -0
  37. package/src/vite/builder.ts +119 -0
  38. package/src/vite/config.ts +42 -0
  39. package/src/vite/plugins.ts +26 -0
  40. package/src/vite/runners/worker.ts +57 -0
  41. package/src/vite/server.ts +36 -0
  42. package/src/vite/servers/main.ts +34 -0
  43. package/src/vite/servers/worker.ts +107 -0
@@ -1,14 +1,17 @@
1
- import { createConsolePrettyDestination, createFactoryInjectable, createLazyInjectable, createOptionalInjectable, createValueInjectable } from '@nmtjs/core';
1
+ import { createConsolePrettyDestination, createFactoryInjectable, createLazyInjectable, createValueInjectable } from '@nmtjs/core';
2
2
  import { createTransport } from '@nmtjs/gateway';
3
- import { createContractProcedure, createContractRouter, createFilter, createGuard, createHook, createJob, createMiddleware, createPlugin, createProcedure, createRouter, createStep, defineApplication } from '@nmtjs/runtime';
3
+ import { createContractProcedure, createContractRouter, createFilter, createGuard, createHook, createJob, createMiddleware, createPlugin, createProcedure, createRootRouter, createRouter, defineApplication, defineServer } from '@nmtjs/runtime';
4
4
  export declare const neemata: {
5
5
  app: typeof defineApplication;
6
+ server: typeof defineServer;
6
7
  injectables: {
7
8
  pubSubAdapter: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").PubSubAdapterType, import("@nmtjs/core").Scope.Global>;
8
9
  pubSubPublish: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").PubSubPublish, import("@nmtjs/core").Scope.Global>;
9
10
  pubSubSubscribe: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").PubSubSubscribe, import("@nmtjs/core").Scope.Global>;
10
11
  jobManager: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").JobManagerInstance, import("@nmtjs/core").Scope.Global>;
11
12
  storeConfig: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").ServerStoreConfig, import("@nmtjs/core").Scope.Global>;
13
+ workerType: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").WorkerType, import("@nmtjs/core").Scope.Global>;
14
+ jobWorkerQueue: import("@nmtjs/core").LazyInjectable<import("@nmtjs/runtime").JobWorkerQueue, import("@nmtjs/core").Scope.Global>;
12
15
  connection: import("@nmtjs/core").LazyInjectable<import("@nmtjs/gateway").GatewayConnection, import("@nmtjs/core").Scope.Connection>;
13
16
  connectionId: import("@nmtjs/core").LazyInjectable<string, import("@nmtjs/core").Scope.Connection>;
14
17
  connectionData: import("@nmtjs/core").LazyInjectable<unknown, import("@nmtjs/core").Scope.Connection>;
@@ -37,10 +40,10 @@ export declare const neemata: {
37
40
  logging: {
38
41
  console: typeof createConsolePrettyDestination;
39
42
  };
40
- optional: typeof createOptionalInjectable;
41
43
  value: typeof createValueInjectable;
42
44
  lazy: typeof createLazyInjectable;
43
45
  factory: typeof createFactoryInjectable;
46
+ rootRouter: typeof createRootRouter;
44
47
  router: typeof createRouter;
45
48
  contractRouter: typeof createContractRouter;
46
49
  procedure: typeof createProcedure;
@@ -49,13 +52,13 @@ export declare const neemata: {
49
52
  guard: typeof createGuard;
50
53
  filter: typeof createFilter;
51
54
  job: typeof createJob;
52
- step: typeof createStep;
53
55
  hook: typeof createHook;
54
56
  };
55
57
  export { c } from '@nmtjs/contract';
56
58
  export { Scope } from '@nmtjs/core';
57
- export { ErrorCode, ProtocolBlob } from '@nmtjs/protocol';
59
+ export { type ConnectionIdentityType, GatewayHook, ProxyableTransportType, } from '@nmtjs/gateway';
60
+ export { ConnectionType, ErrorCode, ProtocolBlob } from '@nmtjs/protocol';
58
61
  export { t } from '@nmtjs/type';
59
- export { ApiError, defineApplication, LifecycleHook } from 'nmtjs/runtime';
62
+ export { ApiError, defineApplication, JobWorkerQueue, LifecycleHook, StoreType, WorkerType, } from 'nmtjs/runtime';
60
63
  export { neemata as n };
61
64
  export default neemata;
@@ -1,8 +1,9 @@
1
- import { CoreInjectables, createConsolePrettyDestination, createFactoryInjectable, createLazyInjectable, createOptionalInjectable, createValueInjectable, } from '@nmtjs/core';
1
+ import { CoreInjectables, createConsolePrettyDestination, createFactoryInjectable, createLazyInjectable, createValueInjectable, } from '@nmtjs/core';
2
2
  import { createTransport, GatewayInjectables } from '@nmtjs/gateway';
3
- import { createContractProcedure, createContractRouter, createFilter, createGuard, createHook, createJob, createMiddleware, createPlugin, createProcedure, createRouter, createStep, defineApplication, RuntimeInjectables, } from '@nmtjs/runtime';
3
+ import { createContractProcedure, createContractRouter, createFilter, createGuard, createHook, createJob, createMiddleware, createPlugin, createProcedure, createRootRouter, createRouter, defineApplication, defineServer, RuntimeInjectables, } from '@nmtjs/runtime';
4
4
  export const neemata = {
5
5
  app: defineApplication,
6
+ server: defineServer,
6
7
  injectables: {
7
8
  ...CoreInjectables,
8
9
  ...GatewayInjectables,
@@ -15,10 +16,10 @@ export const neemata = {
15
16
  // TODO: TSC wants it
16
17
  createConsolePrettyDestination,
17
18
  },
18
- optional: createOptionalInjectable,
19
19
  value: createValueInjectable,
20
20
  lazy: createLazyInjectable,
21
21
  factory: createFactoryInjectable,
22
+ rootRouter: createRootRouter,
22
23
  router: createRouter,
23
24
  contractRouter: createContractRouter,
24
25
  procedure: createProcedure,
@@ -27,14 +28,14 @@ export const neemata = {
27
28
  guard: createGuard,
28
29
  filter: createFilter,
29
30
  job: createJob,
30
- step: createStep,
31
31
  hook: createHook,
32
32
  };
33
33
  export { c } from '@nmtjs/contract';
34
34
  export { Scope } from '@nmtjs/core';
35
- export { ErrorCode, ProtocolBlob } from '@nmtjs/protocol';
35
+ export { GatewayHook, ProxyableTransportType, } from '@nmtjs/gateway';
36
+ export { ConnectionType, ErrorCode, ProtocolBlob } from '@nmtjs/protocol';
36
37
  export { t } from '@nmtjs/type';
37
- export { ApiError, defineApplication, LifecycleHook } from 'nmtjs/runtime';
38
+ export { ApiError, defineApplication, JobWorkerQueue, LifecycleHook, StoreType, WorkerType, } from 'nmtjs/runtime';
38
39
  export { neemata as n };
39
40
  export default neemata;
40
41
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/_exports/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,8BAA8B,EAC9B,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,GAAG,EAAE,iBAAiB;IACtB,WAAW,EAAE;QACX,GAAG,eAAe;QAClB,GAAG,kBAAkB;QACrB,GAAI,kBAAgD;KACrD;IACD,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE;QACP,OAAO;QACL,qBAAqB;QACrB,8BAAuE;KAC1E;IACD,QAAQ,EAAE,wBAAwB;IAClC,KAAK,EAAE,qBAAqB;IAC5B,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,uBAAuB;IAChC,MAAM,EAAE,YAAY;IACpB,cAAc,EAAE,oBAAoB;IACpC,SAAS,EAAE,eAAe;IAC1B,iBAAiB,EAAE,uBAAuB;IAC1C,UAAU,EAAE,gBAAgB;IAC5B,KAAK,EAAE,WAAW;IAClB,MAAM,EAAE,YAAY;IACpB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,UAAU;IAChB,IAAI,EAAE,UAAU;CACjB,CAAA;AAED,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE1E,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,CAAA;AACvB,eAAe,OAAO,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/_exports/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,8BAA8B,EAC9B,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,WAAW,EACX,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,GAAG,EAAE,iBAAiB;IACtB,MAAM,EAAE,YAAY;IACpB,WAAW,EAAE;QACX,GAAG,eAAe;QAClB,GAAG,kBAAkB;QACrB,GAAI,kBAAgD;KACrD;IACD,SAAS,EAAE,eAAe;IAC1B,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE;QACP,OAAO;QACL,qBAAqB;QACrB,8BAAuE;KAC1E;IACD,KAAK,EAAE,qBAAqB;IAC5B,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,uBAAuB;IAChC,UAAU,EAAE,gBAAgB;IAC5B,MAAM,EAAE,YAAY;IACpB,cAAc,EAAE,oBAAoB;IACpC,SAAS,EAAE,eAAe;IAC1B,iBAAiB,EAAE,uBAAuB;IAC1C,UAAU,EAAE,gBAAgB;IAC5B,KAAK,EAAE,WAAW;IAClB,MAAM,EAAE,YAAY;IACpB,GAAG,EAAE,SAAS;IACd,IAAI,EAAE,UAAU;CACjB,CAAA;AAED,OAAO,EAAE,CAAC,EAAE,MAAM,iBAAiB,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAEL,WAAW,EACX,sBAAsB,GACvB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,aAAa,CAAA;AAC/B,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,SAAS,EACT,UAAU,GACX,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,OAAO,IAAI,CAAC,EAAE,CAAA;AACvB,eAAe,OAAO,CAAA"}
@@ -3,6 +3,7 @@ export function createServer(options, config, dev = {}) {
3
3
  return createViteServer({
4
4
  ...config,
5
5
  server: { middlewareMode: true, ws: false },
6
+ resolve: { tsconfigPaths: true, ...config.resolve },
6
7
  environments: {
7
8
  neemata: {
8
9
  consumer: 'server',
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/vite/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAIvD,MAAM,UAAU,YAAY,CAC1B,OAA0B,EAC1B,MAAkB,EAClB,MAA6B,EAAE;IAE/B,OAAO,gBAAgB,CAAC;QACtB,GAAG,MAAM;QACT,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE;QAC3C,YAAY,EAAE;YACZ,OAAO,EAAE;gBACP,QAAQ,EAAE,QAAQ;gBAClB,GAAG;gBACH,MAAM,EAAE;oBACN,eAAe,EAAE,IAAI,CAAC,SAAS,CAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAC/C;oBACD,uBAAuB,EAAE,IAAI,CAAC,SAAS,CACrC,IAAI,CAAC,SAAS,CACZ,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAC5C,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CACzC,CACF,CACF,CACF;iBACF;aACF;SACF;KACF,CAAC,CAAA;AACJ,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/vite/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,MAAM,CAAA;AAIvD,MAAM,UAAU,YAAY,CAC1B,OAA0B,EAC1B,MAAkB,EAClB,MAA6B,EAAE;IAE/B,OAAO,gBAAgB,CAAC;QACtB,GAAG,MAAM;QACT,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE;QAC3C,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE;QACnD,YAAY,EAAE;YACZ,OAAO,EAAE;gBACP,QAAQ,EAAE,QAAQ;gBAClB,GAAG;gBACH,MAAM,EAAE;oBACN,eAAe,EAAE,IAAI,CAAC,SAAS,CAC7B,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAC/C;oBACD,uBAAuB,EAAE,IAAI,CAAC,SAAS,CACrC,IAAI,CAAC,SAAS,CACZ,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAC5C,CAAC,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CACzC,CACF,CACF,CACF;iBACF;aACF;SACF;KACF,CAAC,CAAA;AACJ,CAAC"}
package/package.json CHANGED
@@ -16,22 +16,22 @@
16
16
  "oxc-resolver": "^11.13.2",
17
17
  "vite": "npm:rolldown-vite@7.2.10",
18
18
  "vite-plugin-static-copy": "^3.1.4",
19
- "@nmtjs/common": "0.15.0-beta.3",
20
- "@nmtjs/contract": "0.15.0-beta.3",
21
- "@nmtjs/gateway": "0.15.0-beta.3",
22
- "@nmtjs/json-format": "0.15.0-beta.3",
23
- "@nmtjs/protocol": "0.15.0-beta.3",
24
- "@nmtjs/runtime": "0.15.0-beta.3",
25
- "@nmtjs/core": "0.15.0-beta.3",
26
- "@nmtjs/type": "0.15.0-beta.3",
27
- "@nmtjs/ws-transport": "0.15.0-beta.3",
28
- "@nmtjs/http-transport": "0.15.0-beta.3"
19
+ "@nmtjs/common": "0.15.0-beta.5",
20
+ "@nmtjs/contract": "0.15.0-beta.5",
21
+ "@nmtjs/core": "0.15.0-beta.5",
22
+ "@nmtjs/gateway": "0.15.0-beta.5",
23
+ "@nmtjs/json-format": "0.15.0-beta.5",
24
+ "@nmtjs/protocol": "0.15.0-beta.5",
25
+ "@nmtjs/runtime": "0.15.0-beta.5",
26
+ "@nmtjs/type": "0.15.0-beta.5",
27
+ "@nmtjs/ws-transport": "0.15.0-beta.5",
28
+ "@nmtjs/http-transport": "0.15.0-beta.5"
29
29
  },
30
30
  "devDependencies": {
31
- "@nmtjs/proxy": "0.15.0-beta.3"
31
+ "@nmtjs/proxy": "0.15.0-beta.5"
32
32
  },
33
33
  "peerDependencies": {
34
- "@nmtjs/proxy": "0.15.0-beta.3"
34
+ "@nmtjs/proxy": "0.15.0-beta.5"
35
35
  },
36
36
  "peerDependenciesMeta": {
37
37
  "@nmtjs/proxy": {
@@ -40,10 +40,11 @@
40
40
  },
41
41
  "files": [
42
42
  "dist",
43
+ "src",
43
44
  "LICENSE.md",
44
45
  "README.md"
45
46
  ],
46
- "version": "0.15.0-beta.3",
47
+ "version": "0.15.0-beta.5",
47
48
  "scripts": {
48
49
  "clean-build": "rm -rf ./dist",
49
50
  "build": "tsc --declaration --sourcemap",
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/runtime/application'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/common'
@@ -0,0 +1,2 @@
1
+ export * from '@nmtjs/contract'
2
+ export { default } from '@nmtjs/contract'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/core'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/gateway'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/http-transport/bun'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/http-transport/deno'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/http-transport/node'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/http-transport'
@@ -0,0 +1,75 @@
1
+ import {
2
+ CoreInjectables,
3
+ createConsolePrettyDestination,
4
+ createFactoryInjectable,
5
+ createLazyInjectable,
6
+ createValueInjectable,
7
+ } from '@nmtjs/core'
8
+ import { createTransport, GatewayInjectables } from '@nmtjs/gateway'
9
+ import {
10
+ createContractProcedure,
11
+ createContractRouter,
12
+ createFilter,
13
+ createGuard,
14
+ createHook,
15
+ createJob,
16
+ createMiddleware,
17
+ createPlugin,
18
+ createProcedure,
19
+ createRootRouter,
20
+ createRouter,
21
+ defineApplication,
22
+ defineServer,
23
+ RuntimeInjectables,
24
+ } from '@nmtjs/runtime'
25
+
26
+ export const neemata = {
27
+ app: defineApplication,
28
+ server: defineServer,
29
+ injectables: {
30
+ ...CoreInjectables,
31
+ ...GatewayInjectables,
32
+ ...(RuntimeInjectables as typeof RuntimeInjectables),
33
+ },
34
+ transport: createTransport,
35
+ plugin: createPlugin,
36
+ logging: {
37
+ console:
38
+ // TODO: TSC wants it
39
+ createConsolePrettyDestination as typeof createConsolePrettyDestination,
40
+ },
41
+ value: createValueInjectable,
42
+ lazy: createLazyInjectable,
43
+ factory: createFactoryInjectable,
44
+ rootRouter: createRootRouter,
45
+ router: createRouter,
46
+ contractRouter: createContractRouter,
47
+ procedure: createProcedure,
48
+ contractProcedure: createContractProcedure,
49
+ middleware: createMiddleware,
50
+ guard: createGuard,
51
+ filter: createFilter,
52
+ job: createJob,
53
+ hook: createHook,
54
+ }
55
+
56
+ export { c } from '@nmtjs/contract'
57
+ export { Scope } from '@nmtjs/core'
58
+ export {
59
+ type ConnectionIdentityType,
60
+ GatewayHook,
61
+ ProxyableTransportType,
62
+ } from '@nmtjs/gateway'
63
+ export { ConnectionType, ErrorCode, ProtocolBlob } from '@nmtjs/protocol'
64
+ export { t } from '@nmtjs/type'
65
+ export {
66
+ ApiError,
67
+ defineApplication,
68
+ JobWorkerQueue,
69
+ LifecycleHook,
70
+ StoreType,
71
+ WorkerType,
72
+ } from 'nmtjs/runtime'
73
+
74
+ export { neemata as n }
75
+ export default neemata
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/json-format/server'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/protocol/client'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/protocol/server'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/protocol'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/runtime/types'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/runtime'
@@ -0,0 +1,2 @@
1
+ export * from '@nmtjs/type'
2
+ export { default } from '@nmtjs/type'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/ws-transport/bun'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/ws-transport/deno'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/ws-transport/node'
@@ -0,0 +1 @@
1
+ export * from '@nmtjs/ws-transport'
package/src/cli.ts ADDED
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env node --enable-source-maps
2
+
3
+ import { once } from 'node:events'
4
+ import { relative, resolve } from 'node:path'
5
+ import process from 'node:process'
6
+
7
+ import type { ArgDef } from 'citty'
8
+ import { defineCommand, runMain } from 'citty'
9
+ import { config as dotenv } from 'dotenv'
10
+
11
+ import type { NeemataConfig } from './config.ts'
12
+ import type { ViteConfigOptions } from './vite/config.ts'
13
+ import { resolver } from './resolver.ts'
14
+ import { generateTypings } from './typings.ts'
15
+ import { createBuilder } from './vite/builder.ts'
16
+ import { baseViteConfigOptions } from './vite/config.ts'
17
+ import { createMainServer } from './vite/servers/main.ts'
18
+
19
+ // import { createMainRunner } from './vite/runner.ts'
20
+
21
+ const commonArgs = {
22
+ config: {
23
+ type: 'string',
24
+ alias: 'c',
25
+ default: './neemata.config.ts',
26
+ description: 'Path to Neemata config file',
27
+ required: false,
28
+ },
29
+ } satisfies Record<string, ArgDef>
30
+
31
+ let config: NeemataConfig
32
+ let viteConfigOptions: ViteConfigOptions
33
+ let applicationImports: Record<string, { path: string; specifier: string }>
34
+
35
+ const mainCommand = defineCommand({
36
+ meta: { description: 'Neemata CLI' },
37
+ args: { ...commonArgs },
38
+ async setup(ctx) {
39
+ const configPath = resolve(ctx.args.config as string)
40
+ config = await import(configPath).then((m) => m.default)
41
+
42
+ for (const env of config.env) {
43
+ if (typeof env === 'string') {
44
+ const { error } = dotenv({ path: env })
45
+ if (error) console.warn(error)
46
+ } else if (typeof env === 'object') {
47
+ for (const key in env) {
48
+ process.env[key] = env[key]
49
+ }
50
+ }
51
+ }
52
+
53
+ // const applicationEntryPaths: Record<string, string> = {}
54
+ applicationImports = {}
55
+ const currentPkg = resolver.sync(process.cwd(), './package.json')
56
+
57
+ for (const [appName, appSpecifier] of Object.entries(config.applications)) {
58
+ const resolution = resolver.sync(process.cwd(), appSpecifier)
59
+ if (resolution.error)
60
+ throw new Error(
61
+ `Failed to resolve application path for ${appName}: ${resolution.error}`,
62
+ )
63
+ if (!resolution.path)
64
+ throw new Error(
65
+ `Failed to resolve application path for ${appName}: no path found`,
66
+ )
67
+ const specifier =
68
+ resolution.packageJsonPath === currentPkg.path
69
+ ? relative(resolve('.neemata'), resolution.path)
70
+ : appSpecifier
71
+ applicationImports[appName] = { path: resolution.path, specifier }
72
+ }
73
+
74
+ viteConfigOptions = {
75
+ applicationImports,
76
+ serverEntryPath: resolve(config.serverPath),
77
+ ...baseViteConfigOptions,
78
+ configPath,
79
+ }
80
+ },
81
+ subCommands: {
82
+ prepare: defineCommand({
83
+ async run(ctx) {
84
+ await generateTypings(applicationImports)
85
+ },
86
+ }),
87
+ dev: defineCommand({
88
+ async run(ctx) {
89
+ const { runner } = await createMainServer(
90
+ viteConfigOptions,
91
+ 'development',
92
+ config,
93
+ )
94
+ await runner.import(viteConfigOptions.entrypointMainPath)
95
+ await once(process, 'beforeExit')
96
+ },
97
+ }),
98
+ preview: defineCommand({
99
+ async run(ctx) {
100
+ const { runner } = await createMainServer(
101
+ viteConfigOptions,
102
+ 'production',
103
+ config,
104
+ )
105
+ await runner.import(viteConfigOptions.entrypointMainPath)
106
+ await once(process, 'beforeExit')
107
+ },
108
+ }),
109
+ build: defineCommand({
110
+ async run(ctx) {
111
+ const builder = await createBuilder(viteConfigOptions, config)
112
+ await builder.build()
113
+ },
114
+ }),
115
+ // command: defineCommand({
116
+ // async run(ctx) {
117
+ // const runner = await createRunner(
118
+ // viteConfigOptions,
119
+ // 'production',
120
+ // config,
121
+ // )
122
+ // const workerModule = await runner.import<
123
+ // typeof import('./entrypoints/worker.ts')
124
+ // >(import.meta.resolve('./entrypoints/worker.js'))
125
+ // const commandModule = await runner.import<
126
+ // typeof import('./command.ts')
127
+ // >(import.meta.resolve('./command.js'))
128
+ // const worker = await workerModule.default({
129
+ // applicationWorkerData: undefined,
130
+ // type: ApplicationType.Command,
131
+ // workerType: ApplicationWorkerType.Command,
132
+ // })
133
+ // await runMain(commandModule.default(worker), { rawArgs: ctx.rawArgs })
134
+ // },
135
+ // }),
136
+ },
137
+ })
138
+
139
+ runMain(mainCommand)
package/src/command.ts ADDED
@@ -0,0 +1,30 @@
1
+ // import type { ApplicationWorker } from '@nmtjs/runtime/worker'
2
+ // import { typeToString } from '@nmtjs/type'
3
+ // import { defineCommand } from 'citty'
4
+
5
+ // export default (worker: ApplicationWorker) =>
6
+ // defineCommand({
7
+ // meta: { description: 'Application CLI' },
8
+ // subCommands: {
9
+ // list: defineCommand({
10
+ // async run(ctx) {
11
+ // worker.app.initializeCore()
12
+ // const commands = Array.from(worker.app.registry.commands).map(
13
+ // ([name, command]) => ({
14
+ // command: name,
15
+ // args: typeToString(command.args),
16
+ // kwargs: typeToString(command.kwargs),
17
+ // }),
18
+ // )
19
+ // console.table(commands, ['command', 'args', 'kwargs'])
20
+ // },
21
+ // }),
22
+ // execute: defineCommand({
23
+ // async run(ctx) {
24
+ // const { _: positionals, ...kwargs } = ctx.args
25
+ // const [commandName, ...args] = positionals
26
+ // await worker.runCommand(commandName, args, kwargs)
27
+ // },
28
+ // }),
29
+ // },
30
+ // })
package/src/config.ts ADDED
@@ -0,0 +1,64 @@
1
+ import type { Plugin as VitePlugin } from 'vite'
2
+
3
+ export type ExtrernalDependency = string | RegExp
4
+
5
+ type DeepPartial<T> = {
6
+ [P in keyof T]?: T[P] extends Record<any, unknown> ? DeepPartial<T[P]> : T[P]
7
+ }
8
+
9
+ export interface NeemataConfig {
10
+ /**
11
+ * Path to application entry point
12
+ */
13
+ applications: {
14
+ /**
15
+ * Application name
16
+ */
17
+ [appName: string]: string
18
+ }
19
+ /**
20
+ * Path to server entry point
21
+ */
22
+ serverPath: string
23
+ /**
24
+ * External dependencies to exclude from application bundle
25
+ *
26
+ * 'prod' - exclude production dependencies from package.json
27
+ *
28
+ * 'all' - exclude all dependencies from package.json
29
+ *
30
+ * ExtrernalDependency[] - array of package names or regular expressions to match package names
31
+ */
32
+ externalDependencies: 'prod' | 'all' | ExtrernalDependency[]
33
+ /**
34
+ * Timeout in milliseconds for graceful shutdown of application workers
35
+ */
36
+ timeout: number
37
+
38
+ /**
39
+ * Environment variables to set for application workers
40
+ *
41
+ * Strings are paths to .env files
42
+ * Records are key-value pairs to set directly
43
+ */
44
+ env: (Record<string, string> | string)[]
45
+
46
+ build: { outDir: string; minify: boolean }
47
+ plugins: VitePlugin[]
48
+ }
49
+
50
+ export function defineConfig(
51
+ config: DeepPartial<NeemataConfig> = {},
52
+ ): NeemataConfig {
53
+ return {
54
+ serverPath: './src/server.ts',
55
+ externalDependencies: 'prod',
56
+ timeout: 10000,
57
+ env: [],
58
+ plugins: [],
59
+ ...config,
60
+ // @ts-expect-error
61
+ applications: config.applications || {},
62
+ build: { outDir: './dist', minify: true, ...config.build },
63
+ }
64
+ }
@@ -0,0 +1,13 @@
1
+ // // import { ApplicationType, ApplicationWorkerType } from '@nmtjs/application'
2
+ // import { runMain } from 'citty'
3
+
4
+ // import command from '../command.ts'
5
+ // import createWorker from './worker.ts'
6
+
7
+ // const worker = await createWorker({
8
+ // applicationWorkerData: undefined,
9
+ // // type: ApplicationType.Command,
10
+ // // workerType: ApplicationWorkerType.Command,
11
+ // })
12
+
13
+ // runMain(command(worker))
@@ -0,0 +1,111 @@
1
+ import type { Worker } from 'node:worker_threads'
2
+ import EventEmitter from 'node:events'
3
+ import { fileURLToPath } from 'node:url'
4
+
5
+ import type { ServerConfig } from '@nmtjs/runtime'
6
+ import type { ViteDevServer } from 'vite'
7
+ import { ApplicationServer, isServerConfig } from '@nmtjs/runtime'
8
+
9
+ declare global {
10
+ const __VITE_CONFIG__: string
11
+ const __APPLICATIONS_CONFIG__: string
12
+ }
13
+
14
+ class InvalidServerConfigError extends Error {
15
+ constructor() {
16
+ super(
17
+ `Server config file does not have a default export, or it not a valid application. Please, make sure the application is defined using defineApplication().`,
18
+ )
19
+ this.name = 'InvalidServerConfigError'
20
+ }
21
+ }
22
+
23
+ const _ext = new URL(import.meta.url).pathname.endsWith('.ts') ? '.ts' : '.js'
24
+ const _vite = __VITE_CONFIG__ ? JSON.parse(__VITE_CONFIG__) : undefined
25
+ const applicationsConfig = __APPLICATIONS_CONFIG__
26
+ ? JSON.parse(__APPLICATIONS_CONFIG__)
27
+ : {}
28
+
29
+ let _viteServerEvents: EventEmitter<{ worker: [Worker] }> | undefined
30
+ let _viteWorkerServer: ViteDevServer | undefined
31
+
32
+ let server: ApplicationServer
33
+
34
+ if (import.meta.env.DEV && import.meta.hot) {
35
+ import.meta.hot.accept('#server', async (module) => {
36
+ await server.stop()
37
+ await createServer(module?.default)
38
+ })
39
+ }
40
+
41
+ if (_vite) {
42
+ const { createWorkerServer } = await import('../vite/servers/worker.ts')
43
+ const neemataConfig = await import(
44
+ /* @vite-ignore */
45
+ _vite.options.configPath
46
+ ).then((m) => m.default as import('../config.ts').NeemataConfig)
47
+ _viteServerEvents = new EventEmitter<{ worker: [Worker] }>()
48
+ _viteWorkerServer = await createWorkerServer(
49
+ _vite.options,
50
+ _vite.mode,
51
+ neemataConfig,
52
+ _viteServerEvents,
53
+ )
54
+ }
55
+
56
+ async function createServer(config: ServerConfig) {
57
+ if (!isServerConfig(config)) throw new InvalidServerConfigError()
58
+ server = new ApplicationServer(config, applicationsConfig, {
59
+ path: fileURLToPath(import.meta.resolve(`./thread${_ext}`)),
60
+ workerData: { vite: _vite?.mode },
61
+ worker: _viteServerEvents
62
+ ? (worker) => {
63
+ _viteServerEvents.emit('worker', worker)
64
+ }
65
+ : undefined,
66
+ })
67
+ await server.start()
68
+ }
69
+
70
+ let isTerminating = false
71
+
72
+ async function handleTermination() {
73
+ if (isTerminating) return
74
+ isTerminating = true
75
+ await server?.stop()
76
+ _viteWorkerServer?.close()
77
+ process.exit(0)
78
+ }
79
+
80
+ function handleUnexpectedError(error: Error) {
81
+ console.error(new Error('Unexpected Error:', { cause: error }))
82
+ }
83
+
84
+ process.once('SIGTERM', handleTermination)
85
+ process.once('SIGINT', handleTermination)
86
+ process.on('uncaughtException', handleUnexpectedError)
87
+ process.on('unhandledRejection', handleUnexpectedError)
88
+
89
+ await createServer(
90
+ await import(
91
+ // @ts-expect-error
92
+ '#server'
93
+ ).then((m) => m.default),
94
+ )
95
+
96
+ const { format } = Intl.NumberFormat('en', {
97
+ notation: 'compact',
98
+ maximumFractionDigits: 2,
99
+ unit: 'byte',
100
+ })
101
+
102
+ const printMem = () => {
103
+ globalThis.gc?.()
104
+ // print memory usage every 10 seconds
105
+ const memoryUsage = process.memoryUsage()
106
+ console.log(
107
+ `Memory Usage: RSS=${format(memoryUsage.rss)}, HeapTotal=${format(memoryUsage.heapTotal)}, HeapUsed=${format(memoryUsage.heapUsed)}, External=${format(memoryUsage.external)}, ArrayBuffers=${format(memoryUsage.arrayBuffers)}`,
108
+ )
109
+ }
110
+ // printMem()
111
+ // setInterval(printMem, 5000)
@@ -0,0 +1,69 @@
1
+ import type { MessagePort } from 'node:worker_threads'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { workerData as _workerData } from 'node:worker_threads'
4
+
5
+ import type { ThreadPortMessage } from '@nmtjs/runtime'
6
+ import type { ModuleRunner } from 'vite/module-runner'
7
+
8
+ export type RunWorkerOptions = {
9
+ port: MessagePort
10
+ runtime:
11
+ | { type: 'application'; name: string; path: string; transportsData: any }
12
+ | { type: 'jobs'; jobWorkerQueue: string }
13
+ vite?: 'development' | 'production'
14
+ }
15
+
16
+ const workerData = _workerData as RunWorkerOptions
17
+
18
+ const ext = new URL(import.meta.url).pathname.endsWith('.ts') ? '.ts' : '.js'
19
+ const workerPath = fileURLToPath(import.meta.resolve(`./worker${ext}`))
20
+
21
+ process.on('uncaughtException', (error) => {
22
+ console.error(new Error('Uncaught Exception:', { cause: error }))
23
+ })
24
+
25
+ process.on('unhandledRejection', (error) => {
26
+ console.error(new Error('Unhandled Promise Rejection:', { cause: error }))
27
+ })
28
+
29
+ process.on('beforeExit', (code) => {
30
+ runner?.close()
31
+ })
32
+
33
+ let runner: ModuleRunner
34
+ let workerModule: typeof import('./worker.ts')
35
+
36
+ try {
37
+ if (workerData.vite) {
38
+ const { createModuleRunner } = (await import(
39
+ '../vite/runners/worker.ts'
40
+ )) as typeof import('../vite/runners/worker.ts')
41
+
42
+ runner = createModuleRunner(workerData.vite)
43
+ workerModule = await runner.import(workerPath)
44
+ } else {
45
+ runner = undefined as any
46
+ workerModule = await import(
47
+ /* @vite-ignore */
48
+ workerPath
49
+ )
50
+ }
51
+
52
+ const runtime = await workerModule.run(workerData.runtime)
53
+
54
+ workerData.port.on('message', async (msg) => {
55
+ if (msg.type === 'stop') {
56
+ await runtime.stop()
57
+ process.exit(0)
58
+ }
59
+ })
60
+
61
+ const hosts = (await runtime?.start()) || undefined
62
+
63
+ workerData.port.postMessage({
64
+ type: 'ready',
65
+ data: { hosts },
66
+ } satisfies ThreadPortMessage)
67
+ } catch (error) {
68
+ console.error(new Error('Worker thread error:', { cause: error }))
69
+ }
@@ -0,0 +1,48 @@
1
+ import { workerData } from 'node:worker_threads'
2
+
3
+ import type { ServerConfig } from '@nmtjs/runtime'
4
+ import {
5
+ ApplicationWorkerRuntime,
6
+ isApplicationConfig,
7
+ JobWorkerRuntime,
8
+ } from '@nmtjs/runtime'
9
+
10
+ import type { RunWorkerOptions } from './thread.ts'
11
+
12
+ export async function run(options: RunWorkerOptions['runtime']) {
13
+ const serverConfig: ServerConfig = await import(
14
+ // @ts-expect-error
15
+ '#server'
16
+ ).then((m) => m.default)
17
+ if (options.type === 'application') {
18
+ globalThis._hotAccept = (module: any) => {
19
+ if (module) {
20
+ if (!isApplicationConfig(module.default))
21
+ throw new Error('Invalid application config')
22
+ runtime.reload(module.default)
23
+ }
24
+ }
25
+
26
+ const { name, path, transportsData } = options
27
+ const appConfig = await import(
28
+ /* @vite-ignore */
29
+ path
30
+ ).then((m) => m.default)
31
+
32
+ const runtime = new ApplicationWorkerRuntime(
33
+ serverConfig,
34
+ { name, path, transports: transportsData },
35
+ appConfig,
36
+ )
37
+ return runtime
38
+ } else if (options.type === 'jobs') {
39
+ const { jobWorkerQueue } = options
40
+ const runtime = new JobWorkerRuntime(serverConfig, {
41
+ queueName: jobWorkerQueue,
42
+ port: workerData.port,
43
+ })
44
+ return runtime
45
+ } else {
46
+ throw new Error(`Unknown runtime type: ${(workerData.runtime as any).type}`)
47
+ }
48
+ }
@@ -0,0 +1,16 @@
1
+ import { ResolverFactory } from 'oxc-resolver'
2
+
3
+ const fallback: Record<string, [string]> = {}
4
+
5
+ try {
6
+ // oxc-resolver fails to resolve uWebSockets.js for some reason
7
+ const mdl = 'uWebSockets.js'
8
+ const path = import.meta.resolve(mdl)
9
+ fallback[mdl] = [path]
10
+ } catch {}
11
+
12
+ export const resolver = new ResolverFactory({
13
+ tsconfig: 'auto',
14
+ extensions: ['.ts', '.js', '.mjs', '.mts', '.json', '.node'],
15
+ fallback,
16
+ })
package/src/typings.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises'
2
+ import { resolve } from 'node:path'
3
+
4
+ import dedent from 'dedent'
5
+
6
+ export async function generateTypings(
7
+ applicationImports: Record<string, { path: string; specifier: string }>,
8
+ ) {
9
+ await mkdir('.neemata', { recursive: true }).catch(() => {})
10
+ await writeFile(
11
+ resolve('.neemata', 'types.d.ts'),
12
+ dedent`
13
+ /// <reference types="@nmtjs/runtime/types" />
14
+
15
+ declare module '@nmtjs/runtime/types' {
16
+ interface Applications {
17
+ ${Object.entries(applicationImports)
18
+ .map(
19
+ ([appName, { specifier }]) =>
20
+ `'${appName}': typeof import('${specifier}').default`,
21
+ )
22
+ .join('\n')}
23
+ }
24
+ }
25
+ `,
26
+ )
27
+ }
@@ -0,0 +1,119 @@
1
+ import { isBuiltin } from 'node:module'
2
+ import { resolve } from 'node:path'
3
+
4
+ import { build as viteBuild } from 'vite'
5
+
6
+ import type { NeemataConfig } from '../config.ts'
7
+ import type { ViteConfigOptions } from './config.ts'
8
+ // import pkgJson from '../../package.json' with { type: 'json' }
9
+ import { createConfig } from './config.ts'
10
+ import { buildPlugins } from './plugins.ts'
11
+
12
+ export async function createBuilder(
13
+ configOptions: ViteConfigOptions,
14
+ neemataConfig: NeemataConfig,
15
+ ) {
16
+ const config = createConfig(configOptions)
17
+ async function build(): Promise<any> {
18
+ const packageJson = await import(resolve('./package.json'), {
19
+ with: { type: 'json' },
20
+ }).then((mod) => mod.default)
21
+
22
+ // techinically it's possible to do the same with rolldown directly,
23
+ // but vite handles a lot of things, like defines substitutions, etc.
24
+ // also, since during dev the code is processed via vite anyway,
25
+ // using vite for build as well ensures consistency between dev and prod
26
+ return await viteBuild({
27
+ appType: 'custom',
28
+ clearScreen: false,
29
+ resolve: { alias: config.alias },
30
+ ssr: { noExternal: true },
31
+ plugins: [...buildPlugins, ...neemataConfig.plugins],
32
+ build: {
33
+ lib: { entry: config.entries, formats: ['es'] },
34
+ ssr: true,
35
+ target: 'node20',
36
+ sourcemap: true,
37
+ outDir: resolve(neemataConfig.build.outDir),
38
+ minify: neemataConfig.build.minify,
39
+ emptyOutDir: true,
40
+ rolldownOptions: {
41
+ platform: 'node',
42
+ external: (id) => {
43
+ if (neemataConfig.externalDependencies === 'all') return true
44
+ if (
45
+ isBuiltin(id) ||
46
+ id.includes('vite/server') ||
47
+ id.endsWith('.node')
48
+ )
49
+ return true
50
+
51
+ if (neemataConfig.externalDependencies === 'prod') {
52
+ const prodDeps = Object.keys(packageJson.dependencies ?? {})
53
+ if (prodDeps.includes(id)) return true
54
+ }
55
+
56
+ if (Array.isArray(neemataConfig.externalDependencies)) {
57
+ for (const dep of neemataConfig.externalDependencies) {
58
+ if (typeof dep === 'string' && dep === id) return true
59
+ if (dep instanceof RegExp && dep.test(id)) return true
60
+ }
61
+ }
62
+
63
+ return false
64
+ },
65
+ transform: {
66
+ define: {
67
+ __VITE_CONFIG__: '""',
68
+ __APPLICATIONS_CONFIG__: JSON.stringify(
69
+ JSON.stringify(
70
+ Object.fromEntries(
71
+ Object.keys(configOptions.applicationImports).map(
72
+ (appName) => [appName, `./application.${appName}.js`],
73
+ ),
74
+ ),
75
+ ),
76
+ ),
77
+ __dirname: 'new URL(".", import.meta.url).pathname',
78
+ __filename: 'new URL(import.meta.url).pathname',
79
+ },
80
+ },
81
+ output: {
82
+ entryFileNames: '[name].js',
83
+ chunkFileNames: 'chunks/[name]-[hash].js',
84
+ advancedChunks: {
85
+ groups: [
86
+ {
87
+ name: 'ioredis',
88
+ test: /node_modules[\\/](@ioredis|ioredis|redis)/,
89
+ priority: 4,
90
+ },
91
+ {
92
+ name: 'bullmq',
93
+ test: /node_modules[\\/]bullmq/,
94
+ priority: 2,
95
+ },
96
+ { name: 'zod', test: /node_modules[\\/]zod/, priority: 2 },
97
+ { name: 'pino', test: /node_modules[\\/]pino/, priority: 2 },
98
+ {
99
+ name: '@nmtjs-runtime',
100
+ test: /node_modules[\\/](@nmtjs[\\/]runtime)/,
101
+ priority: 2,
102
+ },
103
+ {
104
+ name: '@nmtjs-common',
105
+ test: /node_modules[\\/]@nmtjs[\\/](?=[^runtime|nmtjs])/,
106
+ priority: 1,
107
+ },
108
+ { name: 'vendor', test: /node_modules/, priority: 0 },
109
+ ],
110
+ },
111
+ minify: neemataConfig.build.minify,
112
+ },
113
+ },
114
+ chunkSizeWarningLimit: 10_000,
115
+ },
116
+ })
117
+ }
118
+ return { build }
119
+ }
@@ -0,0 +1,42 @@
1
+ import { fileURLToPath } from 'node:url'
2
+
3
+ export type ViteConfigOptions = {
4
+ applicationImports: Record<string, { path: string; specifier: string }>
5
+ serverEntryPath: string
6
+ entrypointMainPath: string
7
+ entrypointWorkerPath: string
8
+ entrypointThreadPath: string
9
+ // entrypointCLIPath: string
10
+ configPath: string
11
+ }
12
+
13
+ const ext = new URL(import.meta.url).pathname.endsWith('.ts') ? '.ts' : '.js'
14
+
15
+ export const baseViteConfigOptions = {
16
+ entrypointMainPath: fileURLToPath(
17
+ import.meta.resolve(`../entrypoints/main${ext}`),
18
+ ),
19
+ entrypointWorkerPath: fileURLToPath(
20
+ import.meta.resolve(`../entrypoints/worker${ext}`),
21
+ ),
22
+ entrypointThreadPath: fileURLToPath(
23
+ import.meta.resolve(`../entrypoints/thread${ext}`),
24
+ ),
25
+ // entrypointCLIPath: fileURLToPath(import.meta.resolve('../entrypoints/cli')),
26
+ } satisfies Partial<ViteConfigOptions>
27
+
28
+ export function createConfig(options: ViteConfigOptions) {
29
+ const alias = { '#server': options.serverEntryPath }
30
+ const entries = {
31
+ server: options.serverEntryPath,
32
+ main: options.entrypointMainPath,
33
+ thread: options.entrypointThreadPath,
34
+ worker: options.entrypointWorkerPath,
35
+ }
36
+
37
+ for (const [name, { path }] of Object.entries(options.applicationImports)) {
38
+ entries[`application.${name}`] = path
39
+ }
40
+
41
+ return { alias, entries }
42
+ }
@@ -0,0 +1,26 @@
1
+ import { dirname, join } from 'node:path'
2
+
3
+ import type { Plugin } from 'vite'
4
+ import type { Target } from 'vite-plugin-static-copy'
5
+ import { viteStaticCopy } from 'vite-plugin-static-copy'
6
+
7
+ import { resolver } from '../resolver.ts'
8
+
9
+ const targets: Target[] = []
10
+
11
+ try {
12
+ const { path } = resolver.sync(process.cwd(), '@nmtjs/proxy')
13
+ if (path) {
14
+ targets.push({
15
+ src: join(
16
+ dirname(path),
17
+ `neemata-proxy.${process.platform}-${process.arch}*.node`,
18
+ ),
19
+ dest: './chunks/',
20
+ })
21
+ }
22
+ } catch {}
23
+
24
+ export const buildPlugins: Plugin[] = [
25
+ ...(targets.length ? viteStaticCopy({ targets }) : []),
26
+ ]
@@ -0,0 +1,57 @@
1
+ import {
2
+ BroadcastChannel,
3
+ isInternalThread,
4
+ isMainThread,
5
+ parentPort,
6
+ threadId,
7
+ } from 'node:worker_threads'
8
+
9
+ import type { HotPayload } from 'vite'
10
+ import type { ModuleRunnerTransport } from 'vite/module-runner'
11
+ import { noopFn } from '@nmtjs/common'
12
+ import {
13
+ createNodeImportMeta,
14
+ ESModulesEvaluator,
15
+ ModuleRunner,
16
+ } from 'vite/module-runner'
17
+
18
+ export function createBroadcastChannel(threadId: number): BroadcastChannel {
19
+ return new BroadcastChannel(`nmtjs:vite:${threadId}`)
20
+ }
21
+
22
+ export function createModuleRunner(
23
+ mode: 'development' | 'production' = 'development',
24
+ ): ModuleRunner {
25
+ if (isMainThread || isInternalThread)
26
+ throw new Error('Module runner can only be created inside worker threads.')
27
+
28
+ const channel = createBroadcastChannel(threadId)
29
+
30
+ const transport: ModuleRunnerTransport = {
31
+ connect({ onMessage, onDisconnection }) {
32
+ // @ts-expect-error
33
+ channel.onmessage = (event: MessageEvent<HotPayload>) => {
34
+ onMessage(event.data)
35
+ }
36
+ parentPort!.on('close', onDisconnection)
37
+ },
38
+ send(data) {
39
+ channel.postMessage(data)
40
+ },
41
+ timeout: 5000,
42
+ }
43
+
44
+ const runner = new ModuleRunner(
45
+ {
46
+ transport,
47
+ createImportMeta: createNodeImportMeta,
48
+ hmr:
49
+ mode === 'development'
50
+ ? { logger: { debug: noopFn, error: console.error } }
51
+ : false,
52
+ },
53
+ new ESModulesEvaluator(),
54
+ )
55
+
56
+ return runner
57
+ }
@@ -0,0 +1,36 @@
1
+ import type { DevEnvironmentOptions, UserConfig } from 'vite'
2
+ import { createServer as createViteServer } from 'vite'
3
+
4
+ import type { ViteConfigOptions } from './config.ts'
5
+
6
+ export function createServer(
7
+ options: ViteConfigOptions,
8
+ config: UserConfig,
9
+ dev: DevEnvironmentOptions = {},
10
+ ) {
11
+ return createViteServer({
12
+ ...config,
13
+ server: { middlewareMode: true, ws: false },
14
+ resolve: { tsconfigPaths: true, ...config.resolve },
15
+ environments: {
16
+ neemata: {
17
+ consumer: 'server',
18
+ dev,
19
+ define: {
20
+ __VITE_CONFIG__: JSON.stringify(
21
+ JSON.stringify({ options, mode: config.mode }),
22
+ ),
23
+ __APPLICATIONS_CONFIG__: JSON.stringify(
24
+ JSON.stringify(
25
+ Object.fromEntries(
26
+ Object.entries(options.applicationImports).map(
27
+ ([appName, { path }]) => [appName, path],
28
+ ),
29
+ ),
30
+ ),
31
+ ),
32
+ },
33
+ },
34
+ },
35
+ })
36
+ }
@@ -0,0 +1,34 @@
1
+ import type { ViteDevServer } from 'vite'
2
+ import type { ModuleRunner } from 'vite/module-runner'
3
+ import { noopFn } from '@nmtjs/common'
4
+ import { createServerModuleRunner } from 'vite'
5
+
6
+ import type { NeemataConfig } from '../../config.ts'
7
+ import type { ViteConfigOptions } from '../config.ts'
8
+ import { createConfig } from '../config.ts'
9
+ import { buildPlugins } from '../plugins.ts'
10
+ import { createServer } from '../server.ts'
11
+
12
+ export async function createMainServer(
13
+ options: ViteConfigOptions,
14
+ mode: 'development' | 'production',
15
+ neemataConfig: NeemataConfig,
16
+ ): Promise<{ server: ViteDevServer; runner: ModuleRunner }> {
17
+ const config = createConfig(options)
18
+ const server = await createServer(options, {
19
+ appType: 'custom',
20
+ clearScreen: false,
21
+ resolve: { alias: config.alias },
22
+ mode,
23
+ plugins: [...buildPlugins, ...neemataConfig.plugins],
24
+ })
25
+ const environment = server.environments.neemata
26
+
27
+ const runner = createServerModuleRunner(environment, {
28
+ hmr:
29
+ mode === 'development'
30
+ ? { logger: { debug: noopFn, error: console.error } }
31
+ : false,
32
+ })
33
+ return { server, runner }
34
+ }
@@ -0,0 +1,107 @@
1
+ import type EventEmitter from 'node:events'
2
+ import type { BroadcastChannel, Worker } from 'node:worker_threads'
3
+
4
+ import type {
5
+ HotChannel,
6
+ HotChannelClient,
7
+ HotChannelListener,
8
+ HotPayload,
9
+ ViteDevServer,
10
+ } from 'vite'
11
+ import { DevEnvironment } from 'vite'
12
+
13
+ import type { NeemataConfig } from '../../config.ts'
14
+ import type { ViteConfigOptions } from '../config.ts'
15
+ import { createConfig } from '../config.ts'
16
+ import { buildPlugins } from '../plugins.ts'
17
+ import { createBroadcastChannel } from '../runners/worker.ts'
18
+ import { createServer } from '../server.ts'
19
+
20
+ export async function createWorkerServer(
21
+ options: ViteConfigOptions,
22
+ mode: 'development' | 'production',
23
+ neemataConfig: NeemataConfig,
24
+ events: EventEmitter<{ worker: [Worker] }>,
25
+ ): Promise<ViteDevServer> {
26
+ const config = createConfig(options)
27
+ const applicationEntries = Object.values(options.applicationImports).map(
28
+ (v) => v.path,
29
+ )
30
+
31
+ const _injectHmr = `\n\nif(import.meta.hot) { import.meta.hot.accept(globalThis._hotAccept) }`
32
+
33
+ const server = await createServer(
34
+ options,
35
+ {
36
+ appType: 'custom',
37
+ clearScreen: false,
38
+ resolve: { alias: config.alias },
39
+ mode,
40
+ plugins: [
41
+ ...buildPlugins,
42
+ ...neemataConfig.plugins,
43
+ mode === 'development'
44
+ ? [
45
+ {
46
+ name: 'neemata-worker-application-hmr',
47
+ transform(code, id, options) {
48
+ if (applicationEntries.includes(id)) {
49
+ return code + _injectHmr
50
+ }
51
+ },
52
+ },
53
+ ]
54
+ : [],
55
+ ],
56
+ },
57
+ {
58
+ createEnvironment: async (name, config, context) => {
59
+ const channels = new Map<number, BroadcastChannel>()
60
+ const clients = new Map<BroadcastChannel, HotChannelClient>()
61
+ const handlers = new Map<string, HotChannelListener>()
62
+
63
+ events.on('worker', (worker) => {
64
+ const channel = createBroadcastChannel(worker.threadId)
65
+ channel.onmessage = (event) => {
66
+ const value = event.data
67
+ const handler = handlers.get(value.event)
68
+ if (handler) handler(value.data, client)
69
+ }
70
+ channels.set(worker.threadId, channel)
71
+ const client = {
72
+ send: (payload: HotPayload) => {
73
+ channel.postMessage(payload)
74
+ },
75
+ }
76
+ clients.set(channel, client)
77
+ worker.on('exit', () => {
78
+ const handler = handlers.get('vite:client:disconnect')
79
+ if (handler) handler(undefined, client)
80
+ })
81
+ })
82
+
83
+ const transport: HotChannel = {
84
+ send(data) {
85
+ for (const channel of channels.values()) {
86
+ channel.postMessage(data)
87
+ }
88
+ },
89
+ on(event, handler) {
90
+ handlers.set(event, handler)
91
+ },
92
+ off(event) {
93
+ handlers.delete(event)
94
+ },
95
+ }
96
+
97
+ const environment = new DevEnvironment(name, config, {
98
+ hot: mode === 'development',
99
+ transport,
100
+ })
101
+
102
+ return environment
103
+ },
104
+ },
105
+ )
106
+ return server
107
+ }