@oasisomniverse/web4-api 2.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.
Files changed (116) hide show
  1. package/README.md +464 -0
  2. package/docs/README.md +52 -0
  3. package/docs/auth.md +89 -0
  4. package/docs/getting-started.md +129 -0
  5. package/docs/modules/Avatar.md +4160 -0
  6. package/docs/modules/Bridge.md +394 -0
  7. package/docs/modules/Chat.md +168 -0
  8. package/docs/modules/Clan.md +552 -0
  9. package/docs/modules/Competition.md +594 -0
  10. package/docs/modules/Data.md +796 -0
  11. package/docs/modules/EOSIO.md +508 -0
  12. package/docs/modules/Eggs.md +396 -0
  13. package/docs/modules/Files.md +312 -0
  14. package/docs/modules/Gifts.md +306 -0
  15. package/docs/modules/Health.md +90 -0
  16. package/docs/modules/Holochain.md +374 -0
  17. package/docs/modules/HyperDrive.md +3857 -0
  18. package/docs/modules/Karma.md +644 -0
  19. package/docs/modules/Keys.md +3303 -0
  20. package/docs/modules/Map.md +1026 -0
  21. package/docs/modules/Messaging.md +320 -0
  22. package/docs/modules/Nft.md +2216 -0
  23. package/docs/modules/OLand.md +425 -0
  24. package/docs/modules/ONET.md +442 -0
  25. package/docs/modules/ONODE.md +504 -0
  26. package/docs/modules/Provider.md +1396 -0
  27. package/docs/modules/Search.md +69 -0
  28. package/docs/modules/Seeds.md +167 -0
  29. package/docs/modules/Settings.md +533 -0
  30. package/docs/modules/Share.md +64 -0
  31. package/docs/modules/Social.md +190 -0
  32. package/docs/modules/Solana.md +150 -0
  33. package/docs/modules/Stats.md +359 -0
  34. package/docs/modules/Subscription.md +437 -0
  35. package/docs/modules/Video.md +150 -0
  36. package/docs/modules/Wallet.md +1993 -0
  37. package/index.d.ts +106 -0
  38. package/index.js +3 -0
  39. package/index.mjs +4 -0
  40. package/package.json +120 -0
  41. package/src/core/httpClient.js +110 -0
  42. package/src/core/routeHelper.js +50 -0
  43. package/src/core/tokenStore.js +52 -0
  44. package/src/core/types.d.ts +18 -0
  45. package/src/index.js +46 -0
  46. package/src/modules/Auth.d.ts +28 -0
  47. package/src/modules/Auth.js +98 -0
  48. package/src/modules/Avatar.d.ts +192 -0
  49. package/src/modules/Avatar.js +143 -0
  50. package/src/modules/Bridge.d.ts +24 -0
  51. package/src/modules/Bridge.js +35 -0
  52. package/src/modules/Cargo.js +35 -0
  53. package/src/modules/Chat.d.ts +15 -0
  54. package/src/modules/Chat.js +27 -0
  55. package/src/modules/Clan.d.ts +36 -0
  56. package/src/modules/Clan.js +41 -0
  57. package/src/modules/Competition.d.ts +33 -0
  58. package/src/modules/Competition.js +39 -0
  59. package/src/modules/Core.js +27 -0
  60. package/src/modules/Data.d.ts +36 -0
  61. package/src/modules/Data.js +41 -0
  62. package/src/modules/EOSIO.d.ts +33 -0
  63. package/src/modules/EOSIO.js +39 -0
  64. package/src/modules/Eggs.d.ts +24 -0
  65. package/src/modules/Eggs.js +33 -0
  66. package/src/modules/Files.d.ts +24 -0
  67. package/src/modules/Files.js +33 -0
  68. package/src/modules/Gifts.d.ts +24 -0
  69. package/src/modules/Gifts.js +33 -0
  70. package/src/modules/Health.d.ts +12 -0
  71. package/src/modules/Health.js +25 -0
  72. package/src/modules/Holochain.d.ts +27 -0
  73. package/src/modules/Holochain.js +35 -0
  74. package/src/modules/HyperDrive.d.ts +237 -0
  75. package/src/modules/HyperDrive.js +175 -0
  76. package/src/modules/Karma.d.ts +42 -0
  77. package/src/modules/Karma.js +45 -0
  78. package/src/modules/Keys.d.ts +183 -0
  79. package/src/modules/Keys.js +139 -0
  80. package/src/modules/Map.d.ts +75 -0
  81. package/src/modules/Map.js +65 -0
  82. package/src/modules/Messaging.d.ts +24 -0
  83. package/src/modules/Messaging.js +33 -0
  84. package/src/modules/Nft.d.ts +102 -0
  85. package/src/modules/Nft.js +85 -0
  86. package/src/modules/OAPP.js +31 -0
  87. package/src/modules/OLand.d.ts +27 -0
  88. package/src/modules/OLand.js +35 -0
  89. package/src/modules/ONET.d.ts +39 -0
  90. package/src/modules/ONET.js +43 -0
  91. package/src/modules/ONODE.d.ts +45 -0
  92. package/src/modules/ONODE.js +47 -0
  93. package/src/modules/Provider.d.ts +99 -0
  94. package/src/modules/Provider.js +83 -0
  95. package/src/modules/Search.d.ts +9 -0
  96. package/src/modules/Search.js +23 -0
  97. package/src/modules/Seeds.d.ts +15 -0
  98. package/src/modules/Seeds.js +27 -0
  99. package/src/modules/Settings.d.ts +48 -0
  100. package/src/modules/Settings.js +47 -0
  101. package/src/modules/Share.d.ts +9 -0
  102. package/src/modules/Share.js +23 -0
  103. package/src/modules/Social.d.ts +18 -0
  104. package/src/modules/Social.js +29 -0
  105. package/src/modules/Solana.d.ts +12 -0
  106. package/src/modules/Solana.js +25 -0
  107. package/src/modules/Stats.d.ts +30 -0
  108. package/src/modules/Stats.js +37 -0
  109. package/src/modules/Subscription.d.ts +36 -0
  110. package/src/modules/Subscription.js +41 -0
  111. package/src/modules/Telos.js +39 -0
  112. package/src/modules/Video.d.ts +15 -0
  113. package/src/modules/Video.js +27 -0
  114. package/src/modules/Wallet.d.ts +102 -0
  115. package/src/modules/Wallet.js +85 -0
  116. package/src/modules/index.js +79 -0
