@nitida/sdk 0.28.0 → 0.29.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/src/expo/index.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @nitida/sdk/expo — native multipart uploads for React Native / Expo.
3
3
  *
4
- * Wraps `@aquienpz/asset-uploader-expo`'s `UploadTask`, which delegates
4
+ * Wraps `@nitida/asset-uploader-expo`'s `UploadTask`, which delegates
5
5
  * the actual byte transfer to a native background session (URLSession
6
6
  * on iOS, WorkManager on Android). The upload survives:
7
7
  * - JS thread freezing
@@ -53,7 +53,7 @@
53
53
  * is not built. It is the same gap `/web` documents. Ask; there is no public
54
54
  * tracker.
55
55
  *
56
- * Peer dep: `@aquienpz/asset-uploader-expo` (lazy — apps that don't
56
+ * Peer dep: `@nitida/asset-uploader-expo` (lazy — apps that don't
57
57
  * use the mobile SDK skip the install).
58
58
  * @module @nitida/sdk/expo
59
59
  */
@@ -61,7 +61,7 @@
61
61
  import {
62
62
  UploadTask,
63
63
  type UploadTaskOptions,
64
- } from "@aquienpz/asset-uploader-expo";
64
+ } from "@nitida/asset-uploader-expo";
65
65
  import type { NitidaClient } from "..";
66
66
 
67
67
  export type ExpoUploadOptions = Omit<
@@ -97,9 +97,9 @@ export type {
97
97
  UploadFileInput,
98
98
  UploadSessionState,
99
99
  UploadTaskOptions,
100
- } from "@aquienpz/asset-uploader-expo";
100
+ } from "@nitida/asset-uploader-expo";
101
101
  export {
102
102
  cancelResumableSession,
103
103
  listResumableSessions,
104
104
  UploadTask,
105
- } from "@aquienpz/asset-uploader-expo";
105
+ } from "@nitida/asset-uploader-expo";
package/src/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * platform.
4
4
  *
5
5
  * One ergonomic facade over the underlying packages
