@instantdb/platform 0.22.99-experimental.add-user-perm-rules.20792844601.1 → 0.22.99

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 (48) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/dist/commonjs/ProgressPromise.js +45 -58
  3. package/dist/commonjs/ProgressPromise.js.map +1 -1
  4. package/dist/commonjs/api.js +366 -412
  5. package/dist/commonjs/api.js.map +1 -1
  6. package/dist/commonjs/migrationUtils.js +16 -4
  7. package/dist/commonjs/migrationUtils.js.map +1 -1
  8. package/dist/commonjs/migrations.js +10 -21
  9. package/dist/commonjs/migrations.js.map +1 -1
  10. package/dist/commonjs/oauth.js +52 -55
  11. package/dist/commonjs/oauth.js.map +1 -1
  12. package/dist/commonjs/oauthCommon.js +2 -0
  13. package/dist/commonjs/oauthCommon.js.map +1 -1
  14. package/dist/commonjs/perms.js +1 -1
  15. package/dist/commonjs/perms.js.map +1 -1
  16. package/dist/commonjs/schema.js +8 -14
  17. package/dist/commonjs/schema.js.map +1 -1
  18. package/dist/commonjs/serverOAuth.js +55 -68
  19. package/dist/commonjs/serverOAuth.js.map +1 -1
  20. package/dist/commonjs/typescript-schema.js +1 -2
  21. package/dist/commonjs/typescript-schema.js.map +1 -1
  22. package/dist/commonjs/util.js +1 -1
  23. package/dist/commonjs/util.js.map +1 -1
  24. package/dist/esm/ProgressPromise.js +45 -58
  25. package/dist/esm/ProgressPromise.js.map +1 -1
  26. package/dist/esm/api.js +366 -412
  27. package/dist/esm/api.js.map +1 -1
  28. package/dist/esm/migrationUtils.js +16 -4
  29. package/dist/esm/migrationUtils.js.map +1 -1
  30. package/dist/esm/migrations.js +10 -21
  31. package/dist/esm/migrations.js.map +1 -1
  32. package/dist/esm/oauth.js +52 -55
  33. package/dist/esm/oauth.js.map +1 -1
  34. package/dist/esm/oauthCommon.js +2 -0
  35. package/dist/esm/oauthCommon.js.map +1 -1
  36. package/dist/esm/perms.js +1 -1
  37. package/dist/esm/perms.js.map +1 -1
  38. package/dist/esm/schema.js +8 -14
  39. package/dist/esm/schema.js.map +1 -1
  40. package/dist/esm/serverOAuth.js +55 -68
  41. package/dist/esm/serverOAuth.js.map +1 -1
  42. package/dist/esm/typescript-schema.js +1 -2
  43. package/dist/esm/typescript-schema.js.map +1 -1
  44. package/dist/esm/util.js +1 -1
  45. package/dist/esm/util.js.map +1 -1
  46. package/dist/standalone/index.js +690 -660
  47. package/dist/standalone/index.umd.cjs +16 -16
  48. package/package.json +3 -3
package/dist/esm/api.js CHANGED
@@ -1,50 +1,33 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
11
- if (kind === "m") throw new TypeError("Private method is not writable");
12
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
13
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
14
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
15
- };
16
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
17
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
18
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
19
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
20
- };
21
- var _PlatformApi_auth, _PlatformApi_apiURI;
22
1
  import { InstantAPIError, version as coreVersion, i, } from '@instantdb/core';
23
2
  import version from "./version.js";
24
3
  import { attrFwdLabel, attrFwdName, attrRevName, identName, } from "./schema.js";
25
4
  import { ProgressPromise } from "./ProgressPromise.js";
26
5
  import { capitalizeFirstLetter, deriveClientType, rels, sortedEntries, } from "./util.js";
27
6
  import { exchangeRefreshToken } from "./serverOAuth.js";