package/index.d.ts ADDED
@@ -0,0 +1,106 @@
1
+ // AUTO-GENERATED by scripts/generate-types.js - do not hand-edit.
2
+ import type { OASISResponse, OASISSession } from './src/core/types';
3
+ import type { AuthModule } from './src/modules/Auth';
4
+ import type { AvatarModule } from './src/modules/Avatar';
5
+ import type { BridgeModule } from './src/modules/Bridge';
6
+ import type { ChatModule } from './src/modules/Chat';
7
+ import type { ClanModule } from './src/modules/Clan';
8
+ import type { CompetitionModule } from './src/modules/Competition';
9
+ import type { DataModule } from './src/modules/Data';
10
+ import type { EOSIOModule } from './src/modules/EOSIO';
11
+ import type { EggsModule } from './src/modules/Eggs';
12
+ import type { FilesModule } from './src/modules/Files';
13
+ import type { GiftsModule } from './src/modules/Gifts';
14
+ import type { HealthModule } from './src/modules/Health';
15
+ import type { HolochainModule } from './src/modules/Holochain';
16
+ import type { HyperDriveModule } from './src/modules/HyperDrive';
17
+ import type { KarmaModule } from './src/modules/Karma';
18
+ import type { KeysModule } from './src/modules/Keys';
19
+ import type { MapModule } from './src/modules/Map';
20
+ import type { MessagingModule } from './src/modules/Messaging';
21
+ import type { NftModule } from './src/modules/Nft';
22
+ import type { OLandModule } from './src/modules/OLand';
23
+ import type { ONETModule } from './src/modules/ONET';
24
+ import type { ONODEModule } from './src/modules/ONODE';
25
+ import type { ProviderModule } from './src/modules/Provider';
26
+ import type { SearchModule } from './src/modules/Search';
27
+ import type { SeedsModule } from './src/modules/Seeds';
28
+ import type { SettingsModule } from './src/modules/Settings';
29
+ import type { ShareModule } from './src/modules/Share';
30
+ import type { SocialModule } from './src/modules/Social';
31
+ import type { SolanaModule } from './src/modules/Solana';
32
+ import type { StatsModule } from './src/modules/Stats';
33
+ import type { SubscriptionModule } from './src/modules/Subscription';
34
+ import type { VideoModule } from './src/modules/Video';
35
+ import type { WalletModule } from './src/modules/Wallet';
36
+
37
+ export type { OASISResponse, OASISSession };
38
+
39
+ export interface OASISClientOptions {
40
+ baseUrl?: string;
41
+ persistSession?: boolean;
42
+ fetchImpl?: typeof fetch;
43
+ }
44
+
45
+ export declare class HttpClient {
46
+ constructor(options?: { baseUrl?: string; tokenStore?: unknown; fetchImpl?: typeof fetch });
47
+ setBaseUrl(baseUrl: string): void;
48
+ request(verb: 'GET' | 'POST' | 'PUT' | 'DELETE', path: string, options?: Record<string, any>): Promise<OASISResponse>;
49
+ get(path: string, options?: Record<string, any>): Promise<OASISResponse>;
50
+ post(path: string, options?: Record<string, any>): Promise<OASISResponse>;
51
+ put(path: string, options?: Record<string, any>): Promise<OASISResponse>;
52
+ delete(path: string, options?: Record<string, any>): Promise<OASISResponse>;
53
+ }
54
+
55
+ export declare class TokenStore {
56
+ constructor(options?: { persist?: boolean });
57
+ getSession(): OASISSession | null;
58
+ getToken(): string | null;
59
+ setSession(session: OASISSession | null): void;
60
+ clear(): void;
61
+ }
62
+
63
+ export declare const DEFAULT_BASE_URL: string;
64
+
65
+ export declare class OASISClient {
66
+ constructor(options?: OASISClientOptions);
67
+ readonly http: HttpClient;
68
+ readonly tokenStore: TokenStore;
69
+ readonly auth: AuthModule;
70
+ readonly avatar: AvatarModule;
71
+ readonly bridge: BridgeModule;
72
+ readonly chat: ChatModule;
73
+ readonly clan: ClanModule;
74
+ readonly competition: CompetitionModule;
75
+ readonly data: DataModule;
76
+ readonly eOSIO: EOSIOModule;
77
+ readonly eggs: EggsModule;
78
+ readonly files: FilesModule;
79
+ readonly gifts: GiftsModule;
80
+ readonly health: HealthModule;
81
+ readonly holochain: HolochainModule;
82
+ readonly hyperDrive: HyperDriveModule;
83
+ readonly karma: KarmaModule;
84
+ readonly keys: KeysModule;
85
+ readonly map: MapModule;
86
+ readonly messaging: MessagingModule;
87
+ readonly nft: NftModule;
88
+ readonly oLand: OLandModule;
89
+ readonly oNET: ONETModule;
90
+ readonly oNODE: ONODEModule;
91
+ readonly provider: ProviderModule;
92
+ readonly search: SearchModule;
93
+ readonly seeds: SeedsModule;
94
+ readonly settings: SettingsModule;
95
+ readonly share: ShareModule;
96
+ readonly social: SocialModule;
97
+ readonly solana: SolanaModule;
98
+ readonly stats: StatsModule;
99
+ readonly subscription: SubscriptionModule;
100
+ readonly video: VideoModule;
101
+ readonly wallet: WalletModule;
102
+ setBaseUrl(baseUrl: string): void;
103
+ setToken(jwtToken: string, sessionExtras?: Partial<OASISSession>): void;
104
+ }
105
+
106
+ export default OASISClient;
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 { OASISClient, HttpClient, TokenStore, DEFAULT_BASE_URL } = cjs;
4
+ export default OASISClient;
package/package.json ADDED
@@ -0,0 +1,120 @@
1
+ {
2
+ "name": "@oasisomniverse/web4-api",
3
+ "version": "2.0.0",
4
+ "publishConfig": { "access": "public" },
5
+ "description": "Isomorphic (Node + browser) JavaScript/TypeScript-friendly client for the WEB4 OASIS API - full coverage of the OASIS2 ONODE WebAPI (Avatar, Data, Karma, NFT, Wallet, Map, Search, HyperDrive, and more).",
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-Javascipt-Package.git"
35
+ },
36
+ "homepage": "https://github.com/NextGenSoftwareUK/Our-World-OASIS-API-HoloNET-HoloUnity-And-.NET-HDK#readme",
37
+ "author": "NextGen Software Ltd",
38
+ "license": "MIT",
39
+ "keywords": [
40
+ "OASIS API",
41
+ "Avatar API",
42
+ "Karma API",
43
+ "Data API",
44
+ "SEEDS API",
45
+ "Keys/Wallets API",
46
+ "Providers API",
47
+ "WEB 3",
48
+ "WEB 4",
49
+ "WEB 5",
50
+ "Blockchain",
51
+ "NFT",
52
+ "Tokens",
53
+ "Crypto",
54
+ "Interoperable",
55
+ "Future-Prove",
56
+ "Metaverse",
57
+ "Aggregation",
58
+ "HOT-Swappable-Architecture",
59
+ "P2P",
60
+ "Decentralised",
61
+ "Distributed",
62
+ "Interoprability",
63
+ "Abstraction-Layer",
64
+ "Multi-Network",
65
+ "Multi-Chain",
66
+ "Bridging",
67
+ "Network-Of-Networks",
68
+ "SSO",
69
+ "Auto-FailOver",
70
+ "Auto-LoadBalancing",
71
+ "Auto-Replication",
72
+ "Auto-Sync",
73
+ "Offline-Support",
74
+ "Write-Once-Deploy-Everywhere",
75
+ "Triple-Level-Quantum-Resistant-Encryption",
76
+ "Quantum",
77
+ "Encryption",
78
+ "Smart-Contracts",
79
+ "Intelligent-Key-Management",
80
+ "Zero-Lag",
81
+ "Zero-Downtime",
82
+ "Agent-Centric",
83
+ "Smart-City-Ready",
84
+ "WEB/2D/3D/AR/VR/IR/Map/Meta-Visusalization",
85
+ "Bio-feedback-Ready",
86
+ "IR-(Infinite-Reality)-Ready",
87
+ "Infinite-Players-Online-At-Same-Time",
88
+ "LAN/Bluetooth-Support",
89
+ "AI/Machine-Learning-Over-All-Of-World's-Aggregated-Data",
90
+ "HTTP-REST/gRPC/GraphQL/CLI/Native-Endpoints",
91
+ "Best-Of-All-Worlds",
92
+ "GOD-Protocol/API",
93
+ "Our-World-Geo-Location/AR/IR/Map-UI-(Game-of-Games-Engine)",
94
+ "One-World-Open-World-MMO-(VR)-UI-(Game-of-Games-Engine)",
95
+ "SEEDS",
96
+ "Telos",
97
+ "TRON",
98
+ "Holochain",
99
+ "IPFS",
100
+ "Solana",
101
+ "EOS",
102
+ "Ethereum",
103
+ "MongoDB",
104
+ "Neo4j",
105
+ "SQLLite",
106
+ "ThreeFold",
107
+ "SOLID",
108
+ "ActivityPub",
109
+ "AzureCosmosDB",
110
+ "BlockStack",
111
+ "Chainlink",
112
+ "COSMOS",
113
+ "Elrond",
114
+ "Hashgraph",
115
+ "OrionProtocol",
116
+ "PLAN",
117
+ "Scuttlebutt",
118
+ "More Coming..."
119
+ ]
120
+ }
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ const DEFAULT_BASE_URL = 'https://api.oasisweb4.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 OASIS 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. "api/avatar/authenticate"
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,50 @@
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
+ /**
31
+ * Builds a bound method for a single OASIS endpoint operation.
32
+ * @param {import('./httpClient').HttpClient} http
33
+ * @param {string} routePrefix e.g. "api/avatar"
34
+ * @param {string} verb GET | POST | PUT | DELETE
35
+ * @param {string} route route template relative to routePrefix, e.g. "get-by-id/{id}"
36
+ */
37
+ function makeOperation(http, routePrefix, verb, route) {
38
+ return async function operation(args = {}) {
39
+ const { path, rest } = resolveRoute(route, args);
40
+ const fullPath = path ? `${routePrefix}/${path}` : routePrefix;
41
+ const hasBody = Object.keys(rest).length > 0;
42
+
43
+ if (verb === 'GET') {
44
+ return http.get(fullPath, { query: hasBody ? rest : undefined });
45
+ }
46
+ return http.request(verb, fullPath, { body: hasBody ? rest : undefined });
47
+ };
48
+ }
49
+
50
+ 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,46 @@
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
+ const { AuthModule } = require('./modules/Auth');
7
+
8
+ /**
9
+ * Main SDK entry point. Works in Node 18+ and any modern browser.
10
+ *
11
+ * const { OASISClient } = require('@oasisomniverse/web4-api');
12
+ * const oasis = new OASISClient({ baseUrl: 'https://api.oasisweb4.one' });
13
+ * await oasis.auth.login({ username: 'me@example.com', password: '...' });
14
+ * const karma = await oasis.karma.getKarmaForAvatar({ avatarId: oasis.auth.getSession().avatarId });
15
+ *
16
+ * Every controller on the OASIS2 ONODE WebAPI is reachable as a lowerCamel
17
+ * property (oasis.avatar, oasis.data, oasis.karma, oasis.nft, oasis.wallet,
18
+ * oasis.hyperDrive, oasis.map, oasis.search, ...). Generated methods take a
19
+ * single args object; route template tokens (e.g. {id}) are consumed from it
20
+ * automatically, remaining keys become the query string (GET/DELETE) or JSON
21
+ * body (POST/PUT). oasis.auth is a hand-written convenience wrapper that also
22
+ * manages the session/token for you.
23
+ */
24
+ class OASISClient {
25
+ constructor({ baseUrl = DEFAULT_BASE_URL, persistSession, fetchImpl } = {}) {
26
+ this.tokenStore = new TokenStore({ persist: persistSession });
27
+ this.http = new HttpClient({ baseUrl, tokenStore: this.tokenStore, fetchImpl });
28
+
29
+ attachGeneratedModules(this, this.http);
30
+
31
+ // Hand-written ergonomic wrapper, built on top of the generated avatar module.
32
+ this.auth = new AuthModule(this.http, this.tokenStore, this.avatar);
33
+ }
34
+
35
+ setBaseUrl(baseUrl) {
36
+ this.http.setBaseUrl(baseUrl);
37
+ }
38
+
39
+ /** Use an externally-issued JWT (e.g. one your server already obtained) for subsequent calls. */
40
+ setToken(jwtToken, sessionExtras = {}) {
41
+ this.tokenStore.setSession({ ...sessionExtras, jwtToken });
42
+ }
43
+ }
44
+
45
+ module.exports = { OASISClient, HttpClient, TokenStore, DEFAULT_BASE_URL };
46
+ module.exports.default = OASISClient;
@@ -0,0 +1,28 @@
1
+ // Hand-written type declaration for src/modules/Auth.js
2
+ import type { OASISResponse, OASISSession } from '../core/types';
3
+
4
+ export interface LoginCredentials {
5
+ username: string;
6
+ password: string;
7
+ }
8
+
9
+ export interface RegisterData {
10
+ firstName: string;
11
+ lastName: string;
12
+ email: string;
13
+ password: string;
14
+ confirmPassword?: string;
15
+ username?: string;
16
+ avatarType?: string;
17
+ title?: string;
18
+ acceptTerms?: boolean;
19
+ }
20
+
21
+ export declare class AuthModule {
22
+ constructor(http: unknown, tokenStore: unknown, avatarModule: unknown);
23
+ getSession(): OASISSession | null;
24
+ isAuthenticated(): boolean;
25
+ login(credentials: LoginCredentials): Promise<OASISResponse & { session?: OASISSession }>;
26
+ register(data: RegisterData): Promise<OASISResponse & { session?: OASISSession }>;
27
+ logout(): Promise<void>;
28
+ }
@@ -0,0 +1,98 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Hand-written ergonomic auth wrapper. Built on top of the generated
5
+ * AvatarModule (api/avatar/authenticate, /register, /revoke-token) and
6
+ * manages the SDK's TokenStore automatically on login/logout - this is
7
+ * the one place callers don't have to think about JWTs themselves.
8
+ */
9
+ class AuthModule {
10
+ constructor(http, tokenStore, avatarModule) {
11
+ this._http = http;
12
+ this._tokenStore = tokenStore;
13
+ this._avatar = avatarModule;
14
+ }
15
+
16
+ /** Returns the currently stored session ({ avatarId, username, email, jwtToken, ... }) or null. */
17
+ getSession() {
18
+ return this._tokenStore.getSession();
19
+ }
20
+
21
+ isAuthenticated() {
22
+ return Boolean(this._tokenStore.getToken());
23
+ }
24
+
25
+ /**
26
+ * @param {{username: string, password: string}} credentials `username` may also be an email,
27
+ * OASIS' authenticate endpoint accepts either.
28
+ */
29
+ async login({ username, password }) {
30
+ const res = await this._avatar.authenticate({ Username: username, Password: password });
31
+ if (res.isError || !res.result) return res;
32
+
33
+ const avatar = res.result;
34
+ const session = {
35
+ avatarId: avatar.id || avatar.Id,
36
+ username: avatar.username || avatar.Username || username,
37
+ email: avatar.email || avatar.Email,
38
+ firstName: avatar.firstName || avatar.FirstName,
39
+ lastName: avatar.lastName || avatar.LastName,
40
+ jwtToken: avatar.jwtToken || avatar.JwtToken,
41
+ refreshToken: avatar.refreshToken || avatar.RefreshToken
42
+ };
43
+
44
+ if (!session.jwtToken) {
45
+ return { isError: true, message: 'Authentication succeeded but no JWT token was returned.', raw: res.raw };
46
+ }
47
+
48
+ this._tokenStore.setSession(session);
49
+ return { ...res, session };
50
+ }
51
+
52
+ /**
53
+ * @param {object} data title, firstName, lastName, email, password, confirmPassword, avatarType, username (optional)
54
+ */
55
+ async register(data) {
56
+ const res = await this._avatar.register({
57
+ Title: data.title || 'Mx',
58
+ FirstName: data.firstName,
59
+ LastName: data.lastName,
60
+ Email: data.email,
61
+ Password: data.password,
62
+ ConfirmPassword: data.confirmPassword || data.password,
63
+ Username: data.username || data.email,
64
+ AvatarType: data.avatarType || 'User',
65
+ AcceptTerms: data.acceptTerms !== false
66
+ });
67
+
68
+ if (res.isError || !res.result) return res;
69
+
70
+ const avatar = res.result;
71
+ const session = {
72
+ avatarId: avatar.id || avatar.Id,
73
+ username: avatar.username || avatar.Username,
74
+ email: avatar.email || avatar.Email,
75
+ firstName: avatar.firstName || avatar.FirstName,
76
+ lastName: avatar.lastName || avatar.LastName,
77
+ jwtToken: avatar.jwtToken || avatar.JwtToken,
78
+ refreshToken: avatar.refreshToken || avatar.RefreshToken
79
+ };
80
+
81
+ if (session.jwtToken) this._tokenStore.setSession(session);
82
+ return { ...res, session };
83
+ }
84
+
85
+ async logout() {
86
+ const token = this._tokenStore.getToken();
87
+ if (token) {
88
+ try {
89
+ await this._avatar.revokeToken({ Token: token });
90
+ } catch {
91
+ // Best-effort - always clear the local session regardless of server response.
92
+ }
93
+ }
94
+ this._tokenStore.clear();
95
+ }
96
+ }
97
+
98
+ module.exports = { AuthModule };