@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.
- package/README.md +464 -0
- package/docs/README.md +52 -0
- package/docs/auth.md +89 -0
- package/docs/getting-started.md +129 -0
- package/docs/modules/Avatar.md +4160 -0
- package/docs/modules/Bridge.md +394 -0
- package/docs/modules/Chat.md +168 -0
- package/docs/modules/Clan.md +552 -0
- package/docs/modules/Competition.md +594 -0
- package/docs/modules/Data.md +796 -0
- package/docs/modules/EOSIO.md +508 -0
- package/docs/modules/Eggs.md +396 -0
- package/docs/modules/Files.md +312 -0
- package/docs/modules/Gifts.md +306 -0
- package/docs/modules/Health.md +90 -0
- package/docs/modules/Holochain.md +374 -0
- package/docs/modules/HyperDrive.md +3857 -0
- package/docs/modules/Karma.md +644 -0
- package/docs/modules/Keys.md +3303 -0
- package/docs/modules/Map.md +1026 -0
- package/docs/modules/Messaging.md +320 -0
- package/docs/modules/Nft.md +2216 -0
- package/docs/modules/OLand.md +425 -0
- package/docs/modules/ONET.md +442 -0
- package/docs/modules/ONODE.md +504 -0
- package/docs/modules/Provider.md +1396 -0
- package/docs/modules/Search.md +69 -0
- package/docs/modules/Seeds.md +167 -0
- package/docs/modules/Settings.md +533 -0
- package/docs/modules/Share.md +64 -0
- package/docs/modules/Social.md +190 -0
- package/docs/modules/Solana.md +150 -0
- package/docs/modules/Stats.md +359 -0
- package/docs/modules/Subscription.md +437 -0
- package/docs/modules/Video.md +150 -0
- package/docs/modules/Wallet.md +1993 -0
- package/index.d.ts +106 -0
- package/index.js +3 -0
- package/index.mjs +4 -0
- package/package.json +120 -0
- package/src/core/httpClient.js +110 -0
- package/src/core/routeHelper.js +50 -0
- package/src/core/tokenStore.js +52 -0
- package/src/core/types.d.ts +18 -0
- package/src/index.js +46 -0
- package/src/modules/Auth.d.ts +28 -0
- package/src/modules/Auth.js +98 -0
- package/src/modules/Avatar.d.ts +192 -0
- package/src/modules/Avatar.js +143 -0
- package/src/modules/Bridge.d.ts +24 -0
- package/src/modules/Bridge.js +35 -0
- package/src/modules/Cargo.js +35 -0
- package/src/modules/Chat.d.ts +15 -0
- package/src/modules/Chat.js +27 -0
- package/src/modules/Clan.d.ts +36 -0
- package/src/modules/Clan.js +41 -0
- package/src/modules/Competition.d.ts +33 -0
- package/src/modules/Competition.js +39 -0
- package/src/modules/Core.js +27 -0
- package/src/modules/Data.d.ts +36 -0
- package/src/modules/Data.js +41 -0
- package/src/modules/EOSIO.d.ts +33 -0
- package/src/modules/EOSIO.js +39 -0
- package/src/modules/Eggs.d.ts +24 -0
- package/src/modules/Eggs.js +33 -0
- package/src/modules/Files.d.ts +24 -0
- package/src/modules/Files.js +33 -0
- package/src/modules/Gifts.d.ts +24 -0
- package/src/modules/Gifts.js +33 -0
- package/src/modules/Health.d.ts +12 -0
- package/src/modules/Health.js +25 -0
- package/src/modules/Holochain.d.ts +27 -0
- package/src/modules/Holochain.js +35 -0
- package/src/modules/HyperDrive.d.ts +237 -0
- package/src/modules/HyperDrive.js +175 -0
- package/src/modules/Karma.d.ts +42 -0
- package/src/modules/Karma.js +45 -0
- package/src/modules/Keys.d.ts +183 -0
- package/src/modules/Keys.js +139 -0
- package/src/modules/Map.d.ts +75 -0
- package/src/modules/Map.js +65 -0
- package/src/modules/Messaging.d.ts +24 -0
- package/src/modules/Messaging.js +33 -0
- package/src/modules/Nft.d.ts +102 -0
- package/src/modules/Nft.js +85 -0
- package/src/modules/OAPP.js +31 -0
- package/src/modules/OLand.d.ts +27 -0
- package/src/modules/OLand.js +35 -0
- package/src/modules/ONET.d.ts +39 -0
- package/src/modules/ONET.js +43 -0
- package/src/modules/ONODE.d.ts +45 -0
- package/src/modules/ONODE.js +47 -0
- package/src/modules/Provider.d.ts +99 -0
- package/src/modules/Provider.js +83 -0
- package/src/modules/Search.d.ts +9 -0
- package/src/modules/Search.js +23 -0
- package/src/modules/Seeds.d.ts +15 -0
- package/src/modules/Seeds.js +27 -0
- package/src/modules/Settings.d.ts +48 -0
- package/src/modules/Settings.js +47 -0
- package/src/modules/Share.d.ts +9 -0
- package/src/modules/Share.js +23 -0
- package/src/modules/Social.d.ts +18 -0
- package/src/modules/Social.js +29 -0
- package/src/modules/Solana.d.ts +12 -0
- package/src/modules/Solana.js +25 -0
- package/src/modules/Stats.d.ts +30 -0
- package/src/modules/Stats.js +37 -0
- package/src/modules/Subscription.d.ts +36 -0
- package/src/modules/Subscription.js +41 -0
- package/src/modules/Telos.js +39 -0
- package/src/modules/Video.d.ts +15 -0
- package/src/modules/Video.js +27 -0
- package/src/modules/Wallet.d.ts +102 -0
- package/src/modules/Wallet.js +85 -0
- 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
package/index.mjs
ADDED
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 };
|