jopi-node-space 0.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 (48) hide show
  1. package/README.md +24 -0
  2. package/bun.lock +25 -0
  3. package/dist/browser.d.ts +1 -0
  4. package/dist/browser.js +15 -0
  5. package/dist/browser.js.map +1 -0
  6. package/dist/common.d.ts +85 -0
  7. package/dist/common.js +34 -0
  8. package/dist/common.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +37 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/internal.d.ts +3 -0
  13. package/dist/internal.js +8 -0
  14. package/dist/internal.js.map +1 -0
  15. package/dist/nodeSpaceApp.d.ts +1 -0
  16. package/dist/nodeSpaceApp.js +105 -0
  17. package/dist/nodeSpaceApp.js.map +1 -0
  18. package/dist/nodeSpaceExtensionPoints.d.ts +1 -0
  19. package/dist/nodeSpaceExtensionPoints.js +51 -0
  20. package/dist/nodeSpaceExtensionPoints.js.map +1 -0
  21. package/dist/nodeSpaceProcess.d.ts +1 -0
  22. package/dist/nodeSpaceProcess.js +15 -0
  23. package/dist/nodeSpaceProcess.js.map +1 -0
  24. package/dist/nodeSpaceThread.d.ts +1 -0
  25. package/dist/nodeSpaceThread.js +19 -0
  26. package/dist/nodeSpaceThread.js.map +1 -0
  27. package/dist/nodeSpaceTimer.d.ts +1 -0
  28. package/dist/nodeSpaceTimer.js +7 -0
  29. package/dist/nodeSpaceTimer.js.map +1 -0
  30. package/dist/nodeSpaceWhat.d.ts +1 -0
  31. package/dist/nodeSpaceWhat.js +10 -0
  32. package/dist/nodeSpaceWhat.js.map +1 -0
  33. package/dist/serverSide.d.ts +1 -0
  34. package/dist/serverSide.js +34 -0
  35. package/dist/serverSide.js.map +1 -0
  36. package/package.json +27 -0
  37. package/src/browser.ts +15 -0
  38. package/src/common.ts +128 -0
  39. package/src/index.ts +35 -0
  40. package/src/internal.ts +9 -0
  41. package/src/nodeSpaceApp.ts +113 -0
  42. package/src/nodeSpaceExtensionPoints.ts +67 -0
  43. package/src/nodeSpaceProcess.ts +14 -0
  44. package/src/nodeSpaceThread.ts +21 -0
  45. package/src/nodeSpaceTimer.ts +7 -0
  46. package/src/nodeSpaceWhat.ts +9 -0
  47. package/src/serverSide.ts +43 -0
  48. package/tsconfig.json +33 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ ## What is it?