28
- function jsonFetch(input, init) {
29
- return __awaiter(this, void 0, void 0, function* () {
30
- const headers = Object.assign(Object.assign({}, ((init === null || init === void 0 ? void 0 : init.headers) || {})), { 'Instant-Platform-Version': version, 'Instant-Core-Version': coreVersion, 'X-Instant-Source': 'platform-sdk', 'X-Instant-Version': version });
31
- const res = yield fetch(input, Object.assign(Object.assign({}, init), { headers }));
32
- if (res.status === 200) {
33
- const json = yield res.json();
34
- return Promise.resolve(json);
35
- }
36
- const body = yield res.text();
37
- try {
38
- const json = JSON.parse(body);
39
- return Promise.reject(new InstantAPIError({ status: res.status, body: json }));
40
- }
41
- catch (_e) {
42
- return Promise.reject(new InstantAPIError({
43
- status: res.status,
44
- body: { type: undefined, message: body },
45
- }));
46
- }
47
- });
7
+ async function jsonFetch(input, init) {
8
+ const headers = {
9
+ ...(init?.headers || {}),
10
+ 'Instant-Platform-Version': version,
11
+ 'Instant-Core-Version': coreVersion,
12
+ 'X-Instant-Source': 'platform-sdk',
13
+ 'X-Instant-Version': version,
14
+ };
15
+ const res = await fetch(input, { ...init, headers });
16
+ if (res.status === 200) {
17
+ const json = await res.json();
18
+ return Promise.resolve(json);
19
+ }
20
+ const body = await res.text();
21
+ try {
22
+ const json = JSON.parse(body);
23
+ return Promise.reject(new InstantAPIError({ status: res.status, body: json }));
24
+ }
25
+ catch (_e) {
26
+ return Promise.reject(new InstantAPIError({
27
+ status: res.status,
28
+ body: { type: undefined, message: body },
29
+ }));
30
+ }
48
31
  }
49
32
  function attrDefForType(type) {
50
33
  switch (type) {
@@ -67,7 +50,7 @@ function attrDefForType(type) {
67
50
  }
68
51
  }
69
52
  function apiSchemaAttrToDataAttrDef(attr, opts) {
70
- const derivedType = deriveClientType(attr, opts === null || opts === void 0 ? void 0 : opts.disableTypeInference);
53
+ const derivedType = deriveClientType(attr, opts?.disableTypeInference);
71
54
  let i = attrDefForType(derivedType.type);
72
55
  if (attr['unique?']) {
73
56
  i = i.unique();
@@ -131,7 +114,13 @@ export function apiSchemaToInstantSchemaDef(apiSchema, opts) {
131
114
  return i.schema({ entities, links });
132
115
  }
133
116
  function coerceApp(app) {
134
- const base = Object.assign({ id: app.id, title: app.title, createdAt: new Date(app.created_at), orgId: app.org_id }, (app['admin-token'] ? { adminToken: app['admin-token'] } : {}));
117
+ const base = {
118
+ id: app.id,
119
+ title: app.title,
120
+ createdAt: new Date(app.created_at),
121
+ orgId: app.org_id,
122
+ ...(app['admin-token'] ? { adminToken: app['admin-token'] } : {}),
123
+ };
135
124
  // `in` narrows the union, so it’s safe to read `perms` / `schema`
136
125
  // when the property exists. :contentReference[oaicite:0]{index=0}
137
126
  const permsPart = ('perms' in app ? { perms: app.perms } : {});
@@ -140,7 +129,7 @@ function coerceApp(app) {
140
129
  schema: apiSchemaToInstantSchemaDef(app.schema),
141
130
  }
142
131
  : {});
143
- return Object.assign(Object.assign(Object.assign({}, base), permsPart), schemaPart);
132
+ return { ...base, ...permsPart, ...schemaPart };
144
133
  }
145
134
  function coerceOrg(org) {
146
135
  return {
@@ -149,167 +138,157 @@ function coerceOrg(org) {
149
138
  createdAt: new Date(org.created_at),
150
139
  };
151
140
  }
152
- function getApps(apiURI, token, opts) {
153
- return __awaiter(this, void 0, void 0, function* () {
154
- const url = new URL(`${apiURI}/superadmin/apps`);
155
- const include = [];
156
- if (opts === null || opts === void 0 ? void 0 : opts.includePerms) {
157
- include.push('perms');
158
- }
159
- if (opts === null || opts === void 0 ? void 0 : opts.includeSchema) {
160
- include.push('schema');
161
- }
162
- if (include.length) {
163
- url.searchParams.set('include', include.join(','));
164
- }
165
- const resp = yield jsonFetch(url.toString(), {
166
- method: 'GET',
167
- headers: {
168
- Authorization: `Bearer ${token}`,
169
- },
170
- });
171
- return { apps: resp.apps.map(coerceApp) };
141
+ async function getApps(apiURI, token, opts) {
142
+ const url = new URL(`${apiURI}/superadmin/apps`);
143
+ const include = [];
144
+ if (opts?.includePerms) {
145
+ include.push('perms');
146
+ }
147
+ if (opts?.includeSchema) {
148
+ include.push('schema');
149
+ }
150
+ if (include.length) {
151
+ url.searchParams.set('include', include.join(','));
152
+ }
153
+ const resp = await jsonFetch(url.toString(), {
154
+ method: 'GET',
155
+ headers: {
156
+ Authorization: `Bearer ${token}`,
157
+ },
172
158
  });
173
- }
174
- function getOrgs(apiURI, token) {
175
- return __awaiter(this, void 0, void 0, function* () {
176
- const url = new URL(`${apiURI}/superadmin/orgs`);
177
- const resp = yield jsonFetch(url.toString(), {
178
- method: 'GET',
179
- headers: {
180
- Authorization: `Bearer ${token}`,
181
- },
182
- });
183
- return { orgs: resp.orgs.map(coerceOrg) };
159
+ return { apps: resp.apps.map(coerceApp) };
160
+ }
161
+ async function getOrgs(apiURI, token) {
162
+ const url = new URL(`${apiURI}/superadmin/orgs`);
163
+ const resp = await jsonFetch(url.toString(), {
164
+ method: 'GET',
165
+ headers: {
166
+ Authorization: `Bearer ${token}`,
167
+ },
184
168
  });
169
+ return { orgs: resp.orgs.map(coerceOrg) };
185
170
  }
186
- function getAppsForOrg(apiURI, token, orgId, opts) {
187
- return __awaiter(this, void 0, void 0, function* () {
188
- const url = new URL(`${apiURI}/superadmin/orgs/${orgId}/apps`);
189
- const include = [];
190
- if (opts === null || opts === void 0 ? void 0 : opts.includePerms) {
191
- include.push('perms');
192
- }
193
- if (opts === null || opts === void 0 ? void 0 : opts.includeSchema) {
194
- include.push('schema');
195
- }
196
- if (include.length) {
197
- url.searchParams.set('include', include.join(','));
198
- }
199
- const resp = yield jsonFetch(url.toString(), {
200
- method: 'GET',
201
- headers: {
202
- Authorization: `Bearer ${token}`,
203
- },
204
- });
205
- return { apps: resp.apps.map(coerceApp) };
171
+ async function getAppsForOrg(apiURI, token, orgId, opts) {
172
+ const url = new URL(`${apiURI}/superadmin/orgs/${orgId}/apps`);
173
+ const include = [];
174
+ if (opts?.includePerms) {
175
+ include.push('perms');
176
+ }
177
+ if (opts?.includeSchema) {
178
+ include.push('schema');
179
+ }
180
+ if (include.length) {
181
+ url.searchParams.set('include', include.join(','));
182
+ }
183
+ const resp = await jsonFetch(url.toString(), {
184
+ method: 'GET',
185
+ headers: {
186
+ Authorization: `Bearer ${token}`,
187
+ },
206
188
  });
189
+ return { apps: resp.apps.map(coerceApp) };
207
190
  }
208
- function getAppSchema(apiURI, token, appId) {
209
- return __awaiter(this, void 0, void 0, function* () {
210
- const { schema } = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema`, {
211
- method: 'GET',
212
- headers: {
213
- Authorization: `Bearer ${token}`,
214
- },
215
- });
216
- return { schema: apiSchemaToInstantSchemaDef(schema) };
191
+ async function getAppSchema(apiURI, token, appId) {
192
+ const { schema } = await jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema`, {
193
+ method: 'GET',
194
+ headers: {
195
+ Authorization: `Bearer ${token}`,
196
+ },
217
197
  });
198
+ return { schema: apiSchemaToInstantSchemaDef(schema) };
218
199
  }
219
- function getAppPerms(apiURI, token, appId) {
220
- return __awaiter(this, void 0, void 0, function* () {
221
- return yield jsonFetch(`${apiURI}/superadmin/apps/${appId}/perms`, {
222
- method: 'GET',
223
- headers: {
224
- Authorization: `Bearer ${token}`,
225
- },
226
- });
200
+ async function getAppPerms(apiURI, token, appId) {
201
+ return await jsonFetch(`${apiURI}/superadmin/apps/${appId}/perms`, {
202
+ method: 'GET',
203
+ headers: {
204
+ Authorization: `Bearer ${token}`,
205
+ },
227
206
  });
228
207
  }
229
- function getApp(apiURI, token, appId, opts) {
230
- return __awaiter(this, void 0, void 0, function* () {
231
- let permsPromise = null;
232
- let schemaPromise = null;
233
- if (opts === null || opts === void 0 ? void 0 : opts.includePerms) {
234
- permsPromise = getAppPerms(apiURI, token, appId);
235
- }
236
- if (opts === null || opts === void 0 ? void 0 : opts.includeSchema) {
237
- schemaPromise = getAppSchema(apiURI, token, appId);
238
- }
239
- const { app: apiApp } = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
240
- method: 'GET',
241
- headers: {
242
- Authorization: `Bearer ${token}`,
243
- },
244
- });
245
- if (!permsPromise && !schemaPromise) {
246
- const app = coerceApp(apiApp);
247
- return { app };
248
- }
249
- const app = Object.assign(Object.assign(Object.assign({}, coerceApp(apiApp)), (permsPromise ? { perms: (yield permsPromise).perms } : {})), (schemaPromise ? { schema: (yield schemaPromise).schema } : {}));
250
- return {
251
- app,
252
- };
208
+ async function getApp(apiURI, token, appId, opts) {
209
+ let permsPromise = null;
210
+ let schemaPromise = null;
211
+ if (opts?.includePerms) {
212
+ permsPromise = getAppPerms(apiURI, token, appId);
213
+ }
214
+ if (opts?.includeSchema) {
215
+ schemaPromise = getAppSchema(apiURI, token, appId);
216
+ }
217
+ const { app: apiApp } = await jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
218
+ method: 'GET',
219
+ headers: {
220
+ Authorization: `Bearer ${token}`,
221
+ },
253
222
  });
223
+ if (!permsPromise && !schemaPromise) {
224
+ const app = coerceApp(apiApp);
225
+ return { app };
226
+ }
227
+ const app = {
228
+ ...coerceApp(apiApp),
229
+ ...(permsPromise ? { perms: (await permsPromise).perms } : {}),
230
+ ...(schemaPromise ? { schema: (await schemaPromise).schema } : {}),
231
+ };
232
+ return {
233
+ app,
234
+ };
254
235
  }
255
- function createApp(apiURI, token, fields) {
256
- return __awaiter(this, void 0, void 0, function* () {
257
- const apiFields = fields;
258
- apiFields.org_id = fields.orgId;
259
- const { app } = yield jsonFetch(`${apiURI}/superadmin/apps`, {
260
- method: 'POST',
261
- headers: {
262
- 'Content-Type': 'application/json',
263
- Authorization: `Bearer ${token}`,
264
- },
265
- body: JSON.stringify(apiFields),
266
- });
267
- const withAdminToken = Object.assign(Object.assign({}, coerceApp(app)), { adminToken: app['admin-token'] });
268
- return {
269
- app: withAdminToken,
270
- };
236
+ async function createApp(apiURI, token, fields) {
237
+ const apiFields = fields;
238
+ apiFields.org_id = fields.orgId;
239
+ const { app } = await jsonFetch(`${apiURI}/superadmin/apps`, {
240
+ method: 'POST',
241
+ headers: {
242
+ 'Content-Type': 'application/json',
243
+ Authorization: `Bearer ${token}`,
244
+ },
245
+ body: JSON.stringify(apiFields),
271
246
  });
247
+ const withAdminToken = {
248
+ ...coerceApp(app),
249
+ adminToken: app['admin-token'],
250
+ };
251
+ return {
252
+ app: withAdminToken,
253
+ };
272
254
  }
273
- function createTemporaryApp(apiURI, fields) {
274
- return __awaiter(this, void 0, void 0, function* () {
275
- const response = yield jsonFetch(`${apiURI}/dash/apps/ephemeral`, {
276
- method: 'POST',
277
- headers: {
278
- 'Content-Type': 'application/json',
279
- },
280
- body: JSON.stringify(fields),
281
- });
282
- const withAdminToken = Object.assign(Object.assign({}, coerceApp(response.app)), { adminToken: response.app['admin-token'] });
283
- return {
284
- app: withAdminToken,
285
- expiresMs: response.expires_ms,
286
- };
255
+ async function createTemporaryApp(apiURI, fields) {
256
+ const response = await jsonFetch(`${apiURI}/dash/apps/ephemeral`, {
257
+ method: 'POST',
258
+ headers: {
259
+ 'Content-Type': 'application/json',
260
+ },
261
+ body: JSON.stringify(fields),
287
262
  });
263
+ const withAdminToken = {
264
+ ...coerceApp(response.app),
265
+ adminToken: response.app['admin-token'],
266
+ };
267
+ return {
268
+ app: withAdminToken,
269
+ expiresMs: response.expires_ms,
270
+ };
288
271
  }
289
- function updateApp(apiURI, token, appId, fields) {
290
- return __awaiter(this, void 0, void 0, function* () {
291
- const { app } = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
292
- method: 'POST',
293
- headers: {
294
- 'Content-Type': 'application/json',
295
- Authorization: `Bearer ${token}`,
296
- },
297
- body: JSON.stringify(fields),
298
- });
299
- return { app: coerceApp(app) };
272
+ async function updateApp(apiURI, token, appId, fields) {
273
+ const { app } = await jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
274
+ method: 'POST',
275
+ headers: {
276
+ 'Content-Type': 'application/json',
277
+ Authorization: `Bearer ${token}`,
278
+ },
279
+ body: JSON.stringify(fields),
300
280
  });
301
- }
302
- function deleteApp(apiURI, token, appId) {
303
- return __awaiter(this, void 0, void 0, function* () {
304
- const { app } = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
305
- method: 'DELETE',
306
- headers: {
307
- 'Content-Type': 'application/json',
308
- Authorization: `Bearer ${token}`,
309
- },
310
- });
311
- return { app: coerceApp(app) };
281
+ return { app: coerceApp(app) };
282
+ }
283
+ async function deleteApp(apiURI, token, appId) {
284
+ const { app } = await jsonFetch(`${apiURI}/superadmin/apps/${appId}`, {
285
+ method: 'DELETE',
286
+ headers: {
287
+ 'Content-Type': 'application/json',
288
+ Authorization: `Bearer ${token}`,
289
+ },
312
290
  });
291
+ return { app: coerceApp(app) };
313
292
  }
314
293
  function translatePlanStep(apiStep) {
315
294
  const [stepType, stepParams] = apiStep;
@@ -435,27 +414,29 @@ function translatePushStep(apiStep, jobs) {
435
414
  if (planStep.type !== backgroundJob.type) {
436
415
  throw new Error('Invalid type');
437
416
  }
438
- return Object.assign(Object.assign({}, planStep), { backgroundJob });
417
+ return { ...planStep, backgroundJob };
439
418
  }
440
419
  function translatePushSteps(apiSteps, jobs) {
441
420
  return apiSteps.map((step) => translatePushStep(step, jobs));
442
421
  }
443
- function planSchemaPush(apiURI, token, appId, body) {
444
- return __awaiter(this, void 0, void 0, function* () {
445
- const resp = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema/push/plan`, {
446
- method: 'POST',
447
- headers: {
448
- 'Content-Type': 'application/json',
449
- Authorization: `Bearer ${token}`,
450
- },
451
- body: JSON.stringify(Object.assign(Object.assign({}, body), { check_types: true, supports_background_updates: true })),
452
- });
453
- return {
454
- newSchema: apiSchemaToInstantSchemaDef(resp['new-schema']),
455
- currentSchema: apiSchemaToInstantSchemaDef(resp['current-schema']),
456
- steps: translatePlanSteps(resp['steps']),
457
- };
422
+ async function planSchemaPush(apiURI, token, appId, body) {
423
+ const resp = await jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema/push/plan`, {
424
+ method: 'POST',
425
+ headers: {
426
+ 'Content-Type': 'application/json',
427
+ Authorization: `Bearer ${token}`,
428
+ },
429
+ body: JSON.stringify({
430
+ ...body,
431
+ check_types: true,
432
+ supports_background_updates: true,
433
+ }),
458
434
  });
435
+ return {
436
+ newSchema: apiSchemaToInstantSchemaDef(resp['new-schema']),
437
+ currentSchema: apiSchemaToInstantSchemaDef(resp['current-schema']),
438
+ steps: translatePlanSteps(resp['steps']),
439
+ };
459
440
  }
460
441
  function allJobsComplete(jobs) {
461
442
  return !!jobs.find((j) => j.job_status === 'completed' || j.job_status === 'errored');
@@ -472,47 +453,44 @@ function latestJobUpdate(jobs) {
472
453
  }, null);
473
454
  return res;
474
455
  }
475
- function jobFetchLoop(apiURI, token, appId, groupId, startingJobs, onFetch) {
476
- return __awaiter(this, void 0, void 0, function* () {
477
- let interval = 100;
478
- let lastJobs = startingJobs;
479
- let errorCount = 0;
480
- while (!allJobsComplete(lastJobs)) {
481
- yield new Promise((resolve) => setTimeout(resolve, interval));
482
- try {
483
- const nextJobs = (yield jsonFetch(`${apiURI}/dash/apps/${appId}/indexing-jobs/group/${groupId}`, {
484
- method: 'GET',
485
- headers: {
486
- Authorization: `Bearer ${token}`,
487
- },
488
- })).jobs;
489
- onFetch(nextJobs);
490
- if (allJobsComplete(nextJobs)) {
491
- return nextJobs;
492
- }
493
- errorCount = 0;
494
- const lastUpdate = latestJobUpdate(lastJobs);
495
- const thisUpdate = latestJobUpdate(nextJobs);
496
- interval =
497
- thisUpdate === null || (lastUpdate && lastUpdate >= thisUpdate)
498
- ? Math.min(interval * 2, 10000)
499
- : 100;
456
+ async function jobFetchLoop(apiURI, token, appId, groupId, startingJobs, onFetch) {
457
+ let interval = 100;
458
+ let lastJobs = startingJobs;
459
+ let errorCount = 0;
460
+ while (!allJobsComplete(lastJobs)) {
461
+ await new Promise((resolve) => setTimeout(resolve, interval));
462
+ try {
463
+ const nextJobs = (await jsonFetch(`${apiURI}/dash/apps/${appId}/indexing-jobs/group/${groupId}`, {
464
+ method: 'GET',
465
+ headers: {
466
+ Authorization: `Bearer ${token}`,
467
+ },
468
+ })).jobs;
469
+ onFetch(nextJobs);
470
+ if (allJobsComplete(nextJobs)) {
471
+ return nextJobs;
500
472
  }
501
- catch (e) {
502
- if (errorCount > 3) {
503
- throw e;
504
- }
505
- else {
506
- errorCount++;
507
- interval = Math.min(interval * 2, 10000);
508
- }
473
+ errorCount = 0;
474
+ const lastUpdate = latestJobUpdate(lastJobs);
475
+ const thisUpdate = latestJobUpdate(nextJobs);
476
+ interval =
477
+ thisUpdate === null || (lastUpdate && lastUpdate >= thisUpdate)
478
+ ? Math.min(interval * 2, 10000)
479
+ : 100;
480
+ }
481
+ catch (e) {
482
+ if (errorCount > 3) {
483
+ throw e;
484
+ }
485
+ else {
486
+ errorCount++;
487
+ interval = Math.min(interval * 2, 10000);
509
488
  }
510
489
  }
511
- return lastJobs;
512
- });
490
+ }
491
+ return lastJobs;
513
492
  }
514
493
  function formatJob(job) {
515
- var _a;
516
494
  const baseJob = {
517
495
  id: job.id,
518
496
  createdAt: new Date(job.created_at),
@@ -521,7 +499,7 @@ function formatJob(job) {
521
499
  workEstimate: job.work_estimate,
522
500
  workCompleted: job.work_completed,
523
501
  error: job.error,
524
- invalidTriplesSample: (_a = job.invalid_triples_sample) === null || _a === void 0 ? void 0 : _a.map((s) => {
502
+ invalidTriplesSample: job.invalid_triples_sample?.map((s) => {
525
503
  return { entityId: s.entity_id, value: s.value, jsonType: s.json_type };
526
504
  }),
527
505
  };
@@ -532,13 +510,21 @@ function formatJob(job) {
532
510
  case 'required':
533
511
  case 'remove-required':
534
512
  case 'remove-unique': {
535
- return Object.assign(Object.assign({}, baseJob), { type: job.job_type });
513
+ return { ...baseJob, type: job.job_type };
536
514
  }
537
515
  case 'check-data-type': {
538
- return Object.assign(Object.assign({}, baseJob), { type: job.job_type, checkedDataType: job.checked_data_type });
516
+ return {
517
+ ...baseJob,
518
+ type: job.job_type,
519
+ checkedDataType: job.checked_data_type,
520
+ };
539
521
  }
540
522
  case 'unique': {
541
- return Object.assign(Object.assign({}, baseJob), { type: job.job_type, invalidUniqueValue: job.invalid_unique_value });
523
+ return {
524
+ ...baseJob,
525
+ type: job.job_type,
526
+ invalidUniqueValue: job.invalid_unique_value,
527
+ };
542
528
  }
543
529
  default: {
544
530
  const neverType = job.job_type;
@@ -569,23 +555,27 @@ function stepSummary(steps) {
569
555
  };
570
556
  }
571
557
  function schemaPush(apiURI, token, appId, body) {
572
- return new ProgressPromise((progress, resolve, reject) => __awaiter(this, void 0, void 0, function* () {
558
+ return new ProgressPromise(async (progress, resolve, reject) => {
573
559
  try {
574
- const resp = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema/push/apply`, {
560
+ const resp = await jsonFetch(`${apiURI}/superadmin/apps/${appId}/schema/push/apply`, {
575
561
  method: 'POST',
576
562
  headers: {
577
563
  'Content-Type': 'application/json',
578
564
  Authorization: `Bearer ${token}`,
579
565
  },
580
- body: JSON.stringify(Object.assign(Object.assign({}, body), { check_types: true, supports_background_updates: true })),
566
+ body: JSON.stringify({
567
+ ...body,
568
+ check_types: true,
569
+ supports_background_updates: true,
570
+ }),
581
571
  });
582
572
  const indexingJobs = resp['indexing-jobs'];
583
573
  const jobs = !indexingJobs
584
574
  ? []
585
- : yield jobFetchLoop(apiURI, token, appId, indexingJobs['group-id'], indexingJobs['jobs'], (jobs) => {
575
+ : await jobFetchLoop(apiURI, token, appId, indexingJobs['group-id'], indexingJobs['jobs'], (jobs) => {
586
576
  progress(stepSummary(translatePushSteps(resp.steps, jobs)));
587
577
  });
588
- const schemaRes = yield getAppSchema(apiURI, token, appId);
578
+ const schemaRes = await getAppSchema(apiURI, token, appId);
589
579
  resolve({
590
580
  newSchema: schemaRes.schema,
591
581
  steps: translatePushSteps(resp.steps, jobs),
@@ -595,32 +585,28 @@ function schemaPush(apiURI, token, appId, body) {
595
585
  catch (e) {
596
586
  reject(e);
597
587
  }
598
- }));
588
+ });
599
589
  }
600
- function pushPerms(apiURI, token, appId, body) {
601
- return __awaiter(this, void 0, void 0, function* () {
602
- const result = yield jsonFetch(`${apiURI}/superadmin/apps/${appId}/perms`, {
603
- method: 'POST',
604
- headers: {
605
- 'Content-Type': 'application/json',
606
- Authorization: `Bearer ${token}`,
607
- },
608
- body: JSON.stringify({ code: body.perms }),
609
- });
610
- return { perms: result.rules.code };
590
+ async function pushPerms(apiURI, token, appId, body) {
591
+ const result = await jsonFetch(`${apiURI}/superadmin/apps/${appId}/perms`, {
592
+ method: 'POST',
593
+ headers: {
594
+ 'Content-Type': 'application/json',
595
+ Authorization: `Bearer ${token}`,
596
+ },
597
+ body: JSON.stringify({ code: body.perms }),
611
598
  });
599
+ return { perms: result.rules.code };
612
600
  }
613
- function tokenInfo(apiURI, token) {
614
- return __awaiter(this, void 0, void 0, function* () {
615
- const result = yield jsonFetch(`${apiURI}/platform/oauth/token-info?access_token=${token}`, {
616
- method: 'GET',
617
- });
618
- return {
619
- tokenType: result.token_type,
620
- scopes: result.scopes,
621
- expiresAt: new Date(Date.now() + (result.expires_in - 60) * 1000),
622
- };
601
+ async function tokenInfo(apiURI, token) {
602
+ const result = await jsonFetch(`${apiURI}/platform/oauth/token-info?access_token=${token}`, {
603
+ method: 'GET',
623
604
  });
605
+ return {
606
+ tokenType: result.token_type,
607
+ scopes: result.scopes,
608
+ expiresAt: new Date(Date.now() + (result.expires_in - 60) * 1000),
609
+ };
624
610
  }
625
611
  export class PlatformApiMissingAuthError extends Error {
626
612
  constructor() {
@@ -643,6 +629,8 @@ export class PlatformApiMissingAuthError extends Error {
643
629
  * ```
644
630
  */
645
631
  export class PlatformApi {
632
+ #auth;
633
+ #apiURI;
646
634
  /**
647
635
  * @param config – Runtime configuration.
648
636
  * @param config.auth.token – OAuth access-token obtained via the oauth flow
@@ -650,83 +638,76 @@ export class PlatformApi {
650
638
  * @throws {Error} When `token` is missing.
651
639
  */
652
640
  constructor(config) {
653
- _PlatformApi_auth.set(this, void 0);
654
- _PlatformApi_apiURI.set(this, void 0);
655
- __classPrivateFieldSet(this, _PlatformApi_auth, config === null || config === void 0 ? void 0 : config.auth, "f");
656
- __classPrivateFieldSet(this, _PlatformApi_apiURI, (config === null || config === void 0 ? void 0 : config.apiURI) || 'https://api.instantdb.com', "f");
641
+ this.#auth = config?.auth;
642
+ this.#apiURI = config?.apiURI || 'https://api.instantdb.com';
657
643
  }
658
644
  token() {
659
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
645
+ if (!this.#auth) {
660
646
  throw new PlatformApiMissingAuthError();
661
647
  }
662
- if ('token' in __classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
663
- return __classPrivateFieldGet(this, _PlatformApi_auth, "f").token;
648
+ if ('token' in this.#auth) {
649
+ return this.#auth.token;
664
650
  }
665
- return __classPrivateFieldGet(this, _PlatformApi_auth, "f").accessToken;
651
+ return this.#auth.accessToken;
666
652
  }
667
653
  canRefreshToken() {
668
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
654
+ if (!this.#auth) {
669
655
  throw new PlatformApiMissingAuthError();
670
656
  }
671
- return ('refreshToken' in __classPrivateFieldGet(this, _PlatformApi_auth, "f") &&
672
- 'clientId' in __classPrivateFieldGet(this, _PlatformApi_auth, "f") &&
673
- 'clientSecret' in __classPrivateFieldGet(this, _PlatformApi_auth, "f") &&
674
- __classPrivateFieldGet(this, _PlatformApi_auth, "f").refreshToken != null &&
675
- __classPrivateFieldGet(this, _PlatformApi_auth, "f").clientId != null &&
676
- __classPrivateFieldGet(this, _PlatformApi_auth, "f").clientSecret != null);
657
+ return ('refreshToken' in this.#auth &&
658
+ 'clientId' in this.#auth &&
659
+ 'clientSecret' in this.#auth &&
660
+ this.#auth.refreshToken != null &&
661
+ this.#auth.clientId != null &&
662
+ this.#auth.clientSecret != null);
677
663
  }
678
- refreshToken() {
679
- return __awaiter(this, void 0, void 0, function* () {
680
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
681
- throw new PlatformApiMissingAuthError();
682
- }
683
- if (!this.canRefreshToken() ||
684
- // Checked in canRefreshToken, but this lets
685
- // typescript refine this.#auth here
686
- !('clientId' in __classPrivateFieldGet(this, _PlatformApi_auth, "f"))) {
687
- return null;
688
- }
689
- const token = yield exchangeRefreshToken({
690
- apiURI: __classPrivateFieldGet(this, _PlatformApi_apiURI, "f"),
691
- clientId: __classPrivateFieldGet(this, _PlatformApi_auth, "f").clientId,
692
- clientSecret: __classPrivateFieldGet(this, _PlatformApi_auth, "f").clientSecret,
693
- refreshToken: __classPrivateFieldGet(this, _PlatformApi_auth, "f").refreshToken,
694
- });
695
- __classPrivateFieldGet(this, _PlatformApi_auth, "f").accessToken = token.accessToken;
696
- if (__classPrivateFieldGet(this, _PlatformApi_auth, "f").onRefresh) {
697
- yield __classPrivateFieldGet(this, _PlatformApi_auth, "f").onRefresh(token);
698
- }
699
- return token;
664
+ async refreshToken() {
665
+ if (!this.#auth) {
666
+ throw new PlatformApiMissingAuthError();
667
+ }
668
+ if (!this.canRefreshToken() ||
669
+ // Checked in canRefreshToken, but this lets
670
+ // typescript refine this.#auth here
671
+ !('clientId' in this.#auth)) {
672
+ return null;
673
+ }
674
+ const token = await exchangeRefreshToken({
675
+ apiURI: this.#apiURI,
676
+ clientId: this.#auth.clientId,
677
+ clientSecret: this.#auth.clientSecret,
678
+ refreshToken: this.#auth.refreshToken,
700
679
  });
680
+ this.#auth.accessToken = token.accessToken;
681
+ if (this.#auth.onRefresh) {
682
+ await this.#auth.onRefresh(token);
683
+ }
684
+ return token;
701
685
  }
702
- withRetry(f, args) {
703
- return __awaiter(this, void 0, void 0, function* () {
704
- var _a, _b;
705
- let attempt = 0;
706
- const [apiURI, tokenInArg, ...restArgs] = args;
707
- let token = tokenInArg;
708
- while (attempt < 2) {
709
- try {
710
- return yield f(apiURI, token, ...restArgs);
711
- }
712
- catch (e) {
713
- if (e instanceof InstantAPIError &&
714
- (e.status === 401 ||
715
- ((_a = e.body) === null || _a === void 0 ? void 0 : _a.type) === 'record-expired' ||
716
- (((_b = e.body) === null || _b === void 0 ? void 0 : _b.type) === 'record-not-found' &&
717
- e.body.hint['record-type'].match(/token/i))) &&
718
- this.canRefreshToken()) {
719
- const refreshedToken = yield this.refreshToken();
720
- if (refreshedToken) {
721
- token = refreshedToken.accessToken;
722
- attempt++;
723
- continue;
724
- }
686
+ async withRetry(f, args) {
687
+ let attempt = 0;
688
+ const [apiURI, tokenInArg, ...restArgs] = args;
689
+ let token = tokenInArg;
690
+ while (attempt < 2) {
691
+ try {
692
+ return await f(apiURI, token, ...restArgs);
693
+ }
694
+ catch (e) {
695
+ if (e instanceof InstantAPIError &&
696
+ (e.status === 401 ||
697
+ e.body?.type === 'record-expired' ||
698
+ (e.body?.type === 'record-not-found' &&
699
+ e.body.hint['record-type'].match(/token/i))) &&
700
+ this.canRefreshToken()) {
701
+ const refreshedToken = await this.refreshToken();
702
+ if (refreshedToken) {
703
+ token = refreshedToken.accessToken;
704
+ attempt++;
705
+ continue;
725
706
  }
726
- throw e;
727
707
  }
708
+ throw e;
728
709
  }
729
- });
710
+ }
730
711
  }
731
712
  /**
732
713
  * Fetch a single app by its id.
@@ -745,10 +726,8 @@ export class PlatformApi {
745
726
  * @returns A typed wrapper containing the app, whose shape is expanded
746
727
  * according to `Opts`.
747
728
  */
748
- getApp(appId, opts) {
749
- return __awaiter(this, void 0, void 0, function* () {
750
- return this.withRetry(getApp, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId, opts]);
751
- });
729
+ async getApp(appId, opts) {
730
+ return this.withRetry(getApp, [this.#apiURI, this.token(), appId, opts]);
752
731
  }
753
732
  /**
754
733
  * List **all apps** owned by the auth owner.
@@ -764,10 +743,8 @@ export class PlatformApi {
764
743
  * @param opts – `{ includeSchema?: boolean; includePerms?: boolean }`
765
744
  * @returns An array wrapper; each element’s shape follows `Opts`.
766
745
  */
767
- getApps(opts) {
768
- return __awaiter(this, void 0, void 0, function* () {
769
- return this.withRetry(getApps, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), opts]);
770
- });
746
+ async getApps(opts) {
747
+ return this.withRetry(getApps, [this.#apiURI, this.token(), opts]);
771
748
  }
772
749
  /**
773
750
  * List **all orgs** that the auth owner is a member of.
@@ -778,10 +755,8 @@ export class PlatformApi {
778
755
  *
779
756
  * @returns An array of orgs
780
757
  */
781
- getOrgs() {
782
- return __awaiter(this, void 0, void 0, function* () {
783
- return this.withRetry(getOrgs, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token()]);
784
- });
758
+ async getOrgs() {
759
+ return this.withRetry(getOrgs, [this.#apiURI, this.token()]);
785
760
  }
786
761
  /**
787
762
  * List **all apps** owned by the auth owner.
@@ -797,15 +772,13 @@ export class PlatformApi {
797
772
  * @param opts – `{ includeSchema?: boolean; includePerms?: boolean }`
798
773
  * @returns An array wrapper; each element’s shape follows `Opts`.
799
774
  */
800
- getAppsForOrg(orgId, opts) {
801
- return __awaiter(this, void 0, void 0, function* () {
802
- return this.withRetry(getAppsForOrg, [
803
- __classPrivateFieldGet(this, _PlatformApi_apiURI, "f"),
804
- this.token(),
805
- orgId,
806
- opts,
807
- ]);
808
- });
775
+ async getAppsForOrg(orgId, opts) {
776
+ return this.withRetry(getAppsForOrg, [
777
+ this.#apiURI,
778
+ this.token(),
779
+ orgId,
780
+ opts,
781
+ ]);
809
782
  }
810
783
  /**
811
784
  * Gets the schema for an app by its id.
@@ -816,10 +789,8 @@ export class PlatformApi {
816
789
  *
817
790
  * @param appId -- UUID of the app
818
791
  */
819
- getSchema(appId) {
820
- return __awaiter(this, void 0, void 0, function* () {
821
- return this.withRetry(getAppSchema, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId]);
822
- });
792
+ async getSchema(appId) {
793
+ return this.withRetry(getAppSchema, [this.#apiURI, this.token(), appId]);
823
794
  }
824
795
  /**
825
796
  * Gets the permissions for an app by its id.
@@ -830,10 +801,8 @@ export class PlatformApi {
830
801
  *
831
802
  * @param appId -- UUID of the app
832
803
  */
833
- getPerms(appId) {
834
- return __awaiter(this, void 0, void 0, function* () {
835
- return this.withRetry(getAppPerms, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId]);
836
- });
804
+ async getPerms(appId) {
805
+ return this.withRetry(getAppPerms, [this.#apiURI, this.token(), appId]);
837
806
  }
838
807
  /**
839
808
  * Create a new app.
@@ -861,10 +830,8 @@ export class PlatformApi {
861
830
  * @param fields.perms -- Optional permissions for the app
862
831
  * @param fields.orgId -- Optional id of the org that the app will be placed in
863
832
  */
864
- createApp(fields) {
865
- return __awaiter(this, void 0, void 0, function* () {
866
- return this.withRetry(createApp, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), fields]);
867
- });
833
+ async createApp(fields) {
834
+ return this.withRetry(createApp, [this.#apiURI, this.token(), fields]);
868
835
  }
869
836
  /**
870
837
  * Create a new temporary app.
@@ -888,10 +855,8 @@ export class PlatformApi {
888
855
  * @param fields.schema -- Optional schema for the app
889
856
  * @param fields.perms -- Optional permissions for the app
890
857
  */
891
- createTemporaryApp(fields) {
892
- return __awaiter(this, void 0, void 0, function* () {
893
- return createTemporaryApp(__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), fields);
894
- });
858
+ async createTemporaryApp(fields) {
859
+ return createTemporaryApp(this.#apiURI, fields);
895
860
  }
896
861
  /**
897
862
  * Update the title of an app by its id.
@@ -905,15 +870,13 @@ export class PlatformApi {
905
870
  * @param appId -- UUID of the app
906
871
  * @param fields.title -- New title for the app
907
872
  */
908
- updateApp(appId, fields) {
909
- return __awaiter(this, void 0, void 0, function* () {
910
- return this.withRetry(updateApp, [
911
- __classPrivateFieldGet(this, _PlatformApi_apiURI, "f"),
912
- this.token(),
913
- appId,
914
- fields,
915
- ]);
916
- });
873
+ async updateApp(appId, fields) {
874
+ return this.withRetry(updateApp, [
875
+ this.#apiURI,
876
+ this.token(),
877
+ appId,
878
+ fields,
879
+ ]);
917
880
  }
918
881
  /**
919
882
  * Delete an app by its id.
@@ -924,10 +887,8 @@ export class PlatformApi {
924
887
  *
925
888
  * @param appId -- UUID of the app
926
889
  */
927
- deleteApp(appId) {
928
- return __awaiter(this, void 0, void 0, function* () {
929
- return this.withRetry(deleteApp, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId]);
930
- });
890
+ async deleteApp(appId) {
891
+ return this.withRetry(deleteApp, [this.#apiURI, this.token(), appId]);
931
892
  }
932
893
  /**
933
894
  * Dry-run a **schema push** and receive a _plan_ of steps the server would
@@ -937,15 +898,13 @@ export class PlatformApi {
937
898
  * const { steps } = await api.planSchemaPush(appId, body);
938
899
  * ```
939
900
  */
940
- planSchemaPush(appId, body) {
941
- return __awaiter(this, void 0, void 0, function* () {
942
- return this.withRetry(planSchemaPush, [
943
- __classPrivateFieldGet(this, _PlatformApi_apiURI, "f"),
944
- this.token(),
945
- appId,
946
- body,
947
- ]);
948
- });
901
+ async planSchemaPush(appId, body) {
902
+ return this.withRetry(planSchemaPush, [
903
+ this.#apiURI,
904
+ this.token(),
905
+ appId,
906
+ body,
907
+ ]);
949
908
  }
950
909
  /**
951
910
  * Execute a **schema push**. The server returns a long-running job
@@ -974,19 +933,19 @@ export class PlatformApi {
974
933
  * ```
975
934
  */
976
935
  schemaPush(appId, body) {
977
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
936
+ if (!this.#auth) {
978
937
  throw new PlatformApiMissingAuthError();
979
938
  }
980
- return new ProgressPromise((progress, resolve, reject) => __awaiter(this, void 0, void 0, function* () {
939
+ return new ProgressPromise(async (progress, resolve, reject) => {
981
940
  // It's tricky to add withRetry to the background process that fetches the jobs,
982
941
  // so we'll just refresh the token at the start.
983
942
  if (this.canRefreshToken()) {
984
943
  try {
985
- yield this.refreshToken();
944
+ await this.refreshToken();
986
945
  }
987
946
  catch (_e) { }
988
947
  }
989
- schemaPush(__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId, body).subscribe({
948
+ schemaPush(this.#apiURI, this.token(), appId, body).subscribe({
990
949
  complete(v) {
991
950
  resolve(v);
992
951
  },
@@ -997,7 +956,7 @@ export class PlatformApi {
997
956
  progress(v);
998
957
  },
999
958
  });
1000
- }));
959
+ });
1001
960
  }
1002
961
  /**
1003
962
  * Update permission rules for an app by its id.
@@ -1013,22 +972,17 @@ export class PlatformApi {
1013
972
  * });
1014
973
  * ```
1015
974
  */
1016
- pushPerms(appId, body) {
1017
- return __awaiter(this, void 0, void 0, function* () {
1018
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
1019
- throw new PlatformApiMissingAuthError();
1020
- }
1021
- return this.withRetry(pushPerms, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token(), appId, body]);
1022
- });
975
+ async pushPerms(appId, body) {
976
+ if (!this.#auth) {
977
+ throw new PlatformApiMissingAuthError();
978
+ }
979
+ return this.withRetry(pushPerms, [this.#apiURI, this.token(), appId, body]);
1023
980
  }
1024
- tokenInfo() {
1025
- return __awaiter(this, void 0, void 0, function* () {
1026
- if (!__classPrivateFieldGet(this, _PlatformApi_auth, "f")) {
1027
- throw new PlatformApiMissingAuthError();
1028
- }
1029
- return this.withRetry(tokenInfo, [__classPrivateFieldGet(this, _PlatformApi_apiURI, "f"), this.token()]);
1030
- });
981
+ async tokenInfo() {
982
+ if (!this.#auth) {
983
+ throw new PlatformApiMissingAuthError();
984
+ }
985
+ return this.withRetry(tokenInfo, [this.#apiURI, this.token()]);
1031
986
  }
1032
987
  }
1033
- _PlatformApi_auth = new WeakMap(), _PlatformApi_apiURI = new WeakMap();
1034
988
  //# sourceMappingURL=api.js.map