@nitida/sdk 0.27.1 → 0.28.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/index.ts CHANGED
@@ -48,6 +48,8 @@ import {
48
48
  getVideoTransformUrl,
49
49
  hasPreset,
50
50
  invalidateSlotCache,
51
+ isRequestablePreset,
52
+ REQUESTABLE_PRESETS,
51
53
  type RequestablePreset,
52
54
  type ResolveSlotOptions,
53
55
  resolveSlot,
@@ -58,6 +60,7 @@ import {
58
60
  setCdnBase,
59
61
  setTenantId,
60
62
  type TransformOptions,
63
+ toRequestablePresets,
61
64
  type VariantEntryPreset,
62
65
  type VariantPreset,
63
66
  } from "@nitida/asset-client";
@@ -114,12 +117,25 @@ export type NitidaClientOptions = {
114
117
  * Tenant's HMAC signing key for transform URLs (Phase 3). Required
115
118
  * only when calling `aq.transform(asset, opts, { sign: true })`.
116
119
  *
117
- * 32 random bytes, generated server-side on tenant creation; fetch
118
- * via `POST /admin/projects/:code/rotate-signing-key`, which needs a
119
- * SYSTEM-scope credential the platform operator holds your own admin key
120
- * answers `403 SYSTEM_KEY_REQUIRED`. Ask for it. **Keep it
121
- * server-side only** do not ship in `NEXT_PUBLIC_*` env vars. Sign
122
- * URLs from a BFF route handler, or pre-sign at build time.
120
+ * 32 random bytes, generated server-side on tenant creation.
121
+ *
122
+ * **Where you get it: the response to your project's creation, once.**
123
+ * `POST /admin/projects` returns `signingKey` next to the three API keys,
124
+ * and the console shows it in the same panel. It is shown there and nowhere
125
+ * else save it with the keys.
126
+ *
127
+ * **Never saw one?** Projects created before 2026-08-23 were not handed it,
128
+ * and no endpoint shows you the current one. If you have not signed any URLs
129
+ * yet — true of every project that has not shipped private assets — ask for
130
+ * a rotation: with nothing in flight it invalidates nothing and is free. If
131
+ * you already have signed URLs circulating, ask for the current key instead.
132
+ *
133
+ * Either way it is one request to the platform operator:
134
+ * `POST /admin/projects/:code/rotate-signing-key` needs a SYSTEM-scope
135
+ * credential, and your own admin key answers `403 SYSTEM_KEY_REQUIRED`.
136
+ *
137
+ * **Keep it server-side only** — do not ship in `NEXT_PUBLIC_*` env vars.
138
+ * Sign URLs from a BFF route handler, or pre-sign at build time.
123
139
  */
124
140
  signingKey?: string;
125
141
  };
@@ -254,12 +270,14 @@ export {
254
270
  hasPreset,
255
271
  hlsLadderAlignment,
256
272
  invalidateSlotCache,
273
+ isRequestablePreset,
257
274
  iteratePaletteSwatches,
258
275
  PRESET_EXT,
259
276
  PRESET_LONG,
260
277
  PRESET_MAX_DIM,
261
278
  PRESET_SHORT,
262
279
  pickAmbientBackground,
280
+ REQUESTABLE_PRESETS,
263
281
  relativeLuminance,
264
282
  resolveSlot,
265
283
  resolveSlots,
@@ -269,6 +287,7 @@ export {
269
287
  signAccessUrl,
270
288
  signTransformUrl,
271
289
  TRANSFORM_WIDTHS,
290
+ toRequestablePresets,
272
291
  } from "@nitida/asset-client";
273
292
 
274
293
  // ---------------------------------------------------------------------------
@@ -531,7 +550,12 @@ export type ComposeMarketingResult = {
531
550
  class AssetsApi {
532
551
  constructor(private readonly opts: NitidaClientOptions) {}
533
552
 
534
- /** Look up an asset by full sha256 (64 hex). Returns null on 404. */
553
+ /**
554
+ * Look up an asset by sha256. Accepts the full 64-hex digest that
555
+ * `upload()` returns as `sha256`, or the 16-char short prefix that appears
556
+ * in every CDN URL. Returns null on 404; throws with a message naming the
557
+ * expected shape if the string is neither form.
558
+ */
535
559
  async byHash(sha256: string): Promise<AssetDTO | null> {
536
560
  const r = await fetch(
537
561
  endpointHref(this.opts, `/assets/by-hash/${sha256}`),
@@ -1296,7 +1320,7 @@ export class NitidaClient {
1296
1320
  if (!this.opts.signingKey) {
1297
1321
  throw new Error(
1298
1322
  "aq.transform({ sign: true }) requires `signingKey` in NitidaClientOptions. " +
1299
- "No signingKey on this client. The key is minted by POST /admin/projects/:code/rotate-signing-key, which needs a system-scope credential the platform operator holds your own admin key gets 403 SYSTEM_KEY_REQUIRED, so ask for it. Then pass it to the SDK constructor on a SERVER-side instance only.",
1323
+ "No signingKey on this client. It is returned ONCE, in the response that creates your project (POST /admin/projects → `signingKey`, next to the three API keys; the console shows it in the same panel). If you never saw one — projects created before 2026-08-23 were not handed it ask the platform operator to rotate: with no signed URLs in flight that invalidates nothing and is free. If you DO have signed URLs circulating, ask for the current key instead, because rotating would kill them. Then pass it to the SDK constructor on a SERVER-side instance only.",
1300
1324
  );
1301
1325
  }
1302
1326
  // Signed path — custom (off-ladder) widths allowed. Empty opts → no
@@ -1334,7 +1358,8 @@ export class NitidaClient {
1334
1358
  if (!signOpts?.sign) return getTransformSrcSet(asset, widths, extraOpts);
1335
1359
  if (!this.opts.signingKey) {
1336
1360
  throw new Error(
1337
- "aq.transformSrcSet({ sign: true }) requires `signingKey` in NitidaClientOptions.",
1361
+ "aq.transformSrcSet({ sign: true }) requires `signingKey` in NitidaClientOptions. " +
1362
+ "It was returned ONCE, by the response that created your project (POST /admin/projects → `signingKey`). See the `signingKey` docs on NitidaClientOptions.",
1338
1363
  );
1339
1364
  }
1340
1365
  const key = this.opts.signingKey;
@@ -129,6 +129,7 @@ export {
129
129
  hasPreset,
130
130
  hlsLadderAlignment,
131
131
  invalidateSlotCache,
132
+ isRequestablePreset,
132
133
  isUniversallyPlayableAudio,
133
134
  iteratePaletteSwatches,
134
135
  mimeFromFileName,
@@ -140,6 +141,7 @@ export {
140
141
  PRESET_SHORT,
141
142
  type PresignUploadUrlOptions,
142
143
  pickAmbientBackground,
144
+ REQUESTABLE_PRESETS,
143
145
  type RegenerateResult,
144
146
  type RequestablePreset,
145
147
  type ResolveSlotOptions,
@@ -163,6 +165,7 @@ export {
163
165
  type TransformGravity,
164
166
  type TransformOptions,
165
167
  type TransformWidth,
168
+ toRequestablePresets,
166
169
  type UploadOptions,
167
170
  type UploadResult,
168
171
  type UploadUrlResult,
package/src/web/index.ts CHANGED
@@ -146,6 +146,7 @@ export {
146
146
  hasPreset,
147
147
  hlsLadderAlignment,
148
148
  invalidateSlotCache,
149
+ isRequestablePreset,
149
150
  isUniversallyPlayableAudio,
150
151
  iteratePaletteSwatches,
151
152
  mimeFromFileName,
@@ -156,6 +157,7 @@ export {
156
157
  PRESET_SHORT,
157
158
  type PresignUploadUrlOptions,
158
159
  pickAmbientBackground,
160
+ REQUESTABLE_PRESETS,
159
161
  type RegenerateResult,
160
162
  type RequestablePreset,
161
163
  type ResolveSlotOptions,
@@ -179,6 +181,7 @@ export {
179
181
  type TransformGravity,
180
182
  type TransformOptions,
181
183
  type TransformWidth,
184
+ toRequestablePresets,
182
185
  type UploadOptions,
183
186
  type UploadResult,
184
187
  type UploadUrlResult,