2
+
3
+ ### Server Side or Browser Side
4
+
5
+ Le premier rôle de Jopi NodeSpace, est de permettre de créer des librairies dont le code source est le même pour le serveur et le browser.
6
+
7
+ * Il permet de détecter automatiquement si nous sommes côté serveur ou navigateur.
8
+ * Il permet de gommer certains écarts entre le fonctionnement serveur/browser, notamment quant aux WebWorkers.
9
+ * Il permet un accès uniformisé aux variables d'environnement, que l'on soit browser ou serveur (proccess.env).
10
+ * Il permet d'accéder à des fonctionnalités serveur, sans devoir ajouter des dépendances.
11
+
12
+ > NodeSpace inclut des fonctionnalités d'accès aux fichiers et différents éléments serveur.
13
+ > Ils ne fonctionnent que lorsque nous sommes côté serveur, cependant ils évitent d'avoir à faire des *import*
14
+ lesquels sont incompatibles avec les bundlers (ex: ViteJS).
15
+
16
+ ### Packed with common tools
17
+
18
+ Le second objectif de Jopi NodeSpace est d'apporter des outils communs.
19
+
20
+ * Cycle de vie de l'application : pouvoir associer des écouteurs, afin d'être prévenu quand l'application quitte.
21
+ * Hot-Reload: détection et gestion des hot-reload (une fonctionnalité bun.js).
22
+ * Points d'extension: permet de créer une application extensible.
23
+ * Logs: inclut des fonctionnalités de logs (basé sur jopi-logs).
24
+ * User: inclut des fonctionnalités permettant d'obtenir des informations sur l'utilisateur actuel (app side).
package/bun.lock ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "jopi-node-space",
6
+ "devDependencies": {
7
+ "@types/bun": "latest",
8
+ "@types/node": "latest",
9
+ },
10
+ },
11
+ },
12
+ "packages": {
13
+ "@types/bun": ["@types/bun@1.2.19", "", { "dependencies": { "bun-types": "1.2.19" } }, "sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg=="],
14
+
15
+ "@types/node": ["@types/node@24.1.0", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w=="],
16
+
17
+ "@types/react": ["@types/react@19.1.9", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA=="],
18
+
19
+ "bun-types": ["bun-types@1.2.19", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-uAOTaZSPuYsWIXRpj7o56Let0g/wjihKCkeRqUBhlLVM/Bt+Fj9xTo+LhC1OV1XDaGkz4hNC80et5xgy+9KTHQ=="],
20
+
21
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
22
+
23
+ "undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="],
24
+ }
25
+ }
@@ -0,0 +1 @@
1
+ export declare function initBrowser(): void;
@@ -0,0 +1,15 @@
1
+ import { init_nodeSpaceWhat } from "./nodeSpaceWhat.js";
2
+ import { init_nodeSpaceApp } from "./nodeSpaceApp.js";
3
+ import { init_nodeSpaceProcess } from "./nodeSpaceProcess.js";
4
+ import { init_nodeSpaceTimer } from "./nodeSpaceTimer.js";
5
+ import { init_nodeSpaceThread } from "./nodeSpaceThread.js";
6
+ import { init_nodeSpaceExtensionPoints } from "./nodeSpaceExtensionPoints";
7
+ export function initBrowser() {
8
+ init_nodeSpaceWhat();
9
+ init_nodeSpaceApp();
10
+ init_nodeSpaceProcess();
11
+ init_nodeSpaceTimer();
12
+ init_nodeSpaceThread();
13
+ init_nodeSpaceExtensionPoints();
14
+ }
15
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAC,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAC,iBAAiB,EAAC,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAC,qBAAqB,EAAC,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAC,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAC,6BAA6B,EAAC,MAAM,4BAA4B,CAAC;AAEzE,MAAM,UAAU,WAAW;IACvB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,CAAC;IACxB,mBAAmB,EAAE,CAAC;IACtB,oBAAoB,EAAE,CAAC;IACvB,6BAA6B,EAAE,CAAC;AACpC,CAAC"}
@@ -0,0 +1,85 @@
1
+ declare global {
2
+ var NodeSpace: NodeSpaceType;
3
+ var jopiHotReloader: HotReloadType;
4
+ }
5
+ export declare function execListeners(listeners: Listener[]): Promise<void>;
6
+ export declare function isServerSide(): boolean;
7
+ export declare function isBunJs(): boolean;
8
+ export declare function isNodeJs(): boolean;
9
+ export declare function tick(delayMs: number): Promise<void>;
10
+ export type ServerType = "nodejs" | "bunjs" | "browser";
11
+ export type Listener = () => void | Promise<void>;
12
+ export interface NodeSpaceType {
13
+ what: WhatInfos;
14
+ thread: ThreadImpl;
15
+ process: ProcessImpl;
16
+ timer: TimerImpl;
17
+ app: AppImpl;
18
+ fs?: FileSystemImpl;
19
+ extensionPoints?: ExtensionPointImpl;
20
+ }
21
+ export interface HotReloadType {
22
+ onHotReload: Listener[];
23
+ memory: {
24
+ [key: string]: any;
25
+ };
26
+ }
27
+ interface WhatInfos {
28
+ isNodeJS: boolean;
29
+ isBunJs: boolean;
30
+ isBrowser: boolean;
31
+ isServerSide: boolean;
32
+ serverType: ServerType;
33
+ }
34
+ interface ThreadImpl {
35
+ isMainThread: boolean;
36
+ currentWorker: Worker | null;
37
+ newWorker: (fileName: string | URL, data?: any) => Worker;
38
+ getCurrentWorkerData: () => any;
39
+ unrefThisWorker(worker: Worker): void;
40
+ closeCurrentThread(): void;
41
+ }
42
+ interface ProcessImpl {
43
+ argv: string[];
44
+ env: {
45
+ [key: string]: string;
46
+ };
47
+ isProduction: boolean;
48
+ }
49
+ interface TimerImpl {
50
+ tick: (delayMs: number) => Promise<void>;
51
+ }
52
+ interface FileSystemImpl {
53
+ mkDir: (dirPath: string) => Promise<string | undefined>;
54
+ }
55
+ interface AppImpl {
56
+ onServerSideReady(listener: Listener): void;
57
+ waitServerSideReady: () => Promise<void>;
58
+ declareServerSideReady(): void;
59
+ onAppStart(listener: Listener): void;
60
+ onAppExiting(listener: Listener): void;
61
+ onAppExited(listener: Listener): void;
62
+ executeApp(app: Listener): void;
63
+ declareAppStarted(): void;
64
+ declareAppExiting(): void;
65
+ onHotReload(listener: Listener): void;
66
+ keepOnHotReload<T>(key: string, provider: () => T): T;
67
+ }
68
+ export type EpCaller = (...values: unknown[]) => Promise<void>;
69
+ export type EpListener = (...values: unknown[]) => void | Promise<void>;
70
+ interface ExtensionPointImpl {
71
+ /**
72
+ * Register an extension point.
73
+ * Allow knowing who is using it as an host.
74
+ */
75
+ newHost(epName: string, importMetaUrl: string): EpCaller;
76
+ /**
77
+ * Get a caller, allowing to call the extension point.
78
+ */
79
+ getCaller(epName: string, importMetaUrl: string): EpCaller;
80
+ /**
81
+ * Add a function which is called when the extension point is called.
82
+ */
83
+ on(epName: string, importMetaUrl: string, fct: EpListener): void;
84
+ }
85
+ export {};
package/dist/common.js ADDED
@@ -0,0 +1,34 @@
1
+ globalThis.NodeSpace = {};
2
+ let _isBunJs = false;
3
+ let _isNodeJs = false;
4
+ export async function execListeners(listeners) {
5
+ const list = [...listeners];
6
+ listeners.splice(0);
7
+ for (const listener of list) {
8
+ try {
9
+ const res = listener();
10
+ if (res instanceof Promise)
11
+ await res;
12
+ }
13
+ catch (e) {
14
+ console.error(e);
15
+ }
16
+ }
17
+ }
18
+ export function isServerSide() {
19
+ return isBunJs() || isNodeJs();
20
+ }
21
+ export function isBunJs() {
22
+ if (_isBunJs)
23
+ return _isBunJs;
24
+ return _isBunJs = typeof (Bun) !== "undefined";
25
+ }
26
+ export function isNodeJs() {
27
+ if (_isNodeJs)
28
+ return _isNodeJs;
29
+ return _isNodeJs = typeof (self) === "undefined";
30
+ }
31
+ export function tick(delayMs) {
32
+ return new Promise((resolve) => setTimeout(resolve, delayMs));
33
+ }
34
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAKA,UAAU,CAAC,SAAS,GAAG,EAAmB,CAAC;AAE3C,IAAI,QAAQ,GAAG,KAAK,CAAC;AACrB,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAqB;IACrD,MAAM,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5B,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAEpB,KAAK,MAAM,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC;YACD,MAAM,GAAG,GAAG,QAAQ,EAAE,CAAC;YACvB,IAAI,GAAG,YAAY,OAAO;gBAAE,MAAM,GAAG,CAAC;QAC1C,CAAC;QACD,OAAO,CAAC,EAAE,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY;IACxB,OAAO,OAAO,EAAE,IAAI,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,OAAO;IACnB,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,OAAO,QAAQ,GAAG,OAAM,CAAC,GAAG,CAAC,KAAG,WAAW,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,QAAQ;IACpB,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,OAAO,SAAS,GAAG,OAAM,CAAC,IAAI,CAAC,KAAG,WAAW,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAe;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./common.ts";
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { isBunJs, isNodeJs, isServerSide } from "./common.js";
10
+ export * from "./common.js";
11
+ import { initBrowser } from "./browser.js";
12
+ // Will init with the common stuffs.
13
+ initBrowser();
14
+ if (isServerSide()) {
15
+ let serverType = "nodejs";
16
+ if (isBunJs())
17
+ serverType = "bunjs";
18
+ // Allow conditional code to be ok
19
+ // despite the "await import" is not done yet.
20
+ //
21
+ const nodeSpace = globalThis.NodeSpace;
22
+ nodeSpace.what = {
23
+ isNodeJS: isNodeJs(),
24
+ isBunJs: isBunJs(),
25
+ isBrowser: false,
26
+ isServerSide: true,
27
+ serverType: serverType,
28
+ };
29
+ let ext = import.meta.filename.split(".").pop();
30
+ const fileName = "./serverSide." + ext;
31
+ // To know: the caller will not wait for the await to resolve.
32
+ // Wait is after will not be interpreted immediately by the caller
33
+ // doing that specifics server-side things will not be ok now.
34
+ //
35
+ await import(__rewriteRelativeImportExtension(/* @vite-ignore */ fileName));
36
+ }
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAO,EAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAkB,MAAM,aAAa,CAAC;AAE7E,cAAc,aAAa,CAAC;AAE5B,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AAEzC,oCAAoC;AACpC,WAAW,EAAE,CAAC;AAEd,IAAI,YAAY,EAAE,EAAE,CAAC;IACjB,IAAI,UAAU,GAAe,QAAQ,CAAC;IACtC,IAAI,OAAO,EAAE;QAAE,UAAU,GAAG,OAAO,CAAC;IAEpC,kCAAkC;IAClC,8CAA8C;IAC9C,EAAE;IACF,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;IAEvC,SAAS,CAAC,IAAI,GAAG;QACb,QAAQ,EAAE,QAAQ,EAAE;QACpB,OAAO,EAAE,OAAO,EAAE;QAClB,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,IAAI;QAClB,UAAU,EAAE,UAAU;KACzB,CAAA;IAED,IAAI,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAG,eAAe,GAAG,GAAG,CAAC;IAEvC,8DAA8D;IAC9D,kEAAkE;IAClE,8DAA8D;IAC9D,EAAE;IACF,MAAM,MAAM,kCAAC,kBAAkB,CAAC,QAAQ,EAAC,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare let gIsUsingWorkers: boolean;
2
+ export declare function declareUsingWorker(): void;
3
+ export declare function isUsingWorker(): boolean;
@@ -0,0 +1,8 @@
1
+ export let gIsUsingWorkers = false;
2
+ export function declareUsingWorker() {
3
+ gIsUsingWorkers = true;
4
+ }
5
+ export function isUsingWorker() {
6
+ return gIsUsingWorkers;
7
+ }
8
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAI,eAAe,GAAG,KAAK,CAAC;AAEnC,MAAM,UAAU,kBAAkB;IAC9B,eAAe,GAAG,IAAI,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa;IACzB,OAAO,eAAe,CAAC;AAC3B,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceApp(): void;
@@ -0,0 +1,105 @@
1
+ import { execListeners, isBunJs, isNodeJs } from "./common.js";
2
+ import { isUsingWorker } from "./internal.js";
3
+ export function init_nodeSpaceApp() {
4
+ const onServerSideReady = [];
5
+ const onAppExiting = [];
6
+ const onAppExited = [];
7
+ const onAppStart = [];
8
+ let isServerSideReady = !(isNodeJs() || isBunJs());
9
+ let isHotReload = globalThis.jopiHotReloader !== undefined;
10
+ let isAppStarted = false;
11
+ if (isHotReload) {
12
+ execListeners(globalThis.jopiHotReloader.onHotReload).then();
13
+ }
14
+ else {
15
+ globalThis.jopiHotReloader = {
16
+ onHotReload: [],
17
+ memory: {}
18
+ };
19
+ }
20
+ const onHotReload = globalThis.jopiHotReloader.onHotReload;
21
+ const memory = globalThis.jopiHotReloader.memory;
22
+ NodeSpace.app = {
23
+ onServerSideReady: (listener) => {
24
+ if (isServerSideReady)
25
+ listener();
26
+ else
27
+ onServerSideReady.push(listener);
28
+ },
29
+ waitServerSideReady: () => {
30
+ if (isServerSideReady) {
31
+ return Promise.resolve();
32
+ }
33
+ return new Promise(r => {
34
+ NodeSpace.app.onServerSideReady(r);
35
+ });
36
+ },
37
+ declareServerSideReady: async () => {
38
+ isServerSideReady = true;
39
+ await execListeners(onServerSideReady);
40
+ },
41
+ onAppStart: (listener) => {
42
+ if (isAppStarted)
43
+ listener();
44
+ else
45
+ onAppStart.push(listener);
46
+ },
47
+ onAppExiting: (listener) => {
48
+ if (!isAppStarted)
49
+ listener();
50
+ else
51
+ onAppExiting.push(listener);
52
+ },
53
+ onAppExited: (listener) => {
54
+ if (!isAppStarted)
55
+ listener();
56
+ else
57
+ onAppExited.push(listener);
58
+ },
59
+ declareAppStarted: async () => {
60
+ isAppStarted = true;
61
+ await execListeners(onAppStart);
62
+ },
63
+ declareAppExiting: async () => {
64
+ if (isUsingWorker()) {
65
+ // Wait 1 sec, which allows the worker to correctly initialize.
66
+ await NodeSpace.timer.tick(1000);
67
+ }
68
+ isAppStarted = false;
69
+ await execListeners(onAppExiting);
70
+ if (isUsingWorker()) {
71
+ // Allows to worker to correctly stop their activity.
72
+ await NodeSpace.timer.tick(100);
73
+ }
74
+ if (!NodeSpace.thread.isMainThread) {
75
+ // Allows to worker to correctly stop their activity.
76
+ await NodeSpace.timer.tick(50);
77
+ }
78
+ if (onAppExited.length)
79
+ debugger;
80
+ await execListeners(onAppExited);
81
+ },
82
+ executeApp: async (app) => {
83
+ await NodeSpace.app.waitServerSideReady();
84
+ NodeSpace.app.declareAppStarted();
85
+ try {
86
+ const res = app();
87
+ if (res instanceof Promise)
88
+ await res;
89
+ }
90
+ finally {
91
+ NodeSpace.app.declareAppExiting();
92
+ }
93
+ },
94
+ onHotReload(listener) {
95
+ onHotReload.push(listener);
96
+ },
97
+ keepOnHotReload: (key, provider) => {
98
+ let current = memory[key];
99
+ if (current !== undefined)
100
+ return current;
101
+ return memory[key] = provider();
102
+ }
103
+ };
104
+ }
105
+ //# sourceMappingURL=nodeSpaceApp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceApp.js","sourceRoot":"","sources":["../src/nodeSpaceApp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceExtensionPoints(): void;
@@ -0,0 +1,51 @@
1
+ import {} from "./common.js";
2
+ const gExtensionPoints = {};
3
+ function createExtensionPoint(epName, hostInfo, callerInfo, listenerInfo) {
4
+ async function caller(...args) {
5
+ for (const listener of ep.listeners) {
6
+ const res = listener(...args);
7
+ if (res instanceof Promise)
8
+ await res;
9
+ }
10
+ }
11
+ const listeners = [];
12
+ const ep = {
13
+ listeners, caller,
14
+ allHostPath: [],
15
+ allCallerPath: [],
16
+ allListenerPath: []
17
+ };
18
+ gExtensionPoints[epName] = ep;
19
+ if (hostInfo) {
20
+ ep.allHostPath.push(hostInfo);
21
+ }
22
+ if (callerInfo) {
23
+ ep.allCallerPath.push(callerInfo);
24
+ }
25
+ if (listenerInfo) {
26
+ ep.allListenerPath.push(listenerInfo);
27
+ }
28
+ }
29
+ export function init_nodeSpaceExtensionPoints() {
30
+ NodeSpace.extensionPoints = {
31
+ newHost(epName, importMetaUrl) {
32
+ const ep = gExtensionPoints[epName];
33
+ if (!ep)
34
+ createExtensionPoint(epName, importMetaUrl, null, null);
35
+ return ep.caller;
36
+ },
37
+ getCaller(epName, importMetaUrl) {
38
+ const ep = gExtensionPoints[epName];
39
+ if (!ep)
40
+ createExtensionPoint(epName, null, importMetaUrl, null);
41
+ return ep.caller;
42
+ },
43
+ on(epName, importMetaUrl, listener) {
44
+ const ep = gExtensionPoints[epName];
45
+ if (!ep)
46
+ createExtensionPoint(epName, null, null, importMetaUrl);
47
+ ep.listeners.push(listener);
48
+ }
49
+ };
50
+ }
51
+ //# sourceMappingURL=nodeSpaceExtensionPoints.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceExtensionPoints.js","sourceRoot":"","sources":["../src/nodeSpaceExtensionPoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,MAAM,aAAa,CAAC;AAW3D,MAAM,gBAAgB,GAAuC,EAC5D,CAAA;AAED,SAAS,oBAAoB,CAAC,MAAc,EAAE,QAAqB,EAAE,UAAuB,EAAE,YAAyB;IACnH,KAAK,UAAU,MAAM,CAAC,GAAG,IAAe;QACpC,KAAK,MAAM,QAAQ,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;YAC9B,IAAI,GAAG,YAAY,OAAO;gBAAE,MAAM,GAAG,CAAC;QAC1C,CAAC;IACL,CAAC;IAED,MAAM,SAAS,GAAiB,EAAE,CAAC;IAEnC,MAAM,EAAE,GAAmB;QACvB,SAAS,EAAE,MAAM;QACjB,WAAW,EAAE,EAAE;QACf,aAAa,EAAE,EAAE;QACjB,eAAe,EAAE,EAAE;KACtB,CAAC;IAEF,gBAAgB,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;IAE9B,IAAI,QAAQ,EAAE,CAAC;QACX,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACb,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,YAAY,EAAE,CAAC;QACf,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC1C,CAAC;AACL,CAAC;AAED,MAAM,UAAU,6BAA6B;IACzC,SAAS,CAAC,eAAe,GAAG;QACxB,OAAO,CAAC,MAAc,EAAE,aAAqB;YACzC,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,EAAE;gBAAE,oBAAoB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACjE,OAAO,EAAE,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,SAAS,CAAC,MAAc,EAAE,aAAqB;YAC3C,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,EAAE;gBAAE,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC;YACjE,OAAO,EAAE,CAAC,MAAM,CAAC;QACrB,CAAC;QAED,EAAE,CAAC,MAAc,EAAE,aAAqB,EAAE,QAAoB;YAC1D,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,EAAE;gBAAE,oBAAoB,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;YACjE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceProcess(): void;
@@ -0,0 +1,15 @@
1
+ export function init_nodeSpaceProcess() {
2
+ NodeSpace.process = {
3
+ isProduction: false,
4
+ argv: [],
5
+ env: {},
6
+ };
7
+ // For bundlers.
8
+ try {
9
+ NodeSpace.process.env = import.meta.env;
10
+ NodeSpace.process.isProduction = (import.meta.env.PROD === "true");
11
+ }
12
+ catch {
13
+ }
14
+ }
15
+ //# sourceMappingURL=nodeSpaceProcess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceProcess.js","sourceRoot":"","sources":["../src/nodeSpaceProcess.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,qBAAqB;IACjC,SAAS,CAAC,OAAO,GAAG;QAChB,YAAY,EAAE,KAAK;QACnB,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;KACV,CAAC;IAEF,gBAAgB;IAChB,IAAI,CAAC;QACD,SAAS,CAAC,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,GAAkC,CAAC;QACvE,SAAS,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;IACT,CAAC;AACL,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceThread(): void;
@@ -0,0 +1,19 @@
1
+ import { declareUsingWorker } from "./internal.js";
2
+ export function init_nodeSpaceThread() {
3
+ NodeSpace.thread = {
4
+ isMainThread: true,
5
+ currentWorker: null,
6
+ getCurrentWorkerData: () => { },
7
+ unrefThisWorker: () => { },
8
+ newWorker: (fileName) => {
9
+ declareUsingWorker();
10
+ return new Worker(fileName, { type: 'module' });
11
+ },
12
+ closeCurrentThread() {
13
+ if (self.close) {
14
+ self.close();
15
+ }
16
+ }
17
+ };
18
+ }
19
+ //# sourceMappingURL=nodeSpaceThread.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceThread.js","sourceRoot":"","sources":["../src/nodeSpaceThread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,MAAM,UAAU,oBAAoB;IAChC,SAAS,CAAC,MAAM,GAAG;QACf,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;QACnB,oBAAoB,EAAE,GAAG,EAAE,GAAE,CAAC;QAC9B,eAAe,EAAE,GAAG,EAAE,GAAE,CAAC;QAEzB,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;YACpB,kBAAkB,EAAE,CAAC;YACrB,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC,CAAA;QACjD,CAAC;QAED,kBAAkB;YACd,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,KAAK,EAAE,CAAC;YACjB,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceTimer(): void;
@@ -0,0 +1,7 @@
1
+ import { tick } from "./common.js";
2
+ export function init_nodeSpaceTimer() {
3
+ NodeSpace.timer = {
4
+ tick: tick
5
+ };
6
+ }
7
+ //# sourceMappingURL=nodeSpaceTimer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceTimer.js","sourceRoot":"","sources":["../src/nodeSpaceTimer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,aAAa,CAAC;AAEjC,MAAM,UAAU,mBAAmB;IAC/B,SAAS,CAAC,KAAK,GAAG;QACd,IAAI,EAAE,IAAI;KACb,CAAC;AACN,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function init_nodeSpaceWhat(): void;
@@ -0,0 +1,10 @@
1
+ export function init_nodeSpaceWhat() {
2
+ NodeSpace.what = {
3
+ isNodeJS: false,
4
+ isBunJs: false,
5
+ isServerSide: false,
6
+ isBrowser: true,
7
+ serverType: "browser",
8
+ };
9
+ }
10
+ //# sourceMappingURL=nodeSpaceWhat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodeSpaceWhat.js","sourceRoot":"","sources":["../src/nodeSpaceWhat.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,kBAAkB;IAC9B,SAAS,CAAC,IAAI,GAAG;QACb,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,KAAK;QACd,YAAY,EAAE,KAAK;QACnB,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,SAAS;KACxB,CAAC;AACN,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ import { isMainThread, parentPort, Worker as NodeWorker, workerData } from "node:worker_threads";
2
+ import { declareUsingWorker } from "./internal.js";
3
+ import fs from "node:fs/promises";
4
+ NodeSpace.process = {
5
+ argv: process.argv,
6
+ env: process.env,
7
+ isProduction: process.env.NODE_ENV === 'production'
8
+ };
9
+ NodeSpace.thread = {
10
+ isMainThread: isMainThread,
11
+ currentWorker: parentPort,
12
+ getCurrentWorkerData: () => workerData,
13
+ newWorker: (fileName, data) => {
14
+ declareUsingWorker();
15
+ const res = data ?
16
+ new NodeWorker(fileName, { workerData: data }) :
17
+ new NodeWorker(fileName);
18
+ return res;
19
+ },
20
+ unrefThisWorker: (worker) => {
21
+ worker.unref();
22
+ },
23
+ closeCurrentThread() {
24
+ if (parentPort) {
25
+ parentPort.close();
26
+ }
27
+ }
28
+ };
29
+ NodeSpace.fs = {
30
+ mkDir: (dirPath) => fs.mkdir(dirPath, { recursive: true })
31
+ };
32
+ NodeSpace.app.declareServerSideReady();
33
+ process.on('exit', () => NodeSpace.app.declareAppExiting());
34
+ //# sourceMappingURL=serverSide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serverSide.js","sourceRoot":"","sources":["../src/serverSide.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,UAAU,EAAE,UAAU,EAAC,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAElC,SAAS,CAAC,OAAO,GAAG;IAChB,IAAI,EAAE,OAAO,CAAC,IAAI;IAClB,GAAG,EAAE,OAAO,CAAC,GAAgC;IAC7C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY;CACtD,CAAC;AAEF,SAAS,CAAC,MAAM,GAAG;IACf,YAAY,EAAE,YAAY;IAC1B,aAAa,EAAE,UAA+B;IAC9C,oBAAoB,EAAE,GAAG,EAAE,CAAC,UAAU;IAEtC,SAAS,EAAE,CAAC,QAAQ,EAAE,IAAU,EAAE,EAAE;QAChC,kBAAkB,EAAE,CAAC;QAErB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC;YACd,IAAI,UAAU,CAAC,QAAQ,EAAE,EAAC,UAAU,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAC9C,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QAE7B,OAAO,GAAwB,CAAA;IACnC,CAAC;IAED,eAAe,EAAE,CAAC,MAAc,EAAE,EAAE;QAC/B,MAAgC,CAAC,KAAK,EAAE,CAAC;IAC9C,CAAC;IAED,kBAAkB;QACd,IAAI,UAAU,EAAE,CAAC;YACb,UAAU,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;IACL,CAAC;CACJ,CAAA;AAED,SAAS,CAAC,EAAE,GAAG;IACX,KAAK,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC;CACnE,CAAA;AAED,SAAS,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;AAEvC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": "0.0.1",
3
+ "private": false,
4
+ "name": "jopi-node-space",
5
+ "license": "MIT",
6
+ "homepage": "https://github.com/johanpiquet/jopi-node-space",
7
+
8
+ "keywords": [],
9
+ "author": "Johan PIQUET",
10
+ "description": "An helper for hybrid apps",
11
+
12
+ "type": "module",
13
+ "main": "dist/index.js",
14
+ "types": "dist/index.d.ts",
15
+
16
+ "devDependencies": {
17
+ "@types/node": "latest",
18
+ "@types/bun": "latest"
19
+ },
20
+
21
+ "scripts": {
22
+ "bun-install": "bun install",
23
+ "tsc": "tsc",
24
+
25
+ "npm-publish": "npm publish"
26
+ }
27
+ }
package/src/browser.ts ADDED
@@ -0,0 +1,15 @@
1
+ import {init_nodeSpaceWhat} from "./nodeSpaceWhat.ts";
2
+ import {init_nodeSpaceApp} from "./nodeSpaceApp.ts";
3
+ import {init_nodeSpaceProcess} from "./nodeSpaceProcess.ts";
4
+ import {init_nodeSpaceTimer} from "./nodeSpaceTimer.ts";
5
+ import {init_nodeSpaceThread} from "./nodeSpaceThread.ts";
6
+ import {init_nodeSpaceExtensionPoints} from "./nodeSpaceExtensionPoints";
7
+
8
+ export function initBrowser() {
9
+ init_nodeSpaceWhat();
10
+ init_nodeSpaceApp();
11
+ init_nodeSpaceProcess();
12
+ init_nodeSpaceTimer();
13
+ init_nodeSpaceThread();
14
+ init_nodeSpaceExtensionPoints();
15
+ }
package/src/common.ts ADDED
@@ -0,0 +1,128 @@
1
+ declare global {
2
+ var NodeSpace: NodeSpaceType;
3
+ var jopiHotReloader: HotReloadType;
4
+ }
5
+
6
+ globalThis.NodeSpace = {} as NodeSpaceType;
7
+
8
+ let _isBunJs = false;
9
+ let _isNodeJs = false;
10
+
11
+ export async function execListeners(listeners: Listener[]) {
12
+ const list = [...listeners];
13
+ listeners.splice(0);
14
+
15
+ for (const listener of list) {
16
+ try {
17
+ const res = listener();
18
+ if (res instanceof Promise) await res;
19
+ }
20
+ catch (e) {
21
+ console.error(e);
22
+ }
23
+ }
24
+ }
25
+
26
+ export function isServerSide(): boolean {
27
+ return isBunJs() || isNodeJs();
28
+ }
29
+
30
+ export function isBunJs(): boolean {
31
+ if (_isBunJs) return _isBunJs;
32
+ return _isBunJs = typeof(Bun)!=="undefined";
33
+ }
34
+
35
+ export function isNodeJs(): boolean {
36
+ if (_isNodeJs) return _isNodeJs;
37
+ return _isNodeJs = typeof(self)==="undefined";
38
+ }
39
+
40
+ export function tick(delayMs: number): Promise<void> {
41
+ return new Promise((resolve) => setTimeout(resolve, delayMs));
42
+ }
43
+
44
+ export type ServerType = "nodejs"|"bunjs"|"browser";
45
+ export type Listener = ()=>void|Promise<void>;
46
+
47
+ export interface NodeSpaceType {
48
+ what: WhatInfos;
49
+ thread: ThreadImpl;
50
+ process: ProcessImpl;
51
+ timer: TimerImpl;
52
+ app: AppImpl;
53
+ fs?: FileSystemImpl;
54
+ extensionPoints?: ExtensionPointImpl;
55
+ }
56
+
57
+ export interface HotReloadType {
58
+ onHotReload: Listener[];
59
+ memory: { [key: string]: any };
60
+ }
61
+
62
+ interface WhatInfos {
63
+ isNodeJS: boolean;
64
+ isBunJs: boolean;
65
+ isBrowser: boolean;
66
+ isServerSide: boolean;
67
+ serverType: ServerType;
68
+ }
69
+
70
+ interface ThreadImpl {
71
+ isMainThread: boolean;
72
+ currentWorker: Worker | null;
73
+ newWorker: (fileName: string | URL, data?: any) => Worker;
74
+ getCurrentWorkerData: ()=>any;
75
+ unrefThisWorker(worker: Worker): void;
76
+ closeCurrentThread(): void;
77
+ }
78
+
79
+ interface ProcessImpl {
80
+ argv: string[];
81
+ env: { [key: string]: string };
82
+ isProduction: boolean;
83
+ }
84
+
85
+ interface TimerImpl {
86
+ tick: (delayMs: number) => Promise<void>;
87
+ }
88
+
89
+ interface FileSystemImpl {
90
+ mkDir: (dirPath: string) => Promise<string | undefined>;
91
+ }
92
+
93
+ interface AppImpl {
94
+ onServerSideReady(listener: Listener): void;
95
+ waitServerSideReady: () => Promise<void>;
96
+ declareServerSideReady(): void;
97
+
98
+ onAppStart(listener: Listener): void;
99
+ onAppExiting(listener: Listener): void;
100
+ onAppExited(listener: Listener): void;
101
+ executeApp(app: Listener): void;
102
+ declareAppStarted(): void;
103
+ declareAppExiting(): void;
104
+
105
+ onHotReload(listener: Listener): void;
106
+ keepOnHotReload<T>(key: string, provider: ()=>T): T;
107
+ }
108
+
109
+ export type EpCaller = (...values: unknown[]) => Promise<void>;
110
+ export type EpListener = (...values: unknown[]) => void|Promise<void>;
111
+
112
+ interface ExtensionPointImpl {
113
+ /**
114
+ * Register an extension point.
115
+ * Allow knowing who is using it as an host.
116
+ */
117
+ newHost(epName: string, importMetaUrl: string): EpCaller;
118
+
119
+ /**
120
+ * Get a caller, allowing to call the extension point.
121
+ */
122
+ getCaller(epName: string, importMetaUrl: string): EpCaller;
123
+
124
+ /**
125
+ * Add a function which is called when the extension point is called.
126
+ */
127
+ on(epName: string, importMetaUrl: string, fct: EpListener): void;
128
+ }
package/src/index.ts ADDED
@@ -0,0 +1,35 @@
1
+ import {isBunJs, isNodeJs, isServerSide, type ServerType} from "./common.ts";
2
+
3
+ export * from "./common.ts";
4
+
5
+ import {initBrowser} from "./browser.ts";
6
+
7
+ // Will init with the common stuffs.
8
+ initBrowser();
9
+
10
+ if (isServerSide()) {
11
+ let serverType: ServerType = "nodejs";
12
+ if (isBunJs()) serverType = "bunjs";
13
+
14
+ // Allow conditional code to be ok
15
+ // despite the "await import" is not done yet.
16
+ //
17
+ const nodeSpace = globalThis.NodeSpace;
18
+
19
+ nodeSpace.what = {
20
+ isNodeJS: isNodeJs(),
21
+ isBunJs: isBunJs(),
22
+ isBrowser: false,
23
+ isServerSide: true,
24
+ serverType: serverType,
25
+ }
26
+
27
+ let ext = import.meta.filename.split(".").pop();
28
+ const fileName = "./serverSide." + ext;
29
+
30
+ // To know: the caller will not wait for the await to resolve.
31
+ // Wait is after will not be interpreted immediately by the caller
32
+ // doing that specifics server-side things will not be ok now.
33
+ //
34
+ await import(/* @vite-ignore */ fileName);
35
+ }
@@ -0,0 +1,9 @@
1
+ export let gIsUsingWorkers = false;
2
+
3
+ export function declareUsingWorker() {
4
+ gIsUsingWorkers = true;
5
+ }
6
+
7
+ export function isUsingWorker(): boolean {
8
+ return gIsUsingWorkers;
9
+ }
@@ -0,0 +1,113 @@
1
+ import {execListeners, isBunJs, isNodeJs, type Listener} from "./common.ts";
2
+ import {isUsingWorker} from "./internal.ts";
3
+
4
+ export function init_nodeSpaceApp() {
5
+ const onServerSideReady: Listener[] = [];
6
+ const onAppExiting: Listener[] = [];
7
+ const onAppExited: Listener[] = [];
8
+ const onAppStart: Listener[] = [];
9
+ let isServerSideReady = !(isNodeJs() || isBunJs());
10
+
11
+ let isHotReload = globalThis.jopiHotReloader !== undefined;
12
+ let isAppStarted = false;
13
+
14
+ if (isHotReload) {
15
+ execListeners(globalThis.jopiHotReloader.onHotReload).then();
16
+ } else {
17
+ globalThis.jopiHotReloader = {
18
+ onHotReload: [],
19
+ memory: {}
20
+ }
21
+ }
22
+
23
+ const onHotReload = globalThis.jopiHotReloader.onHotReload;
24
+ const memory = globalThis.jopiHotReloader.memory;
25
+
26
+ NodeSpace.app = {
27
+ onServerSideReady: (listener) => {
28
+ if (isServerSideReady) listener();
29
+ else onServerSideReady.push(listener);
30
+ },
31
+
32
+ waitServerSideReady: () => {
33
+ if (isServerSideReady) {
34
+ return Promise.resolve();
35
+ }
36
+
37
+ return new Promise<void>(r => {
38
+ NodeSpace.app.onServerSideReady(r);
39
+ })
40
+ },
41
+
42
+ declareServerSideReady: async () => {
43
+ isServerSideReady = true;
44
+ await execListeners(onServerSideReady);
45
+ },
46
+
47
+ onAppStart: (listener: Listener) => {
48
+ if (isAppStarted) listener();
49
+ else onAppStart.push(listener);
50
+ },
51
+
52
+ onAppExiting: (listener: Listener) => {
53
+ if (!isAppStarted) listener();
54
+ else onAppExiting.push(listener);
55
+ },
56
+
57
+ onAppExited: (listener: Listener) => {
58
+ if (!isAppStarted) listener();
59
+ else onAppExited.push(listener);
60
+ },
61
+
62
+ declareAppStarted: async () => {
63
+ isAppStarted = true;
64
+ await execListeners(onAppStart);
65
+ },
66
+
67
+ declareAppExiting: async () => {
68
+ if (isUsingWorker()) {
69
+ // Wait 1 sec, which allows the worker to correctly initialize.
70
+ await NodeSpace.timer.tick(1000);
71
+ }
72
+
73
+ isAppStarted = false;
74
+ await execListeners(onAppExiting);
75
+
76
+ if (isUsingWorker()) {
77
+ // Allows to worker to correctly stop their activity.
78
+ await NodeSpace.timer.tick(100);
79
+ }
80
+
81
+ if (!NodeSpace.thread.isMainThread) {
82
+ // Allows to worker to correctly stop their activity.
83
+ await NodeSpace.timer.tick(50);
84
+ }
85
+
86
+ if (onAppExited.length) debugger;
87
+ await execListeners(onAppExited);
88
+ },
89
+
90
+ executeApp: async (app) => {
91
+ await NodeSpace.app.waitServerSideReady();
92
+ NodeSpace.app.declareAppStarted();
93
+
94
+ try {
95
+ const res = app();
96
+ if (res instanceof Promise) await res;
97
+ }
98
+ finally {
99
+ NodeSpace.app.declareAppExiting();
100
+ }
101
+ },
102
+
103
+ onHotReload(listener: Listener) {
104
+ onHotReload.push(listener);
105
+ },
106
+
107
+ keepOnHotReload: (key, provider) => {
108
+ let current = memory[key];
109
+ if (current!==undefined) return current;
110
+ return memory[key] = provider();
111
+ }
112
+ };
113
+ }
@@ -0,0 +1,67 @@
1
+ import {type EpCaller, type EpListener} from "./common.ts";
2
+
3
+ interface ExtensionPoint {
4
+ listeners: EpListener[];
5
+ caller: EpCaller;
6
+
7
+ allHostPath: string[];
8
+ allCallerPath: string[];
9
+ allListenerPath: string[];
10
+ }
11
+
12
+ const gExtensionPoints: {[epName: string]: ExtensionPoint} = {
13
+ }
14
+
15
+ function createExtensionPoint(epName: string, hostInfo: string|null, callerInfo: string|null, listenerInfo: string|null) {
16
+ async function caller(...args: unknown[]) {
17
+ for (const listener of ep.listeners) {
18
+ const res = listener(...args);
19
+ if (res instanceof Promise) await res;
20
+ }
21
+ }
22
+
23
+ const listeners: EpListener[] = [];
24
+
25
+ const ep: ExtensionPoint = {
26
+ listeners, caller,
27
+ allHostPath: [],
28
+ allCallerPath: [],
29
+ allListenerPath: []
30
+ };
31
+
32
+ gExtensionPoints[epName] = ep;
33
+
34
+ if (hostInfo) {
35
+ ep.allHostPath.push(hostInfo);
36
+ }
37
+
38
+ if (callerInfo) {
39
+ ep.allCallerPath.push(callerInfo);
40
+ }
41
+
42
+ if (listenerInfo) {
43
+ ep.allListenerPath.push(listenerInfo);
44
+ }
45
+ }
46
+
47
+ export function init_nodeSpaceExtensionPoints() {
48
+ NodeSpace.extensionPoints = {
49
+ newHost(epName: string, importMetaUrl: string): EpCaller {
50
+ const ep = gExtensionPoints[epName];
51
+ if (!ep) createExtensionPoint(epName, importMetaUrl, null, null);
52
+ return ep.caller;
53
+ },
54
+
55
+ getCaller(epName: string, importMetaUrl: string): EpCaller {
56
+ const ep = gExtensionPoints[epName];
57
+ if (!ep) createExtensionPoint(epName, null, importMetaUrl, null);
58
+ return ep.caller;
59
+ },
60
+
61
+ on(epName: string, importMetaUrl: string, listener: EpListener): void {
62
+ const ep = gExtensionPoints[epName];
63
+ if (!ep) createExtensionPoint(epName, null, null, importMetaUrl);
64
+ ep.listeners.push(listener);
65
+ }
66
+ };
67
+ }
@@ -0,0 +1,14 @@
1
+ export function init_nodeSpaceProcess() {
2
+ NodeSpace.process = {
3
+ isProduction: false,
4
+ argv: [],
5
+ env: {},
6
+ };
7
+
8
+ // For bundlers.
9
+ try {
10
+ NodeSpace.process.env = import.meta.env as ({ [key: string]: string });
11
+ NodeSpace.process.isProduction = (import.meta.env.PROD === "true");
12
+ } catch {
13
+ }
14
+ }
@@ -0,0 +1,21 @@
1
+ import {declareUsingWorker} from "./internal.ts";
2
+
3
+ export function init_nodeSpaceThread() {
4
+ NodeSpace.thread = {
5
+ isMainThread: true,
6
+ currentWorker: null,
7
+ getCurrentWorkerData: () => {},
8
+ unrefThisWorker: () => {},
9
+
10
+ newWorker: (fileName) => {
11
+ declareUsingWorker();
12
+ return new Worker(fileName, {type: 'module'})
13
+ },
14
+
15
+ closeCurrentThread() {
16
+ if (self.close) {
17
+ self.close();
18
+ }
19
+ }
20
+ };
21
+ }
@@ -0,0 +1,7 @@
1
+ import {tick} from "./common.ts";
2
+
3
+ export function init_nodeSpaceTimer() {
4
+ NodeSpace.timer = {
5
+ tick: tick
6
+ };
7
+ }
@@ -0,0 +1,9 @@
1
+ export function init_nodeSpaceWhat() {
2
+ NodeSpace.what = {
3
+ isNodeJS: false,
4
+ isBunJs: false,
5
+ isServerSide: false,
6
+ isBrowser: true,
7
+ serverType: "browser",
8
+ };
9
+ }
@@ -0,0 +1,43 @@
1
+ import {isMainThread, parentPort, Worker as NodeWorker, workerData} from "node:worker_threads";
2
+ import {declareUsingWorker} from "./internal.ts";
3
+ import fs from "node:fs/promises";
4
+
5
+ NodeSpace.process = {
6
+ argv: process.argv,
7
+ env: process.env as { [key: string]: string },
8
+ isProduction: process.env.NODE_ENV === 'production'
9
+ };
10
+
11
+ NodeSpace.thread = {
12
+ isMainThread: isMainThread,
13
+ currentWorker: parentPort as unknown as Worker,
14
+ getCurrentWorkerData: () => workerData,
15
+
16
+ newWorker: (fileName, data?: any) => {
17
+ declareUsingWorker();
18
+
19
+ const res = data ?
20
+ new NodeWorker(fileName, {workerData: data}) :
21
+ new NodeWorker(fileName);
22
+
23
+ return res as unknown as Worker
24
+ },
25
+
26
+ unrefThisWorker: (worker: Worker) => {
27
+ (worker as unknown as NodeWorker).unref();
28
+ },
29
+
30
+ closeCurrentThread() {
31
+ if (parentPort) {
32
+ parentPort.close();
33
+ }
34
+ }
35
+ }
36
+
37
+ NodeSpace.fs = {
38
+ mkDir: (dirPath: string) => fs.mkdir(dirPath, {recursive: true})
39
+ }
40
+
41
+ NodeSpace.app.declareServerSideReady();
42
+
43
+ process.on('exit', () => NodeSpace.app.declareAppExiting());
package/tsconfig.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "compilerOptions": {
3
+ "sourceMap": true,
4
+ "declaration": true,
5
+
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+
9
+ // Permet d'avoir des fonctions comme fetch.
10
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
11
+
12
+ "target": "ES2020",
13
+ "module": "ESNext",
14
+ "moduleResolution": "Bundler",
15
+ "rewriteRelativeImportExtensions": true,
16
+ "esModuleInterop": true,
17
+ "forceConsistentCasingInFileNames": true,
18
+ "strict": true,
19
+ "skipLibCheck": true,
20
+ "noEmitOnError": false,
21
+ "verbatimModuleSyntax": true,
22
+ "allowJs": false
23
+ },
24
+
25
+ "include": [
26
+ "./src/*.ts"
27
+ ],
28
+
29
+ "exclude": [
30
+ "node_modules",
31
+ "**/*.spec.ts"
32
+ ]
33
+ }