@vertexvis/api-client-node 0.20.10 → 0.21.0

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,5 +1,24 @@
1
1
  import { CreateSceneItemRequest, SceneItem } from '../../index';
2
2
  import { BaseReq, Polling } from '../index';
3
+ export declare enum SceneItemErrorStatus {
4
+ NotFound = "404",
5
+ ServerError = "500"
6
+ }
7
+ export declare enum SceneItemErrorCode {
8
+ NotFound = "NotFound",
9
+ ServerError = "ServerError"
10
+ }
11
+ export declare enum SceneItemErrorSourcePointer {
12
+ Parent = "/body/data/attributes/parent",
13
+ SourcePart = "/body/data/relationships/source/data"
14
+ }
15
+ export declare enum SceneItemSystemMetadata {
16
+ IsMissingGeometry = "VERTEX_IS_MISSING_GEOMETRY",
17
+ MissingGeometrySetId = "VERTEX_MISSING_GEOMETRY_SET_ID",
18
+ MissingPartRevisionId = "VERTEX_MISSING_PART_REVISION_ID",
19
+ MissingSuppliedPartId = "VERTEX_MISSING_SUPPLIED_PART_ID",
20
+ MissingSuppliedPartRevisionId = "VERTEX_MISSING_SUPPLIED_PART_REVISION_ID"
21
+ }
3
22
  /**
4
23
  * Create scene item arguments.
5
24
  */
@@ -17,3 +36,5 @@ export interface CreateSceneItemReq extends BaseReq {
17
36
  * @param args - The {@link CreateSceneItemReq}.
18
37
  */
19
38
  export declare function createSceneItem({ client, createSceneItemReq, onMsg, polling, sceneId, verbose, }: CreateSceneItemReq): Promise<SceneItem>;
39
+ export declare function isPartNotFoundError(e: unknown): boolean;
40
+ export declare function isParentNotFoundError(e: unknown): boolean;
@@ -9,8 +9,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.createSceneItem = void 0;
12
+ exports.isParentNotFoundError = exports.isPartNotFoundError = exports.createSceneItem = exports.SceneItemSystemMetadata = exports.SceneItemErrorSourcePointer = exports.SceneItemErrorCode = exports.SceneItemErrorStatus = void 0;
13
13
  const index_1 = require("../index");
14
+ var SceneItemErrorStatus;
15
+ (function (SceneItemErrorStatus) {
16
+ SceneItemErrorStatus["NotFound"] = "404";
17
+ SceneItemErrorStatus["ServerError"] = "500";
18
+ })(SceneItemErrorStatus = exports.SceneItemErrorStatus || (exports.SceneItemErrorStatus = {}));
19
+ var SceneItemErrorCode;
20
+ (function (SceneItemErrorCode) {
21
+ SceneItemErrorCode["NotFound"] = "NotFound";
22
+ SceneItemErrorCode["ServerError"] = "ServerError";
23
+ })(SceneItemErrorCode = exports.SceneItemErrorCode || (exports.SceneItemErrorCode = {}));
24
+ var SceneItemErrorSourcePointer;
25
+ (function (SceneItemErrorSourcePointer) {
26
+ SceneItemErrorSourcePointer["Parent"] = "/body/data/attributes/parent";
27
+ SceneItemErrorSourcePointer["SourcePart"] = "/body/data/relationships/source/data";
28
+ })(SceneItemErrorSourcePointer = exports.SceneItemErrorSourcePointer || (exports.SceneItemErrorSourcePointer = {}));
29
+ var SceneItemSystemMetadata;
30
+ (function (SceneItemSystemMetadata) {
31
+ SceneItemSystemMetadata["IsMissingGeometry"] = "VERTEX_IS_MISSING_GEOMETRY";
32
+ SceneItemSystemMetadata["MissingGeometrySetId"] = "VERTEX_MISSING_GEOMETRY_SET_ID";
33
+ SceneItemSystemMetadata["MissingPartRevisionId"] = "VERTEX_MISSING_PART_REVISION_ID";
34
+ SceneItemSystemMetadata["MissingSuppliedPartId"] = "VERTEX_MISSING_SUPPLIED_PART_ID";
35
+ SceneItemSystemMetadata["MissingSuppliedPartRevisionId"] = "VERTEX_MISSING_SUPPLIED_PART_REVISION_ID";
36
+ })(SceneItemSystemMetadata = exports.SceneItemSystemMetadata || (exports.SceneItemSystemMetadata = {}));
14
37
  /**
15
38
  * Create a scene item.
16
39
  *
@@ -38,3 +61,19 @@ function createSceneItem({ client, createSceneItemReq, onMsg = console.log, poll
38
61
  });
39
62
  }
40
63
  exports.createSceneItem = createSceneItem;
64
+ function isPartNotFoundError(e) {
65
+ return ((0, index_1.defined)(e) &&
66
+ (0, index_1.isApiError)(e) &&
67
+ e.code === SceneItemErrorCode.NotFound &&
68
+ e.source !== undefined &&
69
+ e.source.pointer === SceneItemErrorSourcePointer.SourcePart);
70
+ }
71
+ exports.isPartNotFoundError = isPartNotFoundError;
72
+ function isParentNotFoundError(e) {
73
+ return ((0, index_1.defined)(e) &&
74
+ (0, index_1.isApiError)(e) &&
75
+ e.code === SceneItemErrorCode.NotFound &&
76
+ e.source !== undefined &&
77
+ e.source.pointer === SceneItemErrorSourcePointer.Parent);
78
+ }
79
+ exports.isParentNotFoundError = isParentNotFoundError;
@@ -1,4 +1,6 @@
1
1
  import { AxiosResponse } from 'axios';
2
+ import { Limit } from 'p-limit';
3
+ import { RelationshipData } from '../../index';
2
4
  import { ApiError, BatchOperation, CreateSceneItemRequest, CreateSceneItemRequestData, CreateSceneRequest, Failure, QueuedJob, Scene, SceneData, UpdateSceneRequestDataAttributes } from '../../index';
3
5
  import { BaseReq, DeleteReq, Polling, RenderImageReq, VertexClient } from '../index';
4
6
  export interface CreateSceneAndSceneItemsReq extends BaseReq {
@@ -17,35 +19,23 @@ export interface CreateSceneAndSceneItemsReq extends BaseReq {
17
19
  /** Whether or not to return queued scene items. */
18
20
  readonly returnQueued?: boolean;
19
21
  }
