@oasiz/sdk 1.8.5 → 1.8.6

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 CHANGED
@@ -171,18 +171,20 @@ still returns `backflip`.
171
171
 
172
172
  Inside the Oasiz app, `oasiz.getPlayerCharacter()` returns the authenticated
173
173
  player's real character atlas. On `localhost` or `file://` without the app
174
- bridge, it returns a bundled sample Jibble atlas instead, so browser games can
175
- test sprite loading, atlas slicing, and animation lookup before publishing.
174
+ bridge, it first fetches an Oasiz-owned real sample atlas from
175
+ `https://api.oasiz.ai/api/sdk/sample-character`, so browser games can test
176
+ sprite loading, atlas slicing, and animation lookup before publishing.
176
177
 
177
- The sample atlas includes every catalog ID above, and its `imageUrl` is an
178
- inline `data:image/svg+xml` URL. It does not make a network request and it is
179
- only used when the app bridge is missing.
178
+ The platform sample is generated by the same backend/R2 atlas pipeline as real
179
+ characters, but it is not a user character and it does not expose user id,
180
+ layer config, or personal data. If the endpoint is unavailable, the SDK uses a
181
+ tiny generated atlas as a resilience fallback unless disabled.
180
182
 
181
183
  ```ts
182
184
  const character = await oasiz.getPlayerCharacter();
183
185
 
184
186
  // In Oasiz app: the real signed-in player's character.
185
- // On localhost without the app bridge: "SDK Sample Jibble".
187
+ // On localhost without the app bridge: "Oasiz Sample Jibble".
186
188
  // On non-local pages without the app bridge: null.
187
189
  ```
188
190
 
@@ -195,8 +197,17 @@ const characterOrNull = await oasiz.getPlayerCharacter({ localFallback: false })
195
197
  // Force the sample atlas in a browser test harness.
196
198
  const sampleCharacter = await oasiz.getPlayerCharacter({ localFallback: true });
197
199
 
