pyric-admin 0.1.0-alpha.21 → 0.1.0-alpha.24

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.
Files changed (77) hide show
  1. package/README.md +12 -4
  2. package/dist/app-check/index.d.ts +3 -0
  3. package/dist/app-check/index.d.ts.map +1 -0
  4. package/dist/app-check/index.js +11 -0
  5. package/dist/app-check/index.js.map +1 -0
  6. package/dist/data-connect/index.d.ts +3 -0
  7. package/dist/data-connect/index.d.ts.map +1 -0
  8. package/dist/data-connect/index.js +11 -0
  9. package/dist/data-connect/index.js.map +1 -0
  10. package/dist/deferred.d.ts +21 -0
  11. package/dist/deferred.d.ts.map +1 -0
  12. package/dist/deferred.js +29 -0
  13. package/dist/deferred.js.map +1 -0
  14. package/dist/eventarc/index.d.ts +3 -0
  15. package/dist/eventarc/index.d.ts.map +1 -0
  16. package/dist/eventarc/index.js +11 -0
  17. package/dist/eventarc/index.js.map +1 -0
  18. package/dist/extensions/index.d.ts +3 -0
  19. package/dist/extensions/index.d.ts.map +1 -0
  20. package/dist/extensions/index.js +11 -0
  21. package/dist/extensions/index.js.map +1 -0
  22. package/dist/functions/index.d.ts +3 -0
  23. package/dist/functions/index.d.ts.map +1 -0
  24. package/dist/functions/index.js +11 -0
  25. package/dist/functions/index.js.map +1 -0
  26. package/dist/installations/index.d.ts +3 -0
  27. package/dist/installations/index.d.ts.map +1 -0
  28. package/dist/installations/index.js +11 -0
  29. package/dist/installations/index.js.map +1 -0
  30. package/dist/instance-id/index.d.ts +3 -0
  31. package/dist/instance-id/index.d.ts.map +1 -0
  32. package/dist/instance-id/index.js +11 -0
  33. package/dist/instance-id/index.js.map +1 -0
  34. package/dist/machine-learning/index.d.ts +3 -0
  35. package/dist/machine-learning/index.d.ts.map +1 -0
  36. package/dist/machine-learning/index.js +11 -0
  37. package/dist/machine-learning/index.js.map +1 -0
  38. package/dist/messaging/index.d.ts +0 -1
  39. package/dist/messaging/index.d.ts.map +1 -1
  40. package/dist/messaging/index.js +7 -8
  41. package/dist/messaging/index.js.map +1 -1
  42. package/dist/phone-number-verification/index.d.ts +3 -0
  43. package/dist/phone-number-verification/index.d.ts.map +1 -0
  44. package/dist/phone-number-verification/index.js +11 -0
  45. package/dist/phone-number-verification/index.js.map +1 -0
  46. package/dist/project-management/index.d.ts +3 -0
  47. package/dist/project-management/index.d.ts.map +1 -0
  48. package/dist/project-management/index.js +11 -0
  49. package/dist/project-management/index.js.map +1 -0
  50. package/dist/remote-config/index.d.ts +3 -0
  51. package/dist/remote-config/index.d.ts.map +1 -0
  52. package/dist/remote-config/index.js +11 -0
  53. package/dist/remote-config/index.js.map +1 -0
  54. package/dist/security-rules/index.d.ts +3 -0
  55. package/dist/security-rules/index.d.ts.map +1 -0
  56. package/dist/security-rules/index.js +11 -0
  57. package/dist/security-rules/index.js.map +1 -0
  58. package/dist/storage/index.d.ts +88 -16
  59. package/dist/storage/index.d.ts.map +1 -1
  60. package/dist/storage/index.js +409 -69
  61. package/dist/storage/index.js.map +1 -1
  62. package/package.json +50 -2
  63. package/src/app-check/index.ts +14 -0
  64. package/src/data-connect/index.ts +14 -0
  65. package/src/deferred.ts +33 -0
  66. package/src/eventarc/index.ts +14 -0
  67. package/src/extensions/index.ts +14 -0
  68. package/src/functions/index.ts +14 -0
  69. package/src/installations/index.ts +15 -0
  70. package/src/instance-id/index.ts +14 -0
  71. package/src/machine-learning/index.ts +14 -0
  72. package/src/messaging/index.ts +2 -9
  73. package/src/phone-number-verification/index.ts +14 -0
  74. package/src/project-management/index.ts +15 -0
  75. package/src/remote-config/index.ts +15 -0
  76. package/src/security-rules/index.ts +14 -0
  77. package/src/storage/index.ts +520 -89
@@ -7,10 +7,10 @@
7
7
  *
8
8
  * - **Remote sandbox path** — a handle branded by `@pyric/cli`'
9
9
  * `connectRemoteSandbox()`/`remoteSandbox()` relays every data
