@granular-software/sdk 0.4.52 → 0.4.54

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.
@@ -14336,6 +14336,7 @@ var Environment = class _Environment {
14336
14336
  import: async (records, options) => this.enqueueRecordImport(records, options),
14337
14337
  listImports: async (status) => this.listRecordImports(status),
14338
14338
  getImport: async (importId) => this.getRecordImport(importId),
14339
+ listImportItems: async (importId, status) => this.listRecordImportItems(importId, status),
14339
14340
  getImportSummary: async () => this.getRecordImportSummary(),
14340
14341
  cancelImport: async (importId) => this.cancelRecordImport(importId),
14341
14342
  getAwaitingCount: async () => this.getAwaitingRecordCount()
@@ -15514,6 +15515,15 @@ var Environment = class _Environment {
15514
15515
  `/control/record-imports/${importId}`
15515
15516
  );
15516
15517
  }
15518
+ /**
15519
+ * List the individual records persisted for one asynchronous import. This
15520
+ * makes terminal import failures diagnosable without database access.
15521
+ */
15522
+ async listRecordImportItems(importId, status) {
15523
+ const suffix = status ? `?status=${encodeURIComponent(status)}` : "";
15524
+ const response = await this.controlPlaneRequest(`/control/record-imports/${importId}/items${suffix}`);
15525
+ return Array.isArray(response.items) ? response.items : [];
15526
+ }
15517
15527
  /**
15518
15528
  * Cancel a queued/background record import.
15519
15529
  */
@@ -16330,6 +16340,55 @@ var Granular = class _Granular {
16330
16340
  throw error;
16331
16341
  }
16332
16342
  }
16343
+ /**
16344
+ * Resolve one exact environment only when Granular confirms that it belongs
16345
+ * to the given external user in the requested sandbox (and, optionally,
16346
+ * tag). This is deliberately read-only: callers use it to keep an already
16347
+ * opened delegated workspace stable while a newer active environment is
16348
+ * being prepared in the background.
16349
+ */
16350
+ async getEnvironmentForUser(options) {
16351
+ const sandboxId = options.sandboxId.trim();
16352
+ const userId = options.userId.trim();
16353
+ const environmentId = options.environmentId.trim();
16354
+ const tagName = options.tag?.trim();
16355
+ if (!sandboxId || !userId || !environmentId) {
16356
+ throw new Error(
16357
+ "getEnvironmentForUser() requires sandboxId, userId, and environmentId."
16358
+ );
16359
+ }
16360
+ const subjects = await this.request(
16361
+ `/control/subjects?identityId=${encodeURIComponent(userId)}`
16362
+ );
16363
+ const subject = (subjects.items || []).find(
16364
+ (item) => item.identityId === userId || item.userId === userId
16365
+ );
16366
+ const subjectId = subject?.subjectId || subject?.granularId;
16367
+ if (!subjectId) return null;
16368
+ let environment;
16369
+ try {
16370
+ environment = await this.environments.get(environmentId);
16371
+ } catch (error) {
16372
+ const message = error instanceof Error ? error.message : String(error);
16373
+ if (message.includes("404") || message.includes("not found")) {
16374
+ return null;
16375
+ }
16376
+ throw error;
16377
+ }
16378
+ if (environment.sandboxId !== sandboxId || environment.subjectId !== subjectId) {
16379
+ return null;
16380
+ }
16381
+ if (tagName) {
16382
+ const tags = await this.request(`/control/sandboxes/${encodeURIComponent(sandboxId)}/tags`);
16383
+ const tag = (tags.items || []).find(
16384
+ (candidate) => candidate?.name === tagName
16385
+ );
16386
+ if (!tag || environment.tagId !== tag.tagId) {
16387
+ return null;
16388
+ }
16389
+ }
16390
+ return this.bindEnvironmentHandle(environment);
16391
+ }
16333
16392
  /**
16334
16393
  * Register one reviewed, pre-existing environment as the active workspace
16335
16394
  * for an external user. This is for a controlled migration only: it does