20
- export interface CreateSceneAndSceneItemsReqEXPERIMENTAL extends BaseReq {
21
- /** A list of {@link CreateSceneItemRequest}. */
22
- readonly createSceneItemReqs: Array<Array<CreateSceneItemRequest>>;
23
- /** Function returning a {@link CreateSceneRequest}. */
24
- readonly createSceneReq: () => CreateSceneRequest;
25
- /** Whether or not to fail if any scene item fails initial validation. */
26
- readonly failFast?: boolean;
27
- /** How many requests to run in parallel. */
28
- readonly parallelism: number;
29
- /** {@link Polling} */
30
- readonly polling?: Polling;
31
- /** Callback with total number of requests and number complete. */
32
- onProgress?: (complete: number, total: number) => void;
33
- /** Whether or not to return queued scene items. */
34
- readonly returnQueued?: boolean;
35
- }
36
22
  export interface CreateSceneAndSceneItemsRes {
37
- readonly errors: QueuedSceneItem[];
38
- readonly scene: Scene;
39
- /** Only populated if `returnQueued` is true in request. */
40
- readonly queued: QueuedSceneItem[];
41
- }
42
- export interface CreateSceneAndSceneItemsResEXPERIMENTAL {
43
23
  readonly errors: QueuedBatchOps[];
44
- readonly scene: Scene;
24
+ readonly scene?: Scene;
45
25
  readonly sceneItemErrors: SceneItemError[];
46
26
  /** Only populated if `returnQueued` is true in request. */
47
27
  readonly queued: QueuedBatchOps[];
48
28
  }
