@oasisomniverse/web9-api 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # @oasisomniverse/web9-api
2
+
3
+ Isomorphic (Node 18+ and browser) JavaScript/TypeScript-friendly client for the
4
+ **WEB9 OASIS Singularity API** - one unified, live status view aggregated
5
+ across every other OASIS layer (WEB4-WEB8), built on the OASIS2 WEB9 WebAPI.
6
+ "The network observing itself."
7
+
8
+ Zero dependencies. Wraps the global `fetch`. Works the same in Node and the
9
+ browser.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @oasisomniverse/web9-api
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```js
20
+ const { Web9Client } = require('@oasisomniverse/web9-api');
21
+ // or: import { Web9Client } from '@oasisomniverse/web9-api';
22
+
23
+ const web9 = new Web9Client({ baseUrl: 'https://api.web9.oasisomniverse.one' });
24
+
25
+ const { isError, message, result } = await web9.singularity.getUnifiedStatus();
26
+ if (isError) throw new Error(message);
27
+ console.log(result); // unified status across WEB4-WEB8
28
+ ```
29
+
30
+ Every response has the shape:
31
+
32
+ ```ts
33
+ interface OASISResponse<T = any> {
34
+ isError: boolean;
35
+ message: string | null;
36
+ result: T;
37
+ raw: any;
38
+ statusCode: number;
39
+ }
40
+ ```
41
+
42
+ ## Auth
43
+
44
+ WEB9 is an internal aggregation layer that sits behind the same OASIS avatar
45
+ identity as WEB4-WEB8 - it has no avatar/login endpoints of its own. Reuse a
46
+ JWT you've already obtained elsewhere (e.g. from `web4-oasis-api`'s
47
+ `client.auth.login()`):
48
+
49
+ ```js
50
+ web9.setToken(jwtToken);
51
+ ```
52
+
53
+ ## Module reference
54
+
55
+ 1 module, 1 operation. Full reference lives in [`docs/`](./docs/README.md).
56
+
57
+ | Client property | Route prefix | Operations |
58
+ | --- | --- | --- |
59
+ | `web9.singularity` | `v1/singularity` | 1 |
60
+
61
+ ## Regenerating
62
+
63
+ The generated module, type declarations and docs are produced from
64
+ `endpoints.json` (extracted from the WEB9 WebAPI controller source):
65
+
66
+ ```bash
67
+ npm run generate # src/modules/*.js + src/modules/index.js
68
+ npm run types # src/modules/*.d.ts + index.d.ts + src/core/types.d.ts
69
+ npm run docs # docs/README.md + docs/modules/*.md
70
+ ```
71
+
72
+ ## Testing
73
+
74
+ ```bash
75
+ npm test
76
+ ```
77
+
78
+ ## License
79
+
80
+ MIT
package/docs/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # WEB9 Singularity API — JavaScript SDK Reference
2
+
3
+ Generated from `endpoints.json` (extracted from the WebAPI controllers) by
4
+ `scripts/generate-full-docs.js`. Regenerate the full pipeline after the API
5
+ changes:
6
+
7
+ ```
8
+ node scripts/extract-endpoints.js
9
+ node scripts/generate-modules.js
10
+ node scripts/generate-full-docs.js
11
+ ```
12
+
13
+ - [Module Reference](#module-reference) (1 modules, 1 operations)
14
+
15
+ ## Module Reference
16
+
17
+ | Client property | Route prefix | Operations |
18
+ | --- | --- | --- |
19
+ | [`web9.singularity`](modules/Singularity.md) | `v1/singularity` | 1 |
@@ -0,0 +1,62 @@
1
+ # Singularity — `web9.singularity`
2
+
3
+ Source controller: [`SingularityController.cs`](https://github.com/NextGenSoftwareUK/OASIS2/blob/main/WEB9/NextGenSoftware.OASIS.Web9.WebAPI/Controllers/SingularityController.cs)
4
+ Route prefix: `v1/singularity`
5
+ 1 operation(s).
6
+
7
+ Every method takes a single args object: any key matching a `{token}` in the route is substituted into the URL; everything else becomes the query string (GET/DELETE) or JSON body (POST/PUT). Every call resolves to the standard OASIS envelope:
8
+
9
+ ```ts
10
+ {
11
+ isError: boolean;
12
+ isWarning: boolean;
13
+ message: string;
14
+ errorCode?: string;
15
+ result: T; // see each endpoint's Response section below
16
+ }
17
+ ```
18
+
19
+ ## Operations
20
+
21
+ ### `getUnifiedStatus`
22
+
23
+ Probes WEB4-WEB8 in parallel and returns one unified status report - "the network observing itself".
24
+
25
+ **GET** `v1/singularity/status`
26
+
27
+ **Request**
28
+
29
+ No request body.
30
+
31
+ **Response**
32
+
33
+ Standard `OASISResult` envelope (see top of this page) with:
34
+
35
+ `result` type: `UnifiedStatusReport`
36
+
37
+ | Field | Type |
38
+ | --- | --- |
39
+ | `Layers` | `List<LayerStatus>` |
40
+ | `AllLayersHealthy` | `bool` |
41
+ | `HealthyLayerCount` | `int` |
42
+ | `TotalLayerCount` | `int` |
43
+ | `GeneratedUtc` | `DateTime` |
44
+
45
+ **Example**
46
+
47
+ ```js
48
+ const { isError, message, result } = await web9.singularity.getUnifiedStatus({});
49
+ if (isError) throw new Error(message);
50
+ console.log(result);
51
+ ```
52
+
53
+ Example response:
54
+
55
+ ```json
56
+ {
57
+ "isError": false,
58
+ "message": "",
59
+ "result": { "Layers": [{ "LayerName": "example string", "BaseUrl": "example string", "IsReachable": true, "ResponseTimeMs": 1.0, "Metrics": { "<string>": "example string" }, "Error": "example string", "CheckedUtc": "2026-01-01T00:00:00Z" }], "AllLayersHealthy": true, "HealthyLayerCount": 1, "TotalLayerCount": 1, "GeneratedUtc": "2026-01-01T00:00:00Z" }
60
+ }
61
+ ```
62
+
package/index.d.ts ADDED
@@ -0,0 +1,42 @@
1
+ // AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
2
+ import type { OASISResponse, OASISSession } from './src/core/types';
3
+ import type { SingularityModule } from './src/modules/Singularity';
4
+
5
+ export type { OASISResponse, OASISSession };
6
+
7
+ export interface Web9ClientOptions {
8
+ baseUrl?: string;
9
+ persistSession?: boolean;
10
+ fetchImpl?: typeof fetch;
11
+ }
12
+
13
+ export declare class HttpClient {
14
+ constructor(options?: { baseUrl?: string; tokenStore?: unknown; fetchImpl?: typeof fetch });
15
+ setBaseUrl(baseUrl: string): void;
16
+ request(verb: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, options?: Record<string, any>): Promise<OASISResponse>;
17
+ get(path: string, options?: Record<string, any>): Promise<OASISResponse>;
18
+ post(path: string, options?: Record<string, any>): Promise<OASISResponse>;
19
+ put(path: string, options?: Record<string, any>): Promise<OASISResponse>;
20
+ delete(path: string, options?: Record<string, any>): Promise<OASISResponse>;
21
+ }
22
+
23
+ export declare class TokenStore {
24
+ constructor(options?: { persist?: boolean });
25
+ getSession(): OASISSession | null;
26
+ getToken(): string | null;
27
+ setSession(session: OASISSession | null): void;
28
+ clear(): void;
29
+ }
30
+
31
+ export declare const DEFAULT_BASE_URL: string;
32
+
33
+ export declare class Web9Client {
34
+ constructor(options?: Web9ClientOptions);
35
+ readonly http: HttpClient;
36
+ readonly tokenStore: TokenStore;
37
+ readonly singularity: SingularityModule;
38
+ setBaseUrl(baseUrl: string): void;
39
+ setToken(jwtToken: string, sessionExtras?: Partial<OASISSession>): void;
40
+ }
41
+
42
+ export default Web9Client;
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ 'use strict';
2
+
3
+ module.exports = require('./src/index');
package/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import cjs from './index.js';
2
+
3
+ export const { Web9Client, HttpClient, TokenStore, DEFAULT_BASE_URL } = cjs;
4
+ export default Web9Client;
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@oasisomniverse/web9-api",
3
+ "version": "1.0.0",
4
+ "publishConfig": { "access": "public" },
5
+ "description": "Isomorphic (Node + browser) JavaScript/TypeScript-friendly client for the WEB9 OASIS Singularity API - one unified, live status view aggregated across every other OASIS layer (WEB4-WEB8), built on the OASIS2 WEB9 WebAPI.",
6
+ "main": "index.js",
7
+ "module": "index.mjs",
8
+ "types": "index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./index.d.ts",
12
+ "import": "./index.mjs",
13
+ "require": "./index.js"
14
+ }
15
+ },
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "files": [
20
+ "index.js",
21
+ "index.mjs",
22
+ "index.d.ts",
23
+ "src",
24
+ "docs"
25
+ ],
26
+ "scripts": {
27
+ "generate": "node scripts/generate-modules.js",
28
+ "docs": "node scripts/generate-docs.js",
29
+ "types": "node scripts/generate-types.js",
30
+ "test": "node --test test"
31
+ },
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/NextGenSoftwareUK/OASIS-API-Javascript-Package-WEB9.git"
35
+ },
36
+ "author": "NextGen Software Ltd",
37
+ "license": "MIT",
38
+ "keywords": [
39
+ "WEB9 Singularity API",
40
+ "WEB9 WebAPI",
41
+ "OASIS Singularity",
42
+ "Unified Status",
43
+ "Network Observing Itself",
44
+ "OASIS API",
45
+ "WEB 4",
46
+ "WEB 5",
47
+ "WEB 6",
48
+ "WEB 7",
49
+ "WEB 8",
50
+ "WEB 9",
51
+ "Blockchain",
52
+ "Interoperable",
53
+ "Metaverse",
54
+ "Aggregation",
55
+ "HOT-Swappable-Architecture",
56
+ "Decentralised",
57
+ "Distributed",
58
+ "Abstraction-Layer",
59
+ "SSO",
60
+ "Agent-Centric",
61
+ "GOD-Protocol/API",
62
+ "More Coming..."
63
+ ]
64
+ }
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ const DEFAULT_BASE_URL = 'https://api.web9.oasisomniverse.one';
4
+
5
+ function buildQueryString(query) {
6
+ const entries = Object.entries(query || {}).filter(([, v]) => v !== undefined && v !== null);
7
+ if (!entries.length) return '';
8
+ const params = new URLSearchParams();
9
+ for (const [key, value] of entries) {
10
+ params.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
11
+ }
12
+ return `?${params.toString()}`;
13
+ }
14
+
15
+ /**
16
+ * Thin isomorphic HTTP client around the global fetch API (Node 18+, all modern browsers).
17
+ * Every WEB9 Singularity API call ultimately goes through `request()` below - there are no mocked
18
+ * or stubbed responses anywhere in this SDK.
19
+ */
20
+ class HttpClient {
21
+ constructor({ baseUrl = DEFAULT_BASE_URL, tokenStore, fetchImpl = globalThis.fetch } = {}) {
22
+ if (!fetchImpl) {
23
+ throw new Error(
24
+ 'No global fetch implementation found. Use Node 18+, a modern browser, or pass { fetchImpl } explicitly.'
25
+ );
26
+ }
27
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
28
+ this.tokenStore = tokenStore;
29
+ this.fetchImpl = fetchImpl;
30
+ }
31
+
32
+ setBaseUrl(baseUrl) {
33
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
34
+ }
35
+
36
+ /**
37
+ * @param {string} verb GET | POST | PUT | DELETE
38
+ * @param {string} path e.g. "v1/complete"
39
+ * @param {object} [options]
40
+ * @param {object} [options.query] query string params (GET/DELETE)
41
+ * @param {object} [options.body] JSON body (POST/PUT/DELETE)
42
+ * @param {boolean} [options.auth] attach Authorization: Bearer <token> (default true)
43
+ * @param {string} [options.token] override token for this single request
44
+ */
45
+ async request(verb, path, { query, body, auth = true, token } = {}) {
46
+ const url = `${this.baseUrl}/${path.replace(/^\/+/, '')}${buildQueryString(query)}`;
47
+ const headers = {
48
+ 'Content-Type': 'application/json',
49
+ Accept: 'application/json'
50
+ };
51
+
52
+ const bearer = token || (auth ? this.tokenStore?.getToken() : null);
53
+ if (bearer) headers.Authorization = `Bearer ${bearer}`;
54
+
55
+ const init = { method: verb, headers };
56
+ if (body !== undefined && verb !== 'GET') init.body = JSON.stringify(body);
57
+
58
+ let res;
59
+ try {
60
+ res = await this.fetchImpl(url, init);
61
+ } catch (err) {
62
+ return { isError: true, message: `Network error calling ${url}: ${err.message}`, exception: err };
63
+ }
64
+
65
+ const text = await res.text();
66
+ let json;
67
+ try {
68
+ json = text ? JSON.parse(text) : null;
69
+ } catch {
70
+ json = null;
71
+ }
72
+
73
+ if (!res.ok) {
74
+ const message =
75
+ json?.result?.message || json?.message || json?.title || `Request failed with status ${res.status}`;
76
+ return { isError: true, message, statusCode: res.status, raw: json };
77
+ }
78
+
79
+ // OASIS responses are typically { isError, message, result: { isError, message, result: <payload> } }.
80
+ // We surface the innermost payload as `.result` while keeping the full envelope available as `.raw`.
81
+ const inner = json?.result !== undefined ? json.result : json;
82
+ const payload = inner?.result !== undefined ? inner.result : inner;
83
+
84
+ return {
85
+ isError: Boolean(inner?.isError || json?.isError),
86
+ message: inner?.message || json?.message || null,
87
+ result: payload,
88
+ raw: json,
89
+ statusCode: res.status
90
+ };
91
+ }
92
+
93
+ get(path, options) {
94
+ return this.request('GET', path, options);
95
+ }
96
+
97
+ post(path, options) {
98
+ return this.request('POST', path, options);
99
+ }
100
+
101
+ put(path, options) {
102
+ return this.request('PUT', path, options);
103
+ }
104
+
105
+ delete(path, options) {
106
+ return this.request('DELETE', path, options);
107
+ }
108
+ }
109
+
110
+ module.exports = { HttpClient, DEFAULT_BASE_URL };
@@ -0,0 +1,85 @@
1
+ 'use strict';
2
+
3
+ const TOKEN_PATTERN = /\{(\w+)(?::\w+)?\}/g;
4
+
5
+ /**
6
+ * Resolves a route template like "get-by-id/{id}" against an args object,
7
+ * substituting path tokens and returning the resolved path plus whatever
8
+ * args were *not* consumed as path tokens (these become the query/body).
9
+ */
10
+ function resolveRoute(routeTemplate, args = {}) {
11
+ const consumed = new Set();
12
+ const path = routeTemplate.replace(TOKEN_PATTERN, (match, name) => {
13
+ const key = Object.keys(args).find((k) => k.toLowerCase() === name.toLowerCase());
14
+ consumed.add(key);
15
+ const value = key !== undefined ? args[key] : undefined;
16
+ if (value === undefined) {
17
+ throw new Error(`Missing required route parameter "${name}" for route "${routeTemplate}"`);
18
+ }
19
+ return encodeURIComponent(value);
20
+ });
21
+
22
+ const rest = {};
23
+ for (const [key, value] of Object.entries(args)) {
24
+ if (!consumed.has(key)) rest[key] = value;
25
+ }
26
+
27
+ return { path, rest };
28
+ }
29
+
30
+ function takeKey(obj, name) {
31
+ const matchKey = Object.keys(obj).find((k) => k.toLowerCase() === name.toLowerCase());
32
+ if (matchKey === undefined) return { found: false, value: undefined };
33
+ const value = obj[matchKey];
34
+ delete obj[matchKey];
35
+ return { found: true, value };
36
+ }
37
+
38
+ /**
39
+ * Builds a bound method for a single WEB9 endpoint operation.
40
+ * @param {import('./httpClient').HttpClient} http
41
+ * @param {string} routePrefix e.g. "api/avatar"
42
+ * @param {string} verb GET | POST | PUT | DELETE
43
+ * @param {string} route route template relative to routePrefix, e.g. "get-by-id/{id}"
44
+ * @param {object} [opts]
45
+ * @param {string[]} [opts.query] arg names that ASP.NET binds from the query
46
+ * string on this action regardless of HTTP verb (e.g. `[FromQuery]` flags
47
+ * mixed into an otherwise-body-bound POST/PUT action). Always sent as query.
48
+ * @param {string} [opts.bodyParam] when the action's entire request body is a
49
+ * single `[FromBody]` parameter (primitive or object), the JSON body is
50
+ * that arg's value directly rather than the leftover-args object wrapped
51
+ * around it.
52
+ */
53
+ function makeOperation(http, routePrefix, verb, route, opts = {}) {
54
+ const declaredQueryKeys = opts.query || [];
55
+ const bodyParam = opts.bodyParam;
56
+
57
+ return async function operation(args = {}) {
58
+ const { path, rest } = resolveRoute(route, args);
59
+ const fullPath = path ? `${routePrefix}/${path}` : routePrefix;
60
+
61
+ const query = {};
62
+ for (const key of declaredQueryKeys) {
63
+ const { found, value } = takeKey(rest, key);
64
+ if (found) query[key] = value;
65
+ }
66
+
67
+ let body;
68
+ if (bodyParam) {
69
+ const { found, value } = takeKey(rest, bodyParam);
70
+ if (found) body = value;
71
+ // Any args left over that we don't recognize still get sent (as query)
72
+ // rather than silently dropped.
73
+ Object.assign(query, rest);
74
+ } else if (verb === 'GET' || verb === 'DELETE') {
75
+ Object.assign(query, rest);
76
+ } else {
77
+ body = Object.keys(rest).length ? rest : undefined;
78
+ }
79
+
80
+ const hasQuery = Object.keys(query).length > 0;
81
+ return http.request(verb, fullPath, { query: hasQuery ? query : undefined, body });
82
+ };
83
+ }
84
+
85
+ module.exports = { resolveRoute, makeOperation };
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const hasLocalStorage = typeof globalThis.localStorage !== 'undefined';
4
+ const STORAGE_KEY = 'oasis_session';
5
+
6
+ /**
7
+ * Holds the current JWT/avatar session for the SDK.
8
+ * In the browser it persists to localStorage by default; in Node (or when
9
+ * persistence is disabled) it simply lives in memory for the lifetime of
10
+ * the client instance. Callers can always set/get/clear explicitly.
11
+ */
12
+ class TokenStore {
13
+ constructor({ persist = hasLocalStorage } = {}) {
14
+ this.persist = persist;
15
+ this._session = null;
16
+
17
+ if (this.persist) {
18
+ try {
19
+ const raw = globalThis.localStorage.getItem(STORAGE_KEY);
20
+ if (raw) this._session = JSON.parse(raw);
21
+ } catch {
22
+ this._session = null;
23
+ }
24
+ }
25
+ }
26
+
27
+ getSession() {
28
+ return this._session;
29
+ }
30
+
31
+ getToken() {
32
+ return this._session?.jwtToken || this._session?.token || null;
33
+ }
34
+
35
+ setSession(session) {
36
+ this._session = session || null;
37
+ if (this.persist) {
38
+ try {
39
+ if (session) globalThis.localStorage.setItem(STORAGE_KEY, JSON.stringify(session));
40
+ else globalThis.localStorage.removeItem(STORAGE_KEY);
41
+ } catch {
42
+ // Storage unavailable (e.g. private browsing) - in-memory session still works.
43
+ }
44
+ }
45
+ }
46
+
47
+ clear() {
48
+ this.setSession(null);
49
+ }
50
+ }
51
+
52
+ module.exports = { TokenStore };
@@ -0,0 +1,18 @@
1
+ // AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
2
+ export interface OASISResponse<T = any> {
3
+ isError: boolean;
4
+ message: string | null;
5
+ result: T;
6
+ raw: any;
7
+ statusCode: number;
8
+ }
9
+
10
+ export interface OASISSession {
11
+ avatarId: string;
12
+ username: string;
13
+ email: string;
14
+ firstName?: string;
15
+ lastName?: string;
16
+ jwtToken: string;
17
+ refreshToken?: string;
18
+ }
package/src/index.js ADDED
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ const { HttpClient, DEFAULT_BASE_URL } = require('./core/httpClient');
4
+ const { TokenStore } = require('./core/tokenStore');
5
+ const { attachGeneratedModules } = require('./modules/index');
6
+
7
+ /**
8
+ * Main SDK entry point. Works in Node 18+ and any modern browser.
9
+ *
10
+ * const { Web9Client } = require('@oasisomniverse/web9-api');
11
+ * const web9 = new Web9Client({ baseUrl: 'https://api.web9.oasisomniverse.one' });
12
+ * web9.setToken(jwtToken); // reuse a WEB4 OASIS JWT - WEB9 has no auth of its own
13
+ * const status = await web9.singularity.getUnifiedStatus();
14
+ *
15
+ * The Singularity Layer controller is reachable as `web9.singularity` -
16
+ * a single live unified status probe across WEB4-WEB8. Generated methods
17
+ * take a single args object; remaining keys become the query string
18
+ * (GET/DELETE) or JSON body (POST/PUT).
19
+ */
20
+ class Web9Client {
21
+ constructor({ baseUrl = DEFAULT_BASE_URL, persistSession, fetchImpl } = {}) {
22
+ this.tokenStore = new TokenStore({ persist: persistSession });
23
+ this.http = new HttpClient({ baseUrl, tokenStore: this.tokenStore, fetchImpl });
24
+
25
+ attachGeneratedModules(this, this.http);
26
+ }
27
+
28
+ setBaseUrl(baseUrl) {
29
+ this.http.setBaseUrl(baseUrl);
30
+ }
31
+
32
+ /**
33
+ * WEB9 is an internal aggregation layer sitting behind the same OASIS
34
+ * identity as WEB4-WEB8 - it has no avatar/auth endpoints of its own.
35
+ * Reuse a JWT you already obtained from the WEB4 OASIS API (or your own
36
+ * backend) here.
37
+ */
38
+ setToken(jwtToken, sessionExtras = {}) {
39
+ this.tokenStore.setSession({ ...sessionExtras, jwtToken });
40
+ }
41
+ }
42
+
43
+ module.exports = { Web9Client, HttpClient, TokenStore, DEFAULT_BASE_URL };
44
+ module.exports.default = Web9Client;
@@ -0,0 +1,9 @@
1
+ // AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
2
+ import type { OASISResponse } from '../core/types';
3
+
4
+ export declare class SingularityModule {
5
+ constructor(http: unknown);
6
+
7
+ /** GET v1/singularity/status */
8
+ getUnifiedStatus(args?: Record<string, any>): Promise<OASISResponse>;
9
+ }
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ // AUTO-GENERATED by scripts/generate-modules.js from endpoints.json - do not hand-edit.
4
+ // Regenerate with: node scripts/generate-modules.js
5
+
6
+ const { makeOperation } = require('../core/routeHelper');
7
+
8
+ /**
9
+ * Generated wrapper for v1/singularity (source: WEB9 Singularity WebAPI SingularityController.cs).
10
+ * Every method takes a single args object: path-template tokens (e.g. {id})
11
+ * are consumed from it automatically; any remaining keys are sent as the
12
+ * query string (GET/DELETE) or JSON body (POST/PUT).
13
+ */
14
+ class SingularityModule {
15
+ constructor(http) {
16
+ this._http = http;
17
+
18
+ // GET v1/singularity/status
19
+ this.getUnifiedStatus = makeOperation(http, "v1/singularity", "GET", "status");
20
+ }
21
+ }
22
+
23
+ module.exports = { SingularityModule };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ // AUTO-GENERATED by scripts/generate-modules.js - do not hand-edit.
4
+ const { SingularityModule } = require('./Singularity');
5
+
6
+ /**
7
+ * Attaches every generated module to the client under its lowerCamel controller
8
+ * name (e.g. client.completion, client.images, client.holonicMemory).
9
+ */
10
+ function attachGeneratedModules(client, http) {
11
+ client.singularity = client.singularity || new SingularityModule(http);
12
+ return client;
13
+ }
14
+
15
+ module.exports = { attachGeneratedModules };