deepspace 0.4.0 → 0.4.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/dist/index.d.ts CHANGED
@@ -6230,17 +6230,23 @@ declare function toConnectionStatus(queryStatus: string): ConnectionStatus;
6230
6230
  /**
6231
6231
  * useR2Files — Scoped file storage hook for DeepSpace apps.
6232
6232
  *
6233
- * Provides upload, download, list, and delete for files in R2, scoped to
6234
- * the current app ("self" — uses hostname-based scoping on the server).
6233
+ * Provides upload, download, list, and delete for files in R2.
6234
+ *
6235
+ * Two scopes are supported via the `scope` option:
6236
+ * - `'self'` (default): per-user storage. Reads require auth.
6237
+ * - `'app'`: app-wide storage. Reads are public — the upload URL works
6238
+ * directly as an `<img src>`. Use for avatars, logos, etc.
6235
6239
  *
6236
6240
  * @example
6237
6241
  * ```tsx
6238
- * const { upload, downloadFile, deleteFile, list } = useR2Files()
6242
+ * // Per-user files (default):
6243
+ * const { upload, downloadFile } = useR2Files()
6239
6244
  * await upload(myFile, 'photo.png')
6240
6245
  *
6241
- * const files = await list()
6242
- * await downloadFile(files[0]) // uses originalName automatically
6243
- * await deleteFile(files[0])
6246
+ * // App-shared files (public reads — usable in <img src>):
6247
+ * const { upload } = useR2Files({ scope: 'app' })
6248
+ * const r = await upload(file, `avatars/${userId}.png`)
6249
+ * // r.url is a plain, anon-readable URL.
6244
6250
  * ```
6245
6251
  */
6246
6252
  interface R2UploadResult {
@@ -6314,17 +6320,29 @@ interface UseR2FilesReturn {
6314
6320
  /**
6315
6321
  * Build a plain URL for a file. Accepts an R2FileInfo or a raw key string.
6316
6322
  *
6317
- * **Note**: This URL has no auth token attached. It only works for
6318
- * unauthenticated reads on deployed sites where the prefix is derived
6319
- * from the hostname. For authenticated access, use `downloadFile` or
6320
- * `readFile` instead.
6323
+ * **Note**: This URL has no auth token attached. It works for `'app'`-scope
6324
+ * files (which are publicly readable) but not for `'self'`-scope files —
6325
+ * those require an Authorization header, so use `readFile` / `downloadFile`.
6321
6326
  */
6322
6327
  getUrl: (fileOrKey: R2FileInfo | string) => string;
6323
6328
  /** Whether an upload is currently in progress. */
6324
6329
  isUploading: boolean;
6325
6330
  }
6331
+ /**
6332
+ * Scope controls where files live and who can read them:
6333
+ *
6334
+ * - `'self'` (default) — `apps/<app>/users/<userId>/…`. Per-user storage.
6335
+ * Reads require the caller's auth token; not usable from a plain `<img>`
6336
+ * or unauthenticated browser request.
6337
+ * - `'app'` — `apps/<app>/…`. Shared by everyone in the app. Reads are
6338
+ * public (no auth header needed), so the upload URL works directly as
6339
+ * an `<img src>`. Use this for avatars, logos, attachments, and other
6340
+ * assets meant to be embedded in pages.
6341
+ *
6342
+ * Uploads under `'app'` still require a signed-in user.
6343
+ */
6326
6344
  type R2Scope = {
6327
- scope?: 'self';
6345
+ scope?: 'self' | 'app';
6328
6346
  };
6329
6347
  declare function useR2Files(options?: R2Scope): UseR2FilesReturn;
6330
6348
 
package/dist/index.js CHANGED
@@ -892,7 +892,35 @@ function AuthOverlay({
892
892
  }
893
893
  )
894
894
  ] }),
895
- /* @__PURE__ */ jsxs2("div", { className: "mt-5 flex items-center justify-center gap-1.5 text-[11px] text-muted-foreground", children: [
895
+ /* @__PURE__ */ jsxs2("p", { className: "mt-5 text-xs leading-snug text-muted-foreground", children: [
896
+ "By continuing, you agree to the DeepSpace",
897
+ " ",
898
+ /* @__PURE__ */ jsx2(
899
+ "a",
900
+ {
901
+ href: "https://deep.space/terms",
902
+ target: "_blank",
903
+ rel: "noopener noreferrer",
904
+ className: "underline hover:text-foreground",
905
+ children: "Terms of Service"
906
+ }
907
+ ),
908
+ " ",
909
+ "and",
910
+ " ",
911
+ /* @__PURE__ */ jsx2(
912
+ "a",
913
+ {
914
+ href: "https://deep.space/privacy",
915
+ target: "_blank",
916
+ rel: "noopener noreferrer",
917
+ className: "underline hover:text-foreground",
918
+ children: "Privacy Policy"
919
+ }
920
+ ),
921
+ "."
922
+ ] }),
923
+ /* @__PURE__ */ jsxs2("div", { className: "mt-4 flex items-center justify-center gap-1.5 text-[11px] text-muted-foreground", children: [
896
924
  /* @__PURE__ */ jsx2("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", opacity: "0.5", "aria-hidden": true, children: /* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "10" }) }),
897
925
  "Powered by DeepSpace"
898
926
  ] })
@@ -3407,11 +3435,12 @@ function resolveFile(fileOrKey) {
3407
3435
  }
3408
3436
  function useR2Files(options) {
3409
3437
  const [isUploading, setIsUploading] = useState13(false);
3438
+ const scope = options?.scope ?? "self";
3410
3439
  const scopeParams = useMemo10(() => {
3411
3440
  const params = new URLSearchParams();
3412
- params.set("scope", "self");
3441
+ params.set("scope", scope);
3413
3442
  return params.toString();
3414
- }, []);
3443
+ }, [scope]);
3415
3444
  const authHeaders = useCallback15(async () => {
3416
3445
  const token = await getAuthToken();
3417
3446
  if (token) {