@instantdb/admin 0.22.98-experimental.highl.20766596946.1 → 0.22.99-experimental.add-user-perm-rules.20792844601.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.
@@ -1,4 +1,13 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
13
  };
@@ -18,14 +27,14 @@ function configWithDefaults(config) {
18
27
  const defaultConfig = {
19
28
  apiURI: 'https://api.instantdb.com',
20
29
  };
21
- const r = { ...defaultConfig, ...config };
30
+ const r = Object.assign(Object.assign({}, defaultConfig), config);
22
31
  return r;
23
32
  }
24
33
  function instantConfigWithDefaults(config) {
25
34
  const defaultConfig = {
26
35
  apiURI: 'https://api.instantdb.com',
27
36
  };
28
- const r = { ...defaultConfig, ...config };
37
+ const r = Object.assign(Object.assign({}, defaultConfig), config);
29
38
  return r;
30
39
  }
31
40
  function withImpersonation(headers, opts) {
@@ -88,32 +97,32 @@ function isNextJSVersionThatCachesFetchByDefault() {
88
97
  function getDefaultFetchOpts() {
89
98
  return isNextJSVersionThatCachesFetchByDefault() ? { cache: 'no-store' } : {};
90
99
  }
91
- async function jsonReject(rejectFn, res) {
92
- const body = await res.text();
93
- try {
94
- const json = JSON.parse(body);
95
- return rejectFn(new core_1.InstantAPIError({ status: res.status, body: json }));
96
- }
97
- catch (_e) {
98
- return rejectFn(new core_1.InstantAPIError({
99
- status: res.status,
100
- body: { type: undefined, message: body },
101
- }));
102
- }
100
+ function jsonReject(rejectFn, res) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ const body = yield res.text();
103
+ try {
104
+ const json = JSON.parse(body);
105
+ return rejectFn(new core_1.InstantAPIError({ status: res.status, body: json }));
106
+ }
107
+ catch (_e) {
108
+ return rejectFn(new core_1.InstantAPIError({
109
+ status: res.status,
110
+ body: { type: undefined, message: body },
111
+ }));
112
+ }
113
+ });
103
114
  }
104
- async function jsonFetch(input, init) {
105
- const defaultFetchOpts = getDefaultFetchOpts();
106
- const headers = {
107
- ...(init?.headers || {}),
108
- 'Instant-Admin-Version': version_ts_1.default,
109
- 'Instant-Core-Version': core_1.version,
110
- };
111
- const res = await fetch(input, { ...defaultFetchOpts, ...init, headers });
112
- if (res.status === 200) {
113
- const json = await res.json();
114
- return Promise.resolve(json);
115
- }
116
- return jsonReject((x) => Promise.reject(x), res);
115
+ function jsonFetch(input, init) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ const defaultFetchOpts = getDefaultFetchOpts();
118
+ const headers = Object.assign(Object.assign({}, ((init === null || init === void 0 ? void 0 : init.headers) || {})), { 'Instant-Admin-Version': version_ts_1.default, 'Instant-Core-Version': core_1.version });
119
+ const res = yield fetch(input, Object.assign(Object.assign(Object.assign({}, defaultFetchOpts), init), { headers }));
120
+ if (res.status === 200) {
121
+ const json = yield res.json();
122
+ return Promise.resolve(json);
123
+ }
124
+ return jsonReject((x) => Promise.reject(x), res);
125
+ });
117
126
  }
