@fzgame/sdk 0.0.0-stage → 0.3.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.
- package/LICENSE +15 -0
- package/README.md +248 -2
- package/dist/index.d.mts +1381 -0
- package/dist/index.d.ts +1381 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +100 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +11 -0
- package/dist/react.d.ts +11 -0
- package/dist/react.js +117 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +83 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +91 -4
package/dist/index.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
APP_KEY_HEADER: () => APP_KEY_HEADER,
|
|
34
|
+
APP_SECRET_HEADER: () => APP_SECRET_HEADER,
|
|
35
|
+
SdkConfigError: () => SdkConfigError,
|
|
36
|
+
SdkNotInitializedError: () => SdkNotInitializedError,
|
|
37
|
+
createSdkClient: () => createSdkClient,
|
|
38
|
+
fetchClient: () => fetchClient,
|
|
39
|
+
initializeSDK: () => initializeSDK,
|
|
40
|
+
resolveGameURL: () => resolveGameURL
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(src_exports);
|
|
43
|
+
|
|
44
|
+
// src/sdk.ts
|
|
45
|
+
var import_openapi_fetch = __toESM(require("openapi-fetch"));
|
|
46
|
+
var APP_KEY_HEADER = "x-app-key";
|
|
47
|
+
var APP_SECRET_HEADER = "x-app-secret";
|
|
48
|
+
var SdkNotInitializedError = class extends Error {
|
|
49
|
+
constructor() {
|
|
50
|
+
super("Call initializeSDK() or createSdkClient() before the first request");
|
|
51
|
+
this.name = "SdkNotInitializedError";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var SdkConfigError = class extends Error {
|
|
55
|
+
constructor(message) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = "SdkConfigError";
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
function resolveApiUrl(apiUrl) {
|
|
61
|
+
const trimmed = (apiUrl ?? "").trim().replace(/\/+$/, "");
|
|
62
|
+
if (!trimmed) {
|
|
63
|
+
throw new SdkConfigError("apiUrl is required, for example https://api.example.com");
|
|
64
|
+
}
|
|
65
|
+
return trimmed;
|
|
66
|
+
}
|
|
67
|
+
function withTimeout(fetchImpl, timeoutMs) {
|
|
68
|
+
const base = fetchImpl ?? globalThis.fetch;
|
|
69
|
+
if (!timeoutMs || timeoutMs <= 0) return base;
|
|
70
|
+
return (input, init) => {
|
|
71
|
+
const caller = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
72
|
+
const deadline = AbortSignal.timeout(timeoutMs);
|
|
73
|
+
return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline });
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function authMiddleware({ appKey, appSecret }) {
|
|
77
|
+
return {
|
|
78
|
+
async onRequest({ request }) {
|
|
79
|
+
if (!appKey && !appSecret) return request;
|
|
80
|
+
const next = new Request(request);
|
|
81
|
+
if (appKey) next.headers.set(APP_KEY_HEADER, appKey);
|
|
82
|
+
if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret);
|
|
83
|
+
return next;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function createSdkClient(options) {
|
|
88
|
+
const client = (0, import_openapi_fetch.default)({
|
|
89
|
+
baseUrl: resolveApiUrl(options.apiUrl),
|
|
90
|
+
fetch: withTimeout(options.fetch, options.timeoutMs)
|
|
91
|
+
});
|
|
92
|
+
client.use(authMiddleware(options));
|
|
93
|
+
return client;
|
|
94
|
+
}
|
|
95
|
+
var active = null;
|
|
96
|
+
var activeApiUrl = null;
|
|
97
|
+
var fetchClient = new Proxy({}, {
|
|
98
|
+
get(_target, property) {
|
|
99
|
+
if (typeof property === "symbol") return void 0;
|
|
100
|
+
if (!active) throw new SdkNotInitializedError();
|
|
101
|
+
const value = active[property];
|
|
102
|
+
return typeof value === "function" ? value.bind(active) : value;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
function initializeSDK(options) {
|
|
106
|
+
activeApiUrl = resolveApiUrl(options.apiUrl);
|
|
107
|
+
active = createSdkClient(options);
|
|
108
|
+
return active;
|
|
109
|
+
}
|
|
110
|
+
function resolveGameURL(gameInstance, playerAccessToken, options = {}) {
|
|
111
|
+
const entryPoint = gameInstance?.resolvedUrl;
|
|
112
|
+
if (!entryPoint) {
|
|
113
|
+
throw new SdkConfigError("gameInstance.resolvedUrl is required to build a play URL");
|
|
114
|
+
}
|
|
115
|
+
const token = playerAccessToken?.trim();
|
|
116
|
+
if (!token) {
|
|
117
|
+
throw new SdkConfigError("playerAccessToken is required");
|
|
118
|
+
}
|
|
119
|
+
const apiUrl = options.apiUrl?.trim() || activeApiUrl;
|
|
120
|
+
if (!apiUrl) {
|
|
121
|
+
throw new SdkConfigError("apiUrl is required: call initializeSDK() first, or pass { apiUrl }");
|
|
122
|
+
}
|
|
123
|
+
const url = new URL(entryPoint);
|
|
124
|
+
url.searchParams.set("apiUrl", resolveApiUrl(apiUrl));
|
|
125
|
+
url.searchParams.set("gameInstanceId", gameInstance.id);
|
|
126
|
+
url.searchParams.set("playerAccessToken", token);
|
|
127
|
+
const config = options.config ?? gameInstance.overrides;
|
|
128
|
+
if (config && Object.keys(config).length) {
|
|
129
|
+
url.searchParams.set("gameSetting", JSON.stringify(config));
|
|
130
|
+
}
|
|
131
|
+
return url.toString();
|
|
132
|
+
}
|
|
133
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
134
|
+
0 && (module.exports = {
|
|
135
|
+
APP_KEY_HEADER,
|
|
136
|
+
APP_SECRET_HEADER,
|
|
137
|
+
SdkConfigError,
|
|
138
|
+
SdkNotInitializedError,
|
|
139
|
+
createSdkClient,
|
|
140
|
+
fetchClient,
|
|
141
|
+
initializeSDK,
|
|
142
|
+
resolveGameURL
|
|
143
|
+
});
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/sdk.ts"],"sourcesContent":["export {\n APP_KEY_HEADER,\n APP_SECRET_HEADER,\n SdkConfigError,\n SdkNotInitializedError,\n createSdkClient,\n fetchClient,\n initializeSDK,\n resolveGameURL,\n} from './sdk'\nexport type { GameInstance, InitOptions, ResolveGameUrlOptions } from './sdk'\nexport type { components, operations, paths } from './types/schema'\n","import createClient, { type Client, type Middleware } from 'openapi-fetch'\n\nimport type { components, paths } from './types/schema'\n\n/** Header names the server reads app credentials from (`apps/server/src/auth/auth.guard.ts`). */\nexport const APP_KEY_HEADER = 'x-app-key'\nexport const APP_SECRET_HEADER = 'x-app-secret'\n\nexport type InitOptions = {\n /** Base URL of the API, without a trailing slash. */\n apiUrl: string\n /** Sent as `x-app-key`: the app's `id`, which the auth guard looks the app up by. */\n appKey?: string\n /** Sent as `x-app-secret`: one of the app's credential `clientSecret` values. */\n appSecret?: string\n /** Abort a request after this many milliseconds. `0` or unset means no timeout. */\n timeoutMs?: number\n /** Override the fetch implementation, for a Node polyfill or a test. */\n fetch?: typeof globalThis.fetch\n}\n\n/** Thrown when a request is made before any credentials were configured. */\nexport class SdkNotInitializedError extends Error {\n constructor() {\n super('Call initializeSDK() or createSdkClient() before the first request')\n this.name = 'SdkNotInitializedError'\n }\n}\n\nexport class SdkConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SdkConfigError'\n }\n}\n\nfunction resolveApiUrl(apiUrl: string | undefined): string {\n const trimmed = (apiUrl ?? '').trim().replace(/\\/+$/, '')\n if (!trimmed) {\n throw new SdkConfigError('apiUrl is required, for example https://api.example.com')\n }\n return trimmed\n}\n\nfunction withTimeout(\n fetchImpl: typeof globalThis.fetch | undefined,\n timeoutMs: number | undefined,\n): typeof globalThis.fetch {\n const base = fetchImpl ?? globalThis.fetch\n if (!timeoutMs || timeoutMs <= 0) return base\n return (input, init) => {\n // openapi-fetch calls fetch(request) with no init and folds the caller's\n // signal into the request, so look both places before combining.\n const caller = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const deadline = AbortSignal.timeout(timeoutMs)\n // `any` keeps the caller's cancellation working: the deadline must not\n // replace a signal the caller uses for reasons of its own.\n return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline })\n }\n}\n\n/**\n * App credentials travel in headers, not in the generated document: the server's\n * OpenAPI spec declares `securitySchemes: {}`, so nothing is typed for this and\n * the client has to attach them.\n */\nfunction authMiddleware({ appKey, appSecret }: InitOptions): Middleware {\n return {\n async onRequest({ request }) {\n if (!appKey && !appSecret) return request\n // A fresh Request owns mutable headers, unlike a request handed to a guarded fetch.\n const next = new Request(request)\n if (appKey) next.headers.set(APP_KEY_HEADER, appKey)\n if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret)\n return next\n },\n }\n}\n\n/**\n * A client with its own base URL and credentials. Use this when a process serves\n * more than one app: each client is independent, so one tenant's configuration\n * cannot overwrite another's.\n */\nexport function createSdkClient(options: InitOptions): Client<paths> {\n const client = createClient<paths>({\n baseUrl: resolveApiUrl(options.apiUrl),\n fetch: withTimeout(options.fetch, options.timeoutMs),\n })\n client.use(authMiddleware(options))\n return client\n}\n\nlet active: Client<paths> | null = null\n/** The `apiUrl` of the process-wide client, so `resolveGameURL` can reuse it. */\nlet activeApiUrl: string | null = null\n\n/**\n * Process-wide client configured by `initializeSDK` or `<SDKInitializer>`.\n *\n * Before the first initialization every access throws `SdkNotInitializedError`,\n * so a mis-ordered import fails where it happens instead of sending a request to\n * a placeholder origin.\n */\nexport const fetchClient: Client<paths> = new Proxy({} as Client<paths>, {\n get(_target, property) {\n if (typeof property === 'symbol') return undefined\n if (!active) throw new SdkNotInitializedError()\n const value = (active as unknown as Record<string, unknown>)[property]\n return typeof value === 'function'\n ? (value as (...args: unknown[]) => unknown).bind(active)\n : value\n },\n})\n\n/** Configure the process-wide client and return it. */\nexport function initializeSDK(options: InitOptions): Client<paths> {\n activeApiUrl = resolveApiUrl(options.apiUrl)\n active = createSdkClient(options)\n return active\n}\n\n/** A game instance from `GET /sdk/game-instances`, as generated from the OpenAPI document. */\nexport type GameInstance = components['schemas']['AppGameInstance']\n\nexport type ResolveGameUrlOptions = {\n /** API base URL the frame calls. Defaults to the `apiUrl` passed to `initializeSDK`. */\n apiUrl?: string\n /** Config to hand the game as `gameSetting`. Defaults to the instance overrides. */\n config?: Record<string, unknown> | null\n}\n\n/**\n * Build the URL the host loads in an iframe or webview from the game instance\n * and the token `POST /sdk/login` returned. It appends `apiUrl`,\n * `gameInstanceId`, `playerAccessToken`, and `gameSetting`.\n *\n * `apiUrl` defaults to the one given to `initializeSDK`. A caller that uses\n * `createSdkClient` instead must pass `{ apiUrl }`, because that client is not\n * the process-wide one.\n */\nexport function resolveGameURL(\n gameInstance: GameInstance,\n playerAccessToken: string,\n options: ResolveGameUrlOptions = {},\n): string {\n const entryPoint = gameInstance?.resolvedUrl\n if (!entryPoint) {\n throw new SdkConfigError('gameInstance.resolvedUrl is required to build a play URL')\n }\n const token = playerAccessToken?.trim()\n if (!token) {\n throw new SdkConfigError('playerAccessToken is required')\n }\n const apiUrl = options.apiUrl?.trim() || activeApiUrl\n if (!apiUrl) {\n throw new SdkConfigError('apiUrl is required: call initializeSDK() first, or pass { apiUrl }')\n }\n\n const url = new URL(entryPoint)\n url.searchParams.set('apiUrl', resolveApiUrl(apiUrl))\n url.searchParams.set('gameInstanceId', gameInstance.id)\n url.searchParams.set('playerAccessToken', token)\n\n const config = options.config ?? gameInstance.overrides\n if (config && Object.keys(config).length) {\n url.searchParams.set('gameSetting', JSON.stringify(config))\n }\n return url.toString()\n}\n"],"mappings":"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","names":["createClient"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// src/sdk.ts
|
|
2
|
+
import createClient from "openapi-fetch";
|
|
3
|
+
var APP_KEY_HEADER = "x-app-key";
|
|
4
|
+
var APP_SECRET_HEADER = "x-app-secret";
|
|
5
|
+
var SdkNotInitializedError = class extends Error {
|
|
6
|
+
constructor() {
|
|
7
|
+
super("Call initializeSDK() or createSdkClient() before the first request");
|
|
8
|
+
this.name = "SdkNotInitializedError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var SdkConfigError = class extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "SdkConfigError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
function resolveApiUrl(apiUrl) {
|
|
18
|
+
const trimmed = (apiUrl ?? "").trim().replace(/\/+$/, "");
|
|
19
|
+
if (!trimmed) {
|
|
20
|
+
throw new SdkConfigError("apiUrl is required, for example https://api.example.com");
|
|
21
|
+
}
|
|
22
|
+
return trimmed;
|
|
23
|
+
}
|
|
24
|
+
function withTimeout(fetchImpl, timeoutMs) {
|
|
25
|
+
const base = fetchImpl ?? globalThis.fetch;
|
|
26
|
+
if (!timeoutMs || timeoutMs <= 0) return base;
|
|
27
|
+
return (input, init) => {
|
|
28
|
+
const caller = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
29
|
+
const deadline = AbortSignal.timeout(timeoutMs);
|
|
30
|
+
return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline });
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function authMiddleware({ appKey, appSecret }) {
|
|
34
|
+
return {
|
|
35
|
+
async onRequest({ request }) {
|
|
36
|
+
if (!appKey && !appSecret) return request;
|
|
37
|
+
const next = new Request(request);
|
|
38
|
+
if (appKey) next.headers.set(APP_KEY_HEADER, appKey);
|
|
39
|
+
if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret);
|
|
40
|
+
return next;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function createSdkClient(options) {
|
|
45
|
+
const client = createClient({
|
|
46
|
+
baseUrl: resolveApiUrl(options.apiUrl),
|
|
47
|
+
fetch: withTimeout(options.fetch, options.timeoutMs)
|
|
48
|
+
});
|
|
49
|
+
client.use(authMiddleware(options));
|
|
50
|
+
return client;
|
|
51
|
+
}
|
|
52
|
+
var active = null;
|
|
53
|
+
var activeApiUrl = null;
|
|
54
|
+
var fetchClient = new Proxy({}, {
|
|
55
|
+
get(_target, property) {
|
|
56
|
+
if (typeof property === "symbol") return void 0;
|
|
57
|
+
if (!active) throw new SdkNotInitializedError();
|
|
58
|
+
const value = active[property];
|
|
59
|
+
return typeof value === "function" ? value.bind(active) : value;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
function initializeSDK(options) {
|
|
63
|
+
activeApiUrl = resolveApiUrl(options.apiUrl);
|
|
64
|
+
active = createSdkClient(options);
|
|
65
|
+
return active;
|
|
66
|
+
}
|
|
67
|
+
function resolveGameURL(gameInstance, playerAccessToken, options = {}) {
|
|
68
|
+
const entryPoint = gameInstance?.resolvedUrl;
|
|
69
|
+
if (!entryPoint) {
|
|
70
|
+
throw new SdkConfigError("gameInstance.resolvedUrl is required to build a play URL");
|
|
71
|
+
}
|
|
72
|
+
const token = playerAccessToken?.trim();
|
|
73
|
+
if (!token) {
|
|
74
|
+
throw new SdkConfigError("playerAccessToken is required");
|
|
75
|
+
}
|
|
76
|
+
const apiUrl = options.apiUrl?.trim() || activeApiUrl;
|
|
77
|
+
if (!apiUrl) {
|
|
78
|
+
throw new SdkConfigError("apiUrl is required: call initializeSDK() first, or pass { apiUrl }");
|
|
79
|
+
}
|
|
80
|
+
const url = new URL(entryPoint);
|
|
81
|
+
url.searchParams.set("apiUrl", resolveApiUrl(apiUrl));
|
|
82
|
+
url.searchParams.set("gameInstanceId", gameInstance.id);
|
|
83
|
+
url.searchParams.set("playerAccessToken", token);
|
|
84
|
+
const config = options.config ?? gameInstance.overrides;
|
|
85
|
+
if (config && Object.keys(config).length) {
|
|
86
|
+
url.searchParams.set("gameSetting", JSON.stringify(config));
|
|
87
|
+
}
|
|
88
|
+
return url.toString();
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
APP_KEY_HEADER,
|
|
92
|
+
APP_SECRET_HEADER,
|
|
93
|
+
SdkConfigError,
|
|
94
|
+
SdkNotInitializedError,
|
|
95
|
+
createSdkClient,
|
|
96
|
+
fetchClient,
|
|
97
|
+
initializeSDK,
|
|
98
|
+
resolveGameURL
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sdk.ts"],"sourcesContent":["import createClient, { type Client, type Middleware } from 'openapi-fetch'\n\nimport type { components, paths } from './types/schema'\n\n/** Header names the server reads app credentials from (`apps/server/src/auth/auth.guard.ts`). */\nexport const APP_KEY_HEADER = 'x-app-key'\nexport const APP_SECRET_HEADER = 'x-app-secret'\n\nexport type InitOptions = {\n /** Base URL of the API, without a trailing slash. */\n apiUrl: string\n /** Sent as `x-app-key`: the app's `id`, which the auth guard looks the app up by. */\n appKey?: string\n /** Sent as `x-app-secret`: one of the app's credential `clientSecret` values. */\n appSecret?: string\n /** Abort a request after this many milliseconds. `0` or unset means no timeout. */\n timeoutMs?: number\n /** Override the fetch implementation, for a Node polyfill or a test. */\n fetch?: typeof globalThis.fetch\n}\n\n/** Thrown when a request is made before any credentials were configured. */\nexport class SdkNotInitializedError extends Error {\n constructor() {\n super('Call initializeSDK() or createSdkClient() before the first request')\n this.name = 'SdkNotInitializedError'\n }\n}\n\nexport class SdkConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SdkConfigError'\n }\n}\n\nfunction resolveApiUrl(apiUrl: string | undefined): string {\n const trimmed = (apiUrl ?? '').trim().replace(/\\/+$/, '')\n if (!trimmed) {\n throw new SdkConfigError('apiUrl is required, for example https://api.example.com')\n }\n return trimmed\n}\n\nfunction withTimeout(\n fetchImpl: typeof globalThis.fetch | undefined,\n timeoutMs: number | undefined,\n): typeof globalThis.fetch {\n const base = fetchImpl ?? globalThis.fetch\n if (!timeoutMs || timeoutMs <= 0) return base\n return (input, init) => {\n // openapi-fetch calls fetch(request) with no init and folds the caller's\n // signal into the request, so look both places before combining.\n const caller = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const deadline = AbortSignal.timeout(timeoutMs)\n // `any` keeps the caller's cancellation working: the deadline must not\n // replace a signal the caller uses for reasons of its own.\n return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline })\n }\n}\n\n/**\n * App credentials travel in headers, not in the generated document: the server's\n * OpenAPI spec declares `securitySchemes: {}`, so nothing is typed for this and\n * the client has to attach them.\n */\nfunction authMiddleware({ appKey, appSecret }: InitOptions): Middleware {\n return {\n async onRequest({ request }) {\n if (!appKey && !appSecret) return request\n // A fresh Request owns mutable headers, unlike a request handed to a guarded fetch.\n const next = new Request(request)\n if (appKey) next.headers.set(APP_KEY_HEADER, appKey)\n if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret)\n return next\n },\n }\n}\n\n/**\n * A client with its own base URL and credentials. Use this when a process serves\n * more than one app: each client is independent, so one tenant's configuration\n * cannot overwrite another's.\n */\nexport function createSdkClient(options: InitOptions): Client<paths> {\n const client = createClient<paths>({\n baseUrl: resolveApiUrl(options.apiUrl),\n fetch: withTimeout(options.fetch, options.timeoutMs),\n })\n client.use(authMiddleware(options))\n return client\n}\n\nlet active: Client<paths> | null = null\n/** The `apiUrl` of the process-wide client, so `resolveGameURL` can reuse it. */\nlet activeApiUrl: string | null = null\n\n/**\n * Process-wide client configured by `initializeSDK` or `<SDKInitializer>`.\n *\n * Before the first initialization every access throws `SdkNotInitializedError`,\n * so a mis-ordered import fails where it happens instead of sending a request to\n * a placeholder origin.\n */\nexport const fetchClient: Client<paths> = new Proxy({} as Client<paths>, {\n get(_target, property) {\n if (typeof property === 'symbol') return undefined\n if (!active) throw new SdkNotInitializedError()\n const value = (active as unknown as Record<string, unknown>)[property]\n return typeof value === 'function'\n ? (value as (...args: unknown[]) => unknown).bind(active)\n : value\n },\n})\n\n/** Configure the process-wide client and return it. */\nexport function initializeSDK(options: InitOptions): Client<paths> {\n activeApiUrl = resolveApiUrl(options.apiUrl)\n active = createSdkClient(options)\n return active\n}\n\n/** A game instance from `GET /sdk/game-instances`, as generated from the OpenAPI document. */\nexport type GameInstance = components['schemas']['AppGameInstance']\n\nexport type ResolveGameUrlOptions = {\n /** API base URL the frame calls. Defaults to the `apiUrl` passed to `initializeSDK`. */\n apiUrl?: string\n /** Config to hand the game as `gameSetting`. Defaults to the instance overrides. */\n config?: Record<string, unknown> | null\n}\n\n/**\n * Build the URL the host loads in an iframe or webview from the game instance\n * and the token `POST /sdk/login` returned. It appends `apiUrl`,\n * `gameInstanceId`, `playerAccessToken`, and `gameSetting`.\n *\n * `apiUrl` defaults to the one given to `initializeSDK`. A caller that uses\n * `createSdkClient` instead must pass `{ apiUrl }`, because that client is not\n * the process-wide one.\n */\nexport function resolveGameURL(\n gameInstance: GameInstance,\n playerAccessToken: string,\n options: ResolveGameUrlOptions = {},\n): string {\n const entryPoint = gameInstance?.resolvedUrl\n if (!entryPoint) {\n throw new SdkConfigError('gameInstance.resolvedUrl is required to build a play URL')\n }\n const token = playerAccessToken?.trim()\n if (!token) {\n throw new SdkConfigError('playerAccessToken is required')\n }\n const apiUrl = options.apiUrl?.trim() || activeApiUrl\n if (!apiUrl) {\n throw new SdkConfigError('apiUrl is required: call initializeSDK() first, or pass { apiUrl }')\n }\n\n const url = new URL(entryPoint)\n url.searchParams.set('apiUrl', resolveApiUrl(apiUrl))\n url.searchParams.set('gameInstanceId', gameInstance.id)\n url.searchParams.set('playerAccessToken', token)\n\n const config = options.config ?? gameInstance.overrides\n if (config && Object.keys(config).length) {\n url.searchParams.set('gameSetting', JSON.stringify(config))\n }\n return url.toString()\n}\n"],"mappings":"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","names":[]}
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InitOptions } from './index.mjs';
|
|
2
|
+
import 'openapi-fetch';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configures the process-wide client from React. The effect depends on each
|
|
6
|
+
* value, so a rotated secret or a tenant switch takes effect instead of being
|
|
7
|
+
* dropped after the first render.
|
|
8
|
+
*/
|
|
9
|
+
declare function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }: InitOptions): null;
|
|
10
|
+
|
|
11
|
+
export { SDKInitializer };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InitOptions } from './index.js';
|
|
2
|
+
import 'openapi-fetch';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configures the process-wide client from React. The effect depends on each
|
|
6
|
+
* value, so a rotated secret or a tenant switch takes effect instead of being
|
|
7
|
+
* dropped after the first render.
|
|
8
|
+
*/
|
|
9
|
+
declare function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }: InitOptions): null;
|
|
10
|
+
|
|
11
|
+
export { SDKInitializer };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/react.tsx
|
|
32
|
+
var react_exports = {};
|
|
33
|
+
__export(react_exports, {
|
|
34
|
+
SDKInitializer: () => SDKInitializer
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(react_exports);
|
|
37
|
+
var import_react = require("react");
|
|
38
|
+
|
|
39
|
+
// src/sdk.ts
|
|
40
|
+
var import_openapi_fetch = __toESM(require("openapi-fetch"));
|
|
41
|
+
var APP_KEY_HEADER = "x-app-key";
|
|
42
|
+
var APP_SECRET_HEADER = "x-app-secret";
|
|
43
|
+
var SdkNotInitializedError = class extends Error {
|
|
44
|
+
constructor() {
|
|
45
|
+
super("Call initializeSDK() or createSdkClient() before the first request");
|
|
46
|
+
this.name = "SdkNotInitializedError";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var SdkConfigError = class extends Error {
|
|
50
|
+
constructor(message) {
|
|
51
|
+
super(message);
|
|
52
|
+
this.name = "SdkConfigError";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
function resolveApiUrl(apiUrl) {
|
|
56
|
+
const trimmed = (apiUrl ?? "").trim().replace(/\/+$/, "");
|
|
57
|
+
if (!trimmed) {
|
|
58
|
+
throw new SdkConfigError("apiUrl is required, for example https://api.example.com");
|
|
59
|
+
}
|
|
60
|
+
return trimmed;
|
|
61
|
+
}
|
|
62
|
+
function withTimeout(fetchImpl, timeoutMs) {
|
|
63
|
+
const base = fetchImpl ?? globalThis.fetch;
|
|
64
|
+
if (!timeoutMs || timeoutMs <= 0) return base;
|
|
65
|
+
return (input, init) => {
|
|
66
|
+
const caller = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
67
|
+
const deadline = AbortSignal.timeout(timeoutMs);
|
|
68
|
+
return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline });
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function authMiddleware({ appKey, appSecret }) {
|
|
72
|
+
return {
|
|
73
|
+
async onRequest({ request }) {
|
|
74
|
+
if (!appKey && !appSecret) return request;
|
|
75
|
+
const next = new Request(request);
|
|
76
|
+
if (appKey) next.headers.set(APP_KEY_HEADER, appKey);
|
|
77
|
+
if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret);
|
|
78
|
+
return next;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function createSdkClient(options) {
|
|
83
|
+
const client = (0, import_openapi_fetch.default)({
|
|
84
|
+
baseUrl: resolveApiUrl(options.apiUrl),
|
|
85
|
+
fetch: withTimeout(options.fetch, options.timeoutMs)
|
|
86
|
+
});
|
|
87
|
+
client.use(authMiddleware(options));
|
|
88
|
+
return client;
|
|
89
|
+
}
|
|
90
|
+
var active = null;
|
|
91
|
+
var activeApiUrl = null;
|
|
92
|
+
var fetchClient = new Proxy({}, {
|
|
93
|
+
get(_target, property) {
|
|
94
|
+
if (typeof property === "symbol") return void 0;
|
|
95
|
+
if (!active) throw new SdkNotInitializedError();
|
|
96
|
+
const value = active[property];
|
|
97
|
+
return typeof value === "function" ? value.bind(active) : value;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
function initializeSDK(options) {
|
|
101
|
+
activeApiUrl = resolveApiUrl(options.apiUrl);
|
|
102
|
+
active = createSdkClient(options);
|
|
103
|
+
return active;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// src/react.tsx
|
|
107
|
+
function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }) {
|
|
108
|
+
(0, import_react.useEffect)(() => {
|
|
109
|
+
initializeSDK({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl });
|
|
110
|
+
}, [apiUrl, appKey, appSecret, timeoutMs, fetchImpl]);
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
114
|
+
0 && (module.exports = {
|
|
115
|
+
SDKInitializer
|
|
116
|
+
});
|
|
117
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/sdk.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport { initializeSDK, type InitOptions } from './sdk'\n\n/**\n * Configures the process-wide client from React. The effect depends on each\n * value, so a rotated secret or a tenant switch takes effect instead of being\n * dropped after the first render.\n */\nexport function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }: InitOptions) {\n useEffect(() => {\n initializeSDK({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl })\n }, [apiUrl, appKey, appSecret, timeoutMs, fetchImpl])\n\n return null\n}\n","import createClient, { type Client, type Middleware } from 'openapi-fetch'\n\nimport type { components, paths } from './types/schema'\n\n/** Header names the server reads app credentials from (`apps/server/src/auth/auth.guard.ts`). */\nexport const APP_KEY_HEADER = 'x-app-key'\nexport const APP_SECRET_HEADER = 'x-app-secret'\n\nexport type InitOptions = {\n /** Base URL of the API, without a trailing slash. */\n apiUrl: string\n /** Sent as `x-app-key`: the app's `id`, which the auth guard looks the app up by. */\n appKey?: string\n /** Sent as `x-app-secret`: one of the app's credential `clientSecret` values. */\n appSecret?: string\n /** Abort a request after this many milliseconds. `0` or unset means no timeout. */\n timeoutMs?: number\n /** Override the fetch implementation, for a Node polyfill or a test. */\n fetch?: typeof globalThis.fetch\n}\n\n/** Thrown when a request is made before any credentials were configured. */\nexport class SdkNotInitializedError extends Error {\n constructor() {\n super('Call initializeSDK() or createSdkClient() before the first request')\n this.name = 'SdkNotInitializedError'\n }\n}\n\nexport class SdkConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SdkConfigError'\n }\n}\n\nfunction resolveApiUrl(apiUrl: string | undefined): string {\n const trimmed = (apiUrl ?? '').trim().replace(/\\/+$/, '')\n if (!trimmed) {\n throw new SdkConfigError('apiUrl is required, for example https://api.example.com')\n }\n return trimmed\n}\n\nfunction withTimeout(\n fetchImpl: typeof globalThis.fetch | undefined,\n timeoutMs: number | undefined,\n): typeof globalThis.fetch {\n const base = fetchImpl ?? globalThis.fetch\n if (!timeoutMs || timeoutMs <= 0) return base\n return (input, init) => {\n // openapi-fetch calls fetch(request) with no init and folds the caller's\n // signal into the request, so look both places before combining.\n const caller = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const deadline = AbortSignal.timeout(timeoutMs)\n // `any` keeps the caller's cancellation working: the deadline must not\n // replace a signal the caller uses for reasons of its own.\n return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline })\n }\n}\n\n/**\n * App credentials travel in headers, not in the generated document: the server's\n * OpenAPI spec declares `securitySchemes: {}`, so nothing is typed for this and\n * the client has to attach them.\n */\nfunction authMiddleware({ appKey, appSecret }: InitOptions): Middleware {\n return {\n async onRequest({ request }) {\n if (!appKey && !appSecret) return request\n // A fresh Request owns mutable headers, unlike a request handed to a guarded fetch.\n const next = new Request(request)\n if (appKey) next.headers.set(APP_KEY_HEADER, appKey)\n if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret)\n return next\n },\n }\n}\n\n/**\n * A client with its own base URL and credentials. Use this when a process serves\n * more than one app: each client is independent, so one tenant's configuration\n * cannot overwrite another's.\n */\nexport function createSdkClient(options: InitOptions): Client<paths> {\n const client = createClient<paths>({\n baseUrl: resolveApiUrl(options.apiUrl),\n fetch: withTimeout(options.fetch, options.timeoutMs),\n })\n client.use(authMiddleware(options))\n return client\n}\n\nlet active: Client<paths> | null = null\n/** The `apiUrl` of the process-wide client, so `resolveGameURL` can reuse it. */\nlet activeApiUrl: string | null = null\n\n/**\n * Process-wide client configured by `initializeSDK` or `<SDKInitializer>`.\n *\n * Before the first initialization every access throws `SdkNotInitializedError`,\n * so a mis-ordered import fails where it happens instead of sending a request to\n * a placeholder origin.\n */\nexport const fetchClient: Client<paths> = new Proxy({} as Client<paths>, {\n get(_target, property) {\n if (typeof property === 'symbol') return undefined\n if (!active) throw new SdkNotInitializedError()\n const value = (active as unknown as Record<string, unknown>)[property]\n return typeof value === 'function'\n ? (value as (...args: unknown[]) => unknown).bind(active)\n : value\n },\n})\n\n/** Configure the process-wide client and return it. */\nexport function initializeSDK(options: InitOptions): Client<paths> {\n activeApiUrl = resolveApiUrl(options.apiUrl)\n active = createSdkClient(options)\n return active\n}\n\n/** A game instance from `GET /sdk/game-instances`, as generated from the OpenAPI document. */\nexport type GameInstance = components['schemas']['AppGameInstance']\n\nexport type ResolveGameUrlOptions = {\n /** API base URL the frame calls. Defaults to the `apiUrl` passed to `initializeSDK`. */\n apiUrl?: string\n /** Config to hand the game as `gameSetting`. Defaults to the instance overrides. */\n config?: Record<string, unknown> | null\n}\n\n/**\n * Build the URL the host loads in an iframe or webview from the game instance\n * and the token `POST /sdk/login` returned. It appends `apiUrl`,\n * `gameInstanceId`, `playerAccessToken`, and `gameSetting`.\n *\n * `apiUrl` defaults to the one given to `initializeSDK`. A caller that uses\n * `createSdkClient` instead must pass `{ apiUrl }`, because that client is not\n * the process-wide one.\n */\nexport function resolveGameURL(\n gameInstance: GameInstance,\n playerAccessToken: string,\n options: ResolveGameUrlOptions = {},\n): string {\n const entryPoint = gameInstance?.resolvedUrl\n if (!entryPoint) {\n throw new SdkConfigError('gameInstance.resolvedUrl is required to build a play URL')\n }\n const token = playerAccessToken?.trim()\n if (!token) {\n throw new SdkConfigError('playerAccessToken is required')\n }\n const apiUrl = options.apiUrl?.trim() || activeApiUrl\n if (!apiUrl) {\n throw new SdkConfigError('apiUrl is required: call initializeSDK() first, or pass { apiUrl }')\n }\n\n const url = new URL(entryPoint)\n url.searchParams.set('apiUrl', resolveApiUrl(apiUrl))\n url.searchParams.set('gameInstanceId', gameInstance.id)\n url.searchParams.set('playerAccessToken', token)\n\n const config = options.config ?? gameInstance.overrides\n if (config && Object.keys(config).length) {\n url.searchParams.set('gameSetting', JSON.stringify(config))\n }\n return url.toString()\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAA0B;;;ACF1B,2BAA2D;AAKpD,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAgB1B,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,cAAc;AACZ,UAAM,oEAAoE;AAC1E,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,cAAc,QAAoC;AACzD,QAAM,WAAW,UAAU,IAAI,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACxD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,eAAe,yDAAyD;AAAA,EACpF;AACA,SAAO;AACT;AAEA,SAAS,YACP,WACA,WACyB;AACzB,QAAM,OAAO,aAAa,WAAW;AACrC,MAAI,CAAC,aAAa,aAAa,EAAG,QAAO;AACzC,SAAO,CAAC,OAAO,SAAS;AAGtB,UAAM,SAAS,MAAM,WAAW,iBAAiB,UAAU,MAAM,SAAS;AAC1E,UAAM,WAAW,YAAY,QAAQ,SAAS;AAG9C,WAAO,KAAK,OAAO,EAAE,GAAG,MAAM,QAAQ,SAAS,YAAY,IAAI,CAAC,QAAQ,QAAQ,CAAC,IAAI,SAAS,CAAC;AAAA,EACjG;AACF;AAOA,SAAS,eAAe,EAAE,QAAQ,UAAU,GAA4B;AACtE,SAAO;AAAA,IACL,MAAM,UAAU,EAAE,QAAQ,GAAG;AAC3B,UAAI,CAAC,UAAU,CAAC,UAAW,QAAO;AAElC,YAAM,OAAO,IAAI,QAAQ,OAAO;AAChC,UAAI,OAAQ,MAAK,QAAQ,IAAI,gBAAgB,MAAM;AACnD,UAAI,UAAW,MAAK,QAAQ,IAAI,mBAAmB,SAAS;AAC5D,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAOO,SAAS,gBAAgB,SAAqC;AACnE,QAAM,aAAS,qBAAAA,SAAoB;AAAA,IACjC,SAAS,cAAc,QAAQ,MAAM;AAAA,IACrC,OAAO,YAAY,QAAQ,OAAO,QAAQ,SAAS;AAAA,EACrD,CAAC;AACD,SAAO,IAAI,eAAe,OAAO,CAAC;AAClC,SAAO;AACT;AAEA,IAAI,SAA+B;AAEnC,IAAI,eAA8B;AAS3B,IAAM,cAA6B,IAAI,MAAM,CAAC,GAAoB;AAAA,EACvE,IAAI,SAAS,UAAU;AACrB,QAAI,OAAO,aAAa,SAAU,QAAO;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,uBAAuB;AAC9C,UAAM,QAAS,OAA8C,QAAQ;AACrE,WAAO,OAAO,UAAU,aACnB,MAA0C,KAAK,MAAM,IACtD;AAAA,EACN;AACF,CAAC;AAGM,SAAS,cAAc,SAAqC;AACjE,iBAAe,cAAc,QAAQ,MAAM;AAC3C,WAAS,gBAAgB,OAAO;AAChC,SAAO;AACT;;;AD7GO,SAAS,eAAe,EAAE,QAAQ,QAAQ,WAAW,WAAW,OAAO,UAAU,GAAgB;AACtG,8BAAU,MAAM;AACd,kBAAc,EAAE,QAAQ,QAAQ,WAAW,WAAW,OAAO,UAAU,CAAC;AAAA,EAC1E,GAAG,CAAC,QAAQ,QAAQ,WAAW,WAAW,SAAS,CAAC;AAEpD,SAAO;AACT;","names":["createClient"]}
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react.tsx
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
|
|
6
|
+
// src/sdk.ts
|
|
7
|
+
import createClient from "openapi-fetch";
|
|
8
|
+
var APP_KEY_HEADER = "x-app-key";
|
|
9
|
+
var APP_SECRET_HEADER = "x-app-secret";
|
|
10
|
+
var SdkNotInitializedError = class extends Error {
|
|
11
|
+
constructor() {
|
|
12
|
+
super("Call initializeSDK() or createSdkClient() before the first request");
|
|
13
|
+
this.name = "SdkNotInitializedError";
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var SdkConfigError = class extends Error {
|
|
17
|
+
constructor(message) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "SdkConfigError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function resolveApiUrl(apiUrl) {
|
|
23
|
+
const trimmed = (apiUrl ?? "").trim().replace(/\/+$/, "");
|
|
24
|
+
if (!trimmed) {
|
|
25
|
+
throw new SdkConfigError("apiUrl is required, for example https://api.example.com");
|
|
26
|
+
}
|
|
27
|
+
return trimmed;
|
|
28
|
+
}
|
|
29
|
+
function withTimeout(fetchImpl, timeoutMs) {
|
|
30
|
+
const base = fetchImpl ?? globalThis.fetch;
|
|
31
|
+
if (!timeoutMs || timeoutMs <= 0) return base;
|
|
32
|
+
return (input, init) => {
|
|
33
|
+
const caller = init?.signal ?? (input instanceof Request ? input.signal : void 0);
|
|
34
|
+
const deadline = AbortSignal.timeout(timeoutMs);
|
|
35
|
+
return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline });
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function authMiddleware({ appKey, appSecret }) {
|
|
39
|
+
return {
|
|
40
|
+
async onRequest({ request }) {
|
|
41
|
+
if (!appKey && !appSecret) return request;
|
|
42
|
+
const next = new Request(request);
|
|
43
|
+
if (appKey) next.headers.set(APP_KEY_HEADER, appKey);
|
|
44
|
+
if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret);
|
|
45
|
+
return next;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function createSdkClient(options) {
|
|
50
|
+
const client = createClient({
|
|
51
|
+
baseUrl: resolveApiUrl(options.apiUrl),
|
|
52
|
+
fetch: withTimeout(options.fetch, options.timeoutMs)
|
|
53
|
+
});
|
|
54
|
+
client.use(authMiddleware(options));
|
|
55
|
+
return client;
|
|
56
|
+
}
|
|
57
|
+
var active = null;
|
|
58
|
+
var activeApiUrl = null;
|
|
59
|
+
var fetchClient = new Proxy({}, {
|
|
60
|
+
get(_target, property) {
|
|
61
|
+
if (typeof property === "symbol") return void 0;
|
|
62
|
+
if (!active) throw new SdkNotInitializedError();
|
|
63
|
+
const value = active[property];
|
|
64
|
+
return typeof value === "function" ? value.bind(active) : value;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
function initializeSDK(options) {
|
|
68
|
+
activeApiUrl = resolveApiUrl(options.apiUrl);
|
|
69
|
+
active = createSdkClient(options);
|
|
70
|
+
return active;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/react.tsx
|
|
74
|
+
function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }) {
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
initializeSDK({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl });
|
|
77
|
+
}, [apiUrl, appKey, appSecret, timeoutMs, fetchImpl]);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
SDKInitializer
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=react.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.tsx","../src/sdk.ts"],"sourcesContent":["'use client'\n\nimport { useEffect } from 'react'\n\nimport { initializeSDK, type InitOptions } from './sdk'\n\n/**\n * Configures the process-wide client from React. The effect depends on each\n * value, so a rotated secret or a tenant switch takes effect instead of being\n * dropped after the first render.\n */\nexport function SDKInitializer({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl }: InitOptions) {\n useEffect(() => {\n initializeSDK({ apiUrl, appKey, appSecret, timeoutMs, fetch: fetchImpl })\n }, [apiUrl, appKey, appSecret, timeoutMs, fetchImpl])\n\n return null\n}\n","import createClient, { type Client, type Middleware } from 'openapi-fetch'\n\nimport type { components, paths } from './types/schema'\n\n/** Header names the server reads app credentials from (`apps/server/src/auth/auth.guard.ts`). */\nexport const APP_KEY_HEADER = 'x-app-key'\nexport const APP_SECRET_HEADER = 'x-app-secret'\n\nexport type InitOptions = {\n /** Base URL of the API, without a trailing slash. */\n apiUrl: string\n /** Sent as `x-app-key`: the app's `id`, which the auth guard looks the app up by. */\n appKey?: string\n /** Sent as `x-app-secret`: one of the app's credential `clientSecret` values. */\n appSecret?: string\n /** Abort a request after this many milliseconds. `0` or unset means no timeout. */\n timeoutMs?: number\n /** Override the fetch implementation, for a Node polyfill or a test. */\n fetch?: typeof globalThis.fetch\n}\n\n/** Thrown when a request is made before any credentials were configured. */\nexport class SdkNotInitializedError extends Error {\n constructor() {\n super('Call initializeSDK() or createSdkClient() before the first request')\n this.name = 'SdkNotInitializedError'\n }\n}\n\nexport class SdkConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'SdkConfigError'\n }\n}\n\nfunction resolveApiUrl(apiUrl: string | undefined): string {\n const trimmed = (apiUrl ?? '').trim().replace(/\\/+$/, '')\n if (!trimmed) {\n throw new SdkConfigError('apiUrl is required, for example https://api.example.com')\n }\n return trimmed\n}\n\nfunction withTimeout(\n fetchImpl: typeof globalThis.fetch | undefined,\n timeoutMs: number | undefined,\n): typeof globalThis.fetch {\n const base = fetchImpl ?? globalThis.fetch\n if (!timeoutMs || timeoutMs <= 0) return base\n return (input, init) => {\n // openapi-fetch calls fetch(request) with no init and folds the caller's\n // signal into the request, so look both places before combining.\n const caller = init?.signal ?? (input instanceof Request ? input.signal : undefined)\n const deadline = AbortSignal.timeout(timeoutMs)\n // `any` keeps the caller's cancellation working: the deadline must not\n // replace a signal the caller uses for reasons of its own.\n return base(input, { ...init, signal: caller ? AbortSignal.any([caller, deadline]) : deadline })\n }\n}\n\n/**\n * App credentials travel in headers, not in the generated document: the server's\n * OpenAPI spec declares `securitySchemes: {}`, so nothing is typed for this and\n * the client has to attach them.\n */\nfunction authMiddleware({ appKey, appSecret }: InitOptions): Middleware {\n return {\n async onRequest({ request }) {\n if (!appKey && !appSecret) return request\n // A fresh Request owns mutable headers, unlike a request handed to a guarded fetch.\n const next = new Request(request)\n if (appKey) next.headers.set(APP_KEY_HEADER, appKey)\n if (appSecret) next.headers.set(APP_SECRET_HEADER, appSecret)\n return next\n },\n }\n}\n\n/**\n * A client with its own base URL and credentials. Use this when a process serves\n * more than one app: each client is independent, so one tenant's configuration\n * cannot overwrite another's.\n */\nexport function createSdkClient(options: InitOptions): Client<paths> {\n const client = createClient<paths>({\n baseUrl: resolveApiUrl(options.apiUrl),\n fetch: withTimeout(options.fetch, options.timeoutMs),\n })\n client.use(authMiddleware(options))\n return client\n}\n\nlet active: Client<paths> | null = null\n/** The `apiUrl` of the process-wide client, so `resolveGameURL` can reuse it. */\nlet activeApiUrl: string | null = null\n\n/**\n * Process-wide client configured by `initializeSDK` or `<SDKInitializer>`.\n *\n * Before the first initialization every access throws `SdkNotInitializedError`,\n * so a mis-ordered import fails where it happens instead of sending a request to\n * a placeholder origin.\n */\nexport const fetchClient: Client<paths> = new Proxy({} as Client<paths>, {\n get(_target, property) {\n if (typeof property === 'symbol') return undefined\n if (!active) throw new SdkNotInitializedError()\n const value = (active as unknown as Record<string, unknown>)[property]\n return typeof value === 'function'\n ? (value as (...args: unknown[]) => unknown).bind(active)\n : value\n },\n})\n\n/** Configure the process-wide client and return it. */\nexport function initializeSDK(options: InitOptions): Client<paths> {\n activeApiUrl = resolveApiUrl(options.apiUrl)\n active = createSdkClient(options)\n return active\n}\n\n/** A game instance from `GET /sdk/game-instances`, as generated from the OpenAPI document. */\nexport type GameInstance = components['schemas']['AppGameInstance']\n\nexport type ResolveGameUrlOptions = {\n /** API base URL the frame calls. Defaults to the `apiUrl` passed to `initializeSDK`. */\n apiUrl?: string\n /** Config to hand the game as `gameSetting`. Defaults to the instance overrides. */\n config?: Record<string, unknown> | null\n}\n\n/**\n * Build the URL the host loads in an iframe or webview from the game instance\n * and the token `POST /sdk/login` returned. It appends `apiUrl`,\n * `gameInstanceId`, `playerAccessToken`, and `gameSetting`.\n *\n * `apiUrl` defaults to the one given to `initializeSDK`. A caller that uses\n * `createSdkClient` instead must pass `{ apiUrl }`, because that client is not\n * the process-wide one.\n */\nexport function resolveGameURL(\n gameInstance: GameInstance,\n playerAccessToken: string,\n options: ResolveGameUrlOptions = {},\n): string {\n const entryPoint = gameInstance?.resolvedUrl\n if (!entryPoint) {\n throw new SdkConfigError('gameInstance.resolvedUrl is required to build a play URL')\n }\n const token = playerAccessToken?.trim()\n if (!token) {\n throw new SdkConfigError('playerAccessToken is required')\n }\n const apiUrl = options.apiUrl?.trim() || activeApiUrl\n if (!apiUrl) {\n throw new SdkConfigError('apiUrl is required: call initializeSDK() first, or pass { apiUrl }')\n }\n\n const url = new URL(entryPoint)\n url.searchParams.set('apiUrl', resolveApiUrl(apiUrl))\n url.searchParams.set('gameInstanceId', gameInstance.id)\n url.searchParams.set('playerAccessToken', token)\n\n const config = options.config ?? gameInstance.overrides\n if (config && Object.keys(config).length) {\n url.searchParams.set('gameSetting', JSON.stringify(config))\n }\n return url.toString()\n}\n"],"mappings":";;;AAEA,SAAS,iBAAiB;;;ACF1B,OAAO,kBAAoD;AAKpD,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAgB1B,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,cAAc;AACZ,UAAM,oEAAoE;AAC1E,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,SAAS,cAAc,QAAoC;AACzD,QAAM,WAAW,UAAU,IAAI,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACxD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,eAAe,yDAAyD;AAAA,EACpF;AACA,SAAO;AACT;AAEA,SAAS,YACP,WACA,WACyB;AACzB,QAAM,OAAO,aAAa,WAAW;AACrC,MAAI,CAAC,aAAa,aAAa,EAAG,QAAO;AACzC,SAAO,CAAC,OAAO,SAAS;AAGtB,UAAM,SAAS,MAAM,WAAW,iBAAiB,UAAU,MAAM,SAAS;AAC1E,UAAM,WAAW,YAAY,QAAQ,SAAS;AAG9C,WAAO,KAAK,OAAO,EAAE,GAAG,MAAM,QAAQ,SAAS,YAAY,IAAI,CAAC,QAAQ,QAAQ,CAAC,IAAI,SAAS,CAAC;AAAA,EACjG;AACF;AAOA,SAAS,eAAe,EAAE,QAAQ,UAAU,GAA4B;AACtE,SAAO;AAAA,IACL,MAAM,UAAU,EAAE,QAAQ,GAAG;AAC3B,UAAI,CAAC,UAAU,CAAC,UAAW,QAAO;AAElC,YAAM,OAAO,IAAI,QAAQ,OAAO;AAChC,UAAI,OAAQ,MAAK,QAAQ,IAAI,gBAAgB,MAAM;AACnD,UAAI,UAAW,MAAK,QAAQ,IAAI,mBAAmB,SAAS;AAC5D,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAOO,SAAS,gBAAgB,SAAqC;AACnE,QAAM,SAAS,aAAoB;AAAA,IACjC,SAAS,cAAc,QAAQ,MAAM;AAAA,IACrC,OAAO,YAAY,QAAQ,OAAO,QAAQ,SAAS;AAAA,EACrD,CAAC;AACD,SAAO,IAAI,eAAe,OAAO,CAAC;AAClC,SAAO;AACT;AAEA,IAAI,SAA+B;AAEnC,IAAI,eAA8B;AAS3B,IAAM,cAA6B,IAAI,MAAM,CAAC,GAAoB;AAAA,EACvE,IAAI,SAAS,UAAU;AACrB,QAAI,OAAO,aAAa,SAAU,QAAO;AACzC,QAAI,CAAC,OAAQ,OAAM,IAAI,uBAAuB;AAC9C,UAAM,QAAS,OAA8C,QAAQ;AACrE,WAAO,OAAO,UAAU,aACnB,MAA0C,KAAK,MAAM,IACtD;AAAA,EACN;AACF,CAAC;AAGM,SAAS,cAAc,SAAqC;AACjE,iBAAe,cAAc,QAAQ,MAAM;AAC3C,WAAS,gBAAgB,OAAO;AAChC,SAAO;AACT;;;AD7GO,SAAS,eAAe,EAAE,QAAQ,QAAQ,WAAW,WAAW,OAAO,UAAU,GAAgB;AACtG,YAAU,MAAM;AACd,kBAAc,EAAE,QAAQ,QAAQ,WAAW,WAAW,OAAO,UAAU,CAAC;AAAA,EAC1E,GAAG,CAAC,QAAQ,QAAQ,WAAW,WAAW,SAAS,CAAC;AAEpD,SAAO;AACT;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,93 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fzgame/sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Typed client for the FZ GameHub API, generated from the server's OpenAPI document",
|
|
5
|
+
"license": "ISC",
|
|
6
|
+
"author": "Fanzeal <developer@fanzeal.com>",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.mts",
|
|
14
|
+
"default": "./dist/index.mjs"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"./react": {
|
|
22
|
+
"import": {
|
|
23
|
+
"types": "./dist/react.d.mts",
|
|
24
|
+
"default": "./dist/react.mjs"
|
|
25
|
+
},
|
|
26
|
+
"require": {
|
|
27
|
+
"types": "./dist/react.d.ts",
|
|
28
|
+
"default": "./dist/react.js"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18.17"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://bitbucket.org/fanzeal-intl/fz-gamehub.git",
|
|
46
|
+
"directory": "packages/sdk"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://bitbucket.org/fanzeal-intl/fz-gamehub/src/main/packages/sdk",
|
|
49
|
+
"bugs": {
|
|
50
|
+
"url": "https://bitbucket.org/fanzeal-intl/fz-gamehub/issues"
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"fanzeal",
|
|
54
|
+
"gamehub",
|
|
55
|
+
"fzgame",
|
|
56
|
+
"sdk",
|
|
57
|
+
"openapi",
|
|
58
|
+
"client",
|
|
59
|
+
"typescript"
|
|
60
|
+
],
|
|
61
|
+
"scripts": {
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"compile": "openapi-typescript ../../apps/server/public/openapi-sdk.json -o ./src/types/schema.d.ts --empty-objects-unknown --root-types --root-types-no-schema-prefix --make-paths-enum && tsup",
|
|
64
|
+
"check-types": "tsc --noEmit",
|
|
65
|
+
"test": "vitest",
|
|
66
|
+
"test:run": "vitest run",
|
|
67
|
+
"smoke": "node scripts/smoke-npm-pack.mjs",
|
|
68
|
+
"lint": "eslint src/**/*.ts --ext .ts",
|
|
69
|
+
"format": "prettier --write src",
|
|
70
|
+
"prepack": "pnpm build",
|
|
71
|
+
"prepublishOnly": "pnpm check-types && pnpm test:run && pnpm build"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"openapi-fetch": "^0.15.0"
|
|
75
|
+
},
|
|
76
|
+
"peerDependencies": {
|
|
77
|
+
"react": ">=18.2 <20"
|
|
78
|
+
},
|
|
79
|
+
"peerDependenciesMeta": {
|
|
80
|
+
"react": {
|
|
81
|
+
"optional": true
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"devDependencies": {
|
|
85
|
+
"@fzgame/eslint-config": "workspace:*",
|
|
86
|
+
"@fzgame/typescript-config": "workspace:*",
|
|
87
|
+
"@types/react": "^18.2.0",
|
|
88
|
+
"openapi-typescript": "^6.7.6",
|
|
89
|
+
"tsup": "^8.5.1",
|
|
90
|
+
"typescript": "^5.9.3",
|
|
91
|
+
"vitest": "^4.1.3"
|
|
92
|
+
}
|
|
93
|
+
}
|