6
- * (`@nitida/asset-client` URL builders + `@aquienpz/asset-uploader-web`
6
+ * (`@nitida/asset-client` URL builders + `@nitida/asset-uploader-web`
7
7
  * + the slot resolver). Auth is a bearer API key (`amk_rt_*`), issued
8
8
  * per tenant when the tenant is created; tenant scope comes from
9
9
  * the key's metadata (`X-Tenant-Code` is log-only).
@@ -820,7 +820,49 @@ class AssetsApi {
820
820
  * Default timeout is 5 minutes; videos / HLS ladders may need a
821
821
  * higher cap (pass `10 * 60_000` for compositions, transcodes).
822
822
  */
823
- async waitReady(assetId: string, timeoutMs = 5 * 60_000): Promise<AssetDTO> {
823
+ async waitReady(
824
+ assetId: string,
825
+ /**
826
+ * Milliseconds, OR `{ timeoutMs }`.
827
+ *
828
+ * ⭐ It accepts the object because that is what people write. Found
829
+ * 2026-08-23 while smoke-testing a brand-new tenant: I passed
830
+ * `{ timeoutMs: 90_000 }` — every other option-taking method in this SDK
831
+ * takes an object — and got
832
+ *
833
+ * Error: waitReady: no asset a379fbbb-…
834
+ *
835
+ * about an asset that existed, was `ready`, and whose variants were all
836
+ * serving 200. `Date.now() - start < {…}` compares against NaN, so the
837
+ * loop body never ran, `last` stayed null, and the message blamed the one
838
+ * thing that was fine.
839
+ *
840
+ * TypeScript catches the wrong shape. Running it through `bun` does not —
841
+ * the same gap that let `upload()`'s `sha256` reach a URL builder wanting
842
+ * `sha` and produce `.../undefined.webp`. The lesson there was the same as
843
+ * here: a guard with a good message is still a mistake the user has to
844
+ * make first. Make the obvious call correct instead.
845
+ */
846
+ timeout: number | { timeoutMs?: number } = 5 * 60_000,
847
+ ): Promise<AssetDTO> {
848
+ // A string, a Date, anything else: refuse it. Falling back to the default
849
+ // would be the same silent-success this whole method just stopped doing —
850
+ // `waitReady(id, "90s")` would wait five minutes and the caller would
851
+ // never learn why.
852
+ const timeoutMs =
853
+ typeof timeout === "number"
854
+ ? timeout
855
+ : timeout !== null && typeof timeout === "object"
856
+ ? (timeout.timeoutMs ?? 5 * 60_000)
857
+ : Number.NaN;
858
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
859
+ throw new Error(
860
+ "waitReady: timeout must be a positive number of milliseconds or " +
861
+ `{ timeoutMs }, got ${JSON.stringify(timeout)}. A non-numeric ` +
862
+ "timeout makes the poll loop exit before its first iteration, which " +
863
+ `used to surface as "no asset <id>" about an asset that was fine.`,
864
+ );
865
+ }
824
866
  const start = Date.now();
825
867
  let delay = 500;
826
868
  let last: AssetDTO | null = null;
@@ -830,7 +872,15 @@ class AssetsApi {
830
872
  await new Promise((r) => setTimeout(r, delay));
831
873
  delay = Math.min(delay * 1.5, 5_000);
832
874
  }
833
- if (!last) throw new Error(`waitReady: no asset ${assetId}`);
875
+ // Unreachable now that a non-numeric timeout is refused above: any
876
+ // positive timeout runs the loop at least once, so `last` is set. Kept as
877
+ // a belt, with a message that no longer accuses the asset of not existing.
878
+ if (!last) {
879
+ throw new Error(
880
+ `waitReady: polled ${assetId} zero times in ${timeoutMs}ms — this is a ` +
881
+ "bug in the SDK, not a missing asset.",
882
+ );
883
+ }
834
884
  throw new Error(`waitReady timeout for ${assetId}`);
835
885
  }
836
886
 
@@ -1545,10 +1595,10 @@ export class NitidaClient {
1545
1595
  // was not enough: `bun build --compile` constant-folds simple
1546
1596
  // strings and still eagerly bundled `./web.js`, which
1547
1597
  // top-level-imports the browser-only peer deps
1548
- // `@aquienpz/asset-uploader-web` / `@nitida/asset-compressor-web`
1598
+ // `@nitida/asset-uploader-web` / `@nitida/asset-compressor-web`
1549
1599
  // — neither installed on server consumers — crashing the
1550
1600
  // single-binary on boot with `Cannot find module
1551
- // '@aquienpz/asset-uploader-web'`.
1601
+ // '@nitida/asset-uploader-web'`.
1552
1602
  //
1553
1603
  // The earlier `new URL("./web.js", import.meta.url)` + `await import(URL)`
1554
1604
  // dance survived bun-compile but Turbopack still tracks the URL literal
package/src/web/index.ts CHANGED
@@ -44,7 +44,7 @@
44
44
  * `apiKey` and bundles cleanly only in Node/Bun/edge runtimes.
45
45
  *
46
46
  * Peer deps (auto-installed via npm peer deps — declared optional):
47
- * - `@aquienpz/asset-uploader-web` for multipart uploads
47
+ * - `@nitida/asset-uploader-web` for multipart uploads
48
48
  * - `@nitida/asset-compressor-web` for client-side compression
49
49
  *
50
50
  * Both are lazy-imported; bundles that never call into them skip the cost.
@@ -197,7 +197,7 @@ export {
197
197
 
198
198
  // Multipart uploader helpers are NOT re-exported from this subpath.
199
199
  //
200
- // `@aquienpz/asset-uploader-web` is an optional peer-dep that isn't on
200
+ // `@nitida/asset-uploader-web` is an optional peer-dep that isn't on
201
201
  // npm yet, so a static `import` at module top broke every consumer of
202
202
  // `@nitida/sdk/web` (the bundler tries to resolve before the optional
203
203
  // peer check kicks in). The old `createWebUploader` + `UploadTask`
@@ -209,7 +209,7 @@ export {
209
209
  // token is not exposed yet. Ask us; there is no public tracker.
210
210
  //
211
211
  // Apps that need `UploadTask` directly today should depend on
212
- // `@aquienpz/asset-uploader-web` themselves once it's published.
212
+ // `@nitida/asset-uploader-web` themselves once it's published.
213
213
 
214
214
  // ---------------------------------------------------------------------------
215
215
  // Client-side compression (Phase 1.5)