@makeswift/runtime 0.29.0-canary.19 → 0.29.0-canary.21

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.
@@ -27,7 +27,7 @@ class MakeswiftGraphQLApiClient {
27
27
  graphqlClient;
28
28
  constructor({ endpoint }) {
29
29
  this.graphqlClient = new import_client.GraphQLClient(endpoint, {
30
- "makeswift-runtime-version": "0.29.0-canary.19"
30
+ "makeswift-runtime-version": "0.29.0-canary.21"
31
31
  });
32
32
  }
33
33
  async getUnversionedResources({
@@ -35,6 +35,7 @@ __export(rest_api_client_exports, {
35
35
  module.exports = __toCommonJS(rest_api_client_exports);
36
36
  var import_ky = __toESM(require("./ky"));
37
37
  var Schema = __toESM(require("./schema"));
38
+ const MAX_GLOBAL_ELEMENTS_PER_REQUEST = 100;
38
39
  const RetryBackoffConfig = {
39
40
  MaxAttempts: 3,
40
41
  MaxDelayMs: 5e3
@@ -128,6 +129,30 @@ class MakeswiftRestAPIClient {
128
129
  const globalElement = await response.json();
129
130
  return globalElement;
130
131
  }
132
+ async getGlobalElements(globalElementIds, siteVersion, { locale } = {}) {
133
+ const getGlobalElementsBatch = async (ids) => {
134
+ const url = new URL(`content/v1/global-elements/bulk`, this.apiOrigin);
135
+ ids.forEach((id) => url.searchParams.append("ids", id));
136
+ if (locale != null)
137
+ url.searchParams.set("locale", locale);
138
+ const response = await this.fetch(url.pathname + url.search, siteVersion);
139
+ if (!response.ok) {
140
+ const failedBody = await failedResponseBody(response);
141
+ throw new RestApiClientError(
142
+ `Failed to get global elements for [${ids.join(", ")}]`,
143
+ response,
144
+ { body: failedBody, siteVersion, locale }
145
+ );
146
+ }
147
+ return await response.json();
148
+ };
149
+ const batches = [];
150
+ for (let i = 0; i < globalElementIds.length; i += MAX_GLOBAL_ELEMENTS_PER_REQUEST) {
151
+ batches.push(globalElementIds.slice(i, i + MAX_GLOBAL_ELEMENTS_PER_REQUEST));
152
+ }
153
+ const results = await Promise.all(batches.map(getGlobalElementsBatch));
154
+ return results.flat();
155
+ }
131
156
  async getLocalizedGlobalElement(globalElementId, locale, siteVersion) {
132
157
  const response = await this.fetch(
133
158
  `v3/localized-global-elements/${globalElementId}?locale=${locale}`,
@@ -198,7 +223,7 @@ class MakeswiftRestAPIClient {
198
223
  const requestHeaders = new Headers({
199
224
  "x-api-key": this.apiKey,
200
225
  "makeswift-site-api-key": this.apiKey,
201
- "makeswift-runtime-version": "0.29.0-canary.19"
226
+ "makeswift-runtime-version": "0.29.0-canary.21"
202
227
  });
203
228
  if (siteVersion?.token) {
204
229
  requestUrl.searchParams.set("version", siteVersion.version);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/api/rest-api-client.ts"],"sourcesContent":["import ky, { HTTPError, isHTTPError, type KyInstance } from './ky'\n\nimport {\n type File,\n type GlobalElement,\n type LocalizedGlobalElement,\n type PagePathnameSlice,\n type Swatch,\n type Table,\n type Typography,\n type HttpFetch,\n} from './types'\n\nimport { type SiteVersion } from './site-version'\nimport * as Schema from './schema'\n\nconst RetryBackoffConfig = {\n MaxAttempts: 3,\n MaxDelayMs: 5_000,\n}\n\nexport class MakeswiftRestAPIClient {\n private _fetch: KyInstance\n\n readonly apiKey: string\n readonly apiOrigin: string\n\n constructor({\n fetch,\n apiKey,\n apiOrigin,\n }: {\n fetch: HttpFetch\n apiKey: string\n apiOrigin: string\n }) {\n this._fetch = ky.create({\n fetch,\n timeout: false,\n retry: {\n statusCodes: [408, 429, 500, 502, 503, 504],\n limit: RetryBackoffConfig.MaxAttempts,\n backoffLimit: RetryBackoffConfig.MaxDelayMs,\n delay: attemptCount => 2 ** (attemptCount - 1) * 1000,\n jitter: true,\n },\n hooks: {\n beforeRetry: [\n async ({ request, error, retryCount }) => {\n console.warn(\n `Request to ${request.url} failed with ${error}. Retrying (${retryCount}/${RetryBackoffConfig.MaxAttempts})`,\n )\n // Drain the response body before retrying so we don't leak unconsumed\n // response bodies (see the comment on `failedResponseBody` below).\n if (isHTTPError(error)) await failedResponseBody(error.response)\n },\n ],\n },\n })\n\n this.apiKey = apiKey\n this.apiOrigin = apiOrigin\n }\n\n async getSwatch(swatchId: string, siteVersion: SiteVersion | null): Promise<Swatch | null> {\n const response = await this.fetch(`v3/swatches/${swatchId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get swatch '${swatchId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const swatch = await response.json()\n\n return swatch\n }\n\n async getFile(fileId: string): Promise<File | null> {\n const response = await this.fetch(`v1/files/${fileId}`, null)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get file '${fileId}'`, response, {\n body: failedBody,\n })\n }\n\n const file = await response.json()\n\n return file\n }\n\n async getTypography(\n typographyId: string,\n siteVersion: SiteVersion | null,\n ): Promise<Typography | null> {\n const response = await this.fetch(`v3/typographies/${typographyId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get typography '${typographyId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const typography = await response.json()\n\n return typography\n }\n\n async getGlobalElement(\n globalElementId: string,\n siteVersion: SiteVersion | null,\n ): Promise<GlobalElement | null> {\n const response = await this.fetch(`v3/global-elements/${globalElementId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get global element '${globalElementId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const globalElement = await response.json()\n\n return globalElement\n }\n\n async getLocalizedGlobalElement(\n globalElementId: string,\n locale: string,\n siteVersion: SiteVersion | null,\n ): Promise<LocalizedGlobalElement | null> {\n const response = await this.fetch(\n `v3/localized-global-elements/${globalElementId}?locale=${locale}`,\n siteVersion,\n )\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(\n `Failed to get localized global element '${globalElementId}'`,\n response,\n { body: failedBody, siteVersion, locale },\n )\n }\n\n const localizedGlobalElement = await response.json()\n\n return localizedGlobalElement\n }\n\n async getTable(tableId: string): Promise<Table | null> {\n const response = await this.fetch(`v1/tables/${tableId}`, null)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get table '${tableId}'`, response, {\n body: failedBody,\n })\n }\n\n const table = await response.json()\n\n return table\n }\n\n async getPagePathnameSlices(\n pageIds: string[],\n siteVersion: SiteVersion | null,\n { locale }: { locale?: string | null },\n ): Promise<(PagePathnameSlice | null)[]> {\n if (pageIds.length === 0) return []\n\n const url = new URL(`v3/page-pathname-slices/bulk`, this.apiOrigin)\n\n pageIds.forEach(id => url.searchParams.append('ids', id))\n if (locale != null) url.searchParams.set('locale', locale)\n\n const response = await this.fetch(url.pathname + url.search, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return []\n\n throw new RestApiClientError(\n `Failed to get page pathname slice(s) for ${pageIds.join(', ')}`,\n response,\n { body: failedBody, siteVersion, locale },\n )\n }\n\n const json = await response.json()\n\n const pagePathnameSlices = Schema.pagePathnameSlices.parse(json)\n\n // We're mapping the basePageId to be the id, because we're still using the GraphQL\n // fragment as our APIResource. The id on the APIResource needs to match the pageId\n // so that we can find the corresponding page pathname slice when we call getPagePathnameSlice(pageId).\n // TODO: Update this once we move away from the GraphQL fragments.\n return pagePathnameSlices.map(pagePathnameSlice => {\n if (pagePathnameSlice == null) return null\n\n return {\n ...pagePathnameSlice,\n id: pagePathnameSlice.basePageId,\n localizedPathname: pagePathnameSlice.localizedPathname ?? null,\n }\n })\n }\n\n async getPagePathnameSlice(\n pageId: string,\n siteVersion: SiteVersion | null,\n { locale }: { locale?: string | null } = {},\n ): Promise<PagePathnameSlice | null> {\n const pagePathnameSlices = await this.getPagePathnameSlices([pageId], siteVersion, { locale })\n\n return pagePathnameSlices.at(0) ?? null\n }\n\n protected async fetch(\n path: string,\n siteVersion: SiteVersion | null,\n init?: RequestInit,\n ): Promise<Response> {\n const requestUrl = new URL(path, this.apiOrigin)\n\n const requestHeaders = new Headers({\n 'x-api-key': this.apiKey,\n 'makeswift-site-api-key': this.apiKey,\n 'makeswift-runtime-version': PACKAGE_VERSION,\n })\n\n if (siteVersion?.token) {\n requestUrl.searchParams.set('version', siteVersion.version)\n requestHeaders.set('makeswift-preview-token', siteVersion.token)\n }\n\n if (init?.headers) {\n new Headers(init.headers).forEach((value, key) => {\n requestHeaders.set(key, value)\n })\n }\n\n try {\n return await this._fetch(requestUrl.toString(), {\n ...init,\n headers: requestHeaders,\n ...(siteVersion != null ? { cache: 'no-store' } : {}),\n })\n } catch (error) {\n if (error instanceof HTTPError) return error.response\n throw error\n }\n }\n}\n\n// This function attempts to consume the response body of a failed response, and\n// returns either the parsed JSON or raw text. This is useful for logging more\n// detailed error information when an API request fails.\n//\n// Cloudflare Worker Note: The Cloudflare Worker runtime has automatic deadlock\n// prevention (in the form of auto-cancelling responses) that triggers when too\n// many response bodies are unconsumed. This applies for error responses as\n// well. As such, in this client we use this function to consume the response\n// body whenever the request fails, even if we don't end up logging the body\n// itself, to avoid hitting the deadlock prevention.\nexport async function failedResponseBody(response: Response): Promise<unknown> {\n try {\n const text = await response.text()\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n } catch (e) {\n return `Failed to extract response body: ${e}`\n }\n}\n\nfunction responseError(response: Response): string {\n return `${response.status} ${response.statusText}`\n}\n\nexport class RestApiClientError extends Error {\n readonly status: number\n\n constructor(message: string, response: Response, cause: Record<string, unknown>) {\n super(`${message}: ${responseError(response)}`, { cause })\n\n this.name = 'RestApiClientError'\n this.status = response.status\n }\n}\n"],"mappings":"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","names":["ky"]}
1
+ {"version":3,"sources":["../../../src/api/rest-api-client.ts"],"sourcesContent":["import ky, { HTTPError, isHTTPError, type KyInstance } from './ky'\n\nimport {\n type File,\n type GlobalElement,\n type LocalizedGlobalElement,\n type PagePathnameSlice,\n type Swatch,\n type Table,\n type Typography,\n type HttpFetch,\n} from './types'\n\nimport { type SiteVersion } from './site-version'\nimport * as Schema from './schema'\n\nexport type GlobalElementWithLocalized = {\n base: GlobalElement | null\n localized: LocalizedGlobalElement | null\n}\n\nconst MAX_GLOBAL_ELEMENTS_PER_REQUEST = 100\n\nconst RetryBackoffConfig = {\n MaxAttempts: 3,\n MaxDelayMs: 5_000,\n}\n\nexport class MakeswiftRestAPIClient {\n private _fetch: KyInstance\n\n readonly apiKey: string\n readonly apiOrigin: string\n\n constructor({\n fetch,\n apiKey,\n apiOrigin,\n }: {\n fetch: HttpFetch\n apiKey: string\n apiOrigin: string\n }) {\n this._fetch = ky.create({\n fetch,\n timeout: false,\n retry: {\n statusCodes: [408, 429, 500, 502, 503, 504],\n limit: RetryBackoffConfig.MaxAttempts,\n backoffLimit: RetryBackoffConfig.MaxDelayMs,\n delay: attemptCount => 2 ** (attemptCount - 1) * 1000,\n jitter: true,\n },\n hooks: {\n beforeRetry: [\n async ({ request, error, retryCount }) => {\n console.warn(\n `Request to ${request.url} failed with ${error}. Retrying (${retryCount}/${RetryBackoffConfig.MaxAttempts})`,\n )\n // Drain the response body before retrying so we don't leak unconsumed\n // response bodies (see the comment on `failedResponseBody` below).\n if (isHTTPError(error)) await failedResponseBody(error.response)\n },\n ],\n },\n })\n\n this.apiKey = apiKey\n this.apiOrigin = apiOrigin\n }\n\n async getSwatch(swatchId: string, siteVersion: SiteVersion | null): Promise<Swatch | null> {\n const response = await this.fetch(`v3/swatches/${swatchId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get swatch '${swatchId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const swatch = await response.json()\n\n return swatch\n }\n\n async getFile(fileId: string): Promise<File | null> {\n const response = await this.fetch(`v1/files/${fileId}`, null)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get file '${fileId}'`, response, {\n body: failedBody,\n })\n }\n\n const file = await response.json()\n\n return file\n }\n\n async getTypography(\n typographyId: string,\n siteVersion: SiteVersion | null,\n ): Promise<Typography | null> {\n const response = await this.fetch(`v3/typographies/${typographyId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get typography '${typographyId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const typography = await response.json()\n\n return typography\n }\n\n async getGlobalElement(\n globalElementId: string,\n siteVersion: SiteVersion | null,\n ): Promise<GlobalElement | null> {\n const response = await this.fetch(`v3/global-elements/${globalElementId}`, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get global element '${globalElementId}'`, response, {\n body: failedBody,\n siteVersion,\n })\n }\n\n const globalElement = await response.json()\n\n return globalElement\n }\n\n async getGlobalElements(\n globalElementIds: string[],\n siteVersion: SiteVersion | null,\n { locale }: { locale?: string | null } = {},\n ): Promise<GlobalElementWithLocalized[]> {\n const getGlobalElementsBatch = async (ids: string[]): Promise<GlobalElementWithLocalized[]> => {\n const url = new URL(`content/v1/global-elements/bulk`, this.apiOrigin)\n\n ids.forEach(id => url.searchParams.append('ids', id))\n if (locale != null) url.searchParams.set('locale', locale)\n\n const response = await this.fetch(url.pathname + url.search, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n\n throw new RestApiClientError(\n `Failed to get global elements for [${ids.join(', ')}]`,\n response,\n { body: failedBody, siteVersion, locale },\n )\n }\n\n return await response.json()\n }\n\n const batches: string[][] = []\n\n for (let i = 0; i < globalElementIds.length; i += MAX_GLOBAL_ELEMENTS_PER_REQUEST) {\n batches.push(globalElementIds.slice(i, i + MAX_GLOBAL_ELEMENTS_PER_REQUEST))\n }\n\n const results = await Promise.all(batches.map(getGlobalElementsBatch))\n\n return results.flat()\n }\n\n async getLocalizedGlobalElement(\n globalElementId: string,\n locale: string,\n siteVersion: SiteVersion | null,\n ): Promise<LocalizedGlobalElement | null> {\n const response = await this.fetch(\n `v3/localized-global-elements/${globalElementId}?locale=${locale}`,\n siteVersion,\n )\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(\n `Failed to get localized global element '${globalElementId}'`,\n response,\n { body: failedBody, siteVersion, locale },\n )\n }\n\n const localizedGlobalElement = await response.json()\n\n return localizedGlobalElement\n }\n\n async getTable(tableId: string): Promise<Table | null> {\n const response = await this.fetch(`v1/tables/${tableId}`, null)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return null\n\n throw new RestApiClientError(`Failed to get table '${tableId}'`, response, {\n body: failedBody,\n })\n }\n\n const table = await response.json()\n\n return table\n }\n\n async getPagePathnameSlices(\n pageIds: string[],\n siteVersion: SiteVersion | null,\n { locale }: { locale?: string | null },\n ): Promise<(PagePathnameSlice | null)[]> {\n if (pageIds.length === 0) return []\n\n const url = new URL(`v3/page-pathname-slices/bulk`, this.apiOrigin)\n\n pageIds.forEach(id => url.searchParams.append('ids', id))\n if (locale != null) url.searchParams.set('locale', locale)\n\n const response = await this.fetch(url.pathname + url.search, siteVersion)\n\n if (!response.ok) {\n const failedBody = await failedResponseBody(response)\n if (response.status === 404) return []\n\n throw new RestApiClientError(\n `Failed to get page pathname slice(s) for ${pageIds.join(', ')}`,\n response,\n { body: failedBody, siteVersion, locale },\n )\n }\n\n const json = await response.json()\n\n const pagePathnameSlices = Schema.pagePathnameSlices.parse(json)\n\n // We're mapping the basePageId to be the id, because we're still using the GraphQL\n // fragment as our APIResource. The id on the APIResource needs to match the pageId\n // so that we can find the corresponding page pathname slice when we call getPagePathnameSlice(pageId).\n // TODO: Update this once we move away from the GraphQL fragments.\n return pagePathnameSlices.map(pagePathnameSlice => {\n if (pagePathnameSlice == null) return null\n\n return {\n ...pagePathnameSlice,\n id: pagePathnameSlice.basePageId,\n localizedPathname: pagePathnameSlice.localizedPathname ?? null,\n }\n })\n }\n\n async getPagePathnameSlice(\n pageId: string,\n siteVersion: SiteVersion | null,\n { locale }: { locale?: string | null } = {},\n ): Promise<PagePathnameSlice | null> {\n const pagePathnameSlices = await this.getPagePathnameSlices([pageId], siteVersion, { locale })\n\n return pagePathnameSlices.at(0) ?? null\n }\n\n protected async fetch(\n path: string,\n siteVersion: SiteVersion | null,\n init?: RequestInit,\n ): Promise<Response> {\n const requestUrl = new URL(path, this.apiOrigin)\n\n const requestHeaders = new Headers({\n 'x-api-key': this.apiKey,\n 'makeswift-site-api-key': this.apiKey,\n 'makeswift-runtime-version': PACKAGE_VERSION,\n })\n\n if (siteVersion?.token) {\n requestUrl.searchParams.set('version', siteVersion.version)\n requestHeaders.set('makeswift-preview-token', siteVersion.token)\n }\n\n if (init?.headers) {\n new Headers(init.headers).forEach((value, key) => {\n requestHeaders.set(key, value)\n })\n }\n\n try {\n return await this._fetch(requestUrl.toString(), {\n ...init,\n headers: requestHeaders,\n ...(siteVersion != null ? { cache: 'no-store' } : {}),\n })\n } catch (error) {\n if (error instanceof HTTPError) return error.response\n throw error\n }\n }\n}\n\n// This function attempts to consume the response body of a failed response, and\n// returns either the parsed JSON or raw text. This is useful for logging more\n// detailed error information when an API request fails.\n//\n// Cloudflare Worker Note: The Cloudflare Worker runtime has automatic deadlock\n// prevention (in the form of auto-cancelling responses) that triggers when too\n// many response bodies are unconsumed. This applies for error responses as\n// well. As such, in this client we use this function to consume the response\n// body whenever the request fails, even if we don't end up logging the body\n// itself, to avoid hitting the deadlock prevention.\nexport async function failedResponseBody(response: Response): Promise<unknown> {\n try {\n const text = await response.text()\n try {\n return JSON.parse(text)\n } catch {\n return text\n }\n } catch (e) {\n return `Failed to extract response body: ${e}`\n }\n}\n\nfunction responseError(response: Response): string {\n return `${response.status} ${response.statusText}`\n}\n\nexport class RestApiClientError extends Error {\n readonly status: number\n\n constructor(message: string, response: Response, cause: Record<string, unknown>) {\n super(`${message}: ${responseError(response)}`, { cause })\n\n this.name = 'RestApiClientError'\n this.status = response.status\n }\n}\n"],"mappings":"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","names":["ky"]}
@@ -28,7 +28,7 @@ async function manifestHandler(req, { apiKey, manifest }) {
28
28
  return import_request_response.ApiResponse.json({ message: "Unauthorized" }, { status: 401 });
29
29
  }
30
30
  return import_request_response.ApiResponse.json({
31
- version: "0.29.0-canary.19",
31
+ version: "0.29.0-canary.21",
32
32
  interactionMode: true,
33
33
  clientSideNavigation: false,
34
34
  elementFromPoint: false,
@@ -187,128 +187,14 @@ Received "${apiKey}" instead.`
187
187
  const swatches = await this.getSwatches(swatchIds, siteVersion);
188
188
  return { ...unversionedResources, swatches };
189
189
  }
190
- // TODO: Consolidate this method with the introspectMany method once the
191
- // unstable_getComponentSnapshots method is stable and tested in production.
192
190
  async introspect(element, siteVersion, locale) {
193
- const descriptors = this.getElementDescriptors();
194
- const swatchIds = /* @__PURE__ */ new Set();
195
- const fileIds = /* @__PURE__ */ new Set();
196
- const typographyIds = /* @__PURE__ */ new Set();
197
- const tableIds = /* @__PURE__ */ new Set();
198
- const pageIds = /* @__PURE__ */ new Set();
199
- const globalElements = /* @__PURE__ */ new Map();
200
- const localizedGlobalElements = /* @__PURE__ */ new Map();
201
- const localizedResourcesMap = /* @__PURE__ */ new Map();
202
- const remaining = [element];
203
- const seen = /* @__PURE__ */ new Set();
204
- let current;
205
- while (current = remaining.pop()) {
206
- let getResourcesFromElementDescriptors2 = function(elementDescriptors2, props) {
207
- Object.entries(elementDescriptors2).forEach(([propName, descriptor]) => {
208
- (0, import_introspection.getSwatchIds)(descriptor, props[propName]).forEach((swatchId) => {
209
- swatchIds.add(swatchId);
210
- });
211
- (0, import_introspection.getFileIds)(descriptor, props[propName]).forEach((fileId) => fileIds.add(fileId));
212
- (0, import_introspection.getTypographyIds)(descriptor, props[propName]).forEach(
213
- (typographyId) => typographyIds.add(typographyId)
214
- );
215
- (0, import_introspection.getTableIds)(descriptor, props[propName]).forEach((tableId) => tableIds.add(tableId));
216
- (0, import_introspection.getPageIds)(descriptor, props[propName]).forEach((pageId) => pageIds.add(pageId));
217
- (0, import_introspection.getElementChildren)(descriptor, props[propName]).forEach((child) => {
218
- if (!seen.has(child.key)) {
219
- seen.add(child.key);
220
- remaining.push(child);
221
- }
222
- });
223
- });
224
- };
225
- var getResourcesFromElementDescriptors = getResourcesFromElementDescriptors2;
226
- let element2;
227
- if ((0, import_read_only_state.isElementReference)(current)) {
228
- const globalElementId = current.value;
229
- const globalElement = await this.getGlobalElement(globalElementId, siteVersion);
230
- let elementData = globalElement?.data;
231
- if (locale) {
232
- const localizedGlobalElement = await this.getLocalizedGlobalElement(
233
- globalElementId,
234
- locale,
235
- siteVersion
236
- );
237
- if (localizedGlobalElement) {
238
- elementData = localizedGlobalElement.data;
239
- localizedResourcesMap.set(globalElementId, localizedGlobalElement.id);
240
- localizedGlobalElements.set(localizedGlobalElement.id, localizedGlobalElement);
241
- } else {
242
- localizedResourcesMap.set(globalElementId, null);
243
- }
244
- }
245
- globalElements.set(globalElementId, globalElement);
246
- if (elementData == null)
247
- continue;
248
- element2 = elementData;
249
- } else {
250
- element2 = current;
251
- }
252
- const elementDescriptors = descriptors.get(element2.type);
253
- if (elementDescriptors == null)
254
- continue;
255
- getResourcesFromElementDescriptors2(elementDescriptors, element2.props);
256
- }
257
- const typographies = await this.getTypographies([...typographyIds], siteVersion);
258
- typographies.forEach((typography) => {
259
- typography?.style.forEach((style) => {
260
- const swatchId = style.value.color?.swatchId;
261
- if (swatchId != null)
262
- swatchIds.add(swatchId);
263
- });
264
- });
265
- const pagePathnames = await this.getPagePathnameSlices([...pageIds], siteVersion, { locale });
266
- const { swatches, files, tables } = await this.getIntrospectedResources(
267
- {
268
- swatchIds: [...swatchIds],
269
- fileIds: [...fileIds],
270
- tableIds: [...tableIds]
271
- },
272
- siteVersion
191
+ const treeId = "root";
192
+ const cacheDataMap = await this.introspectMany(
193
+ [{ id: treeId, data: element }],
194
+ siteVersion,
195
+ locale
273
196
  );
274
- const apiResources = {
275
- [import_types2.APIResourceType.Swatch]: [...swatchIds].map((id) => ({
276
- id,
277
- value: swatches.find((swatch) => swatch?.id === id) ?? null
278
- })),
279
- [import_types2.APIResourceType.File]: [...fileIds].map((id) => ({
280
- id,
281
- value: files.find((file) => file?.id === id) ?? null
282
- })),
283
- [import_types2.APIResourceType.Typography]: [...typographyIds].map((id) => ({
284
- id,
285
- value: typographies.find((typography) => typography?.id === id) ?? null
286
- })),
287
- [import_types2.APIResourceType.Table]: [...tableIds].map((id) => ({
288
- id,
289
- value: tables.find((table) => table?.id === id) ?? null
290
- })),
291
- [import_types2.APIResourceType.PagePathnameSlice]: [...pageIds].map((id) => ({
292
- id,
293
- value: pagePathnames.find((pagePathnameSlice) => pagePathnameSlice?.id === id) ?? null,
294
- locale
295
- })),
296
- [import_types2.APIResourceType.GlobalElement]: [...globalElements.entries()].map(([id, value]) => ({
297
- id,
298
- value
299
- })),
300
- [import_types2.APIResourceType.LocalizedGlobalElement]: [...localizedGlobalElements.entries()].map(
301
- ([id, value]) => ({
302
- id,
303
- value,
304
- locale
305
- })
306
- )
307
- };
308
- return {
309
- apiResources,
310
- localizedResourcesMap: locale != null ? { [locale]: Object.fromEntries(localizedResourcesMap.entries()) } : {}
311
- };
197
+ return cacheDataMap.get(treeId);
312
198
  }
313
199
  async introspectMany(trees, siteVersion, locale) {
314
200
  if (trees.length === 0)
@@ -316,106 +202,116 @@ Received "${apiKey}" instead.`
316
202
  const descriptors = this.getElementDescriptors();
317
203
  const globalElementCache = /* @__PURE__ */ new Map();
318
204
  const localizedGlobalElementCache = /* @__PURE__ */ new Map();
319
- const treeCaches = new Map(
205
+ function createTreeCache() {
206
+ return {
207
+ swatchIds: /* @__PURE__ */ new Set(),
208
+ fileIds: /* @__PURE__ */ new Set(),
209
+ typographyIds: /* @__PURE__ */ new Set(),
210
+ tableIds: /* @__PURE__ */ new Set(),
211
+ pageIds: /* @__PURE__ */ new Set(),
212
+ globalElements: /* @__PURE__ */ new Map(),
213
+ localizedGlobalElements: /* @__PURE__ */ new Map(),
214
+ localizedResourcesMap: /* @__PURE__ */ new Map()
215
+ };
216
+ }
217
+ const traversals = new Map(
320
218
  trees.map((tree) => [
321
219
  tree.id,
322
220
  {
323
- data: tree.data,
324
- swatchIds: /* @__PURE__ */ new Set(),
325
- fileIds: /* @__PURE__ */ new Set(),
326
- typographyIds: /* @__PURE__ */ new Set(),
327
- tableIds: /* @__PURE__ */ new Set(),
328
- pageIds: /* @__PURE__ */ new Set(),
329
- globalElements: /* @__PURE__ */ new Map(),
330
- localizedGlobalElements: /* @__PURE__ */ new Map(),
331
- localizedResourcesMap: /* @__PURE__ */ new Map()
221
+ cache: createTreeCache(),
222
+ remaining: [tree.data],
223
+ seen: /* @__PURE__ */ new Set()
332
224
  }
333
225
  ])
334
226
  );
335
- for (const currentTreeCache of treeCaches.values()) {
336
- const remaining = [currentTreeCache.data];
337
- const seen = /* @__PURE__ */ new Set();
338
- let current;
339
- while (current = remaining.pop()) {
340
- let getResourcesFromElementDescriptors2 = function(elementDescriptors2, props) {
341
- Object.entries(elementDescriptors2).forEach(([propName, descriptor]) => {
342
- (0, import_introspection.getSwatchIds)(descriptor, props[propName]).forEach((swatchId) => {
343
- currentTreeCache.swatchIds.add(swatchId);
344
- });
345
- (0, import_introspection.getFileIds)(descriptor, props[propName]).forEach((fileId) => {
346
- currentTreeCache.fileIds.add(fileId);
227
+ while (true) {
228
+ const pendingGlobalElementIds = /* @__PURE__ */ new Set();
229
+ const deferred = [];
230
+ for (const [treeId, traversal] of traversals) {
231
+ const { remaining, seen, cache: currentTreeCache } = traversal;
232
+ let current;
233
+ while (current = remaining.pop()) {
234
+ let getResourcesFromElementDescriptors2 = function(elementDescriptors2, props) {
235
+ Object.entries(elementDescriptors2).forEach(([propName, descriptor]) => {
236
+ (0, import_introspection.getSwatchIds)(descriptor, props[propName]).forEach((swatchId) => {
237
+ currentTreeCache.swatchIds.add(swatchId);
238
+ });
239
+ (0, import_introspection.getFileIds)(descriptor, props[propName]).forEach((fileId) => {
240
+ currentTreeCache.fileIds.add(fileId);
241
+ });
242
+ (0, import_introspection.getTypographyIds)(descriptor, props[propName]).forEach((typographyId) => {
243
+ currentTreeCache.typographyIds.add(typographyId);
244
+ });
245
+ (0, import_introspection.getTableIds)(descriptor, props[propName]).forEach((tableId) => {
246
+ currentTreeCache.tableIds.add(tableId);
247
+ });
248
+ (0, import_introspection.getPageIds)(descriptor, props[propName]).forEach((pageId) => {
249
+ currentTreeCache.pageIds.add(pageId);
250
+ });
251
+ (0, import_introspection.getElementChildren)(descriptor, props[propName]).forEach((child) => {
252
+ if (!seen.has(child.key)) {
253
+ seen.add(child.key);
254
+ remaining.push(child);
255
+ }
256
+ });
347
257
  });
348
- (0, import_introspection.getTypographyIds)(descriptor, props[propName]).forEach((typographyId) => {
349
- currentTreeCache.typographyIds.add(typographyId);
350
- });
351
- (0, import_introspection.getTableIds)(descriptor, props[propName]).forEach((tableId) => {
352
- currentTreeCache.tableIds.add(tableId);
353
- });
354
- (0, import_introspection.getPageIds)(descriptor, props[propName]).forEach((pageId) => {
355
- currentTreeCache.pageIds.add(pageId);
356
- });
357
- (0, import_introspection.getElementChildren)(descriptor, props[propName]).forEach((child) => {
358
- if (!seen.has(child.key)) {
359
- seen.add(child.key);
360
- remaining.push(child);
361
- }
362
- });
363
- });
364
- };
365
- var getResourcesFromElementDescriptors = getResourcesFromElementDescriptors2;
366
- let element;
367
- if ((0, import_read_only_state.isElementReference)(current)) {
368
- const globalElementId = current.value;
369
- let globalElement;
370
- if (globalElementCache.has(globalElementId)) {
371
- globalElement = globalElementCache.get(globalElementId);
372
- } else {
373
- globalElement = await this.getGlobalElement(globalElementId, siteVersion);
374
- globalElementCache.set(globalElementId, globalElement);
375
- }
376
- let elementData = globalElement?.data;
377
- if (locale) {
378
- let localizedGlobalElement;
379
- if (localizedGlobalElementCache.has(globalElementId)) {
380
- localizedGlobalElement = localizedGlobalElementCache.get(globalElementId);
381
- } else {
382
- localizedGlobalElement = await this.getLocalizedGlobalElement(
383
- globalElementId,
384
- locale,
385
- siteVersion
386
- );
387
- localizedGlobalElementCache.set(globalElementId, localizedGlobalElement);
258
+ };
259
+ var getResourcesFromElementDescriptors = getResourcesFromElementDescriptors2;
260
+ let element;
261
+ if ((0, import_read_only_state.isElementReference)(current)) {
262
+ const globalElementId = current.value;
263
+ if (!globalElementCache.has(globalElementId)) {
264
+ pendingGlobalElementIds.add(globalElementId);
265
+ deferred.push({ treeId, element: current });
266
+ continue;
388
267
  }
389
- if (localizedGlobalElement) {
390
- elementData = localizedGlobalElement.data;
391
- currentTreeCache.localizedResourcesMap.set(globalElementId, localizedGlobalElement.id);
392
- currentTreeCache.localizedGlobalElements.set(
393
- localizedGlobalElement.id,
394
- localizedGlobalElement
395
- );
396
- } else {
397
- currentTreeCache.localizedResourcesMap.set(globalElementId, null);
268
+ const globalElement = globalElementCache.get(globalElementId) ?? null;
269
+ let elementData = globalElement?.data;
270
+ if (locale) {
271
+ const localizedGlobalElement = localizedGlobalElementCache.get(globalElementId) ?? null;
272
+ if (localizedGlobalElement) {
273
+ elementData = localizedGlobalElement.data;
274
+ currentTreeCache.localizedResourcesMap.set(
275
+ globalElementId,
276
+ localizedGlobalElement.id
277
+ );
278
+ currentTreeCache.localizedGlobalElements.set(
279
+ localizedGlobalElement.id,
280
+ localizedGlobalElement
281
+ );
282
+ } else {
283
+ currentTreeCache.localizedResourcesMap.set(globalElementId, null);
284
+ }
398
285
  }
286
+ currentTreeCache.globalElements.set(globalElementId, globalElement);
287
+ if (elementData == null)
288
+ continue;
289
+ element = elementData;
290
+ } else {
291
+ element = current;
399
292
  }
400
- currentTreeCache.globalElements.set(globalElementId, globalElement);
401
- if (elementData == null)
293
+ const elementDescriptors = descriptors.get(element.type);
294
+ if (elementDescriptors == null)
402
295
  continue;
403
- element = elementData;
404
- } else {
405
- element = current;
296
+ getResourcesFromElementDescriptors2(elementDescriptors, element.props);
406
297
  }
407
- const elementDescriptors = descriptors.get(element.type);
408
- if (elementDescriptors == null)
409
- continue;
410
- getResourcesFromElementDescriptors2(elementDescriptors, element.props);
411
298
  }
299
+ if (pendingGlobalElementIds.size === 0)
300
+ break;
301
+ const ids = [...pendingGlobalElementIds];
302
+ const results = await this.getGlobalElements(ids, siteVersion, { locale });
303
+ ids.forEach((id, index) => {
304
+ globalElementCache.set(id, results[index]?.base ?? null);
305
+ localizedGlobalElementCache.set(id, results[index]?.localized ?? null);
306
+ });
307
+ deferred.forEach(({ treeId, element }) => traversals.get(treeId).remaining.push(element));
412
308
  }
413
309
  const allSwatchIds = /* @__PURE__ */ new Set();
414
310
  const allFileIds = /* @__PURE__ */ new Set();
415
311
  const allTypographyIds = /* @__PURE__ */ new Set();
416
312
  const allTableIds = /* @__PURE__ */ new Set();
417
313
  const allPageIds = /* @__PURE__ */ new Set();
418
- for (const currentTreeCache of treeCaches.values()) {
314
+ for (const { cache: currentTreeCache } of traversals.values()) {
419
315
  currentTreeCache.swatchIds.forEach((id) => allSwatchIds.add(id));
420
316
  currentTreeCache.fileIds.forEach((id) => allFileIds.add(id));
421
317
  currentTreeCache.typographyIds.forEach((id) => allTypographyIds.add(id));
@@ -435,7 +331,7 @@ Received "${apiKey}" instead.`
435
331
  }
436
332
  });
437
333
  if (secondarySwatchIds.length > 0) {
438
- for (const currentTreeCache of treeCaches.values()) {
334
+ for (const { cache: currentTreeCache } of traversals.values()) {
439
335
  if (currentTreeCache.typographyIds.has(typography.id)) {
440
336
  secondarySwatchIds.forEach((id) => currentTreeCache.swatchIds.add(id));
441
337
  }
@@ -454,7 +350,7 @@ Received "${apiKey}" instead.`
454
350
  )
455
351
  ]);
456
352
  const result = /* @__PURE__ */ new Map();
457
- for (const [treeId, currentTreeCache] of treeCaches) {
353
+ for (const [treeId, { cache: currentTreeCache }] of traversals) {
458
354
  const apiResources = {
459
355
  [import_types2.APIResourceType.Swatch]: [...currentTreeCache.swatchIds].map((id) => ({
460
356
  id,
@@ -545,71 +441,33 @@ Received "${apiKey}" instead.`
545
441
  async getComponentSnapshot(id, {
546
442
  siteVersion: siteVersionPromise,
547
443
  locale,
548
- allowLocaleFallback = true,
549
- unstable_enforceSuccess = false
444
+ allowLocaleFallback = true
550
445
  }) {
551
446
  const siteVersion = await siteVersionPromise;
552
447
  const key = (0, import_deterministic_uuid.deterministicUUID)({ id, locale, seed: this.apiKey.split("-").at(0) });
553
- const baseLocaleWasRequested = locale == null;
554
- const canAttemptLocaleFallback = !baseLocaleWasRequested && allowLocaleFallback;
555
- const parseElementTreeResponse = async (response) => {
556
- if (!response.ok) {
557
- const failedBody = await (0, import_rest_api_client.failedResponseBody)(response);
558
- if (response.status === 404) {
559
- return null;
560
- }
561
- throw new import_rest_api_client.RestApiClientError(`Failed to get component snapshot for '${id}'`, response, {
562
- body: failedBody,
563
- siteVersion,
564
- locale
565
- });
566
- }
567
- const responseBody = await response.json();
568
- const parsed = Schema.componentDocumentResponse.parse(responseBody);
569
- if ("notFound" in parsed)
570
- return null;
571
- return parsed;
572
- };
573
- const getElementTree = async (searchParams) => {
574
- const response = await this.fetch(
575
- `v2/element-trees/${encodeURIComponent(id)}?${searchParams.toString()}`,
576
- siteVersion
577
- );
578
- return await parseElementTreeResponse(response);
579
- };
580
- const getPrimaryTree = async () => {
581
- const searchParams = new URLSearchParams();
582
- if (locale)
583
- searchParams.set("locale", locale);
584
- if (unstable_enforceSuccess)
585
- searchParams.set("unstable_enforceSuccess", "true");
586
- return await getElementTree(searchParams);
587
- };
588
- const getFallbackTree = async () => {
589
- const searchParams = new URLSearchParams();
590
- if (unstable_enforceSuccess)
591
- searchParams.set("unstable_enforceSuccess", "true");
592
- return await getElementTree(searchParams);
593
- };
594
- const primaryTree = await getPrimaryTree();
595
- const result = primaryTree == null && canAttemptLocaleFallback ? await getFallbackTree() : primaryTree;
596
- if (result == null) {
597
- return {
598
- document: {
599
- id,
600
- locale: locale ?? null,
601
- data: null
602
- },
603
- key,
604
- cacheData: import_api_resources_client.CacheData.empty(),
605
- meta: {
606
- allowLocaleFallback,
607
- requestedLocale: locale ?? null
608
- }
609
- };
448
+ const searchParams = new URLSearchParams();
449
+ if (locale)
450
+ searchParams.set("locale", locale);
451
+ const response = await this.fetch(
452
+ `content/v1/element-trees/${encodeURIComponent(id)}?${searchParams.toString()}`,
453
+ siteVersion
454
+ );
455
+ if (!response.ok) {
456
+ const failedBody = await (0, import_rest_api_client.failedResponseBody)(response);
457
+ throw new import_rest_api_client.RestApiClientError(`Failed to get component snapshot for '${id}'`, response, {
458
+ body: failedBody,
459
+ siteVersion,
460
+ locale
461
+ });
610
462
  }
611
- const document = result;
612
- const cacheData = await this.introspect(document.data, siteVersion, document.locale);
463
+ const responseBody = await response.json();
464
+ const documentResponse = Schema.componentDocumentResponse.parse(responseBody);
465
+ const document = !allowLocaleFallback && documentResponse.locale != locale ? {
466
+ id,
467
+ locale: locale ?? null,
468
+ data: null
469
+ } : documentResponse;
470
+ const cacheData = document.data == null ? import_api_resources_client.CacheData.empty() : await this.introspect(document.data, siteVersion, document.locale);
613
471
  return {
614
472
  document,
615
473
  cacheData,