29
+ export interface CreateSceneItemBatchReq extends CreateSceneItemsReq {
30
+ /** {@link Polling} */
31
+ readonly polling?: Polling;
32
+ }
33
+ export interface CreateSceneItemBatchRes {
34
+ batchOps: QueuedBatchOps[];
35
+ batchErrors: QueuedBatchOps[];
36
+ itemErrors: SceneItemError[];
37
+ itemResults: SceneItemResult[];
38
+ }
49
39
  export interface CreateSceneItemsReq extends Base {
50
40
  /** A list of {@link CreateSceneItemRequest}. */
51
41
  readonly createSceneItemReqs: CreateSceneItemRequest[];
@@ -53,14 +43,10 @@ export interface CreateSceneItemsReq extends Base {
53
43
  readonly failFast: boolean;
54
44
  /** Callback with total number of requests and number complete. */
55
45
  readonly onProgress?: (complete: number, total: number) => void;
56
- /** How many requests to run in parallel. */
57
- readonly parallelism: number;
46
+ /** Limit for requests to run in parallel. */
47
+ readonly limit: Limit;
58
48
  }
59
49
  export interface CreateSceneItemsRes {
60
- readonly leaves: number;
61
- readonly queuedSceneItems: QueuedSceneItem[];
62
- }
63
- export interface CreateSceneItemsResEXPERIMENTAL {
64
50
  readonly chunks: number;
65
51
  readonly queuedBatchOps: QueuedBatchOps[];
66
52
  }
@@ -71,6 +57,11 @@ export interface QueuedBatchOps {
71
57
  export interface SceneItemError {
72
58
  readonly req: CreateSceneItemRequestData;
73
59
  readonly res?: ApiError;
60
+ placeholderItem?: RelationshipData;
61
+ }
62
+ export interface SceneItemResult {
63
+ readonly req: CreateSceneItemRequestData;
64
+ readonly res: RelationshipData | ApiError;
74
65
  }
75
66
  /**
76
67
  * Poll scene ready arguments.
@@ -104,15 +95,7 @@ export declare function createSceneAndSceneItems({ client, createSceneItemReqs,
104
95
  /**
105
96
  * Create scene items within a scene.
106
97
  */
107
- export declare function createSceneItems({ client, createSceneItemReqs, failFast, onProgress, parallelism, sceneId, }: CreateSceneItemsReq): Promise<CreateSceneItemsRes>;
108
- /**
109
- * Create a scene with scene items using experimental strategy.
110
- */
111
- export declare function createSceneAndSceneItemsEXPERIMENTAL({ client, createSceneItemReqs, createSceneReq, failFast, onMsg, onProgress, parallelism, polling, returnQueued, verbose, }: CreateSceneAndSceneItemsReqEXPERIMENTAL): Promise<CreateSceneAndSceneItemsResEXPERIMENTAL>;
112
- /**
113
- * Create scene items within a scene.
114
- */
115
- export declare function createSceneItemsEXPERIMENTAL({ client, createSceneItemReqs, failFast, parallelism, sceneId, }: CreateSceneItemsReq): Promise<CreateSceneItemsResEXPERIMENTAL>;
98
+ export declare function createSceneItems({ client, createSceneItemReqs, failFast, limit, sceneId, }: CreateSceneItemsReq): Promise<CreateSceneItemsRes>;
116
99
  /**
117
100
  * Delete all scenes.
118
101
  *
@@ -12,246 +12,285 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.updateScene = exports.renderScene = exports.pollSceneReady = exports.deleteAllScenes = exports.createSceneItemsEXPERIMENTAL = exports.createSceneAndSceneItemsEXPERIMENTAL = exports.createSceneItems = exports.createSceneAndSceneItems = void 0;
15
+ exports.updateScene = exports.renderScene = exports.pollSceneReady = exports.deleteAllScenes = exports.createSceneItems = exports.createSceneAndSceneItems = void 0;
16
16
  const p_limit_1 = __importDefault(require("p-limit"));
17
17
  const process_1 = require("process");
18
18
  const index_1 = require("../../index");
19
19
  const index_2 = require("../index");
20
20
  const utils_1 = require("../utils");
21
21
  const queued_jobs_1 = require("./queued-jobs");
22
- const PollPercentage = 10;
22
+ const defaultPolling = { intervalMs: 200, maxAttempts: 4500 }; // 15 minute timeout for batch completions
23
+ const sceneReadyPolling = { intervalMs: 1000, maxAttempts: 3600 }; // one hour timeout for scene state ready
23
24
  /**
24
25
  * Create a scene with scene items.
25
26
  */
26
- function createSceneAndSceneItems({ client, createSceneItemReqs, createSceneReq, failFast = false, onMsg = console.log, onProgress, parallelism, polling = { intervalMs: index_2.PollIntervalMs, maxAttempts: index_2.MaxAttempts }, returnQueued = false, verbose, }) {
27
- return __awaiter(this, void 0, void 0, function* () {
28
- const scene = (yield client.scenes.createScene({ createSceneRequest: createSceneReq() })).data;
29
- const sceneId = scene.data.id;
30
- const createRes = yield createSceneItems({
31
- client,
32
- createSceneItemReqs,
33
- failFast,
34
- onProgress,
35
- parallelism,
36
- sceneId,
37
- });
38
- const { a: queuedItems, b: errors } = (0, index_2.partition)(createRes.queuedSceneItems, (i) => (0, index_2.isQueuedJob)(i.res));
39
- const queued = returnQueued ? createRes.queuedSceneItems : [];
40
- if (queuedItems.length === 0 || errors.length === createRes.leaves) {
41
- return { errors, queued, scene };
42
- }
43
- if (verbose)
44
- onMsg(`Polling for completed scene-items...`);
45
- const limit = (0, p_limit_1.default)(Math.min(parallelism, 20));
46
- const cnt = queuedItems.length;
47
- const step = Math.floor(cnt / ((PollPercentage / 100) * cnt));
48
- const qis = [];
49
- // Poll for percentage of items starting at end of `queuedItems` array
50
- for (let i = 0; i < cnt; i += step)
51
- qis.push(queuedItems[cnt - i - 1]);
52
- function poll({ req, res }) {
53
- return __awaiter(this, void 0, void 0, function* () {
54
- const r = yield (0, queued_jobs_1.pollQueuedJob)({
55
- id: res.data.id,
56
- getQueuedJob: (id, cancelToken) => client.sceneItems.getQueuedSceneItem({ id }, { cancelToken }),
57
- allow404: true,
58
- limit,
59
- polling,
60
- });
61
- if ((0, queued_jobs_1.isPollError)(r.res)) {
62
- failFast ? (0, queued_jobs_1.throwOnError)(r) : errors.push({ req, res: r.res });
63
- }
64
- });
65
- }
66
- yield Promise.all(qis.map((is) => limit(poll, is)));
67
- if (verbose)
68
- onMsg(`Committing scene and polling until ready...`);
69
- yield updateScene({
70
- attributes: { state: index_1.UpdateSceneRequestDataAttributesStateEnum.Commit },
71
- client,
72
- sceneId,
73
- });
74
- yield pollSceneReady({ client, id: sceneId, onMsg, polling, verbose });
75
- if (verbose)
76
- onMsg(`Fitting scene's camera to scene-items...`);
77
- const updated = (yield updateScene({
78
- attributes: { camera: { type: index_1.CameraFitTypeEnum.FitVisibleSceneItems } },
79
- client,
80
- sceneId,
81
- })).scene;
82
- return { errors, queued, scene: updated };
83
- });
84
- }
85
- exports.createSceneAndSceneItems = createSceneAndSceneItems;
86
- /**
87
- * Create scene items within a scene.
88
- */
89
- function createSceneItems({ client, createSceneItemReqs, failFast, onProgress, parallelism, sceneId, }) {
90
- return __awaiter(this, void 0, void 0, function* () {
91
- const limit = (0, p_limit_1.default)(parallelism);
92
- let complete = 0;
93
- let leaves = 0;
94
- const queuedSceneItems = yield Promise.all(createSceneItemReqs.map((r) => limit((req) => __awaiter(this, void 0, void 0, function* () {
95
- var _a;
96
- let res;
97
- try {
98
- if ((0, index_2.defined)(req.data.attributes.source) ||
99
- (0, index_2.defined)(req.data.relationships.source)) {
100
- leaves++;
101
- }
102
- res = (yield client.sceneItems.createSceneItem({
103
- id: sceneId,
104
- createSceneItemRequest: req,
105
- })).data;
106
- }
107
- catch (error) {
108
- if (!failFast && (0, index_2.hasVertexError)(error)) {
109
- res = (_a = error.vertexError) === null || _a === void 0 ? void 0 : _a.res;
110
- }
111
- else
112
- throw error;
113
- }
114
- if (onProgress != null) {
115
- complete += 1;
116
- onProgress(complete, createSceneItemReqs.length);
117
- }
118
- return { req, res };
119
- }), r)));
120
- return { leaves, queuedSceneItems };
121
- });
122
- }
123
- exports.createSceneItems = createSceneItems;
124
- /**
125
- * Create a scene with scene items using experimental strategy.
126
- */
127
- function createSceneAndSceneItemsEXPERIMENTAL({ client, createSceneItemReqs, createSceneReq, failFast = false, onMsg = console.log, onProgress, parallelism, polling = { intervalMs: index_2.PollIntervalMs, maxAttempts: index_2.MaxAttempts }, returnQueued = false, verbose, }) {
27
+ function createSceneAndSceneItems({ client, createSceneItemReqs, createSceneReq, failFast = false, onMsg = console.log, onProgress, parallelism, polling = defaultPolling, returnQueued = false, verbose, }) {
128
28
  return __awaiter(this, void 0, void 0, function* () {
29
+ const limit = (0, p_limit_1.default)(Math.min(parallelism, 100));
129
30
  const startTime = process_1.hrtime.bigint();
130
31
  if (verbose)
131
32
  onMsg(`Creating scene...`);
132
33
  const scene = (yield client.scenes.createScene({ createSceneRequest: createSceneReq() })).data;
133
34
  const sceneId = scene.data.id;
35
+ if (verbose)
36
+ onMsg(`Scene ID: ${sceneId}`);
134
37
  if (verbose)
135
38
  onMsg(`Creating scene items...`);
136
39
  let itemCount = 0;
137
- let batchQueuedOps = [];
138
- let batchErrors = [];
139
- let sceneItemErrors = [];
140
- for (let depth = 0; depth < createSceneItemReqs.length; depth++) {
141
- const createItemReqs = createSceneItemReqs[depth];
40
+ let createFailed = false;
41
+ let sceneResult;
42
+ const reqMap = new Map();
43
+ // create parent map and set ordinals based on request order
44
+ createSceneItemReqs.forEach((req) => {
45
+ var _a, _b, _c;
46
+ const reqParent = (_c = (_a = req.data.attributes.parent) !== null && _a !== void 0 ? _a : (_b = req.data.relationships.parent) === null || _b === void 0 ? void 0 : _b.data.id) !== null && _c !== void 0 ? _c : '';
47
+ if (!reqMap.has(reqParent)) {
48
+ reqMap.set(reqParent, []);
49
+ }
50
+ const siblings = reqMap.get(reqParent);
51
+ if (req.data.attributes.ordinal == null) {
52
+ req.data.attributes.ordinal = siblings === null || siblings === void 0 ? void 0 : siblings.length;
53
+ }
54
+ siblings === null || siblings === void 0 ? void 0 : siblings.push(req);
55
+ });
56
+ // sort all scene item requests into depth sorted array of arrays
57
+ const depthSortedItems = [];
58
+ // fetch list of scene items with no parent (root items)
59
+ let nextChildren = reqMap.get('') || [];
60
+ reqMap.delete('');
61
+ while (nextChildren.length > 0) {
62
+ depthSortedItems.push(nextChildren);
63
+ nextChildren = nextChildren.flatMap((req) => {
64
+ if (req.data.attributes.suppliedId &&
65
+ reqMap.has(req.data.attributes.suppliedId)) {
66
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
+ const children = reqMap.get(req.data.attributes.suppliedId);
68
+ reqMap.delete(req.data.attributes.suppliedId);
69
+ return children;
70
+ }
71
+ else {
72
+ return [];
73
+ }
74
+ });
75
+ }
76
+ let resultQueuedOps = [];
77
+ let resultBatchErrors = [];
78
+ let resultItemErrors = [];
79
+ // if we had any scene item requests with invalid parents,
80
+ // add error entries indicating so.
81
+ reqMap.forEach((children) => {
82
+ children.forEach((childItem) => {
83
+ resultItemErrors.push({
84
+ req: childItem.data,
85
+ res: {
86
+ status: '404',
87
+ code: 'NotFound',
88
+ title: 'The requested resource was not found.',
89
+ source: { pointer: '/body/data/attributes/parent' },
90
+ },
91
+ });
92
+ });
93
+ });
94
+ let depth = 0;
95
+ for (depth; depth < depthSortedItems.length; depth++) {
96
+ const createItemReqs = depthSortedItems[depth];
142
97
  itemCount += createItemReqs.length;
143
98
  if (verbose)
144
99
  onMsg(`Creating ${createItemReqs.length} scene items at depth ${depth}...`);
145
100
  // Await is used intentionally to defer loop iteration
146
101
  // until all scene items have been created at each depth.
102
+ const { batchOps: queuedBatchOps, batchErrors: queuedBatchErrors, itemErrors: batchItemErrors, } =
147
103
  // eslint-disable-next-line no-await-in-loop
148
- const createRes = yield createSceneItemsEXPERIMENTAL({
104
+ yield createSceneItemBatch({
149
105
  client,
150
106
  createSceneItemReqs: createItemReqs,
151
107
  failFast,
152
108
  onProgress,
153
- parallelism,
109
+ limit,
154
110
  sceneId,
111
+ polling,
155
112
  });
156
- const { a: queuedOps, b: errors } = (0, index_2.partition)(createRes.queuedBatchOps, (i) => (0, index_2.isQueuedJob)(i.res));
157
- batchQueuedOps = batchQueuedOps.concat(queuedOps);
158
- if (errors.length) {
159
- batchErrors = batchErrors.concat(errors);
160
- if (verbose)
161
- onMsg(`WARNING: ${errors.length} scene item batch errors at depth ${depth}.`);
162
- }
163
- // Nothing succeeded, return early as something is likely wrong
164
- if (queuedOps.length === 0 || errors.length === createRes.chunks) {
165
- return {
166
- errors,
167
- queued: returnQueued ? createRes.queuedBatchOps : [],
168
- scene,
169
- sceneItemErrors: [],
170
- };
171
- }
172
- const limit = (0, p_limit_1.default)(Math.min(parallelism, 20));
173
- function poll({ ops, res, }) {
174
- return __awaiter(this, void 0, void 0, function* () {
175
- const r = yield (0, queued_jobs_1.pollQueuedJob)({
176
- id: res.data.id,
177
- getQueuedJob: (id, cancelToken) => client.batches.getQueuedBatch({ id }, { cancelToken }),
178
- allow404: true,
179
- limit,
180
- polling,
181
- });
182
- if ((0, queued_jobs_1.isPollError)(r.res)) {
183
- failFast ? (0, queued_jobs_1.throwOnError)(r) : errors.push({ ops, res: r.res });
184
- }
185
- return r;
186
- });
187
- }
188
- // eslint-disable-next-line no-await-in-loop
189
- const batchRes = yield Promise.all(queuedOps.map((is) => limit(poll, is)));
190
- const batchItemErrors = batchRes
191
- .flatMap((b, i) => (0, queued_jobs_1.isBatch)(b.res)
192
- ? b.res['vertexvis/batch:results'].map((r, j) => (0, utils_1.isApiError)(r)
193
- ? { req: queuedOps[i].ops[j].data, res: r }
194
- : undefined)
195
- : [])
196
- .filter(index_2.defined);
113
+ resultQueuedOps = resultQueuedOps.concat(queuedBatchOps);
114
+ resultBatchErrors = resultBatchErrors.concat(queuedBatchErrors);
197
115
  if (batchItemErrors.length) {
198
- sceneItemErrors = sceneItemErrors.concat(batchItemErrors);
199
116
  if (verbose)
200
117
  onMsg(`WARNING: ${batchItemErrors.length} scene item creation errors at depth ${depth}.`);
118
+ resultItemErrors = resultItemErrors.concat(batchItemErrors);
119
+ if (failFast) {
120
+ createFailed = true;
121
+ break;
122
+ }
123
+ else {
124
+ // evaluate item errors and generate retry list
125
+ const retryErrors = batchItemErrors.filter((v) => (0, index_2.isPartNotFoundError)(v.res));
126
+ const retries = retryErrors.map((itemError) => {
127
+ var _a, _b, _c, _d, _e, _f;
128
+ const item = itemError.req;
129
+ return {
130
+ data: {
131
+ type: 'scene-item',
132
+ attributes: Object.assign(Object.assign({}, item.attributes), { metadata: Object.assign(Object.assign({}, item.attributes.metadata), { [index_2.SceneItemSystemMetadata.IsMissingGeometry]: toMetadataOrUndefined('1'), [index_2.SceneItemSystemMetadata.MissingGeometrySetId]: toMetadataOrUndefined((_a = item.relationships.source) === null || _a === void 0 ? void 0 : _a.data.id, ((_b = item.relationships.source) === null || _b === void 0 ? void 0 : _b.data.type) === 'geometry-set'), [index_2.SceneItemSystemMetadata.MissingPartRevisionId]: toMetadataOrUndefined((_c = item.relationships.source) === null || _c === void 0 ? void 0 : _c.data.id, ((_d = item.relationships.source) === null || _d === void 0 ? void 0 : _d.data.type) === 'part-revision'), [index_2.SceneItemSystemMetadata.MissingSuppliedPartId]: toMetadataOrUndefined((_e = item.attributes.source) === null || _e === void 0 ? void 0 : _e.suppliedPartId), [index_2.SceneItemSystemMetadata.MissingSuppliedPartRevisionId]: toMetadataOrUndefined((_f = item.attributes.source) === null || _f === void 0 ? void 0 : _f.suppliedRevisionId) }), source: undefined }),
133
+ relationships: Object.assign(Object.assign({}, item.relationships), { source: undefined }),
134
+ },
135
+ };
136
+ });
137
+ if (retries.length > 0) {
138
+ onMsg(`Creating ${retries.length} placeholder scene items at depth ${depth}.`);
139
+ // wait for placeholders to be created
140
+ const { itemResults: placeholderItemResults } =
141
+ // eslint-disable-next-line no-await-in-loop
142
+ yield createSceneItemBatch({
143
+ client,
144
+ createSceneItemReqs: retries,
145
+ failFast,
146
+ onProgress,
147
+ limit,
148
+ sceneId,
149
+ polling,
150
+ });
151
+ // attach placeholder references to item errors
152
+ placeholderItemResults.forEach((resultItem, i) => {
153
+ if ((0, utils_1.isSceneItemRelationship)(resultItem.res)) {
154
+ retryErrors[i].placeholderItem = resultItem.res;
155
+ }
156
+ });
157
+ }
158
+ }
201
159
  }
202
160
  }
203
- if (verbose) {
204
- onMsg(`Scene item creation complete for ${itemCount} scene items with max depth of ${createSceneItemReqs.length - 1}.`);
205
- if (batchErrors.length) {
206
- onMsg(` Batch errors: ${batchErrors.length}`);
161
+ if (createFailed) {
162
+ if (verbose) {
163
+ onMsg(`Scene item creation failed in ${(0, utils_1.formatTime)(Number(process_1.hrtime.bigint() - startTime) / 1000000000)} at depth ${depth}.`);
207
164
  }
208
- if (sceneItemErrors.length) {
209
- onMsg(` Scene item errors: ${sceneItemErrors.length}`);
165
+ }
166
+ else {
167
+ if (verbose) {
168
+ onMsg(`Scene item creation completed in ${(0, utils_1.formatTime)(Number(process_1.hrtime.bigint() - startTime) / 1000000000)} for ${itemCount} scene items with max depth of ${depthSortedItems.length - 1}.`);
169
+ if (resultBatchErrors.length) {
170
+ onMsg(`Batch errors: ${resultBatchErrors.length}`);
171
+ }
172
+ if (resultItemErrors.length) {
173
+ onMsg(`Scene item errors: ${resultItemErrors.length}`);
174
+ }
210
175
  }
176
+ if (verbose)
177
+ onMsg(`Committing scene and polling until ready...`);
178
+ yield updateScene({
179
+ attributes: { state: index_1.UpdateSceneRequestDataAttributesStateEnum.Commit },
180
+ client,
181
+ sceneId,
182
+ });
183
+ yield pollSceneReady({
184
+ client,
185
+ id: sceneId,
186
+ onMsg,
187
+ polling: sceneReadyPolling,
188
+ verbose,
189
+ });
190
+ if (verbose)
191
+ onMsg(`Fitting scene's camera to scene items...`);
192
+ sceneResult = (yield updateScene({
193
+ attributes: {
194
+ camera: { type: index_1.CameraFitTypeEnum.FitVisibleSceneItems },
195
+ },
196
+ client,
197
+ sceneId,
198
+ })).scene;
211
199
  }
212
- if (verbose)
213
- onMsg(`Committing scene and polling until ready...`);
214
- yield updateScene({
215
- attributes: { state: index_1.UpdateSceneRequestDataAttributesStateEnum.Commit },
216
- client,
217
- sceneId,
218
- });
219
- yield pollSceneReady({ client, id: sceneId, onMsg, polling, verbose });
220
- if (verbose)
221
- onMsg(`Fitting scene's camera to scene items...`);
222
- const sceneResult = (yield updateScene({
223
- attributes: {
224
- camera: { type: index_1.CameraFitTypeEnum.FitVisibleSceneItems },
225
- },
226
- client,
227
- sceneId,
228
- })).scene;
229
200
  if (verbose) {
230
- const formatTime = (seconds) => {
231
- const h = Math.floor(seconds / 3600);
232
- const m = Math.floor((seconds % 3600) / 60);
233
- const s = Math.round(seconds % 60);
234
- return [h, m > 9 ? m : h ? '0' + m : m || '0', s > 9 ? s : '0' + s]
235
- .filter(Boolean)
236
- .join(':');
237
- };
238
- onMsg(`Scene creation completed in ${formatTime(Number(process_1.hrtime.bigint() - startTime) / 1000000000)}.`);
201
+ onMsg(`Scene creation completed in ${(0, utils_1.formatTime)(Number(process_1.hrtime.bigint() - startTime) / 1000000000)}.`);
239
202
  }
240
203
  return {
241
- errors: batchErrors,
242
- queued: batchQueuedOps,
204
+ errors: resultBatchErrors,
205
+ queued: returnQueued ? resultQueuedOps : [],
243
206
  scene: sceneResult,
244
- sceneItemErrors,
207
+ sceneItemErrors: resultItemErrors,
245
208
  };
246
209
  });
247
210
  }
248
- exports.createSceneAndSceneItemsEXPERIMENTAL = createSceneAndSceneItemsEXPERIMENTAL;
211
+ exports.createSceneAndSceneItems = createSceneAndSceneItems;
212
+ /**
213
+ * Helper function for building a metadata string object.
214
+ *
215
+ * @param value Value to convert to metadata object
216
+ * @param condition Setting to `false` will cause result to be `undefined`
217
+ * @returns Instance of a `MetadataValue` object
218
+ */
219
+ function toMetadataOrUndefined(value, condition = true) {
220
+ return condition && (0, index_2.defined)(value)
221
+ ? {
222
+ type: 'string',
223
+ value,
224
+ }
225
+ : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
226
+ undefined;
227
+ }
228
+ /**
229
+ * This async function takes a long list of create scene item data and handles
230
+ * batch based scene item creation. Batch operation results and errors are
231
+ * returned to the caller.
232
+ */
233
+ const createSceneItemBatch = ({ client, createSceneItemReqs: createItemReqs, failFast, onProgress, limit, sceneId, polling = { intervalMs: index_2.PollIntervalMs, maxAttempts: index_2.MaxAttempts }, }) => __awaiter(void 0, void 0, void 0, function* () {
234
+ let batchErrors = [];
235
+ let itemErrors = [];
236
+ let itemResults = [];
237
+ const createRes = yield createSceneItems({
238
+ client,
239
+ createSceneItemReqs: createItemReqs,
240
+ failFast,
241
+ onProgress,
242
+ limit,
243
+ sceneId,
244
+ });
245
+ const { a: batchOps, b: errors } = (0, index_2.partition)(createRes.queuedBatchOps, (i) => (0, index_2.isQueuedJob)(i.res));
246
+ if (errors.length) {
247
+ batchErrors = batchErrors.concat(errors);
248
+ }
249
+ // Nothing succeeded, return early as something is likely wrong
250
+ if (batchOps.length === 0 || errors.length === createRes.chunks) {
251
+ return { batchOps, batchErrors, itemErrors, itemResults };
252
+ }
253
+ else {
254
+ function poll({ ops, res, }) {
255
+ return __awaiter(this, void 0, void 0, function* () {
256
+ const r = yield (0, queued_jobs_1.pollQueuedJob)({
257
+ id: res.data.id,
258
+ getQueuedJob: (id, cancelToken) => client.batches.getQueuedBatch({ id }, { cancelToken }),
259
+ allow404: true,
260
+ limit,
261
+ polling,
262
+ });
263
+ if ((0, queued_jobs_1.isPollError)(r.res)) {
264
+ failFast ? (0, queued_jobs_1.throwOnError)(r) : errors.push({ ops, res: r.res });
265
+ }
266
+ return r;
267
+ });
268
+ }
269
+ // eslint-disable-next-line no-await-in-loop
270
+ const batchRes = yield Promise.all(batchOps.map((is) => limit(poll, is)));
271
+ itemResults = batchRes.flatMap((b, i) => (0, queued_jobs_1.isBatch)(b.res)
272
+ ? b.res['vertexvis/batch:results'].map((r, j) => {
273
+ return { req: batchOps[i].ops[j].data, res: r };
274
+ })
275
+ : []);
276
+ itemErrors = itemErrors.concat(itemResults.filter((resultItem) => (0, utils_1.isApiError)(resultItem.res)));
277
+ }
278
+ // if the full batch failed add batch item error for each item
279
+ errors.forEach((error) => {
280
+ console.log(error);
281
+ error.ops.forEach((op) => {
282
+ // `error.res` guaranteed to be non-null due to `isApiError()` condition above
283
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
284
+ itemErrors.push({ req: op.data, res: error.res });
285
+ });
286
+ });
287
+ return { batchOps, batchErrors, itemErrors, itemResults };
288
+ });
249
289
  /**
250
290
  * Create scene items within a scene.
251
291
  */
252
- function createSceneItemsEXPERIMENTAL({ client, createSceneItemReqs, failFast, parallelism, sceneId, }) {
292
+ function createSceneItems({ client, createSceneItemReqs, failFast, limit, sceneId, }) {
253
293
  return __awaiter(this, void 0, void 0, function* () {
254
- const limit = (0, p_limit_1.default)(parallelism);
255
294
  const batchSize = 500;
256
295
  const opChunks = (0, utils_1.arrayChunked)(createSceneItemReqs.map((req) => ({
257
296
  data: req.data,
@@ -281,7 +320,7 @@ function createSceneItemsEXPERIMENTAL({ client, createSceneItemReqs, failFast, p
281
320
  return { chunks: opChunks.length, queuedBatchOps };
282
321
  });
283
322
  }
284
- exports.createSceneItemsEXPERIMENTAL = createSceneItemsEXPERIMENTAL;
323
+ exports.createSceneItems = createSceneItems;
285
324
  /**
286
325
  * Delete all scenes.
287
326
  *