118
127
  /**
119
128
  *
@@ -145,12 +154,8 @@ function init(
145
154
  // Allows config with missing `useDateObjects`, but keeps `UseDates`
146
155
  // as a non-nullable in the InstantConfig type.
147
156
  config) {
148
- const configStrict = {
149
- ...config,
150
- appId: config.appId?.trim(),
151
- adminToken: config.adminToken?.trim(),
152
- useDateObjects: (config.useDateObjects ?? false),
153
- };
157
+ var _a, _b, _c;
158
+ const configStrict = Object.assign(Object.assign({}, config), { appId: (_a = config.appId) === null || _a === void 0 ? void 0 : _a.trim(), adminToken: (_b = config.adminToken) === null || _b === void 0 ? void 0 : _b.trim(), useDateObjects: ((_c = config.useDateObjects) !== null && _c !== void 0 ? _c : false) });
154
159
  return new InstantAdminDatabase(configStrict);
155
160
  }
156
161
  /**
@@ -174,171 +179,175 @@ function steps(inputChunks) {
174
179
  return chunks.flatMap(core_1.getOps);
175
180
  }
176
181
  class Rooms {
177
- config;
178
182
  constructor(config) {
179
183
  this.config = config;
180
184
  }
181
- async getPresence(roomType, roomId) {
182
- const res = await jsonFetch(`${this.config.apiURI}/admin/rooms/presence?room-type=${String(roomType)}&room-id=${roomId}`, {
183
- method: 'GET',
184
- headers: authorizedHeaders(this.config),
185
+ getPresence(roomType, roomId) {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ const res = yield jsonFetch(`${this.config.apiURI}/admin/rooms/presence?room-type=${String(roomType)}&room-id=${roomId}`, {
188
+ method: 'GET',
189
+ headers: authorizedHeaders(this.config),
190
+ });
191
+ return res.sessions || {};
185
192
  });
186
- return res.sessions || {};
187
193
  }
188
194
  }
189
195
  class Auth {
190
- config;
191
196
  constructor(config) {
192
- this.config = config;
193
- this.createToken = this.createToken.bind(this);
194
- }
195
- /**
196
- * Generates a magic code for the user with the given email.
197
- * This is useful if you want to use your own email provider
198
- * to send magic codes.
199
- *
200
- * @example
201
- * // Generate a magic code
202
- * const { code } = await db.auth.generateMagicCode({ email })
203
- * // Send the magic code to the user with your own email provider
204
- * await customEmailProvider.sendMagicCode(email, code)
205
- *
206
- * @see https://instantdb.com/docs/backend#custom-magic-codes
207
- */
208
- generateMagicCode = async (email) => {
209
- return jsonFetch(`${this.config.apiURI}/admin/magic_code`, {
210
- method: 'POST',
211
- headers: authorizedHeaders(this.config),
212
- body: JSON.stringify({ email }),
197
+ /**
198
+ * Generates a magic code for the user with the given email.
199
+ * This is useful if you want to use your own email provider
200
+ * to send magic codes.
201
+ *
202
+ * @example
203
+ * // Generate a magic code
204
+ * const { code } = await db.auth.generateMagicCode({ email })
205
+ * // Send the magic code to the user with your own email provider
206
+ * await customEmailProvider.sendMagicCode(email, code)
207
+ *
208
+ * @see https://instantdb.com/docs/backend#custom-magic-codes
209
+ */
210
+ this.generateMagicCode = (email) => __awaiter(this, void 0, void 0, function* () {
211
+ return jsonFetch(`${this.config.apiURI}/admin/magic_code`, {
212
+ method: 'POST',
213
+ headers: authorizedHeaders(this.config),
214
+ body: JSON.stringify({ email }),
215
+ });
213
216
  });
214
- };
215
- /**
216
- * Sends a magic code to the user with the given email.
217
- * This uses Instant's built-in email provider.
218
- *
219
- * @example
220
- * // Send an email to user with magic code
221
- * await db.auth.sendMagicCode({ email })
222
- *
223
- * @see https://instantdb.com/docs/backend#custom-magic-codes
224
- */
225
- sendMagicCode = async (email) => {
226
- return jsonFetch(`${this.config.apiURI}/admin/send_magic_code`, {
227
- method: 'POST',
228
- headers: authorizedHeaders(this.config),
229
- body: JSON.stringify({ email }),
217
+ /**
218
+ * Sends a magic code to the user with the given email.
219
+ * This uses Instant's built-in email provider.
220
+ *
221
+ * @example
222
+ * // Send an email to user with magic code
223
+ * await db.auth.sendMagicCode({ email })
224
+ *
225
+ * @see https://instantdb.com/docs/backend#custom-magic-codes
226
+ */
227
+ this.sendMagicCode = (email) => __awaiter(this, void 0, void 0, function* () {
228
+ return jsonFetch(`${this.config.apiURI}/admin/send_magic_code`, {
229
+ method: 'POST',
230
+ headers: authorizedHeaders(this.config),
231
+ body: JSON.stringify({ email }),
232
+ });
230
233
  });
231
- };
232
- /**
233
- * Verifies a magic code for the user with the given email.
234
- *
235
- * @example
236
- * const user = await db.auth.verifyMagicCode({ email, code })
237
- * console.log("Verified user:", user)
238
- *
239
- * @see https://instantdb.com/docs/backend#custom-magic-codes
240
- */
241
- verifyMagicCode = async (email, code) => {
242
- const { user } = await jsonFetch(`${this.config.apiURI}/admin/verify_magic_code`, {
243
- method: 'POST',
244
- headers: authorizedHeaders(this.config),
245
- body: JSON.stringify({ email, code }),
234
+ /**
235
+ * Verifies a magic code for the user with the given email.
236
+ *
237
+ * @example
238
+ * const user = await db.auth.verifyMagicCode({ email, code })
239
+ * console.log("Verified user:", user)
240
+ *
241
+ * @see https://instantdb.com/docs/backend#custom-magic-codes
242
+ */
243
+ this.verifyMagicCode = (email, code) => __awaiter(this, void 0, void 0, function* () {
244
+ const { user } = yield jsonFetch(`${this.config.apiURI}/admin/verify_magic_code`, {
245
+ method: 'POST',
246
+ headers: authorizedHeaders(this.config),
247
+ body: JSON.stringify({ email, code }),
248
+ });
249
+ return user;
246
250
  });
247
- return user;
248
- };
249
- async createToken(input) {
250
- const body = typeof input === 'string' ? { email: input } : input;
251
- const ret = await jsonFetch(`${this.config.apiURI}/admin/refresh_tokens`, {
252
- method: 'POST',
253
- headers: authorizedHeaders(this.config),
254
- body: JSON.stringify(body),
251
+ /**
252
+ * Verifies a given token and returns the associated user.
253
+ *
254
+ * This is often useful for writing custom endpoints, where you need
255
+ * to authenticate users.
256
+ *
257
+ * @example
258
+ * app.post('/custom_endpoint', async (req, res) => {
259
+ * const user = await db.auth.verifyToken(req.headers['token'])
260
+ * if (!user) {
261
+ * return res.status(401).send('Uh oh, you are not authenticated')
262
+ * }
263
+ * // ...
264
+ * })
265
+ * @see https://instantdb.com/docs/backend#custom-endpoints
266
+ */
267
+ this.verifyToken = (token) => __awaiter(this, void 0, void 0, function* () {
268
+ const res = yield jsonFetch(`${this.config.apiURI}/runtime/auth/verify_refresh_token`, {
269
+ method: 'POST',
270
+ headers: { 'content-type': 'application/json' },
271
+ body: JSON.stringify({
272
+ 'app-id': this.config.appId,
273
+ 'refresh-token': token,
274
+ }),
275
+ });
276
+ return res.user;
255
277
  });
256
- return ret.user.refresh_token;
257
- }
258
- /**
259
- * Verifies a given token and returns the associated user.
260
- *
261
- * This is often useful for writing custom endpoints, where you need
262
- * to authenticate users.
263
- *
264
- * @example
265
- * app.post('/custom_endpoint', async (req, res) => {
266
- * const user = await db.auth.verifyToken(req.headers['token'])
267
- * if (!user) {
268
- * return res.status(401).send('Uh oh, you are not authenticated')
269
- * }
270
- * // ...
271
- * })
272
- * @see https://instantdb.com/docs/backend#custom-endpoints
273
- */
274
- verifyToken = async (token) => {
275
- const res = await jsonFetch(`${this.config.apiURI}/runtime/auth/verify_refresh_token`, {
276
- method: 'POST',
277
- headers: { 'content-type': 'application/json' },
278
- body: JSON.stringify({
279
- 'app-id': this.config.appId,
280
- 'refresh-token': token,
281
- }),
278
+ /**
279
+ * Retrieves an app user by id, email, or refresh token.
280
+ *
281
+ * @example
282
+ * try {
283
+ * const user = await db.auth.getUser({ email })
284
+ * console.log("Found user:", user)
285
+ * } catch (err) {
286
+ * console.error("Failed to retrieve user:", err.message);
287
+ * }
288
+ *
289
+ * @see https://instantdb.com/docs/backend#retrieve-a-user
290
+ */
291
+ this.getUser = (params) => __awaiter(this, void 0, void 0, function* () {
292
+ const qs = Object.entries(params)
293
+ .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
294
+ .join('&');
295
+ const response = yield jsonFetch(`${this.config.apiURI}/admin/users?${qs}`, {
296
+ method: 'GET',
297
+ headers: authorizedHeaders(this.config),
298
+ });
299
+ return response.user;
282
300
  });
283
- return res.user;
284
- };
285
- /**
286
- * Retrieves an app user by id, email, or refresh token.
287
- *
288
- * @example
289
- * try {
290
- * const user = await db.auth.getUser({ email })
291
- * console.log("Found user:", user)
292
- * } catch (err) {
293
- * console.error("Failed to retrieve user:", err.message);
294
- * }
295
- *
296
- * @see https://instantdb.com/docs/backend#retrieve-a-user
297
- */
298
- getUser = async (params) => {
299
- const qs = Object.entries(params)
300
- .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
301
- .join('&');
302
- const response = await jsonFetch(`${this.config.apiURI}/admin/users?${qs}`, {
303
- method: 'GET',
304
- headers: authorizedHeaders(this.config),
301
+ /**
302
+ * Deletes an app user by id, email, or refresh token.
303
+ *
304
+ * NB: This _only_ deletes the user; it does not delete all user data.
305
+ * You will need to handle this manually.
306
+ *
307
+ * @example
308
+ * try {
309
+ * const deletedUser = await db.auth.deleteUser({ email })
310
+ * console.log("Deleted user:", deletedUser)
311
+ * } catch (err) {
312
+ * console.error("Failed to delete user:", err.message);
313
+ * }
314
+ *
315
+ * @see https://instantdb.com/docs/backend#delete-a-user
316
+ */
317
+ this.deleteUser = (params) => __awaiter(this, void 0, void 0, function* () {
318
+ const qs = Object.entries(params).map(([k, v]) => `${k}=${v}`);
319
+ const response = yield jsonFetch(`${this.config.apiURI}/admin/users?${qs}`, {
320
+ method: 'DELETE',
321
+ headers: authorizedHeaders(this.config),
322
+ });
323
+ return response.deleted;
305
324
  });
306
- return response.user;
307
- };
308
- /**
309
- * Deletes an app user by id, email, or refresh token.
310
- *
311
- * NB: This _only_ deletes the user; it does not delete all user data.
312
- * You will need to handle this manually.
313
- *
314
- * @example
315
- * try {
316
- * const deletedUser = await db.auth.deleteUser({ email })
317
- * console.log("Deleted user:", deletedUser)
318
- * } catch (err) {
319
- * console.error("Failed to delete user:", err.message);
320
- * }
321
- *
322
- * @see https://instantdb.com/docs/backend#delete-a-user
323
- */
324
- deleteUser = async (params) => {
325
- const qs = Object.entries(params).map(([k, v]) => `${k}=${v}`);
326
- const response = await jsonFetch(`${this.config.apiURI}/admin/users?${qs}`, {
327
- method: 'DELETE',
328
- headers: authorizedHeaders(this.config),
325
+ this.config = config;
326
+ this.createToken = this.createToken.bind(this);
327
+ }
328
+ createToken(input) {
329
+ return __awaiter(this, void 0, void 0, function* () {
330
+ const body = typeof input === 'string' ? { email: input } : input;
331
+ const ret = yield jsonFetch(`${this.config.apiURI}/admin/refresh_tokens`, {
332
+ method: 'POST',
333
+ headers: authorizedHeaders(this.config),
334
+ body: JSON.stringify(body),
335
+ });
336
+ return ret.user.refresh_token;
329
337
  });
330
- return response.deleted;
331
- };
332
- async signOut(input) {
333
- // If input is a string, we assume it's an email.
334
- // This is because of backwards compatibility: we used to only
335
- // accept email strings. Eventually we can remove this
336
- const params = typeof input === 'string' ? { email: input } : input;
337
- const config = this.config;
338
- await jsonFetch(`${config.apiURI}/admin/sign_out`, {
339
- method: 'POST',
340
- headers: authorizedHeaders(config),
341
- body: JSON.stringify(params),
338
+ }
339
+ signOut(input) {
340
+ return __awaiter(this, void 0, void 0, function* () {
341
+ // If input is a string, we assume it's an email.
342
+ // This is because of backwards compatibility: we used to only
343
+ // accept email strings. Eventually we can remove this
344
+ const params = typeof input === 'string' ? { email: input } : input;
345
+ const config = this.config;
346
+ yield jsonFetch(`${config.apiURI}/admin/sign_out`, {
347
+ method: 'POST',
348
+ headers: authorizedHeaders(config),
349
+ body: JSON.stringify(params),
350
+ });
342
351
  });
343
352
  }
344
353
  }
@@ -351,137 +360,127 @@ const isWebReadable = (v) => v && typeof v.getReader === 'function';
351
360
  * Functions to manage file storage.
352
361
  */
353
362
  class Storage {
354
- config;
355
- impersonationOpts;
356
363
  constructor(config, impersonationOpts) {
357
- this.config = config;
358
- this.impersonationOpts = impersonationOpts;
359
- }
360
- /**
361
- * Uploads file at the provided path. Accepts a Buffer or a Readable stream.
362
- *
363
- * @see https://instantdb.com/docs/storage
364
- * @example
365
- * const buffer = fs.readFileSync('demo.png');
366
- * const isSuccess = await db.storage.uploadFile('photos/demo.png', buffer);
367
- */
368
- uploadFile = async (path, file, metadata = {}) => {
369
- const headers = {
370
- ...authorizedHeaders(this.config, this.impersonationOpts),
371
- path,
372
- };
373
- if (metadata.contentDisposition) {
374
- headers['content-disposition'] = metadata.contentDisposition;
375
- }
376
- // headers.content-type will become "undefined" (string)
377
- // if not removed from the object
378
- delete headers['content-type'];
379
- if (metadata.contentType) {
380
- headers['content-type'] = metadata.contentType;
381
- }
382
- let duplex;
383
- if (isNodeReadable(file)) {
384
- duplex = 'half'; // one-way stream
385
- }
386
- if (isNodeReadable(file) || isWebReadable(file)) {
387
- if (!metadata.fileSize) {
388
- throw new Error('fileSize is required in metadata when uploading streams');
364
+ /**
365
+ * Uploads file at the provided path. Accepts a Buffer or a Readable stream.
366
+ *
367
+ * @see https://instantdb.com/docs/storage
368
+ * @example
369
+ * const buffer = fs.readFileSync('demo.png');
370
+ * const isSuccess = await db.storage.uploadFile('photos/demo.png', buffer);
371
+ */
372
+ this.uploadFile = (path_1, file_1, ...args_1) => __awaiter(this, [path_1, file_1, ...args_1], void 0, function* (path, file, metadata = {}) {
373
+ const headers = Object.assign(Object.assign({}, authorizedHeaders(this.config, this.impersonationOpts)), { path });
374
+ if (metadata.contentDisposition) {
375
+ headers['content-disposition'] = metadata.contentDisposition;
389
376
  }
390
- headers['content-length'] = metadata.fileSize.toString();
391
- }
392
- let options = {
393
- method: 'PUT',
394
- headers,
395
- body: file,
396
- ...(duplex && { duplex }),
397
- };
398
- return jsonFetch(`${this.config.apiURI}/admin/storage/upload`, options);
399
- };
400
- /**
401
- * Deletes a file by its path name (e.g. "photos/demo.png").
402
- *
403
- * @see https://instantdb.com/docs/storage
404
- * @example
405
- * await db.storage.delete("photos/demo.png");
406
- */
407
- delete = async (pathname) => {
408
- return jsonFetch(`${this.config.apiURI}/admin/storage/files?filename=${encodeURIComponent(pathname)}`, {
409
- method: 'DELETE',
410
- headers: authorizedHeaders(this.config, this.impersonationOpts),
377
+ // headers.content-type will become "undefined" (string)
378
+ // if not removed from the object
379
+ delete headers['content-type'];
380
+ if (metadata.contentType) {
381
+ headers['content-type'] = metadata.contentType;
382
+ }
383
+ let duplex;
384
+ if (isNodeReadable(file)) {
385
+ duplex = 'half'; // one-way stream
386
+ }
387
+ if (isNodeReadable(file) || isWebReadable(file)) {
388
+ if (!metadata.fileSize) {
389
+ throw new Error('fileSize is required in metadata when uploading streams');
390
+ }
391
+ headers['content-length'] = metadata.fileSize.toString();
392
+ }
393
+ let options = Object.assign({ method: 'PUT', headers, body: file }, (duplex && { duplex }));
394
+ return jsonFetch(`${this.config.apiURI}/admin/storage/upload`, options);
411
395
  });
412
- };
413
- /**
414
- * Deletes multiple files by their path names (e.g. "photos/demo.png", "essays/demo.txt").
415
- *
416
- * @see https://instantdb.com/docs/storage
417
- * @example
418
- * await db.storage.deleteMany(["images/1.png", "images/2.png", "images/3.png"]);
419
- */
420
- deleteMany = async (pathnames) => {
421
- return jsonFetch(`${this.config.apiURI}/admin/storage/files/delete`, {
422
- method: 'POST',
423
- headers: authorizedHeaders(this.config, this.impersonationOpts),
424
- body: JSON.stringify({ filenames: pathnames }),
396
+ /**
397
+ * Deletes a file by its path name (e.g. "photos/demo.png").
398
+ *
399
+ * @see https://instantdb.com/docs/storage
400
+ * @example
401
+ * await db.storage.delete("photos/demo.png");
402
+ */
403
+ this.delete = (pathname) => __awaiter(this, void 0, void 0, function* () {
404
+ return jsonFetch(`${this.config.apiURI}/admin/storage/files?filename=${encodeURIComponent(pathname)}`, {
405
+ method: 'DELETE',
406
+ headers: authorizedHeaders(this.config, this.impersonationOpts),
407
+ });
425
408
  });
426
- };
427
- /**
428
- * @deprecated. This method will be removed in the future. Use `uploadFile`
429
- * instead
430
- */
431
- upload = async (pathname, file, metadata = {}) => {
432
- const { data: presignedUrl } = await jsonFetch(`${this.config.apiURI}/admin/storage/signed-upload-url`, {
433
- method: 'POST',
434
- headers: authorizedHeaders(this.config),
435
- body: JSON.stringify({
436
- app_id: this.config.appId,
437
- filename: pathname,
438
- }),
409
+ /**
410
+ * Deletes multiple files by their path names (e.g. "photos/demo.png", "essays/demo.txt").
411
+ *
412
+ * @see https://instantdb.com/docs/storage
413
+ * @example
414
+ * await db.storage.deleteMany(["images/1.png", "images/2.png", "images/3.png"]);
415
+ */
416
+ this.deleteMany = (pathnames) => __awaiter(this, void 0, void 0, function* () {
417
+ return jsonFetch(`${this.config.apiURI}/admin/storage/files/delete`, {
418
+ method: 'POST',
419
+ headers: authorizedHeaders(this.config, this.impersonationOpts),
420
+ body: JSON.stringify({ filenames: pathnames }),
421
+ });
439
422
  });
440
- const headers = {};
441
- const contentType = metadata.contentType;
442
- if (contentType) {
443
- headers['Content-Type'] = contentType;
444
- }
445
- const { ok } = await fetch(presignedUrl, {
446
- method: 'PUT',
447
- body: file,
448
- headers,
423
+ /**
424
+ * @deprecated. This method will be removed in the future. Use `uploadFile`
425
+ * instead
426
+ */
427
+ this.upload = (pathname_1, file_1, ...args_1) => __awaiter(this, [pathname_1, file_1, ...args_1], void 0, function* (pathname, file, metadata = {}) {
428
+ const { data: presignedUrl } = yield jsonFetch(`${this.config.apiURI}/admin/storage/signed-upload-url`, {
429
+ method: 'POST',
430
+ headers: authorizedHeaders(this.config),
431
+ body: JSON.stringify({
432
+ app_id: this.config.appId,
433
+ filename: pathname,
434
+ }),
435
+ });
436
+ const headers = {};
437
+ const contentType = metadata.contentType;
438
+ if (contentType) {
439
+ headers['Content-Type'] = contentType;
440
+ }
441
+ const { ok } = yield fetch(presignedUrl, {
442
+ method: 'PUT',
443
+ body: file,
444
+ headers,
445
+ });
446
+ return ok;
449
447
  });
450
- return ok;
451
- };
452
- /**
453
- * @deprecated. This method will be removed in the future. Use `query` instead
454
- * @example
455
- * const files = await db.query({ $files: {}})
456
- */
457
- list = async () => {
458
- const { data } = await jsonFetch(`${this.config.apiURI}/admin/storage/files`, {
459
- method: 'GET',
460
- headers: authorizedHeaders(this.config),
448
+ /**
449
+ * @deprecated. This method will be removed in the future. Use `query` instead
450
+ * @example
451
+ * const files = await db.query({ $files: {}})
452
+ */
453
+ this.list = () => __awaiter(this, void 0, void 0, function* () {
454
+ const { data } = yield jsonFetch(`${this.config.apiURI}/admin/storage/files`, {
455
+ method: 'GET',
456
+ headers: authorizedHeaders(this.config),
457
+ });
458
+ return data;
461
459
  });
462
- return data;
463
- };
464
- /**
465
- * @deprecated. getDownloadUrl will be removed in the future.
466
- * Use `query` instead to query and fetch for valid urls
467
- *
468
- * db.useQuery({
469
- * $files: {
470
- * $: {
471
- * where: {
472
- * path: "moop.png"
473
- * }
474
- * }
475
- * }
476
- * })
477
- */
478
- getDownloadUrl = async (pathname) => {
479
- const { data } = await jsonFetch(`${this.config.apiURI}/admin/storage/signed-download-url?app_id=${this.config.appId}&filename=${encodeURIComponent(pathname)}`, {
480
- method: 'GET',
481
- headers: authorizedHeaders(this.config),
460
+ /**
461
+ * @deprecated. getDownloadUrl will be removed in the future.
462
+ * Use `query` instead to query and fetch for valid urls
463
+ *
464
+ * db.useQuery({
465
+ * $files: {
466
+ * $: {
467
+ * where: {
468
+ * path: "moop.png"
469
+ * }
470
+ * }
471
+ * }
472
+ * })
473
+ */
474
+ this.getDownloadUrl = (pathname) => __awaiter(this, void 0, void 0, function* () {
475
+ const { data } = yield jsonFetch(`${this.config.apiURI}/admin/storage/signed-download-url?app_id=${this.config.appId}&filename=${encodeURIComponent(pathname)}`, {
476
+ method: 'GET',
477
+ headers: authorizedHeaders(this.config),
478
+ });
479
+ return data;
482
480
  });
483
- return data;
484
- };
481
+ this.config = config;
482
+ this.impersonationOpts = impersonationOpts;
483
+ }
485
484
  }
486
485
  /**
487
486
  *
@@ -493,72 +492,158 @@ class Storage {
493
492
  * const db = init({ appId: "my-app-id", adminToken: "my-admin-token" })
494
493
  */
495
494
  class InstantAdminDatabase {
496
- config;
497
- auth;
498
- storage;
499
- rooms;
500
- impersonationOpts;
501
- tx = (0, core_1.txInit)();
502
495
  constructor(_config) {
496
+ this.tx = (0, core_1.txInit)();
497
+ /**
498
+ * Sometimes you want to scope queries to a specific user.
499
+ *
500
+ * You can provide a user's auth token, email, or impersonate a guest.
501
+ *
502
+ * @see https://instantdb.com/docs/backend#impersonating-users
503
+ * @example
504
+ * await db.asUser({email: "stopa@instantdb.com"}).query({ goals: {} })
505
+ */
506
+ this.asUser = (opts) => {
507
+ const newClient = new InstantAdminDatabase(Object.assign({}, this.config));
508
+ newClient.impersonationOpts = opts;
509
+ newClient.storage = new Storage(this.config, opts);
510
+ return newClient;
511
+ };
512
+ /**
513
+ * Use this to query your data!
514
+ *
515
+ * @see https://instantdb.com/docs/instaql
516
+ *
517
+ * @example
518
+ * // fetch all goals
519
+ * await db.query({ goals: {} })
520
+ *
521
+ * // goals where the title is "Get Fit"
522
+ * await db.query({ goals: { $: { where: { title: "Get Fit" } } } })
523
+ *
524
+ * // all goals, _alongside_ their todos
525
+ * await db.query({ goals: { todos: {} } })
526
+ */
527
+ this.query = (query, opts = {}) => {
528
+ if (query && opts && 'ruleParams' in opts) {
529
+ query = Object.assign({ $$ruleParams: opts['ruleParams'] }, query);
530
+ }
531
+ if (!this.config.disableValidation) {
532
+ (0, core_1.validateQuery)(query, this.config.schema);
533
+ }
534
+ const fetchOpts = opts.fetchOpts || {};
535
+ const fetchOptsHeaders = fetchOpts['headers'] || {};
536
+ return jsonFetch(`${this.config.apiURI}/admin/query`, Object.assign(Object.assign({}, fetchOpts), { method: 'POST', headers: Object.assign(Object.assign({}, fetchOptsHeaders), authorizedHeaders(this.config, this.impersonationOpts)), body: JSON.stringify({
537
+ query: query,
538
+ 'inference?': !!this.config.schema,
539
+ }) }));
540
+ };
541
+ /**
542
+ * Use this to write data! You can create, update, delete, and link objects
543
+ *
544
+ * @see https://instantdb.com/docs/instaml
545
+ *
546
+ * @example
547
+ * // Create a new object in the `goals` namespace
548
+ * const goalId = id();
549
+ * db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
550
+ *
551
+ * // Update the title
552
+ * db.transact(db.tx.goals[goalId].update({title: "Get super fit"}))
553
+ *
554
+ * // Delete it
555
+ * db.transact(db.tx.goals[goalId].delete())
556
+ *
557
+ * // Or create an association:
558
+ * todoId = id();
559
+ * db.transact([
560
+ * db.tx.todos[todoId].update({ title: 'Go on a run' }),
561
+ * db.tx.goals[goalId].link({todos: todoId}),
562
+ * ])
563
+ */
564
+ this.transact = (inputChunks) => {
565
+ if (!this.config.disableValidation) {
566
+ (0, core_1.validateTransactions)(inputChunks, this.config.schema);
567
+ }
568
+ return jsonFetch(`${this.config.apiURI}/admin/transact`, {
569
+ method: 'POST',
570
+ headers: authorizedHeaders(this.config, this.impersonationOpts),
571
+ body: JSON.stringify({
572
+ steps: steps(inputChunks),
573
+ 'throw-on-missing-attrs?': !!this.config.schema,
574
+ }),
575
+ });
576
+ };
577
+ /**
578
+ * Like `query`, but returns debugging information
579
+ * for permissions checks along with the result.
580
+ * Useful for inspecting the values returned by the permissions checks.
581
+ * Note, this will return debug information for *all* entities
582
+ * that match the query's `where` clauses.
583
+ *
584
+ * Requires a user/guest context to be set with `asUser`,
585
+ * since permissions checks are user-specific.
586
+ *
587
+ * Accepts an optional configuration object with a `rules` key.
588
+ * The provided rules will override the rules in the database for the query.
589
+ *
590
+ * @see https://instantdb.com/docs/instaql
591
+ *
592
+ * @example
593
+ * await db.asUser({ guest: true }).debugQuery(
594
+ * { goals: {} },
595
+ * { rules: { goals: { allow: { read: "auth.id != null" } } }
596
+ * )
597
+ */
598
+ this.debugQuery = (query, opts) => __awaiter(this, void 0, void 0, function* () {
599
+ if (query && opts && 'ruleParams' in opts) {
600
+ query = Object.assign({ $$ruleParams: opts['ruleParams'] }, query);
601
+ }
602
+ const response = yield jsonFetch(`${this.config.apiURI}/admin/query_perms_check`, {
603
+ method: 'POST',
604
+ headers: authorizedHeaders(this.config, this.impersonationOpts),
605
+ body: JSON.stringify({ query, 'rules-override': opts === null || opts === void 0 ? void 0 : opts.rules }),
606
+ });
607
+ return {
608
+ result: response.result,
609
+ checkResults: response['check-results'],
610
+ };
611
+ });
612
+ /**
613
+ * Like `transact`, but does not write to the database.
614
+ * Returns debugging information for permissions checks.
615
+ * Useful for inspecting the values returned by the permissions checks.
616
+ *
617
+ * Requires a user/guest context to be set with `asUser`,
618
+ * since permissions checks are user-specific.
619
+ *
620
+ * Accepts an optional configuration object with a `rules` key.
621
+ * The provided rules will override the rules in the database for the duration of the transaction.
622
+ *
623
+ * @example
624
+ * const goalId = id();
625
+ * db.asUser({ guest: true }).debugTransact(
626
+ * [db.tx.goals[goalId].update({title: "Get fit"})],
627
+ * { rules: { goals: { allow: { update: "auth.id != null" } } }
628
+ * )
629
+ */
630
+ this.debugTransact = (inputChunks, opts) => {
631
+ return jsonFetch(`${this.config.apiURI}/admin/transact_perms_check`, {
632
+ method: 'POST',
633
+ headers: authorizedHeaders(this.config, this.impersonationOpts),
634
+ body: JSON.stringify({
635
+ steps: steps(inputChunks),
636
+ 'rules-override': opts === null || opts === void 0 ? void 0 : opts.rules,
637
+ // @ts-expect-error because we're using a private API (for now)
638
+ 'dangerously-commit-tx': opts === null || opts === void 0 ? void 0 : opts.__dangerouslyCommit,
639
+ }),
640
+ });
641
+ };
503
642
  this.config = instantConfigWithDefaults(_config);
504
643
  this.auth = new Auth(this.config);
505
644
  this.storage = new Storage(this.config, this.impersonationOpts);
506
645
  this.rooms = new Rooms(this.config);
507
646
  }
508
- /**
509
- * Sometimes you want to scope queries to a specific user.
510
- *
511
- * You can provide a user's auth token, email, or impersonate a guest.
512
- *
513
- * @see https://instantdb.com/docs/backend#impersonating-users
514
- * @example
515
- * await db.asUser({email: "stopa@instantdb.com"}).query({ goals: {} })
516
- */
517
- asUser = (opts) => {
518
- const newClient = new InstantAdminDatabase({
519
- ...this.config,
520
- });
521
- newClient.impersonationOpts = opts;
522
- newClient.storage = new Storage(this.config, opts);
523
- return newClient;
524
- };
525
- /**
526
- * Use this to query your data!
527
- *
528
- * @see https://instantdb.com/docs/instaql
529
- *
530
- * @example
531
- * // fetch all goals
532
- * await db.query({ goals: {} })
533
- *
534
- * // goals where the title is "Get Fit"
535
- * await db.query({ goals: { $: { where: { title: "Get Fit" } } } })
536
- *
537
- * // all goals, _alongside_ their todos
538
- * await db.query({ goals: { todos: {} } })
539
- */
540
- query = (query, opts = {}) => {
541
- if (query && opts && 'ruleParams' in opts) {
542
- query = { $$ruleParams: opts['ruleParams'], ...query };
543
- }
544
- if (!this.config.disableValidation) {
545
- (0, core_1.validateQuery)(query, this.config.schema);
546
- }
547
- const fetchOpts = opts.fetchOpts || {};
548
- const fetchOptsHeaders = fetchOpts['headers'] || {};
549
- return jsonFetch(`${this.config.apiURI}/admin/query`, {
550
- ...fetchOpts,
551
- method: 'POST',
552
- headers: {
553
- ...fetchOptsHeaders,
554
- ...authorizedHeaders(this.config, this.impersonationOpts),
555
- },
556
- body: JSON.stringify({
557
- query: query,
558
- 'inference?': !!this.config.schema,
559
- }),
560
- });
561
- };
562
647
  /**
563
648
  * Use this to to get a live view of your data!
564
649
  *
@@ -596,17 +681,14 @@ class InstantAdminDatabase {
596
681
  */
597
682
  subscribeQuery(query, cb, opts = {}) {
598
683
  if (query && opts && 'ruleParams' in opts) {
599
- query = { $$ruleParams: opts['ruleParams'], ...query };
684
+ query = Object.assign({ $$ruleParams: opts['ruleParams'] }, query);
600
685
  }
601
686
  if (!this.config.disableValidation) {
602
687
  (0, core_1.validateQuery)(query, this.config.schema);
603
688
  }
604
689
  const fetchOpts = opts.fetchOpts || {};
605
690
  const fetchOptsHeaders = fetchOpts['headers'] || {};
606
- const headers = {
607
- ...fetchOptsHeaders,
608
- ...authorizedHeaders(this.config, this.impersonationOpts),
609
- };
691
+ const headers = Object.assign(Object.assign({}, fetchOptsHeaders), authorizedHeaders(this.config, this.impersonationOpts));
610
692
  const inference = !!this.config.schema;
611
693
  return (0, subscribe_ts_1.subscribe)(query, cb, {
612
694
  headers,
@@ -614,106 +696,5 @@ class InstantAdminDatabase {
614
696
  apiURI: this.config.apiURI,
615
697
  });
616
698
  }
617
- /**
618
- * Use this to write data! You can create, update, delete, and link objects
619
- *
620
- * @see https://instantdb.com/docs/instaml
621
- *
622
- * @example
623
- * // Create a new object in the `goals` namespace
624
- * const goalId = id();
625
- * db.transact(db.tx.goals[goalId].update({title: "Get fit"}))
626
- *
627
- * // Update the title
628
- * db.transact(db.tx.goals[goalId].update({title: "Get super fit"}))
629
- *
630
- * // Delete it
631
- * db.transact(db.tx.goals[goalId].delete())
632
- *
633
- * // Or create an association:
634
- * todoId = id();
635
- * db.transact([
636
- * db.tx.todos[todoId].update({ title: 'Go on a run' }),
637
- * db.tx.goals[goalId].link({todos: todoId}),
638
- * ])
639
- */
640
- transact = (inputChunks) => {
641
- if (!this.config.disableValidation) {
642
- (0, core_1.validateTransactions)(inputChunks, this.config.schema);
643
- }
644
- return jsonFetch(`${this.config.apiURI}/admin/transact`, {
645
- method: 'POST',
646
- headers: authorizedHeaders(this.config, this.impersonationOpts),
647
- body: JSON.stringify({
648
- steps: steps(inputChunks),
649
- 'throw-on-missing-attrs?': !!this.config.schema,
650
- }),
651
- });
652
- };
653
- /**
654
- * Like `query`, but returns debugging information
655
- * for permissions checks along with the result.
656
- * Useful for inspecting the values returned by the permissions checks.
657
- * Note, this will return debug information for *all* entities
658
- * that match the query's `where` clauses.
659
- *
660
- * Requires a user/guest context to be set with `asUser`,
661
- * since permissions checks are user-specific.
662
- *
663
- * Accepts an optional configuration object with a `rules` key.
664
- * The provided rules will override the rules in the database for the query.
665
- *
666
- * @see https://instantdb.com/docs/instaql
667
- *
668
- * @example
669
- * await db.asUser({ guest: true }).debugQuery(
670
- * { goals: {} },
671
- * { rules: { goals: { allow: { read: "auth.id != null" } } }
672
- * )
673
- */
674
- debugQuery = async (query, opts) => {
675
- if (query && opts && 'ruleParams' in opts) {
676
- query = { $$ruleParams: opts['ruleParams'], ...query };
677
- }
678
- const response = await jsonFetch(`${this.config.apiURI}/admin/query_perms_check`, {
679
- method: 'POST',
680
- headers: authorizedHeaders(this.config, this.impersonationOpts),
681
- body: JSON.stringify({ query, 'rules-override': opts?.rules }),
682
- });
683
- return {
684
- result: response.result,
685
- checkResults: response['check-results'],
686
- };
687
- };
688
- /**
689
- * Like `transact`, but does not write to the database.
690
- * Returns debugging information for permissions checks.
691
- * Useful for inspecting the values returned by the permissions checks.
692
- *
693
- * Requires a user/guest context to be set with `asUser`,
694
- * since permissions checks are user-specific.
695
- *
696
- * Accepts an optional configuration object with a `rules` key.
697
- * The provided rules will override the rules in the database for the duration of the transaction.
698
- *
699
- * @example
700
- * const goalId = id();
701
- * db.asUser({ guest: true }).debugTransact(
702
- * [db.tx.goals[goalId].update({title: "Get fit"})],
703
- * { rules: { goals: { allow: { update: "auth.id != null" } } }
704
- * )
705
- */
706
- debugTransact = (inputChunks, opts) => {
707
- return jsonFetch(`${this.config.apiURI}/admin/transact_perms_check`, {
708
- method: 'POST',
709
- headers: authorizedHeaders(this.config, this.impersonationOpts),
710
- body: JSON.stringify({
711
- steps: steps(inputChunks),
712
- 'rules-override': opts?.rules,
713
- // @ts-expect-error because we're using a private API (for now)
714
- 'dangerously-commit-tx': opts?.__dangerouslyCommit,
715
- }),
716
- });
717
- };
718
699
  }
719
700
  //# sourceMappingURL=index.js.map