@ibgib/space-gib 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 (84) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/Dockerfile +14 -0
  3. package/IMPLEMENTATION.md +484 -0
  4. package/README.md +46 -0
  5. package/dist/client/bootstrap.mjs +58 -0
  6. package/dist/client/bootstrap.mjs.map +7 -0
  7. package/dist/client/chunk-CT47Z5WU.mjs +21 -0
  8. package/dist/client/chunk-CT47Z5WU.mjs.map +7 -0
  9. package/dist/client/chunk-RHEDTRKF.mjs +235 -0
  10. package/dist/client/chunk-RHEDTRKF.mjs.map +7 -0
  11. package/dist/client/index.html +147 -0
  12. package/dist/client/index.mjs +2 -0
  13. package/dist/client/index.mjs.map +7 -0
  14. package/dist/client/script.mjs +2 -0
  15. package/dist/client/script.mjs.map +7 -0
  16. package/dist/client/style.css +605 -0
  17. package/dist/respec-gib.node.mjs +5 -0
  18. package/dist/server/server.mjs +20157 -0
  19. package/dist/server/server.mjs.map +7 -0
  20. package/generate-version-file.js +35 -0
  21. package/package.json +27 -0
  22. package/src/client/AUTO-GENERATED-version.mts +11 -0
  23. package/src/client/README.md +19 -0
  24. package/src/client/api/function-infos.web.mts +38 -0
  25. package/src/client/api/space-gib-api-bridge.mts +85 -0
  26. package/src/client/bootstrap.mts +49 -0
  27. package/src/client/components/keystone-creator/keystone-creator.css +139 -0
  28. package/src/client/components/keystone-creator/keystone-creator.html +26 -0
  29. package/src/client/components/keystone-creator/keystone-creator.mts +229 -0
  30. package/src/client/constants.mts +76 -0
  31. package/src/client/custom.d.ts +11 -0
  32. package/src/client/dev-tools.mts +540 -0
  33. package/src/client/helpers.web.mts +178 -0
  34. package/src/client/index.html +147 -0
  35. package/src/client/index.mts +59 -0
  36. package/src/client/script.mts +13 -0
  37. package/src/client/style.css +605 -0
  38. package/src/client/types.mts +85 -0
  39. package/src/client/ui/shell/space-gib-shell-constants.mts +24 -0
  40. package/src/client/ui/shell/space-gib-shell-service.mts +233 -0
  41. package/src/client/ui/shell/space-gib-shell-types.mts +5 -0
  42. package/src/client/witness/app/space-gib/space-gib-app-v1.mts +160 -0
  43. package/src/client/witness/app/space-gib/space-gib-constants.mts +38 -0
  44. package/src/client/witness/app/space-gib/space-gib-helper.mts +72 -0
  45. package/src/client/witness/app/space-gib/space-gib-types.mts +47 -0
  46. package/src/common/keystone-policies.mts +159 -0
  47. package/src/respec-gib.node.mts +6 -0
  48. package/src/server/README.md +18 -0
  49. package/src/server/bootstrap-helper.mts +141 -0
  50. package/src/server/bootstrap-helper.respec.mts +100 -0
  51. package/src/server/metaspace-nodeindexedspace/metaspace-nodeindexedspace.mts +85 -0
  52. package/src/server/path-constants.mts +89 -0
  53. package/src/server/path-helper.mts +101 -0
  54. package/src/server/path-helper.respec.mts +94 -0
  55. package/src/server/serve-gib/CHANGELOG.md +29 -0
  56. package/src/server/serve-gib/README.md +34 -0
  57. package/src/server/serve-gib/constants.mts +1 -0
  58. package/src/server/serve-gib/handlers/api/debug/ws-echo.handler.mts +104 -0
  59. package/src/server/serve-gib/handlers/api/health.handler.mts +23 -0
  60. package/src/server/serve-gib/handlers/api/health.respec.mts +51 -0
  61. package/src/server/serve-gib/handlers/api/ibgib/ibgib-handler-types.mts +49 -0
  62. package/src/server/serve-gib/handlers/api/ibgib/ibgib.handler.mts +176 -0
  63. package/src/server/serve-gib/handlers/api/keystone/keystone-evolve.handler.mts +261 -0
  64. package/src/server/serve-gib/handlers/api/keystone/keystone-genesis.handler.mts +146 -0
  65. package/src/server/serve-gib/handlers/api/keystone/keystone-get.handler.mts +198 -0
  66. package/src/server/serve-gib/handlers/api/keystone/keystone-get.respec.mts +107 -0
  67. package/src/server/serve-gib/handlers/api/keystone/keystone-handler-types.mts +29 -0
  68. package/src/server/serve-gib/handlers/api/keystone/keystone-post.handler.mts +70 -0
  69. package/src/server/serve-gib/handlers/api/keystone/keystone-post.respec.mts +130 -0
  70. package/src/server/serve-gib/handlers/error-handler.mts +36 -0
  71. package/src/server/serve-gib/handlers/handler-base.mts +383 -0
  72. package/src/server/serve-gib/handlers/static-handler.mts +82 -0
  73. package/src/server/serve-gib/handlers/ws/sync-upgrade.handler.mts +498 -0
  74. package/src/server/serve-gib/handlers/ws/ws-helper.mts +111 -0
  75. package/src/server/serve-gib/handlers/ws/ws-types.mts +53 -0
  76. package/src/server/serve-gib/serve-gib-helpers.mts +32 -0
  77. package/src/server/serve-gib/serve-gib-v1.mts +172 -0
  78. package/src/server/serve-gib/serve-gib.respec.mts +90 -0
  79. package/src/server/serve-gib/types.mts +102 -0
  80. package/src/server/server-constants.mts +2 -0
  81. package/src/server/server.mts +96 -0
  82. package/tsconfig.json +29 -0
  83. package/tsconfig.server.json +29 -0
  84. package/tsconfig.test.json +27 -0