198
- // Or fetch the sample directly without checking the bridge.
199
- const directSample = oasiz.getSamplePlayerCharacter();
200
+ // Strict mode: require the platform-generated sample, with no generated backup.
201
+ const platformOnlySample = await oasiz.getPlayerCharacter({
202
+ localFallback: true,
203
+ generatedFallback: false,
204
+ });
205
+
206
+ // Override the sample endpoint when testing against staging.
207
+ const stagingSample = await oasiz.getPlayerCharacter({
208
+ localFallback: true,
209
+ sampleCharacterUrl: "https://staging-api.oasiz.ai/api/sdk/sample-character",
210
+ });
200
211
  ```
201
212
 
202
213
  #### HTML5 / TypeScript
package/dist/index.cjs CHANGED
@@ -1685,6 +1685,8 @@ function getSamplePlayerCharacter() {
1685
1685
  }
1686
1686
 
1687
1687
  // src/character.ts
1688
+ var DEFAULT_SAMPLE_CHARACTER_URL = "https://api.oasiz.ai/api/sdk/sample-character";
1689
+ var DEFAULT_SAMPLE_FETCH_TIMEOUT_MS = 1500;
1688
1690
  function isDevelopment2() {
1689
1691
  const nodeEnv = globalThis.process?.env?.NODE_ENV;
1690
1692
  return nodeEnv !== "production";
@@ -1718,6 +1720,56 @@ function warnMissingBridge2(methodName, usingFallback) {
1718
1720
  );
1719
1721
  }
1720
1722
  }
1723
+ function isRecord2(value) {
1724
+ return typeof value === "object" && value !== null;
1725
+ }
1726
+ function isTextureAtlas(value) {
1727
+ if (!isRecord2(value)) {
1728
+ return false;
1729
+ }
1730
+ return typeof value.imageUrl === "string" && typeof value.imageWidth === "number" && Number.isFinite(value.imageWidth) && typeof value.imageHeight === "number" && Number.isFinite(value.imageHeight) && Array.isArray(value.frames) && Array.isArray(value.animations);
1731
+ }
1732
+ function isPlayerCharacter(value) {
1733
+ if (!isRecord2(value)) {
1734
+ return false;
1735
+ }
1736
+ return (typeof value.characterName === "string" || value.characterName === null) && typeof value.baseCharacterId === "string" && typeof value.compositionCode === "string" && isTextureAtlas(value.textureAtlas) && (value.editorTextureAtlas === null || isTextureAtlas(value.editorTextureAtlas));
1737
+ }
1738
+ function unwrapSampleCharacterResponse(payload) {
1739
+ if (isPlayerCharacter(payload)) {
1740
+ return payload;
1741
+ }
1742
+ if (isRecord2(payload) && isPlayerCharacter(payload.character)) {
1743
+ return payload.character;
1744
+ }
1745
+ return null;
1746
+ }
1747
+ async function fetchPlatformSampleCharacter(options) {
1748
+ if (typeof fetch !== "function") {
1749
+ return null;
1750
+ }
1751
+ const timeoutMs = options.sampleFetchTimeoutMs ?? DEFAULT_SAMPLE_FETCH_TIMEOUT_MS;
1752
+ const controller = typeof AbortController === "function" ? new AbortController() : null;
1753
+ const timeout = controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
1754
+ try {
1755
+ const response = await fetch(
1756
+ options.sampleCharacterUrl ?? DEFAULT_SAMPLE_CHARACTER_URL,
1757
+ {
1758
+ signal: controller?.signal
1759
+ }
1760
+ );
1761
+ if (!response.ok) {
1762
+ return null;
1763
+ }
1764
+ return unwrapSampleCharacterResponse(await response.json());
1765
+ } catch {
1766
+ return null;
1767
+ } finally {
1768
+ if (timeout) {
1769
+ clearTimeout(timeout);
1770
+ }
1771
+ }
1772
+ }
1721
1773
  async function getPlayerCharacter(options = {}) {
1722
1774
  const bridge = getBridgeWindow2();
1723
1775
  if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
@@ -1726,7 +1778,14 @@ async function getPlayerCharacter(options = {}) {
1726
1778
  options.localFallback ?? "auto"
1727
1779
  );
1728
1780
  warnMissingBridge2("getPlayerCharacter", useLocalFallback);
1729
- return useLocalFallback ? getSamplePlayerCharacter() : null;
1781
+ if (!useLocalFallback) {
1782
+ return null;
1783
+ }
1784
+ const platformSample = await fetchPlatformSampleCharacter(options);
1785
+ if (platformSample) {
1786
+ return platformSample;
1787
+ }
1788
+ return options.generatedFallback === false ? null : getSamplePlayerCharacter();
1730
1789
  }
1731
1790
  try {
1732
1791
  const result = await bridge.__oasizGetPlayerCharacter();
@@ -2990,7 +3049,7 @@ function warnMissingBridge7(methodName) {
2990
3049
  );
2991
3050
  }
2992
3051
  }
2993
- function isRecord2(value) {
3052
+ function isRecord3(value) {
2994
3053
  return typeof value === "object" && value !== null;
2995
3054
  }
2996
3055
  function toFiniteNumber(value) {
@@ -3159,11 +3218,11 @@ function callBridgeFunction(bridge, name) {
3159
3218
  }
3160
3219
  }
3161
3220
  function readInsetObjectValue(value, side, group) {
3162
- if (!isRecord2(value)) {
3221
+ if (!isRecord3(value)) {
3163
3222
  return void 0;
3164
3223
  }
3165
3224
  if (group) {
3166
- return isRecord2(value[group]) ? value[group][side] : void 0;
3225
+ return isRecord3(value[group]) ? value[group][side] : void 0;
3167
3226
  }
3168
3227
  return value[side];
3169
3228
  }
@@ -3300,7 +3359,7 @@ function getBridgeWindow10() {
3300
3359
  }
3301
3360
  return window;
3302
3361
  }
3303
- function isRecord3(value) {
3362
+ function isRecord4(value) {
3304
3363
  return typeof value === "object" && value !== null;
3305
3364
  }
3306
3365
  function toFiniteNumber2(value) {
@@ -3366,7 +3425,7 @@ function normalizeMetric(value) {
3366
3425
  }
3367
3426
  return void 0;
3368
3427
  }
3369
- if (!isRecord3(value)) {
3428
+ if (!isRecord4(value)) {
3370
3429
  return void 0;
3371
3430
  }
3372
3431
  const fpsCandidate = firstDefined2(
package/dist/index.d.cts CHANGED
@@ -226,6 +226,19 @@ interface GetPlayerCharacterOptions {
226
226
  * missing. `"auto"` returns the sample on localhost/file URLs only.
227
227
  */
228
228
  localFallback?: boolean | "auto";
229
+ /**
230
+ * Public endpoint used for the real platform-generated local sample atlas.
231
+ */
232
+ sampleCharacterUrl?: string;
233
+ /**
234
+ * Timeout for the public sample endpoint before falling back locally.
235
+ */
236
+ sampleFetchTimeoutMs?: number;
237
+ /**
238
+ * When true, a tiny generated atlas is used if the platform sample endpoint
239
+ * is unavailable. Set false for strict platform-sample-only local testing.
240
+ */
241
+ generatedFallback?: boolean;
229
242
  }
230
243
  /**
231
244
  * Fetch the authenticated player's character, including a TexturePacker /
package/dist/index.d.ts CHANGED
@@ -226,6 +226,19 @@ interface GetPlayerCharacterOptions {
226
226
  * missing. `"auto"` returns the sample on localhost/file URLs only.
227
227
  */
228
228
  localFallback?: boolean | "auto";
229
+ /**
230
+ * Public endpoint used for the real platform-generated local sample atlas.
231
+ */
232
+ sampleCharacterUrl?: string;
233
+ /**
234
+ * Timeout for the public sample endpoint before falling back locally.
235
+ */
236
+ sampleFetchTimeoutMs?: number;
237
+ /**
238
+ * When true, a tiny generated atlas is used if the platform sample endpoint
239
+ * is unavailable. Set false for strict platform-sample-only local testing.
240
+ */
241
+ generatedFallback?: boolean;
229
242
  }
230
243
  /**
231
244
  * Fetch the authenticated player's character, including a TexturePacker /
package/dist/index.js CHANGED
@@ -1624,6 +1624,8 @@ function getSamplePlayerCharacter() {
1624
1624
  }
1625
1625
 
1626
1626
  // src/character.ts
1627
+ var DEFAULT_SAMPLE_CHARACTER_URL = "https://api.oasiz.ai/api/sdk/sample-character";
1628
+ var DEFAULT_SAMPLE_FETCH_TIMEOUT_MS = 1500;
1627
1629
  function isDevelopment2() {
1628
1630
  const nodeEnv = globalThis.process?.env?.NODE_ENV;
1629
1631
  return nodeEnv !== "production";
@@ -1657,6 +1659,56 @@ function warnMissingBridge2(methodName, usingFallback) {
1657
1659
  );
1658
1660
  }
1659
1661
  }
1662
+ function isRecord2(value) {
1663
+ return typeof value === "object" && value !== null;
1664
+ }
1665
+ function isTextureAtlas(value) {
1666
+ if (!isRecord2(value)) {
1667
+ return false;
1668
+ }
1669
+ return typeof value.imageUrl === "string" && typeof value.imageWidth === "number" && Number.isFinite(value.imageWidth) && typeof value.imageHeight === "number" && Number.isFinite(value.imageHeight) && Array.isArray(value.frames) && Array.isArray(value.animations);
1670
+ }
1671
+ function isPlayerCharacter(value) {
1672
+ if (!isRecord2(value)) {
1673
+ return false;
1674
+ }
1675
+ return (typeof value.characterName === "string" || value.characterName === null) && typeof value.baseCharacterId === "string" && typeof value.compositionCode === "string" && isTextureAtlas(value.textureAtlas) && (value.editorTextureAtlas === null || isTextureAtlas(value.editorTextureAtlas));
1676
+ }
1677
+ function unwrapSampleCharacterResponse(payload) {
1678
+ if (isPlayerCharacter(payload)) {
1679
+ return payload;
1680
+ }
1681
+ if (isRecord2(payload) && isPlayerCharacter(payload.character)) {
1682
+ return payload.character;
1683
+ }
1684
+ return null;
1685
+ }
1686
+ async function fetchPlatformSampleCharacter(options) {
1687
+ if (typeof fetch !== "function") {
1688
+ return null;
1689
+ }
1690
+ const timeoutMs = options.sampleFetchTimeoutMs ?? DEFAULT_SAMPLE_FETCH_TIMEOUT_MS;
1691
+ const controller = typeof AbortController === "function" ? new AbortController() : null;
1692
+ const timeout = controller && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : void 0;
1693
+ try {
1694
+ const response = await fetch(
1695
+ options.sampleCharacterUrl ?? DEFAULT_SAMPLE_CHARACTER_URL,
1696
+ {
1697
+ signal: controller?.signal
1698
+ }
1699
+ );
1700
+ if (!response.ok) {
1701
+ return null;
1702
+ }
1703
+ return unwrapSampleCharacterResponse(await response.json());
1704
+ } catch {
1705
+ return null;
1706
+ } finally {
1707
+ if (timeout) {
1708
+ clearTimeout(timeout);
1709
+ }
1710
+ }
1711
+ }
1660
1712
  async function getPlayerCharacter(options = {}) {
1661
1713
  const bridge = getBridgeWindow2();
1662
1714
  if (typeof bridge?.__oasizGetPlayerCharacter !== "function") {
@@ -1665,7 +1717,14 @@ async function getPlayerCharacter(options = {}) {
1665
1717
  options.localFallback ?? "auto"
1666
1718
  );
1667
1719
  warnMissingBridge2("getPlayerCharacter", useLocalFallback);
1668
- return useLocalFallback ? getSamplePlayerCharacter() : null;
1720
+ if (!useLocalFallback) {
1721
+ return null;
1722
+ }
1723
+ const platformSample = await fetchPlatformSampleCharacter(options);
1724
+ if (platformSample) {
1725
+ return platformSample;
1726
+ }
1727
+ return options.generatedFallback === false ? null : getSamplePlayerCharacter();
1669
1728
  }
1670
1729
  try {
1671
1730
  const result = await bridge.__oasizGetPlayerCharacter();
@@ -2929,7 +2988,7 @@ function warnMissingBridge7(methodName) {
2929
2988
  );
2930
2989
  }
2931
2990
  }
2932
- function isRecord2(value) {
2991
+ function isRecord3(value) {
2933
2992
  return typeof value === "object" && value !== null;
2934
2993
  }
2935
2994
  function toFiniteNumber(value) {
@@ -3098,11 +3157,11 @@ function callBridgeFunction(bridge, name) {
3098
3157
  }
3099
3158
  }
3100
3159
  function readInsetObjectValue(value, side, group) {
3101
- if (!isRecord2(value)) {
3160
+ if (!isRecord3(value)) {
3102
3161
  return void 0;
3103
3162
  }
3104
3163
  if (group) {
3105
- return isRecord2(value[group]) ? value[group][side] : void 0;
3164
+ return isRecord3(value[group]) ? value[group][side] : void 0;
3106
3165
  }
3107
3166
  return value[side];
3108
3167
  }
@@ -3239,7 +3298,7 @@ function getBridgeWindow10() {
3239
3298
  }
3240
3299
  return window;
3241
3300
  }
3242
- function isRecord3(value) {
3301
+ function isRecord4(value) {
3243
3302
  return typeof value === "object" && value !== null;
3244
3303
  }
3245
3304
  function toFiniteNumber2(value) {
@@ -3305,7 +3364,7 @@ function normalizeMetric(value) {
3305
3364
  }
3306
3365
  return void 0;
3307
3366
  }
3308
- if (!isRecord3(value)) {
3367
+ if (!isRecord4(value)) {
3309
3368
  return void 0;
3310
3369
  }
3311
3370
  const fpsCandidate = firstDefined2(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oasiz/sdk",
3
- "version": "1.8.5",
3
+ "version": "1.8.6",
4
4
  "description": "Typed SDK for Oasiz game platform bridge APIs.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",