10
- * operation over the bridge to the browser-hosted SharedWorker's
11
- * object store (admin lens pinned — rules bypass). Single bucket;
12
- * 8 MiB per-op byte cap; `getSignedUrl` stays the local stub. See
13
- * the remote arm section below.
10
+ * operation to the sandbox's host (admin lens pinned — rules bypass).
11
+ * Bytes move over the host's HTTP byte route when it has one, and as
12
+ * frames when it does not (a browser tab's SharedWorker). Single bucket;
13
+ * `getSignedUrl` stays the local stub. See the remote arm section below.
14
14
  *
15
15
  * - **Sandbox path** — returns an in-process {@link Storage} backed
16
16
  * by an in-memory `Map<bucketName, Map<path, FileEntry>>`. State
@@ -23,16 +23,24 @@
23
23
  * - `storage.bucket(name?)` → {@link Bucket}-shaped handle
24
24
  * - `bucket.file(path)` → {@link File}-shaped handle
25
25
  * - `file.save(data, options?)` — `Buffer | string | Uint8Array`
26
- * - `file.download(options?)` → `[Buffer]`
26
+ * - `file.download(options?)` → `[Buffer]`, whole or `start..end`
27
+ * - `file.createReadStream(options?)`, whole or `start..end`
28
+ * - `file.createWriteStream(options?)`
29
+ * - `file.getMetadata()` / `file.setMetadata(metadata)`: settable fields
30
+ * and custom metadata; a custom key set to `null` is removed
31
+ * - `getDownloadURL(file)`: mints a token into
32
+ * `firebaseStorageDownloadTokens` when the file has none. The Node
33
+ * host returns its HTTP URL; elsewhere the URL is a `data:` URI
27
34
  * - `file.delete()` — idempotent
28
35
  * - `file.exists()` → `[boolean]`
29
36
  * - `file.getSignedUrl(options)` → `['pyric-sandbox-storage://…']`
30
37
  *
31
38
  * **Deferred in the sandbox backend** (throws `"not implemented in
32
- * pyric-admin/storage sandbox backend"`): streaming uploads
33
- * (`createWriteStream`), resumable uploads, signed cookies, IAM
34
- * policies, lifecycle rules, ACLs, copy/move, notifications.
39
+ * pyric-admin/storage sandbox backend"`): resumable uploads, signed
40
+ * cookies, IAM policies, lifecycle rules, ACLs, copy/move,
41
+ * notifications.
35
42
  */
43
+ import { Readable, Writable } from 'node:stream';
36
44
  import { type PyricAdminApp } from '../app/index.js';
37
45
  /**
38
46
  * `pyric-admin/storage`'s sandbox `Storage` handle. It exposes the subset
@@ -64,9 +72,9 @@ export interface Bucket {
64
72
  * / getSignedUrl, etc.) so common consumer code retains the familiar shape.
65
73
  *
66
74
  * The sandbox backend implements the methods documented here. Any
67
- * other `File` method from `@google-cloud/storage` (`createWriteStream`,
68
- * `createReadStream`, `copy`, `move`, `setMetadata` beyond the basic
69
- * `save` options, etc.) throws on the sandbox path — see module header.
75
+ * other `File` method from `@google-cloud/storage` (`copy`, `move`,
76
+ * `setMetadata` beyond the basic `save` options, etc.) is not implemented
77
+ * on the sandbox path — see module header.
70
78
  */
71
79
  export interface File {
72
80
  /** Name (path) of the file within its bucket. */
@@ -82,11 +90,30 @@ export interface File {
82
90
  */
83
91
  save(data: Buffer | string | Uint8Array, options?: SaveOptions): Promise<void>;
84
92
  /**
85
- * Read the file's bytes. Returns a `[Buffer]` tuple to mirror
86
- * `@google-cloud/storage`'s `File.download` (which returns
87
- * `[Buffer, ...]`). Throws if the file does not exist.
93
+ * Read the file's bytes, or the inclusive range `start..end` of them.
94
+ * Returns a `[Buffer]` tuple to mirror `@google-cloud/storage`'s
95
+ * `File.download` (which returns `[Buffer, ...]`). Throws if the file
96
+ * does not exist.
88
97
  */
89
98
  download(options?: DownloadOptions): Promise<[Buffer]>;
99
+ /**
100
+ * A readable stream of the file's bytes, or of the inclusive range
101
+ * `start..end`. A missing file surfaces as the stream's error.
102
+ */
103
+ createReadStream(options?: CreateReadStreamOptions): Readable;
104
+ /**
105
+ * A writable stream whose bytes replace the file's content once the
106
+ * stream finishes, as {@link File.save} does.
107
+ */
108
+ createWriteStream(options?: CreateWriteStreamOptions): Writable;
109
+ /** The file's metadata, as a `[metadata]` tuple. Throws if the file does not exist. */
110
+ getMetadata(): Promise<[FileMetadata]>;
111
+ /**
112
+ * Change the file's metadata: the named settable fields, and the custom
113
+ * keys under `metadata`, where `null` removes a key and the others stay.
114
+ * Removing `firebaseStorageDownloadTokens` revokes the file's download URL.
115
+ */
116
+ setMetadata(metadata: FileMetadataUpdate): Promise<[FileMetadata]>;
90
117
  /**
91
118
  * Remove the file from its bucket. Idempotent — deleting a missing
92
119
  * file is a no-op (matches `@google-cloud/storage`'s
@@ -127,9 +154,49 @@ export interface SaveOptions {
127
154
  }
128
155
  /** Options bag for {@link File.download}. Subset of `@google-cloud/storage`'s `DownloadOptions`. */
129
156
  export interface DownloadOptions {
157
+ /** First byte to read, inclusive. */
158
+ start?: number;
159
+ /** Last byte to read, inclusive. */
160
+ end?: number;
130
161
  /** The sandbox accepts but ignores `validation`. */
131
162
  validation?: 'md5' | 'crc32c' | boolean;
132
163
  }
164
+ /** Options bag for {@link File.createReadStream}. Subset of `@google-cloud/storage`'s `CreateReadStreamOptions`. */
165
+ export type CreateReadStreamOptions = DownloadOptions;
166
+ /** Options bag for {@link File.createWriteStream}. Subset of `@google-cloud/storage`'s `CreateWriteStreamOptions`. */
167
+ export interface CreateWriteStreamOptions {
168
+ /** Stored alongside the file, as {@link SaveOptions.metadata} is. */
169
+ metadata?: Record<string, unknown>;
170
+ /** Content type stored on the file. */
171
+ contentType?: string;
172
+ }
173
+ /** Settable fields the sandbox keeps, besides custom metadata. */
174
+ declare const SETTABLE_FIELDS: readonly ["contentType", "cacheControl", "contentDisposition", "contentEncoding", "contentLanguage"];
175
+ type SettableField = (typeof SETTABLE_FIELDS)[number];
176
+ /** A file's metadata. Subset of `@google-cloud/storage`'s `FileMetadata`. */
177
+ export interface FileMetadata {
178
+ name: string;
179
+ bucket: string;
180
+ generation: string;
181
+ metageneration: string;
182
+ /** Size in bytes, as a decimal string. */
183
+ size: string;
184
+ timeCreated: string;
185
+ updated: string;
186
+ contentType?: string;
187
+ cacheControl?: string;
188
+ contentDisposition?: string;
189
+ contentEncoding?: string;
190
+ contentLanguage?: string;
191
+ md5Hash?: string;
192
+ /** Custom metadata, including `firebaseStorageDownloadTokens` once the file has a download URL. Absent when there is none. */
193
+ metadata?: Record<string, string>;
194
+ }
195
+ /** What {@link File.setMetadata} takes. Subset of `@google-cloud/storage`'s `FileMetadata`. */
196
+ export type FileMetadataUpdate = Partial<Pick<FileMetadata, SettableField>> & {
197
+ /** Custom keys to set; `null` removes a key. Values are stored as strings. */
198
+ metadata?: Record<string, string | number | boolean | null>;
199
+ };
133
200
  /** Options bag for {@link File.getSignedUrl}. Mirrors `@google-cloud/storage`'s shape. */
134
201
  export interface GetSignedUrlOptions {
135
202
  /** `'read' | 'write' | 'delete' | 'resumable'`. Sandbox stamps it into the URL only as a hint. */
@@ -157,8 +224,13 @@ export type StorageApp = PyricAdminApp;
157
224
  */
158
225
  export declare function getStorage(app?: StorageApp): Storage;
159
226
  /**
160
- * Link-compatible mirror of `firebase-admin/storage`'s `getDownloadURL(file)`.
161
- * Returns a deterministic sandbox storage stub URL from `file.getSignedUrl()`.
227
+ * Mirror of `firebase-admin/storage`'s `getDownloadURL(file)`. A file without
228
+ * a download token gets one in `firebaseStorageDownloadTokens`, as production
229
+ * mints it. On the Node host the URL is its HTTP byte route URL, which serves
230
+ * ranges and stops working when the token is removed. In process and on a
231
+ * SharedWorker host there is no HTTP origin, so the URL is a `data:` URI that
232
+ * carries the bytes.
162
233
  */
163
234
  export declare function getDownloadURL(file: File): Promise<string>;
235
+ export {};
164
236
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AASH,OAAO,EAGL,KAAK,aAAa,EAEnB,MAAM,iBAAiB,CAAC;AAKzB;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,IAAI;IACnB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD;;;;OAIG;IACH,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,qGAAqG;IACrG,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7B;;;;;;OAMG;IACH,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;CAC/D;AAED,4FAA4F;AAC5F,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,oGAAoG;AACpG,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,UAAU,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACzC;AAED,0FAA0F;AAC1F,MAAM,WAAW,mBAAmB;IAClC,kGAAkG;IAClG,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;IAClD;;;;OAIG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,CAAC;AAEvC;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,UAAU,GAAG,OAAO,CAuBpD;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/storage/index.ts"],"names":[],"mappings":"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"}