@@ -0,0 +1,172 @@
1
+ /**
2
+ * @module serve-gib/serve-gib-v1
3
+ *
4
+ * The main entry point for processing incoming requests in the serve-gib
5
+ * framework.
6
+ */
7
+
8
+ import { IncomingMessage, ServerResponse } from 'node:http';
9
+
10
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
11
+
12
+ import { GLOBAL_LOG_A_LOT } from './constants.mjs';
13
+ import { RequestContext, ResponseResult, ServeGibHandler, ServeGibHttpMethod } from './types.mjs';
14
+
15
+ const logalot = GLOBAL_LOG_A_LOT;
16
+
17
+ export interface ServeGibOptions {
18
+ /** Pipeline of handlers to check in order. */
19
+ handlers: ServeGibHandler<any, any>[];
20
+ /** Dedicated handler for errors (404, 500, etc.). */
21
+ errorHandler: ServeGibHandler<any, any>;
22
+ /** Port the server is listening on. */
23
+ port: number;
24
+ /**
25
+ * Root data directory for the server. We will use this as the root dir for
26
+ * all spaces that house multitenant ibgib data.
27
+ */
28
+ dataDir: string;
29
+ }
30
+
31
+ export class ServeGib_V1 {
32
+ private lc = `[${ServeGib_V1.name}]`;
33
+
34
+ constructor(private options: ServeGibOptions) { }
35
+
36
+ /**
37
+ * Entry point for all incoming HTTP requests.
38
+ */
39
+ async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {
40
+ const lc = `${this.lc}[${this.handleRequest.name}]`;
41
+ const start = Date.now();
42
+ let reqCtx: RequestContext | undefined;
43
+
44
+ try {
45
+ // Contextualize the request
46
+ reqCtx = await this.prepareContext(req);
47
+ if (!reqCtx) { throw new Error(`(UNEXPECTED) reqCtx falsy? couldn't prepare context? (E: 401888c0f649dfdf0e2d21f86b3ff826)`); }
48
+
49
+ // Execute pipeline
50
+ let result: ResponseResult | undefined;
51
+ for (const handler of this.options.handlers) {
52
+ result = await handler.handleRoute(reqCtx);
53
+ if (result) { break; }
54
+ }
55
+
56
+ // Fallback if no handler matched
57
+ if (!result) {
58
+ result = await this.options.errorHandler.handleRoute(reqCtx);
59
+ }
60
+
61
+ // Final output
62
+ if (result) {
63
+ this.sendResponse(res, result);
64
+ } else {
65
+ // If even the error handler didn't produce a result
66
+ this.sendResponse(res, { status: 404, body: 'Not Found' });
67
+ }
68
+
69
+ } catch (error) {
70
+ console.error(`${lc} Fatal error handling ${req.method} ${req.url}: ${extractErrorMsg(error)}`);
71
+ try {
72
+ // Try to use the error handler for the fatal error
73
+ if (reqCtx) {
74
+ const errorResult = await this.options.errorHandler.handleRoute(reqCtx);
75
+ this.sendResponse(res, errorResult ?? { status: 500, body: 'Internal Server Error' });
76
+ } else {
77
+ throw new Error(`errored before reqCtx could be set. (E: d77ab84b4f8874e188cfa8e9895f1226)`);
78
+ }
79
+ } catch (innerError) {
80
+ // Total collapse fallback
81
+ console.error(`${lc} Collapse in error handler: ${extractErrorMsg(innerError)}`);
82
+ res.writeHead(500);
83
+ res.end('Critical Server Error');
84
+ }
85
+ } finally {
86
+ const duration = Date.now() - start;
87
+ // Standard access logging
88
+ console.log(`${lc} ${req.method} ${req.url} -> ${res.statusCode} (${duration}ms)`);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Builds request context (e.g. extracting/decoding URL, path segments, body
94
+ * content, etc.), and initializes the request's metaspace if applicable.
95
+ */
96
+ public async prepareContext(req: IncomingMessage): Promise<RequestContext> {
97
+ const lc = `${this.lc}[${this.prepareContext.name}]`;
98
+ try {
99
+ if (logalot) { console.log(`${lc} starting... (I: ad9e9c678d0538c2d1e16ca8063d4426)`); }
100
+
101
+ /**
102
+ * These are NOT all of the validation we do on the context, rather,
103
+ * it is just simple initial validation.
104
+ */
105
+ const initialValidationErrors: string[] = [];
106
+
107
+ const rawUrl = req.url ?? '/';
108
+ const protocol = (req.headers['x-forwarded-proto'] as string) || 'http'; // todo: who owns the req.headers? Can an attacker manipulate this?
109
+ const url = new URL(rawUrl, `${protocol}://localhost:${this.options.port}`); // todo: wth?? Why are we hard-coding localhost? in the URL object?
110
+
111
+ const pathname = url.pathname;
112
+ const rawPathSegments = pathname.split('/');
113
+ const decodedPathSegments = rawPathSegments.map(s => decodeURIComponent(s));
114
+
115
+ const body = await this.readBody(req);
116
+
117
+ const reqCtx: RequestContext = {
118
+ rawUrl,
119
+ pathname,
120
+ method: req.method?.toUpperCase() as ServeGibHttpMethod ?? 'GET',
121
+ protocol,
122
+ body,
123
+ rawPathSegments,
124
+ decodedPathSegments,
125
+ url,
126
+ dataDir: this.options.dataDir,
127
+ headers: req.headers,
128
+ }
129
+
130
+ return reqCtx;
131
+ } catch (error) {
132
+ console.error(`${lc} ${extractErrorMsg(error)}`);
133
+ throw error;
134
+ } finally {
135
+ if (logalot) { console.log(`${lc} complete.`); }
136
+ }
137
+ }
138
+
139
+ /** Reads the full request body as UTF-8. */
140
+ private readBody(req: IncomingMessage): Promise<string> {
141
+ return new Promise((resolve, reject) => {
142
+ const chunks: Buffer[] = [];
143
+ req.on('data', (chunk: Buffer) => chunks.push(chunk));
144
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
145
+ req.on('error', reject);
146
+ });
147
+ }
148
+
149
+ /** Sends the response result to the client. */
150
+ private sendResponse(res: ServerResponse, result: ResponseResult): void {
151
+ const lc = `${this.lc}[${this.sendResponse.name}]`;
152
+ try {
153
+ if (logalot) { console.log(`${lc} starting... (I: 37369cf120c14780e8652bf27ada1726)`); }
154
+
155
+ const { status, headers = {}, body, isJson = false } = result;
156
+
157
+ let payload: any = body;
158
+ if (isJson) {
159
+ headers['Content-Type'] = 'application/json; charset=utf-8';
160
+ payload = JSON.stringify(body);
161
+ }
162
+
163
+ res.writeHead(status, headers);
164
+ res.end(payload);
165
+ } catch (error) {
166
+ console.error(`${lc} ${extractErrorMsg(error)}`);
167
+ throw error;
168
+ } finally {
169
+ if (logalot) { console.log(`${lc} complete.`); }
170
+ }
171
+ }
172
+ }
@@ -0,0 +1,90 @@
1
+ import { respecfully, iReckon, ifWe } from '@ibgib/helper-gib/dist/respec-gib/respec-gib.mjs';
2
+ import { ServeGib_V1 } from './serve-gib-v1.mjs';
3
+ import { HealthHandler } from './handlers/api/health.handler.mjs';
4
+ import { ErrorHandler } from './handlers/error-handler.mjs';
5
+
6
+ const sir = `[${import.meta.url}]`;
7
+
8
+ await respecfully(sir, 'ServeGib ServeGib_V1', async () => {
9
+
10
+ await ifWe(sir, 'construct a RouteInfo object', async () => {
11
+ const serveGib = new ServeGib_V1({
12
+ port: 3000,
13
+ dataDir: './test-data',
14
+ handlers: [],
15
+ errorHandler: new ErrorHandler()
16
+ });
17
+
18
+ // Mock request
19
+ const req: any = {
20
+ url: '/api/health?foo=bar',
21
+ method: 'GET',
22
+ headers: { 'x-forwarded-proto': 'https' },
23
+ on: (event: string, cb: any) => {
24
+ if (event === 'end') { cb(); }
25
+ } // immediate end for readBody
26
+ };
27
+
28
+ const info = await (serveGib as any).buildRouteInfo(req);
29
+
30
+ iReckon(sir, info.pathname).isGonnaBe('/api/health');
31
+ iReckon(sir, info.method).isGonnaBe('GET');
32
+ iReckon(sir, info.protocol).isGonnaBe('https');
33
+ iReckon(sir, info.pathSegments).includes('api');
34
+ iReckon(sir, info.pathSegments).includes('health');
35
+ });
36
+
37
+ await ifWe(sir, 'execute a handler in the pipeline', async () => {
38
+ const health = new HealthHandler();
39
+ const serveGib = new ServeGib_V1({
40
+ port: 3000,
41
+ dataDir: './test-data',
42
+ handlers: [health],
43
+ errorHandler: new ErrorHandler()
44
+ });
45
+
46
+ // Mock objects
47
+ const req: any = {
48
+ url: '/api/health',
49
+ method: 'GET',
50
+ headers: {},
51
+ on: (event: string, cb: any) => {
52
+ if (event === 'end') { cb(); }
53
+ }
54
+ };
55
+ const res: any = {
56
+ writeHead: () => { },
57
+ end: () => { },
58
+ statusCode: 200
59
+ };
60
+
61
+ await serveGib.handleRequest(req, res);
62
+ iReckon(sir, res.statusCode).isGonnaBe(200);
63
+ });
64
+
65
+ await ifWe(sir, 'fall back to error handler when no handler matches', async () => {
66
+ const serveGib = new ServeGib_V1({
67
+ port: 3000,
68
+ dataDir: './test-data',
69
+ handlers: [],
70
+ errorHandler: new ErrorHandler()
71
+ });
72
+
73
+ const req: any = {
74
+ url: '/not/found',
75
+ method: 'GET',
76
+ headers: {},
77
+ on: (event: string, cb: any) => {
78
+ if (event === 'end') { cb(); }
79
+ }
80
+ };
81
+ const res: any = {
82
+ writeHead: () => { },
83
+ end: () => { },
84
+ statusCode: 404
85
+ };
86
+
87
+ await serveGib.handleRequest(req, res);
88
+ iReckon(sir, res.statusCode).isGonnaBe(404);
89
+ });
90
+ });
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @module serve-gib/types
3
+ *
4
+ * Foundational types for the serve-gib microframework.
5
+ */
6
+
7
+ import { Gib, Ib, IbGibAddr } from '@ibgib/ts-gib/dist/types.mjs';
8
+ import { GibInfo } from '@ibgib/ts-gib/dist/V1/types.mjs';
9
+ import { MetaspaceService } from '@ibgib/core-gib/dist/witness/space/metaspace/metaspace-types.mjs';
10
+
11
+ /**
12
+ * Standard HTTP methods supported by the serve-gib framework, plus 'ALL' for catch-all handlers.
13
+ */
14
+ export type ServeGibHttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS' | 'ALL';
15
+
16
+ /**
17
+ * @see {@link RequestContext.domainInfo}
18
+ */
19
+ export interface DomainInfo {
20
+ ib: Ib;
21
+ gib: Gib;
22
+ addr: IbGibAddr;
23
+ gibInfo: GibInfo;
24
+ /** The physical root directory for the current domain. */
25
+ // rootPath?: string;
26
+ }
27
+
28
+ export interface ParamsWithDomain {
29
+ domainInfo: DomainInfo;
30
+ }
31
+
32
+ /**
33
+ * Encapsulates the context of an incoming HTTP request.
34
+ */
35
+ export interface RequestContext<TParams = any, TQueryParams = any> {
36
+ /** The native Node.js/Web URL object. */
37
+ url: URL;
38
+ /** The root data directory for spaces. */
39
+ dataDir: string;
40
+ /** The original request URL string. */
41
+ rawUrl: string;
42
+ /** The pathname part of the URL (e.g. /api/health). */
43
+ pathname: string;
44
+ /** HTTP method (GET, POST, etc.). */
45
+ method: ServeGibHttpMethod;
46
+ /** Request protocol (http or https). */
47
+ protocol: string;
48
+ /** The raw request body as a string. */
49
+ body: string;
50
+ /** Array of raw path segments split by '/'. */
51
+ rawPathSegments: string[];
52
+ /**
53
+ * Same as {@link rawPathSegments}, but with any ibgib addr(s) URL decoded.
54
+ */
55
+ decodedPathSegments: string[];
56
+ params?: TParams;
57
+ /** Parsed query parameters. */
58
+ queryParams?: TQueryParams;
59
+ /** Request headers. */
60
+ headers: Record<string, string | string[] | undefined>;
61
+ /**
62
+ * The bootstrapped MetaspaceService for the current domain.
63
+ *
64
+ * Note that not all routes require this, hence it's optional.
65
+ */
66
+ metaspace?: MetaspaceService;
67
+ /**
68
+ * keystones define "domains" to enable multitenancy. This is info about the
69
+ * keystone domain.
70
+ *
71
+ * ## notes
72
+ *
73
+ * I would call this "KeystoneInfo", and right now, this is only one keystone's
74
+ * info. but ultimately I _think_ that we will have nested domains.
75
+ */
76
+ domainInfo?: DomainInfo;
77
+ }
78
+
79
+ /**
80
+ * Standardized response shape returned by handlers.
81
+ */
82
+ export interface ResponseResult {
83
+ /** HTTP status code (200, 404, etc.). */
84
+ status: number;
85
+ /** Optional response headers. */
86
+ headers?: Record<string, string>;
87
+ /** Response body content. */
88
+ body: any;
89
+ /** If true, body will be stringified as JSON and Content-Type set accordingly. */
90
+ isJson?: boolean;
91
+ }
92
+
93
+ /**
94
+ * Interface for a serve-gib route handler.
95
+ */
96
+ export interface ServeGibHandler<TParams, TQueryParams> {
97
+ /**
98
+ * Attempts to handle the request.
99
+ * @returns A ResponseResult if handled, or undefined to pass to the next handler.
100
+ */
101
+ handleRoute(reqCtx: RequestContext<TParams, TQueryParams>): Promise<ResponseResult | undefined>;
102
+ }
@@ -0,0 +1,2 @@
1
+ export const GLOBAL_LOG_A_LOT = false;
2
+ export const GLOBAL_TIMER_NAME = '[space^gib server timer]';
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @module server
3
+ *
4
+ * Native Node.js HTTP server for space-gib — using the serve-gib microframework.
5
+ */
6
+
7
+ import { createServer } from 'node:http';
8
+ import { join, dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+
11
+ import { extractErrorMsg } from '@ibgib/helper-gib/dist/helpers/utils-helper.mjs';
12
+
13
+ import { ServeGib_V1 } from './serve-gib/serve-gib-v1.mjs';
14
+ import { HealthHandler } from './serve-gib/handlers/api/health.handler.mjs';
15
+ import { IbGibHandler } from './serve-gib/handlers/api/ibgib/ibgib.handler.mjs';
16
+ import { KeystonePostHandler } from './serve-gib/handlers/api/keystone/keystone-post.handler.mjs';
17
+ import { KeystoneGetHandler } from './serve-gib/handlers/api/keystone/keystone-get.handler.mjs';
18
+ import { KeystoneGenesisHandler } from './serve-gib/handlers/api/keystone/keystone-genesis.handler.mjs';
19
+ import { KeystoneEvolveHandler } from './serve-gib/handlers/api/keystone/keystone-evolve.handler.mjs';
20
+ import { StaticFileHandler } from './serve-gib/handlers/static-handler.mjs';
21
+ import { ErrorHandler } from './serve-gib/handlers/error-handler.mjs';
22
+ import { canHandleWsUpgrade, handleWsEchoUpgrade } from './serve-gib/handlers/api/debug/ws-echo.handler.mjs';
23
+ import { SyncUpgradeHandler } from './serve-gib/handlers/ws/sync-upgrade.handler.mjs';
24
+
25
+ const __dirname = dirname(fileURLToPath(import.meta.url));
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Config
29
+ // ---------------------------------------------------------------------------
30
+
31
+ const PORT = parseInt(process.env.PORT ?? '3000', 10);
32
+ const DATA_DIR = process.env.DATA_DIR ?? join(__dirname, '../../.data/ibgib-space');
33
+ const CLIENT_DIR = join(__dirname, '../client');
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Main
37
+ // ---------------------------------------------------------------------------
38
+
39
+ async function main(): Promise<void> {
40
+ const lc = '[space-gib server]';
41
+ try {
42
+ console.log(`${lc} starting...`);
43
+
44
+ console.log(`${lc} dataDir: ${DATA_DIR}`);
45
+
46
+ const syncUpgradeHandler = new SyncUpgradeHandler();
47
+
48
+ // Initialize serve-gib
49
+ const serveGib = new ServeGib_V1({
50
+ port: PORT,
51
+ dataDir: DATA_DIR,
52
+ handlers: [
53
+ new HealthHandler(),
54
+ new IbGibHandler(),
55
+ new KeystoneGenesisHandler(),
56
+ new KeystoneEvolveHandler(),
57
+ new KeystonePostHandler(),
58
+ new KeystoneGetHandler(),
59
+ new StaticFileHandler(CLIENT_DIR),
60
+ ],
61
+ errorHandler: new ErrorHandler()
62
+ });
63
+
64
+ const server = createServer(async (req, res) => {
65
+ await serveGib.handleRequest(req, res);
66
+ });
67
+
68
+ // WebSocket upgrade handling — separate from the HTTP request pipeline
69
+ // since Node.js fires `upgrade` events independently of `request` events.
70
+ server.on('upgrade', async (req, socket, head) => {
71
+ const reqCtx = await serveGib.prepareContext(req);
72
+
73
+ // Check sync upgrade handler first
74
+ const isSync = await syncUpgradeHandler.handleUpgrade(reqCtx, socket as any, head);
75
+
76
+ // Fallback to debug echo if not handled by sync
77
+ if (!isSync && canHandleWsUpgrade(req)) {
78
+ handleWsEchoUpgrade(req, socket as any, head);
79
+ } else if (!isSync) {
80
+ // Reject unrecognized upgrade requests
81
+ socket.write('HTTP/1.1 404 Not Found\r\n\r\n');
82
+ socket.destroy();
83
+ }
84
+ });
85
+
86
+ server.listen(PORT, '0.0.0.0', () => {
87
+ console.log(`${lc} listening on http://0.0.0.0:${PORT}`);
88
+ });
89
+
90
+ } catch (error) {
91
+ console.error(`${lc} fatal: ${extractErrorMsg(error)}`);
92
+ process.exit(1);
93
+ }
94
+ }
95
+
96
+ main();
package/tsconfig.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "declarationMap": false,
6
+ "sourceMap": false,
7
+ "rootDir": "./src",
8
+ "composite": false,
9
+ "outDir": "./dist/client",
10
+ "module": "ESNext",
11
+ "lib": [
12
+ "DOM",
13
+ "ES2022",
14
+ "ES2023"
15
+ ]
16
+ },
17
+ "include": [
18
+ "src/client/**/*.ts",
19
+ "src/client/**/*.mts",
20
+ "src/client/**/*.d.ts",
21
+ "src/common/**/*.ts",
22
+ "src/common/**/*.mts"
23
+ ],
24
+ "exclude": [
25
+ "node_modules",
26
+ "**/*.respec.mts",
27
+ "./dist/**/*"
28
+ ]
29
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "declarationMap": false,
6
+ "sourceMap": false,
7
+ "rootDir": "./src",
8
+ "composite": false,
9
+ "outDir": "./dist/server",
10
+ "module": "ESNext",
11
+ "lib": [
12
+ "ES2022",
13
+ "ES2023"
14
+ ],
15
+ "types": ["node"]
16
+ },
17
+ "include": [
18
+ "src/server/**/*.ts",
19
+ "src/server/**/*.mts",
20
+ "src/server/**/*.d.ts",
21
+ "src/common/**/*.ts",
22
+ "src/common/**/*.mts"
23
+ ],
24
+ "exclude": [
25
+ "node_modules",
26
+ "**/*.respec.mts",
27
+ "./dist/**/*"
28
+ ]
29
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "declaration": false,
5
+ "declarationMap": false,
6
+ "sourceMap": false,
7
+ "rootDir": "./src",
8
+ "composite": false,
9
+ "outDir": "./dist",
10
+ "module": "ESNext",
11
+ "lib": [
12
+ "ES2022",
13
+ "ES2023"
14
+ ],
15
+ "types": ["node"]
16
+ },
17
+ "include": [
18
+ "src/server/**/*.ts",
19
+ "src/server/**/*.mts",
20
+ "src/server/**/*.d.ts",
21
+ "src/respec-gib.node.mts"
22
+ ],
23
+ "exclude": [
24
+ "node_modules",
25
+ "./dist/**/*"
26
+ ]
27
+ }