@slicemachine/manager 0.24.15 → 0.24.16-alpha.coderabbitai-chat-dniAA6r9GseKm4ouqNyJ8dl.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"CustomTypesManager.js","sources":["../../../../src/managers/customTypes/CustomTypesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport {\n\tCustomType,\n\tGroup,\n\tNestableWidget,\n\tNestedGroup,\n\tSharedSlice,\n\tUID,\n\ttraverseCustomType,\n\ttraverseSharedSlice,\n} from \"@prismicio/types-internal/lib/customtypes\";\nimport {\n\tCallHookReturnType,\n\tCustomTypeCreateHook,\n\tCustomTypeCreateHookData,\n\tCustomTypeReadHookData,\n\tCustomTypeRenameHook,\n\tCustomTypeRenameHookData,\n\tCustomTypeUpdateHook,\n\tCustomTypeUpdateHookData,\n\tHookError,\n} from \"@slicemachine/plugin-kit\";\nimport { z } from \"zod\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\nimport fetch from \"../../lib/fetch\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../../constants/SLICE_MACHINE_USER_AGENT\";\nimport { UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\nimport { CustomTypeFormat } from \"./types\";\n\ntype SliceMachineManagerReadCustomTypeLibraryReturnType = {\n\tids: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype CustomTypesManagerReadAllCustomTypesArgs = {\n\tformat: CustomTypeFormat;\n};\n\ntype SliceMachineManagerReadAllCustomTypeReturnType = {\n\tmodels: { model: CustomType }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadCustomTypeReturnType = {\n\tmodel: CustomType | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushCustomTypeArgs = {\n\tid: string;\n\tuserAgent?: string;\n};\n\ntype SliceMachineManagerReadCustomTypeMocksConfigArgs = {\n\tcustomTypeID: string;\n};\n\ntype SliceMachineManagerReadCustomTypeMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateCustomTypeMocksConfigArgs = {\n\tcustomTypeID: string;\n\t// TODO\n\tmocksConfig: Record<string, unknown>;\n};\n\ntype SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType = {\n\terrors: HookError[];\n};\n\ntype CustomTypesMachineManagerDeleteCustomTypeArgs = {\n\tid: string;\n};\n\ntype CustomTypesMachineManagerDeleteCustomTypeReturnType = {\n\terrors: (DecodeError | HookError)[];\n};\n\ntype CustomTypesMachineManagerUpdateCustomTypeReturnType = {\n\terrors: (DecodeError | HookError)[];\n};\n\ntype CustomTypeFieldIdChangedMeta = {\n\tpreviousPath: string[];\n\tnewPath: string[];\n};\n\ntype CrCustomType =\n\t| string\n\t| { id: string; fields?: readonly CrCustomTypeNestedCr[] };\ntype CrCustomTypeNestedCr =\n\t| string\n\t| { id: string; customtypes: readonly CrCustomTypeFieldLeaf[] };\ntype CrCustomTypeFieldLeaf =\n\t| string\n\t| { id: string; fields?: readonly string[] };\n\nexport class CustomTypesManager extends BaseManager {\n\tasync readCustomTypeLibrary(): Promise<SliceMachineManagerReadCustomTypeLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type-library:read\",\n\t\t\tundefined,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tids: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tids: data[0]?.ids || [],\n\t\t\terrors,\n\t\t};\n\t}\n\n\tasync readAllCustomTypes(\n\t\targs?: CustomTypesManagerReadAllCustomTypesArgs,\n\t): Promise<SliceMachineManagerReadAllCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllCustomTypeReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { ids, errors } = await this.readCustomTypeLibrary();\n\t\tres.errors = [...res.errors, ...errors];\n\n\t\tif (ids) {\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst { model, errors } = await this.readCustomType({ id });\n\t\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\t\tif (model && (!args || args.format === model.format)) {\n\t\t\t\t\tres.models.push({ model });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createCustomType(\n\t\targs: CustomTypeCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<CustomTypeCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:create\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync readCustomType(\n\t\targs: CustomTypeReadHookData,\n\t): Promise<SliceMachineManagerReadCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomType,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tmodel: data[0]?.model,\n\t\t\terrors,\n\t\t};\n\t}\n\n\t/**\n\t * Update the Content Relationship API IDs for all existing custom types and\n\t * slices. The change is determined by properties inside the `updateMeta`\n\t * property.\n\t */\n\tprivate async updateContentRelationships(\n\t\targs: { model: CustomType } & CustomTypeFieldIdChangedMeta,\n\t): Promise<\n\t\tOnlyHookErrors<CallHookReturnType<CustomTypeUpdateHook>> & {\n\t\t\trollback?: () => Promise<void>;\n\t\t}\n\t> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst { model } = args;\n\t\tlet { newPath, previousPath } = args;\n\n\t\tif (previousPath.join(\".\") !== newPath.join(\".\")) {\n\t\t\tpreviousPath = [model.id, ...previousPath];\n\t\t\tnewPath = [model.id, ...newPath];\n\n\t\t\tconst crUpdates: {\n\t\t\t\tupdatePromise: Promise<{ errors: HookError[] }>;\n\t\t\t\trollback: () => void;\n\t\t\t}[] = [];\n\n\t\t\t// Find existing content relationships that link to the renamed field id in\n\t\t\t// any custom type and update them to use the new one.\n\t\t\tconst customTypes = await this.readAllCustomTypes();\n\n\t\t\tupdateCustomTypeContentRelationships({\n\t\t\t\tmodels: customTypes.models,\n\t\t\t\tonUpdate: ({ previousModel, model: updatedModel }) => {\n\t\t\t\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t\t\t\tcrUpdates.push({\n\t\t\t\t\t\tupdatePromise: this.sliceMachinePluginRunner?.callHook(\n\t\t\t\t\t\t\t\"custom-type:update\",\n\t\t\t\t\t\t\t{ model: updatedModel },\n\t\t\t\t\t\t),\n\t\t\t\t\t\trollback: () => {\n\t\t\t\t\t\t\tthis.sliceMachinePluginRunner?.callHook(\"custom-type:update\", {\n\t\t\t\t\t\t\t\tmodel: previousModel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tpreviousPath,\n\t\t\t\tnewPath,\n\t\t\t});\n\n\t\t\t// Find existing slice with content relationships that link to the renamed\n\t\t\t// field id in all libraries and update them to use the new one.\n\t\t\tconst { libraries } = await this.slices.readAllSliceLibraries();\n\n\t\t\tfor (const library of libraries) {\n\t\t\t\tconst slices = await this.slices.readAllSlicesForLibrary({\n\t\t\t\t\tlibraryID: library.libraryID,\n\t\t\t\t});\n\n\t\t\t\tupdateSharedSliceContentRelationships({\n\t\t\t\t\tmodels: slices.models,\n\t\t\t\t\tonUpdate: ({ previousModel, model: updatedModel }) => {\n\t\t\t\t\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t\t\t\t\tcrUpdates.push({\n\t\t\t\t\t\t\tupdatePromise: this.sliceMachinePluginRunner?.callHook(\n\t\t\t\t\t\t\t\t\"slice:update\",\n\t\t\t\t\t\t\t\t{ libraryID: library.libraryID, model: updatedModel },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\trollback: () => {\n\t\t\t\t\t\t\t\tthis.sliceMachinePluginRunner?.callHook(\"slice:update\", {\n\t\t\t\t\t\t\t\t\tlibraryID: library.libraryID,\n\t\t\t\t\t\t\t\t\tmodel: previousModel,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Process all the Content Relationship updates at once.\n\t\t\tconst crUpdatesResult = await Promise.all(\n\t\t\t\tcrUpdates.map((update) => update.updatePromise),\n\t\t\t);\n\n\t\t\tif (crUpdatesResult.some((result) => result.errors.length > 0)) {\n\t\t\t\treturn {\n\t\t\t\t\terrors: crUpdatesResult.flatMap((result) => result.errors),\n\t\t\t\t\trollback: async () => {\n\t\t\t\t\t\tawait Promise.all(crUpdates.map((update) => update.rollback()));\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn { errors: [] };\n\t}\n\n\tasync updateCustomType(\n\t\targs: CustomTypeUpdateHookData,\n\t): Promise<CustomTypesMachineManagerUpdateCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\t\tconst { model } = args;\n\t\tconst { fieldIdChanged } = args.updateMeta ?? {};\n\n\t\tlet previousCustomType: CustomType | undefined;\n\n\t\tif (fieldIdChanged) {\n\t\t\tconst customTypeRead = await this.readCustomType({ id: model.id });\n\n\t\t\tif (customTypeRead.errors.length > 0) {\n\t\t\t\treturn { errors: customTypeRead.errors };\n\t\t\t}\n\t\t\tif (!customTypeRead.model) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`readCustomType succeeded reading custom type ${model.id} but model is undefined.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpreviousCustomType = customTypeRead.model;\n\t\t}\n\n\t\tconst customTypeUpdateResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:update\",\n\t\t\t{ model },\n\t\t);\n\n\t\tif (customTypeUpdateResult.errors.length > 0) {\n\t\t\treturn { errors: customTypeUpdateResult.errors };\n\t\t}\n\n\t\tif (previousCustomType && fieldIdChanged) {\n\t\t\tconst crUpdateResult = await this.updateContentRelationships({\n\t\t\t\t...fieldIdChanged,\n\t\t\t\tmodel: previousCustomType,\n\t\t\t});\n\n\t\t\tif (crUpdateResult.errors.length > 0) {\n\t\t\t\t// put the previous custom type back\n\t\t\t\tawait this.sliceMachinePluginRunner?.callHook(\"custom-type:update\", {\n\t\t\t\t\tmodel: previousCustomType,\n\t\t\t\t});\n\t\t\t\t// revert the content relationships updates\n\t\t\t\tawait crUpdateResult.rollback?.();\n\n\t\t\t\treturn { errors: crUpdateResult.errors };\n\t\t\t}\n\t\t}\n\n\t\treturn { errors: [] };\n\t}\n\n\tasync renameCustomType(\n\t\targs: CustomTypeRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<CustomTypeRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:rename\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync deleteCustomType(\n\t\targs: CustomTypesMachineManagerDeleteCustomTypeArgs,\n\t): Promise<CustomTypesMachineManagerDeleteCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst { model, errors: readCustomTypeErrors } = await this.readCustomType({\n\t\t\tid: args.id,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\t\"custom-type:delete\",\n\t\t\t\t{ model },\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\terrors: readCustomTypeErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync pushCustomType(\n\t\targs: SliceMachineManagerPushCustomTypeArgs,\n\t): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst repositoryName = await this.project.getResolvedRepositoryName();\n\n\t\t// TODO: Handle errors\n\t\tconst { model } = await this.readCustomType({ id: args.id });\n\n\t\tif (model) {\n\t\t\t// TODO: Create a single shared client.\n\t\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\t\trepositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t\tfetchOptions: {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": args.userAgent || SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Custom Type already exists on the repository.\n\t\t\t\tawait client.getCustomTypeByID(args.id);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateCustomType(model);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If it doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertCustomType(model);\n\t\t\t\t} else if (error instanceof prismicCustomTypesClient.ForbiddenError) {\n\t\t\t\t\tthrow new UnauthorizedError(\n\t\t\t\t\t\t\"You do not have access to push types to this Prismic repository.\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcause: error,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO: Remove\n\tasync readCustomTypeMocksConfig(\n\t\targs: SliceMachineManagerReadCustomTypeMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadCustomTypeMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:asset:read\",\n\t\t\t{\n\t\t\t\tcustomTypeID: args.customTypeID,\n\t\t\t\tassetID: \"mocks.config.json\",\n\t\t\t},\n\t\t);\n\t\tconst data = hookResult.data[0]?.data;\n\n\t\t// TODO: Validate the returned data.\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocksConfig: JSON.parse(data.toString()),\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocksConfig: undefined,\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t}\n\t}\n\n\t// TODO: Remove\n\tasync updateCustomTypeMocksConfig(\n\t\targs: SliceMachineManagerUpdateCustomTypeMocksConfigArgs,\n\t): Promise<SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:asset:update\",\n\t\t\t{\n\t\t\t\tcustomTypeID: args.customTypeID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.config.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocksConfig, null, \"\\t\")),\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync fetchRemoteCustomTypes(): Promise<CustomType[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst repositoryName = await this.project.getResolvedRepositoryName();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t\tfetchOptions: {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\treturn await client.getAllCustomTypes();\n\t}\n\n\tasync inferSlice({\n\t\timageUrl,\n\t}: {\n\t\timageUrl: string;\n\t}): Promise<InferSliceResponse> {\n\t\tconst authToken = await this.user.getAuthenticationToken();\n\t\tconst headers = {\n\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t};\n\n\t\tconst repository = await this.project.getResolvedRepositoryName();\n\t\tconst searchParams = new URLSearchParams({\n\t\t\trepository,\n\t\t});\n\n\t\tconst url = new URL(\"./slices/infer\", API_ENDPOINTS.CustomTypeService);\n\t\turl.search = searchParams.toString();\n\n\t\tconst response = await fetch(url.toString(), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: headers,\n\t\t\tbody: JSON.stringify({ imageUrl }),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to infer slice: ${response.statusText}`);\n\t\t}\n\n\t\tconst json = await response.json();\n\n\t\treturn InferSliceResponse.parse(json);\n\t}\n}\n\ntype InferSliceResponse = z.infer<typeof InferSliceResponse>;\n\nconst InferSliceResponse = z.object({\n\tslice: z.custom().transform((value, ctx) => {\n\t\tconst result = SharedSlice.decode(value);\n\t\tif (result._tag === \"Right\") {\n\t\t\treturn result.right;\n\t\t}\n\t\tctx.addIssue({\n\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\tmessage: `Invalid shared slice: ${JSON.stringify(value, null, 2)}`,\n\t\t});\n\n\t\treturn z.NEVER;\n\t}),\n\tlangSmithUrl: z.string().url().optional(),\n});\n\nfunction updateCRCustomType(\n\targs: { customType: CrCustomType } & CustomTypeFieldIdChangedMeta,\n): CrCustomType {\n\tconst [previousCustomTypeId, previousFieldId] = args.previousPath;\n\tconst [newCustomTypeId, newFieldId] = args.newPath;\n\n\tif (!previousCustomTypeId || !newCustomTypeId) {\n\t\tthrow new Error(\n\t\t\t\"Could not find a customtype id in previousPath and/or newPath, which should not be possible.\",\n\t\t);\n\t}\n\n\tif (!previousFieldId || !newFieldId) {\n\t\tthrow new Error(\n\t\t\t\"Could not find a field id in previousPath and/or newPath, which should not be possible.\",\n\t\t);\n\t}\n\n\tconst customType = shallowCloneIfObject(args.customType);\n\n\tif (typeof customType === \"string\" || !customType.fields) {\n\t\treturn customType;\n\t}\n\n\tconst matchedCustomTypeId = customType.id === previousCustomTypeId;\n\n\tconst newFields = customType.fields.map((fieldArg) => {\n\t\tconst customTypeField = shallowCloneIfObject(fieldArg);\n\n\t\tif (typeof customTypeField === \"string\") {\n\t\t\tif (\n\t\t\t\tmatchedCustomTypeId &&\n\t\t\t\tcustomTypeField === previousFieldId &&\n\t\t\t\tcustomTypeField !== newFieldId\n\t\t\t) {\n\t\t\t\t// We have reached a field id that matches the id that was renamed,\n\t\t\t\t// so we update it new one. The field is a string, so return the new\n\t\t\t\t// id.\n\t\t\t\treturn newFieldId;\n\t\t\t}\n\n\t\t\treturn customTypeField;\n\t\t}\n\n\t\tif (\n\t\t\tmatchedCustomTypeId &&\n\t\t\tcustomTypeField.id === previousFieldId &&\n\t\t\tcustomTypeField.id !== newFieldId\n\t\t) {\n\t\t\t// We have reached a field id that matches the id that was renamed,\n\t\t\t// so we update it new one.\n\t\t\t// Since field is not a string, we don't exit, as we might have\n\t\t\t// something to update further down in customtypes.\n\t\t\tcustomTypeField.id = newFieldId;\n\t\t}\n\n\t\treturn {\n\t\t\t...customTypeField,\n\t\t\tcustomtypes: customTypeField.customtypes.map((customTypeArg) => {\n\t\t\t\tconst nestedCustomType = shallowCloneIfObject(customTypeArg);\n\n\t\t\t\tif (\n\t\t\t\t\ttypeof nestedCustomType === \"string\" ||\n\t\t\t\t\t!nestedCustomType.fields ||\n\t\t\t\t\t// Since we are on the last level, if we don't start matching right\n\t\t\t\t\t// at the custom type id, we can return exit early because it's not\n\t\t\t\t\t// a match.\n\t\t\t\t\tnestedCustomType.id !== previousCustomTypeId\n\t\t\t\t) {\n\t\t\t\t\treturn nestedCustomType;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\t...nestedCustomType,\n\t\t\t\t\tfields: nestedCustomType.fields.map((fieldArg) => {\n\t\t\t\t\t\tconst nestedCustomTypeField = shallowCloneIfObject(fieldArg);\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnestedCustomTypeField === previousFieldId &&\n\t\t\t\t\t\t\tnestedCustomTypeField !== newFieldId\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// Matches the previous id, so we update it and return because\n\t\t\t\t\t\t\t// it's the last level.\n\t\t\t\t\t\t\treturn newFieldId;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn nestedCustomTypeField;\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t}),\n\t\t};\n\t});\n\n\treturn { ...customType, fields: newFields };\n}\n\n/**\n * Update the Content Relationship API IDs of a single field. The change is\n * determined by the `previousPath` and `newPath` properties.\n */\nfunction updateFieldContentRelationships<\n\tT extends UID | NestableWidget | Group | NestedGroup,\n>(args: { field: T } & CustomTypeFieldIdChangedMeta): T {\n\tconst { field, ...updateMeta } = args;\n\tif (\n\t\tfield.type !== \"Link\" ||\n\t\tfield.config?.select !== \"document\" ||\n\t\t!field.config?.customtypes\n\t) {\n\t\t// not a content relationship field\n\t\treturn field;\n\t}\n\n\tconst newCustomTypes = field.config.customtypes.map((customType) => {\n\t\treturn updateCRCustomType({ customType, ...updateMeta });\n\t});\n\n\treturn {\n\t\t...field,\n\t\tconfig: { ...field.config, customtypes: newCustomTypes },\n\t};\n}\n\nexport function updateCustomTypeContentRelationships(\n\targs: {\n\t\tmodels: { model: CustomType }[];\n\t\tonUpdate: (model: { previousModel: CustomType; model: CustomType }) => void;\n\t} & CustomTypeFieldIdChangedMeta,\n): void {\n\tconst { models, previousPath, newPath, onUpdate } = args;\n\n\tfor (const { model: customType } of models) {\n\t\tconst updatedCustomType = traverseCustomType({\n\t\t\tcustomType,\n\t\t\tonField: ({ field }) => {\n\t\t\t\treturn updateFieldContentRelationships({\n\t\t\t\t\tfield,\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tif (!isEqualModel(customType, updatedCustomType)) {\n\t\t\tonUpdate({ model: updatedCustomType, previousModel: customType });\n\t\t}\n\t}\n}\n\nexport function updateSharedSliceContentRelationships(\n\targs: {\n\t\tmodels: { model: SharedSlice }[];\n\t\tonUpdate: (model: {\n\t\t\tpreviousModel: SharedSlice;\n\t\t\tmodel: SharedSlice;\n\t\t}) => void;\n\t} & CustomTypeFieldIdChangedMeta,\n): void {\n\tconst { models, previousPath, newPath, onUpdate } = args;\n\n\tfor (const { model: slice } of models) {\n\t\tconst updateSlice = traverseSharedSlice({\n\t\t\tpath: [\".\"],\n\t\t\tslice,\n\t\t\tonField: ({ field }) => {\n\t\t\t\treturn updateFieldContentRelationships({\n\t\t\t\t\tfield,\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tif (!isEqualModel(slice, updateSlice)) {\n\t\t\tonUpdate({ model: updateSlice, previousModel: slice });\n\t\t}\n\t}\n}\n\nfunction isEqualModel<T extends CustomType | SharedSlice>(\n\tmodelA: T,\n\tmodelB: T,\n): boolean {\n\treturn JSON.stringify(modelA) === JSON.stringify(modelB);\n}\n\nfunction shallowCloneIfObject<T>(value: T): T {\n\tif (typeof value === \"object\") {\n\t\treturn { ...value };\n\t}\n\n\treturn value;\n}\n"],"names":["errors","_a","fieldArg"],"mappings":"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"}
1
+ {"version":3,"file":"CustomTypesManager.js","sources":["../../../../src/managers/customTypes/CustomTypesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport {\n\tCustomType,\n\tGroup,\n\tLinkConfig,\n\tNestableWidget,\n\tNestedGroup,\n\tSharedSlice,\n\tUID,\n\ttraverseCustomType,\n\ttraverseSharedSlice,\n} from \"@prismicio/types-internal/lib/customtypes\";\nimport {\n\tCallHookReturnType,\n\tCustomTypeCreateHook,\n\tCustomTypeCreateHookData,\n\tCustomTypeReadHookData,\n\tCustomTypeRenameHook,\n\tCustomTypeRenameHookData,\n\tCustomTypeUpdateHook,\n\tCustomTypeUpdateHookData,\n\tHookError,\n} from \"@slicemachine/plugin-kit\";\nimport { z } from \"zod\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\nimport fetch from \"../../lib/fetch\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { SLICE_MACHINE_USER_AGENT } from \"../../constants/SLICE_MACHINE_USER_AGENT\";\nimport { UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\nimport { CustomTypeFormat } from \"./types\";\n\ntype SliceMachineManagerReadCustomTypeLibraryReturnType = {\n\tids: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype CustomTypesManagerReadAllCustomTypesArgs = {\n\tformat: CustomTypeFormat;\n};\n\ntype SliceMachineManagerReadAllCustomTypeReturnType = {\n\tmodels: { model: CustomType }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadCustomTypeReturnType = {\n\tmodel: CustomType | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushCustomTypeArgs = {\n\tid: string;\n\tuserAgent?: string;\n};\n\ntype SliceMachineManagerReadCustomTypeMocksConfigArgs = {\n\tcustomTypeID: string;\n};\n\ntype SliceMachineManagerReadCustomTypeMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateCustomTypeMocksConfigArgs = {\n\tcustomTypeID: string;\n\t// TODO\n\tmocksConfig: Record<string, unknown>;\n};\n \n/** `[field]` or `[group, field]` – path INSIDE the Custom Type */\ntype PathWithinCustomType = [string] | [string, string];\n \n/** `[ct, field]` or `[ct, group, field]` – path WITH Custom Type ID */\ntype PathWithCustomType = [string, string] | [string, string, string];\n \ntype UnprefixedFieldIdChangedMeta = {\n\tpreviousPath: PathWithinCustomType;\n\tnewPath: PathWithinCustomType;\n};\n \nexport type SliceMachineManagerUpdateCustomTypeArgs =\n\tCustomTypeUpdateHookData & {\n\t\tupdateMeta?: {\n\t\t\tfieldIdChanged?: {\n\t\t\t\t/**\n\t\t\t\t * Previous path of the changed field. `[field]` or `[group, field]`\n\t\t\t\t */\n\t\t\t\tpreviousPath: PathWithinCustomType;\n\t\t\t\t/**\n\t\t\t\t * New path of the changed field. `[field]` or `[group, field]`\n\t\t\t\t */\n\t\t\t\tnewPath: PathWithinCustomType;\n\t\t\t};\n\t\t};\n\t};\n \ntype SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType = {\n\terrors: HookError[];\n};\n \ntype CustomTypesMachineManagerDeleteCustomTypeArgs = {\n\tid: string;\n};\n \ntype CustomTypesMachineManagerDeleteCustomTypeReturnType = {\n\terrors: (DecodeError | HookError)[];\n};\n \ntype CustomTypesMachineManagerUpdateCustomTypeReturnType = {\n\terrors: (DecodeError | HookError)[];\n};\n};\n\n/** `[ct, field]` or `[ct, group, field]` – path **with** Custom Type ID */\ntype PathWithCustomType = [string, string] | [string, string, string];\n\ntype CustomTypeFieldIdChangedMeta = {\n\tpreviousPath: PathWithCustomType;\n\tnewPath: PathWithCustomType;\n};\n\ntype LinkCustomType = NonNullable<LinkConfig[\"customtypes\"]>[number];\n\nexport class CustomTypesManager extends BaseManager {\n\tasync readCustomTypeLibrary(): Promise<SliceMachineManagerReadCustomTypeLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type-library:read\",\n\t\t\tundefined,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tids: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tids: data[0]?.ids || [],\n\t\t\terrors,\n\t\t};\n\t}\n\n\tasync readAllCustomTypes(\n\t\targs?: CustomTypesManagerReadAllCustomTypesArgs,\n\t): Promise<SliceMachineManagerReadAllCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllCustomTypeReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { ids, errors } = await this.readCustomTypeLibrary();\n\t\tres.errors = [...res.errors, ...errors];\n\n\t\tif (ids) {\n\t\t\tfor (const id of ids) {\n\t\t\t\tconst { model, errors } = await this.readCustomType({ id });\n\t\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\t\tif (model && (!args || args.format === model.format)) {\n\t\t\t\t\tres.models.push({ model });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createCustomType(\n\t\targs: CustomTypeCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<CustomTypeCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:create\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync readCustomType(\n\t\targs: CustomTypeReadHookData,\n\t): Promise<SliceMachineManagerReadCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomType,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tmodel: data[0]?.model,\n\t\t\terrors,\n\t\t};\n\t}\n\n\t/**\n\t * Update the Content Relationship API IDs for all existing custom types and\n\t * slices. The change is determined by properties inside the `updateMeta`\n\t * property.\n\t */\n\tprivate async updateContentRelationships(\n\t\targs: {\n\t\t\tmodel: CustomType;\n\t\t} & SliceMachineManagerUpdateCustomTypeFieldIdChanged,\n\t): Promise<\n\t\tOnlyHookErrors<CallHookReturnType<CustomTypeUpdateHook>> & {\n\t\t\trollback?: () => Promise<void>;\n\t\t}\n\t> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst {\n\t\t\tmodel,\n\t\t\tpreviousPath: previousFieldPath,\n\t\t\tnewPath: newFieldPath,\n\t\t} = args;\n\n\t\tif (previousFieldPath.join(\".\") !== newFieldPath.join(\".\")) {\n\t\t\tconst { id: ctId } = model;\n\t\t\tconst previousPath: PathWithCustomType = [ctId, ...previousFieldPath];\n\t\t\tconst newPath: PathWithCustomType = [ctId, ...newFieldPath];\n\n\t\t\tconst crUpdates: {\n\t\t\t\tupdatePromise: Promise<{ errors: HookError[] }>;\n\t\t\t\trollback: () => void;\n\t\t\t}[] = [];\n\n\t\t\t// Find existing content relationships that link to the renamed field id in\n\t\t\t// any custom type and update them to use the new one.\n\t\t\tconst customTypes = await this.readAllCustomTypes();\n\n\t\t\tupdateCustomTypeContentRelationships({\n\t\t\t\tmodels: customTypes.models,\n\t\t\t\tonUpdate: ({ previousModel, model: updatedModel }) => {\n\t\t\t\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t\t\t\tcrUpdates.push({\n\t\t\t\t\t\tupdatePromise: this.sliceMachinePluginRunner?.callHook(\n\t\t\t\t\t\t\t\"custom-type:update\",\n\t\t\t\t\t\t\t{ model: updatedModel },\n\t\t\t\t\t\t),\n\t\t\t\t\t\trollback: () => {\n\t\t\t\t\t\t\tthis.sliceMachinePluginRunner?.callHook(\"custom-type:update\", {\n\t\t\t\t\t\t\t\tmodel: previousModel,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tpreviousPath,\n\t\t\t\tnewPath,\n\t\t\t});\n\n\t\t\t// Find existing slice with content relationships that link to the renamed\n\t\t\t// field id in all libraries and update them to use the new one.\n\t\t\tconst { libraries } = await this.slices.readAllSliceLibraries();\n\n\t\t\tfor (const library of libraries) {\n\t\t\t\tconst slices = await this.slices.readAllSlicesForLibrary({\n\t\t\t\t\tlibraryID: library.libraryID,\n\t\t\t\t});\n\n\t\t\t\tupdateSharedSliceContentRelationships({\n\t\t\t\t\tmodels: slices.models,\n\t\t\t\t\tonUpdate: ({ previousModel, model: updatedModel }) => {\n\t\t\t\t\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t\t\t\t\tcrUpdates.push({\n\t\t\t\t\t\t\tupdatePromise: this.sliceMachinePluginRunner?.callHook(\n\t\t\t\t\t\t\t\t\"slice:update\",\n\t\t\t\t\t\t\t\t{ libraryID: library.libraryID, model: updatedModel },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\trollback: () => {\n\t\t\t\t\t\t\t\tthis.sliceMachinePluginRunner?.callHook(\"slice:update\", {\n\t\t\t\t\t\t\t\t\tlibraryID: library.libraryID,\n\t\t\t\t\t\t\t\t\tmodel: previousModel,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Process all the Content Relationship updates at once.\n\t\t\tconst crUpdatesResult = await Promise.all(\n\t\t\t\tcrUpdates.map((update) => update.updatePromise),\n\t\t\t);\n\n\t\t\tif (crUpdatesResult.some((result) => result.errors.length > 0)) {\n\t\t\t\treturn {\n\t\t\t\t\terrors: crUpdatesResult.flatMap((result) => result.errors),\n\t\t\t\t\trollback: async () => {\n\t\t\t\t\t\tawait Promise.all(crUpdates.map((update) => update.rollback()));\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn { errors: [] };\n\t}\n\n\tasync updateCustomType(\n\t\targs: SliceMachineManagerUpdateCustomTypeArgs,\n\t): Promise<CustomTypesMachineManagerUpdateCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\t\tconst { model } = args;\n\t\tconst { fieldIdChanged } = args.updateMeta ?? {};\n\n\t\tlet previousCustomType: CustomType | undefined;\n\n\t\tif (fieldIdChanged) {\n\t\t\tconst customTypeRead = await this.readCustomType({ id: model.id });\n\n\t\t\tif (customTypeRead.errors.length > 0) {\n\t\t\t\treturn { errors: customTypeRead.errors };\n\t\t\t}\n\t\t\tif (!customTypeRead.model) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`readCustomType succeeded reading custom type ${model.id} but model is undefined.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tpreviousCustomType = customTypeRead.model;\n\t\t}\n\n\t\tconst customTypeUpdateResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:update\",\n\t\t\t{ model },\n\t\t);\n\n\t\tif (customTypeUpdateResult.errors.length > 0) {\n\t\t\treturn { errors: customTypeUpdateResult.errors };\n\t\t}\n\n\t\tif (previousCustomType && fieldIdChanged) {\n\t\t\tconst crUpdateResult = await this.updateContentRelationships({\n\t\t\t\t...fieldIdChanged,\n\t\t\t\tmodel: previousCustomType,\n\t\t\t});\n\n\t\t\tif (crUpdateResult.errors.length > 0) {\n\t\t\t\t// put the previous custom type back\n\t\t\t\tawait this.sliceMachinePluginRunner?.callHook(\"custom-type:update\", {\n\t\t\t\t\tmodel: previousCustomType,\n\t\t\t\t});\n\t\t\t\t// revert the content relationships updates\n\t\t\t\tawait crUpdateResult.rollback?.();\n\n\t\t\t\treturn { errors: crUpdateResult.errors };\n\t\t\t}\n\t\t}\n\n\t\treturn { errors: [] };\n\t}\n\n\tasync renameCustomType(\n\t\targs: CustomTypeRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<CustomTypeRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:rename\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync deleteCustomType(\n\t\targs: CustomTypesMachineManagerDeleteCustomTypeArgs,\n\t): Promise<CustomTypesMachineManagerDeleteCustomTypeReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst { model, errors: readCustomTypeErrors } = await this.readCustomType({\n\t\t\tid: args.id,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\t\"custom-type:delete\",\n\t\t\t\t{ model },\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\terrors: readCustomTypeErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync pushCustomType(\n\t\targs: SliceMachineManagerPushCustomTypeArgs,\n\t): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst repositoryName = await this.project.getResolvedRepositoryName();\n\n\t\t// TODO: Handle errors\n\t\tconst { model } = await this.readCustomType({ id: args.id });\n\n\t\tif (model) {\n\t\t\t// TODO: Create a single shared client.\n\t\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\t\trepositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t\tfetchOptions: {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": args.userAgent || SLICE_MACHINE_USER_AGENT,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Custom Type already exists on the repository.\n\t\t\t\tawait client.getCustomTypeByID(args.id);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateCustomType(model);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If it doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertCustomType(model);\n\t\t\t\t} else if (error instanceof prismicCustomTypesClient.ForbiddenError) {\n\t\t\t\t\tthrow new UnauthorizedError(\n\t\t\t\t\t\t\"You do not have access to push types to this Prismic repository.\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcause: error,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO: Remove\n\tasync readCustomTypeMocksConfig(\n\t\targs: SliceMachineManagerReadCustomTypeMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadCustomTypeMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:asset:read\",\n\t\t\t{\n\t\t\t\tcustomTypeID: args.customTypeID,\n\t\t\t\tassetID: \"mocks.config.json\",\n\t\t\t},\n\t\t);\n\t\tconst data = hookResult.data[0]?.data;\n\n\t\t// TODO: Validate the returned data.\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocksConfig: JSON.parse(data.toString()),\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocksConfig: undefined,\n\t\t\t\terrors: hookResult.errors,\n\t\t\t};\n\t\t}\n\t}\n\n\t// TODO: Remove\n\tasync updateCustomTypeMocksConfig(\n\t\targs: SliceMachineManagerUpdateCustomTypeMocksConfigArgs,\n\t): Promise<SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"custom-type:asset:update\",\n\t\t\t{\n\t\t\t\tcustomTypeID: args.customTypeID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.config.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocksConfig, null, \"\\t\")),\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\tasync fetchRemoteCustomTypes(): Promise<CustomType[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst repositoryName = await this.project.getResolvedRepositoryName();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t\tfetchOptions: {\n\t\t\t\theaders: {\n\t\t\t\t\t\"User-Agent\": SLICE_MACHINE_USER_AGENT,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\treturn await client.getAllCustomTypes();\n\t}\n\n\tasync inferSlice({\n\t\timageUrl,\n\t}: {\n\t\timageUrl: string;\n\t}): Promise<InferSliceResponse> {\n\t\tconst authToken = await this.user.getAuthenticationToken();\n\t\tconst headers = {\n\t\t\tAuthorization: `Bearer ${authToken}`,\n\t\t};\n\n\t\tconst repository = await this.project.getResolvedRepositoryName();\n\t\tconst searchParams = new URLSearchParams({\n\t\t\trepository,\n\t\t});\n\n\t\tconst url = new URL(\"./slices/infer\", API_ENDPOINTS.CustomTypeService);\n\t\turl.search = searchParams.toString();\n\n\t\tconst response = await fetch(url.toString(), {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: headers,\n\t\t\tbody: JSON.stringify({ imageUrl }),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`Failed to infer slice: ${response.statusText}`);\n\t\t}\n\n\t\tconst json = await response.json();\n\n\t\treturn InferSliceResponse.parse(json);\n\t}\n}\n\ntype InferSliceResponse = z.infer<typeof InferSliceResponse>;\n\nconst InferSliceResponse = z.object({\n\tslice: z.custom().transform((value, ctx) => {\n\t\tconst result = SharedSlice.decode(value);\n\t\tif (result._tag === \"Right\") {\n\t\t\treturn result.right;\n\t\t}\n\t\tctx.addIssue({\n\t\t\tcode: z.ZodIssueCode.custom,\n\t\t\tmessage: `Invalid shared slice: ${JSON.stringify(value, null, 2)}`,\n\t\t});\n\n\t\treturn z.NEVER;\n\t}),\n\tlangSmithUrl: z.string().url().optional(),\n});\n\nfunction updateCRCustomType(\n\targs: { customType: LinkCustomType } & CustomTypeFieldIdChangedMeta,\n): LinkCustomType {\n\tconst previousPath = getPathIds(args.previousPath);\n\tconst newPath = getPathIds(args.newPath);\n\n\tif (!previousPath.customTypeId || !newPath.customTypeId) {\n\t\tthrow new Error(\n\t\t\t`Could not find a customtype id in previousPath (${args.previousPath.join(\n\t\t\t\t\".\",\n\t\t\t)}) and/or newPath (${args.newPath.join(\n\t\t\t\t\".\",\n\t\t\t)}), which should not be possible.`,\n\t\t);\n\t}\n\n\tif (!previousPath.fieldId || !newPath.fieldId) {\n\t\tthrow new Error(\n\t\t\t`Could not find a field id in previousPath (${args.previousPath.join(\n\t\t\t\t\".\",\n\t\t\t)}) and/or newPath (${args.newPath.join(\n\t\t\t\t\".\",\n\t\t\t)}), which should not be possible.`,\n\t\t);\n\t}\n\n\tconst customType = shallowCloneIfObject(args.customType);\n\n\tif (typeof customType === \"string\") {\n\t\t// Legacy format support, we don't have anything to update here.\n\t\treturn customType;\n\t}\n\n\tconst matchedCustomTypeId = customType.id === previousPath.customTypeId;\n\n\treturn {\n\t\t...customType,\n\t\tfields: customType.fields.map((fieldArg) => {\n\t\t\tconst customTypeField = shallowCloneIfObject(fieldArg);\n\n\t\t\t// Regular field\n\t\t\tif (typeof customTypeField === \"string\") {\n\t\t\t\tif (\n\t\t\t\t\tmatchedCustomTypeId &&\n\t\t\t\t\tcustomTypeField === previousPath.fieldId &&\n\t\t\t\t\tcustomTypeField !== newPath.fieldId\n\t\t\t\t) {\n\t\t\t\t\t// The id of the field has changed.\n\t\t\t\t\treturn newPath.fieldId;\n\t\t\t\t}\n\n\t\t\t\treturn customTypeField;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tmatchedCustomTypeId &&\n\t\t\t\tcustomTypeField.id === previousPath.fieldId &&\n\t\t\t\tcustomTypeField.id !== newPath.fieldId\n\t\t\t) {\n\t\t\t\t// The id of the field has changed. We don't exit return because there\n\t\t\t\t// might be other fields further down in nested custom types or groups\n\t\t\t\t// that need to be updated.\n\t\t\t\tcustomTypeField.id = newPath.fieldId;\n\t\t\t}\n\n\t\t\t// Group field\n\t\t\tif (\"fields\" in customTypeField) {\n\t\t\t\tif (\n\t\t\t\t\t!previousPath.groupId &&\n\t\t\t\t\t!newPath.groupId &&\n\t\t\t\t\tcustomTypeField.id === previousPath.fieldId &&\n\t\t\t\t\tcustomTypeField.id !== newPath.fieldId\n\t\t\t\t) {\n\t\t\t\t\t// Only the id of the group has changed. Group id is not defined, so\n\t\t\t\t\t// we can return early.\n\t\t\t\t\treturn newPath.fieldId;\n\t\t\t\t}\n\n\t\t\t\tconst matchedGroupId = customTypeField.id === previousPath.groupId;\n\n\t\t\t\tif (\n\t\t\t\t\tpreviousPath.groupId &&\n\t\t\t\t\tnewPath.groupId &&\n\t\t\t\t\tmatchedGroupId &&\n\t\t\t\t\tcustomTypeField.id !== newPath.groupId\n\t\t\t\t) {\n\t\t\t\t\t// The id of the group field has changed, so we update it. We don't\n\t\t\t\t\t// return because there are group fields that may need to be updated.\n\t\t\t\t\tcustomTypeField.id = newPath.groupId;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\t...customTypeField,\n\t\t\t\t\tfields: customTypeField.fields.map((groupFieldArg) => {\n\t\t\t\t\t\tconst groupField = shallowCloneIfObject(groupFieldArg);\n\n\t\t\t\t\t\t// Regular field inside a group field\n\t\t\t\t\t\tif (typeof groupField === \"string\") {\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tmatchedGroupId &&\n\t\t\t\t\t\t\t\tgroupField === previousPath.fieldId &&\n\t\t\t\t\t\t\t\tgroupField !== newPath.fieldId\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t// The id of the field inside the group has changed.\n\t\t\t\t\t\t\t\treturn newPath.fieldId;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn groupField;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Content relationship field inside a group field\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...groupField,\n\t\t\t\t\t\t\tfields: updateContentRelationshipFields({\n\t\t\t\t\t\t\t\tcustomtypes: groupField.customtypes,\n\t\t\t\t\t\t\t\tpreviousPath,\n\t\t\t\t\t\t\t\tnewPath,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Content relationship field\n\t\t\treturn {\n\t\t\t\t...customTypeField,\n\t\t\t\tcustomtypes: updateContentRelationshipFields({\n\t\t\t\t\tcustomtypes: customTypeField.customtypes,\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t}),\n\t\t\t};\n\t\t}),\n\t};\n}\n\nfunction updateContentRelationshipFields(args: {\n\tcustomtypes: readonly (\n\t\t| string\n\t\t| {\n\t\t\t\tid: string;\n\t\t\t\tfields: readonly (string | { id: string; fields: readonly string[] })[];\n\t\t }\n\t)[];\n\tpreviousPath: CrUpdatePathIds;\n\tnewPath: CrUpdatePathIds;\n}) {\n\tconst { customtypes, previousPath, newPath } = args;\n\n\treturn customtypes.map((nestedCtArg) => {\n\t\tconst nestedCt = shallowCloneIfObject(nestedCtArg);\n\n\t\tif (\n\t\t\ttypeof nestedCt === \"string\" ||\n\t\t\t// Since we are entering a new custom type, if the previous id\n\t\t\t// doesn't match, we can return early, because it's not the\n\t\t\t// custom type we are looking for.\n\t\t\tnestedCt.id !== previousPath.customTypeId\n\t\t) {\n\t\t\treturn nestedCt;\n\t\t}\n\n\t\treturn {\n\t\t\t...nestedCt,\n\t\t\tfields: nestedCt.fields.map((nestedCtFieldArg) => {\n\t\t\t\tconst nestedCtField = shallowCloneIfObject(nestedCtFieldArg);\n\n\t\t\t\t// Regular field\n\t\t\t\tif (typeof nestedCtField === \"string\") {\n\t\t\t\t\tif (\n\t\t\t\t\t\tnestedCtField === previousPath.fieldId &&\n\t\t\t\t\t\tnestedCtField !== newPath.fieldId\n\t\t\t\t\t) {\n\t\t\t\t\t\t// The id of the field has changed.\n\t\t\t\t\t\treturn newPath.fieldId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn nestedCtField;\n\t\t\t\t}\n\n\t\t\t\t// Group field\n\n\t\t\t\tif (\n\t\t\t\t\tnestedCtField.id === previousPath.fieldId &&\n\t\t\t\t\tnestedCtField.id !== newPath.fieldId\n\t\t\t\t) {\n\t\t\t\t\t// The id of the field has changed.\n\t\t\t\t\tnestedCtField.id = newPath.fieldId;\n\t\t\t\t}\n\n\t\t\t\t// Further down the path, the field can only be a group field. So if we have\n\t\t\t\t// no group id defined, no need to continue.\n\t\t\t\tif (\n\t\t\t\t\t!previousPath.groupId ||\n\t\t\t\t\t!newPath.groupId ||\n\t\t\t\t\tnestedCtField.id !== previousPath.groupId\n\t\t\t\t) {\n\t\t\t\t\treturn nestedCtField;\n\t\t\t\t}\n\n\t\t\t\tif (nestedCtField.id !== newPath.groupId) {\n\t\t\t\t\t// The id of the group has changed.\n\t\t\t\t\tnestedCtField.id = newPath.groupId;\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\t...nestedCtField,\n\t\t\t\t\tfields: nestedCtField.fields.map((nestedCtGroupFieldId) => {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tnestedCtGroupFieldId === previousPath.fieldId &&\n\t\t\t\t\t\t\tnestedCtGroupFieldId !== newPath.fieldId\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// The id of the field inside the group has changed.\n\t\t\t\t\t\t\treturn newPath.fieldId;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn nestedCtGroupFieldId;\n\t\t\t\t\t}),\n\t\t\t\t};\n\t\t\t}),\n\t\t};\n\t});\n}\n\n/**\n * Update the Content Relationship API IDs of a single field. The change is\n * determined by the `previousPath` and `newPath` properties.\n */\nfunction updateFieldContentRelationships<\n\tT extends UID | NestableWidget | Group | NestedGroup,\n>(args: { field: T } & CustomTypeFieldIdChangedMeta): T {\n\tconst { field, ...updateMeta } = args;\n\tif (\n\t\tfield.type !== \"Link\" ||\n\t\tfield.config?.select !== \"document\" ||\n\t\t!field.config?.customtypes\n\t) {\n\t\t// not a content relationship field\n\t\treturn field;\n\t}\n\n\tconst newCustomTypes = field.config.customtypes.map((customType) => {\n\t\treturn updateCRCustomType({ customType, ...updateMeta });\n\t});\n\n\treturn {\n\t\t...field,\n\t\tconfig: { ...field.config, customtypes: newCustomTypes },\n\t};\n}\n\nexport function updateCustomTypeContentRelationships(\n\targs: {\n\t\tmodels: { model: CustomType }[];\n\t\tonUpdate: (model: { previousModel: CustomType; model: CustomType }) => void;\n\t} & CustomTypeFieldIdChangedMeta,\n): void {\n\tconst { models, previousPath, newPath, onUpdate } = args;\n\n\tfor (const { model: customType } of models) {\n\t\tconst updatedCustomType = traverseCustomType({\n\t\t\tcustomType,\n\t\t\tonField: ({ field }) => {\n\t\t\t\treturn updateFieldContentRelationships({\n\t\t\t\t\tfield,\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tif (!isEqualModel(customType, updatedCustomType)) {\n\t\t\tonUpdate({ model: updatedCustomType, previousModel: customType });\n\t\t}\n\t}\n}\n\nexport function updateSharedSliceContentRelationships(\n\targs: {\n\t\tmodels: { model: SharedSlice }[];\n\t\tonUpdate: (model: {\n\t\t\tpreviousModel: SharedSlice;\n\t\t\tmodel: SharedSlice;\n\t\t}) => void;\n\t} & CustomTypeFieldIdChangedMeta,\n): void {\n\tconst { models, previousPath, newPath, onUpdate } = args;\n\n\tfor (const { model: slice } of models) {\n\t\tconst updateSlice = traverseSharedSlice({\n\t\t\tpath: [],\n\t\t\tslice,\n\t\t\tonField: ({ field }) => {\n\t\t\t\treturn updateFieldContentRelationships({\n\t\t\t\t\tfield,\n\t\t\t\t\tpreviousPath,\n\t\t\t\t\tnewPath,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tif (!isEqualModel(slice, updateSlice)) {\n\t\t\tonUpdate({ model: updateSlice, previousModel: slice });\n\t\t}\n\t}\n}\n\ninterface CrUpdatePathIds {\n\tcustomTypeId: string;\n\tgroupId: string | undefined;\n\tfieldId: string;\n}\n\nfunction getPathIds(path: PathWithCustomType): CrUpdatePathIds {\n\tif (path.length < 2) {\n\t\tthrow new Error(\n\t\t\t`Unexpected path length ${\n\t\t\t\tpath.length\n\t\t\t}. Expected at least 2 segments (got: ${path.join(\".\")}).`,\n\t\t);\n\t}\n\n\tconst [customTypeId, groupOrFieldId, fieldId] = path;\n\n\treturn {\n\t\tcustomTypeId,\n\t\t/**\n\t\t * Id of a changed group. If it's defined, it means that a group or a field\n\t\t * inside a group had its API ID renamed. It's defined when the path has a\n\t\t * third element (e.g. `[\"customtypeA\", \"groupA\", \"fieldA\"]`).\n\t\t */\n\t\tgroupId: fieldId ? groupOrFieldId : undefined,\n\t\tfieldId: fieldId || groupOrFieldId,\n\t};\n}\n\nfunction isEqualModel<T extends CustomType | SharedSlice>(\n\tmodelA: T,\n\tmodelB: T,\n): boolean {\n\treturn JSON.stringify(modelA) === JSON.stringify(modelB);\n}\n\nfunction shallowCloneIfObject<T>(value: T): T {\n\tif (typeof value === \"object\") {\n\t\treturn { ...value };\n\t}\n\n\treturn value;\n}\n"],"names":["errors","_a"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slicemachine/manager",
3
- "version": "0.24.15",
3
+ "version": "0.24.16-alpha.coderabbitai-chat-dniAA6r9GseKm4ouqNyJ8dl.1",
4
4
  "description": "Manage all aspects of a Slice Machine project.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -68,9 +68,9 @@
68
68
  "@prismicio/client": "7.17.0",
69
69
  "@prismicio/custom-types-client": "2.1.0",
70
70
  "@prismicio/mocks": "2.13.0",
71
- "@prismicio/types-internal": "3.10.0",
71
+ "@prismicio/types-internal": "3.11.0",
72
72
  "@segment/analytics-node": "^2.1.2",
73
- "@slicemachine/plugin-kit": "0.4.77",
73
+ "@slicemachine/plugin-kit": "0.4.78-alpha.coderabbitai-chat-dniAA6r9GseKm4ouqNyJ8dl.1",
74
74
  "cookie": "^1.0.1",
75
75
  "cors": "^2.8.5",
76
76
  "execa": "^7.1.1",
@@ -130,5 +130,6 @@
130
130
  },
131
131
  "publishConfig": {
132
132
  "access": "public"
133
- }
133
+ },
134
+ "stableVersion": "0.24.15"
134
135
  }
@@ -3,6 +3,7 @@ import * as prismicCustomTypesClient from "@prismicio/custom-types-client";
3
3
  import {
4
4
  CustomType,
5
5
  Group,
6
+ LinkConfig,
6
7
  NestableWidget,
7
8
  NestedGroup,
8
9
  SharedSlice,
@@ -75,37 +76,60 @@ type SliceMachineManagerUpdateCustomTypeMocksConfigArgs = {
75
76
  // TODO
76
77
  mocksConfig: Record<string, unknown>;
77
78
  };
78
-
79
+
80
+ /** `[field]` or `[group, field]` – path INSIDE the Custom Type */
81
+ type PathWithinCustomType = [string] | [string, string];
82
+
83
+ /** `[ct, field]` or `[ct, group, field]` – path WITH Custom Type ID */
84
+ type PathWithCustomType = [string, string] | [string, string, string];
85
+
86
+ type UnprefixedFieldIdChangedMeta = {
87
+ previousPath: PathWithinCustomType;
88
+ newPath: PathWithinCustomType;
89
+ };
90
+
91
+ export type SliceMachineManagerUpdateCustomTypeArgs =
92
+ CustomTypeUpdateHookData & {
93
+ updateMeta?: {
94
+ fieldIdChanged?: {
95
+ /**
96
+ * Previous path of the changed field. `[field]` or `[group, field]`
97
+ */
98
+ previousPath: PathWithinCustomType;
99
+ /**
100
+ * New path of the changed field. `[field]` or `[group, field]`
101
+ */
102
+ newPath: PathWithinCustomType;
103
+ };
104
+ };
105
+ };
106
+
79
107
  type SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType = {
80
108
  errors: HookError[];
81
109
  };
82
-
110
+
83
111
  type CustomTypesMachineManagerDeleteCustomTypeArgs = {
84
112
  id: string;
85
113
  };
86
-
114
+
87
115
  type CustomTypesMachineManagerDeleteCustomTypeReturnType = {
88
116
  errors: (DecodeError | HookError)[];
89
117
  };
90
-
118
+
91
119
  type CustomTypesMachineManagerUpdateCustomTypeReturnType = {
92
120
  errors: (DecodeError | HookError)[];
93
121
  };
122
+ };
123
+
124
+ /** `[ct, field]` or `[ct, group, field]` – path **with** Custom Type ID */
125
+ type PathWithCustomType = [string, string] | [string, string, string];
94
126
 
95
127
  type CustomTypeFieldIdChangedMeta = {
96
- previousPath: string[];
97
- newPath: string[];
128
+ previousPath: PathWithCustomType;
129
+ newPath: PathWithCustomType;
98
130
  };
99
131
 
100
- type CrCustomType =
101
- | string
102
- | { id: string; fields?: readonly CrCustomTypeNestedCr[] };
103
- type CrCustomTypeNestedCr =
104
- | string
105
- | { id: string; customtypes: readonly CrCustomTypeFieldLeaf[] };
106
- type CrCustomTypeFieldLeaf =
107
- | string
108
- | { id: string; fields?: readonly string[] };
132
+ type LinkCustomType = NonNullable<LinkConfig["customtypes"]>[number];
109
133
 
110
134
  export class CustomTypesManager extends BaseManager {
111
135
  async readCustomTypeLibrary(): Promise<SliceMachineManagerReadCustomTypeLibraryReturnType> {
@@ -198,7 +222,9 @@ export class CustomTypesManager extends BaseManager {
198
222
  * property.
199
223
  */
200
224
  private async updateContentRelationships(
201
- args: { model: CustomType } & CustomTypeFieldIdChangedMeta,
225
+ args: {
226
+ model: CustomType;
227
+ } & SliceMachineManagerUpdateCustomTypeFieldIdChanged,
202
228
  ): Promise<
203
229
  OnlyHookErrors<CallHookReturnType<CustomTypeUpdateHook>> & {
204
230
  rollback?: () => Promise<void>;
@@ -206,12 +232,16 @@ export class CustomTypesManager extends BaseManager {
206
232
  > {
207
233
  assertPluginsInitialized(this.sliceMachinePluginRunner);
208
234
 
209
- const { model } = args;
210
- let { newPath, previousPath } = args;
235
+ const {
236
+ model,
237
+ previousPath: previousFieldPath,
238
+ newPath: newFieldPath,
239
+ } = args;
211
240
 
212
- if (previousPath.join(".") !== newPath.join(".")) {
213
- previousPath = [model.id, ...previousPath];
214
- newPath = [model.id, ...newPath];
241
+ if (previousFieldPath.join(".") !== newFieldPath.join(".")) {
242
+ const { id: ctId } = model;
243
+ const previousPath: PathWithCustomType = [ctId, ...previousFieldPath];
244
+ const newPath: PathWithCustomType = [ctId, ...newFieldPath];
215
245
 
216
246
  const crUpdates: {
217
247
  updatePromise: Promise<{ errors: HookError[] }>;
@@ -294,7 +324,7 @@ export class CustomTypesManager extends BaseManager {
294
324
  }
295
325
 
296
326
  async updateCustomType(
297
- args: CustomTypeUpdateHookData,
327
+ args: SliceMachineManagerUpdateCustomTypeArgs,
298
328
  ): Promise<CustomTypesMachineManagerUpdateCustomTypeReturnType> {
299
329
  assertPluginsInitialized(this.sliceMachinePluginRunner);
300
330
  const { model } = args;
@@ -560,99 +590,227 @@ const InferSliceResponse = z.object({
560
590
  });
561
591
 
562
592
  function updateCRCustomType(
563
- args: { customType: CrCustomType } & CustomTypeFieldIdChangedMeta,
564
- ): CrCustomType {
565
- const [previousCustomTypeId, previousFieldId] = args.previousPath;
566
- const [newCustomTypeId, newFieldId] = args.newPath;
593
+ args: { customType: LinkCustomType } & CustomTypeFieldIdChangedMeta,
594
+ ): LinkCustomType {
595
+ const previousPath = getPathIds(args.previousPath);
596
+ const newPath = getPathIds(args.newPath);
567
597
 
568
- if (!previousCustomTypeId || !newCustomTypeId) {
598
+ if (!previousPath.customTypeId || !newPath.customTypeId) {
569
599
  throw new Error(
570
- "Could not find a customtype id in previousPath and/or newPath, which should not be possible.",
600
+ `Could not find a customtype id in previousPath (${args.previousPath.join(
601
+ ".",
602
+ )}) and/or newPath (${args.newPath.join(
603
+ ".",
604
+ )}), which should not be possible.`,
571
605
  );
572
606
  }
573
607
 
574
- if (!previousFieldId || !newFieldId) {
608
+ if (!previousPath.fieldId || !newPath.fieldId) {
575
609
  throw new Error(
576
- "Could not find a field id in previousPath and/or newPath, which should not be possible.",
610
+ `Could not find a field id in previousPath (${args.previousPath.join(
611
+ ".",
612
+ )}) and/or newPath (${args.newPath.join(
613
+ ".",
614
+ )}), which should not be possible.`,
577
615
  );
578
616
  }
579
617
 
580
618
  const customType = shallowCloneIfObject(args.customType);
581
619
 
582
- if (typeof customType === "string" || !customType.fields) {
620
+ if (typeof customType === "string") {
621
+ // Legacy format support, we don't have anything to update here.
583
622
  return customType;
584
623
  }
585
624
 
586
- const matchedCustomTypeId = customType.id === previousCustomTypeId;
625
+ const matchedCustomTypeId = customType.id === previousPath.customTypeId;
626
+
627
+ return {
628
+ ...customType,
629
+ fields: customType.fields.map((fieldArg) => {
630
+ const customTypeField = shallowCloneIfObject(fieldArg);
631
+
632
+ // Regular field
633
+ if (typeof customTypeField === "string") {
634
+ if (
635
+ matchedCustomTypeId &&
636
+ customTypeField === previousPath.fieldId &&
637
+ customTypeField !== newPath.fieldId
638
+ ) {
639
+ // The id of the field has changed.
640
+ return newPath.fieldId;
641
+ }
587
642
 
588
- const newFields = customType.fields.map((fieldArg) => {
589
- const customTypeField = shallowCloneIfObject(fieldArg);
643
+ return customTypeField;
644
+ }
590
645
 
591
- if (typeof customTypeField === "string") {
592
646
  if (
593
647
  matchedCustomTypeId &&
594
- customTypeField === previousFieldId &&
595
- customTypeField !== newFieldId
648
+ customTypeField.id === previousPath.fieldId &&
649
+ customTypeField.id !== newPath.fieldId
596
650
  ) {
597
- // We have reached a field id that matches the id that was renamed,
598
- // so we update it new one. The field is a string, so return the new
599
- // id.
600
- return newFieldId;
651
+ // The id of the field has changed. We don't exit return because there
652
+ // might be other fields further down in nested custom types or groups
653
+ // that need to be updated.
654
+ customTypeField.id = newPath.fieldId;
601
655
  }
602
656
 
603
- return customTypeField;
604
- }
657
+ // Group field
658
+ if ("fields" in customTypeField) {
659
+ if (
660
+ !previousPath.groupId &&
661
+ !newPath.groupId &&
662
+ customTypeField.id === previousPath.fieldId &&
663
+ customTypeField.id !== newPath.fieldId
664
+ ) {
665
+ // Only the id of the group has changed. Group id is not defined, so
666
+ // we can return early.
667
+ return newPath.fieldId;
668
+ }
669
+
670
+ const matchedGroupId = customTypeField.id === previousPath.groupId;
671
+
672
+ if (
673
+ previousPath.groupId &&
674
+ newPath.groupId &&
675
+ matchedGroupId &&
676
+ customTypeField.id !== newPath.groupId
677
+ ) {
678
+ // The id of the group field has changed, so we update it. We don't
679
+ // return because there are group fields that may need to be updated.
680
+ customTypeField.id = newPath.groupId;
681
+ }
682
+
683
+ return {
684
+ ...customTypeField,
685
+ fields: customTypeField.fields.map((groupFieldArg) => {
686
+ const groupField = shallowCloneIfObject(groupFieldArg);
687
+
688
+ // Regular field inside a group field
689
+ if (typeof groupField === "string") {
690
+ if (
691
+ matchedGroupId &&
692
+ groupField === previousPath.fieldId &&
693
+ groupField !== newPath.fieldId
694
+ ) {
695
+ // The id of the field inside the group has changed.
696
+ return newPath.fieldId;
697
+ }
698
+
699
+ return groupField;
700
+ }
701
+
702
+ // Content relationship field inside a group field
703
+ return {
704
+ ...groupField,
705
+ fields: updateContentRelationshipFields({
706
+ customtypes: groupField.customtypes,
707
+ previousPath,
708
+ newPath,
709
+ }),
710
+ };
711
+ }),
712
+ };
713
+ }
714
+
715
+ // Content relationship field
716
+ return {
717
+ ...customTypeField,
718
+ customtypes: updateContentRelationshipFields({
719
+ customtypes: customTypeField.customtypes,
720
+ previousPath,
721
+ newPath,
722
+ }),
723
+ };
724
+ }),
725
+ };
726
+ }
727
+
728
+ function updateContentRelationshipFields(args: {
729
+ customtypes: readonly (
730
+ | string
731
+ | {
732
+ id: string;
733
+ fields: readonly (string | { id: string; fields: readonly string[] })[];
734
+ }
735
+ )[];
736
+ previousPath: CrUpdatePathIds;
737
+ newPath: CrUpdatePathIds;
738
+ }) {
739
+ const { customtypes, previousPath, newPath } = args;
740
+
741
+ return customtypes.map((nestedCtArg) => {
742
+ const nestedCt = shallowCloneIfObject(nestedCtArg);
605
743
 
606
744
  if (
607
- matchedCustomTypeId &&
608
- customTypeField.id === previousFieldId &&
609
- customTypeField.id !== newFieldId
745
+ typeof nestedCt === "string" ||
746
+ // Since we are entering a new custom type, if the previous id
747
+ // doesn't match, we can return early, because it's not the
748
+ // custom type we are looking for.
749
+ nestedCt.id !== previousPath.customTypeId
610
750
  ) {
611
- // We have reached a field id that matches the id that was renamed,
612
- // so we update it new one.
613
- // Since field is not a string, we don't exit, as we might have
614
- // something to update further down in customtypes.
615
- customTypeField.id = newFieldId;
751
+ return nestedCt;
616
752
  }
617
753
 
618
754
  return {
619
- ...customTypeField,
620
- customtypes: customTypeField.customtypes.map((customTypeArg) => {
621
- const nestedCustomType = shallowCloneIfObject(customTypeArg);
755
+ ...nestedCt,
756
+ fields: nestedCt.fields.map((nestedCtFieldArg) => {
757
+ const nestedCtField = shallowCloneIfObject(nestedCtFieldArg);
758
+
759
+ // Regular field
760
+ if (typeof nestedCtField === "string") {
761
+ if (
762
+ nestedCtField === previousPath.fieldId &&
763
+ nestedCtField !== newPath.fieldId
764
+ ) {
765
+ // The id of the field has changed.
766
+ return newPath.fieldId;
767
+ }
768
+
769
+ return nestedCtField;
770
+ }
771
+
772
+ // Group field
622
773
 
623
774
  if (
624
- typeof nestedCustomType === "string" ||
625
- !nestedCustomType.fields ||
626
- // Since we are on the last level, if we don't start matching right
627
- // at the custom type id, we can return exit early because it's not
628
- // a match.
629
- nestedCustomType.id !== previousCustomTypeId
775
+ nestedCtField.id === previousPath.fieldId &&
776
+ nestedCtField.id !== newPath.fieldId
630
777
  ) {
631
- return nestedCustomType;
778
+ // The id of the field has changed.
779
+ nestedCtField.id = newPath.fieldId;
632
780
  }
633
781
 
634
- return {
635
- ...nestedCustomType,
636
- fields: nestedCustomType.fields.map((fieldArg) => {
637
- const nestedCustomTypeField = shallowCloneIfObject(fieldArg);
782
+ // Further down the path, the field can only be a group field. So if we have
783
+ // no group id defined, no need to continue.
784
+ if (
785
+ !previousPath.groupId ||
786
+ !newPath.groupId ||
787
+ nestedCtField.id !== previousPath.groupId
788
+ ) {
789
+ return nestedCtField;
790
+ }
638
791
 
792
+ if (nestedCtField.id !== newPath.groupId) {
793
+ // The id of the group has changed.
794
+ nestedCtField.id = newPath.groupId;
795
+ }
796
+
797
+ return {
798
+ ...nestedCtField,
799
+ fields: nestedCtField.fields.map((nestedCtGroupFieldId) => {
639
800
  if (
640
- nestedCustomTypeField === previousFieldId &&
641
- nestedCustomTypeField !== newFieldId
801
+ nestedCtGroupFieldId === previousPath.fieldId &&
802
+ nestedCtGroupFieldId !== newPath.fieldId
642
803
  ) {
643
- // Matches the previous id, so we update it and return because
644
- // it's the last level.
645
- return newFieldId;
804
+ // The id of the field inside the group has changed.
805
+ return newPath.fieldId;
646
806
  }
647
807
 
648
- return nestedCustomTypeField;
808
+ return nestedCtGroupFieldId;
649
809
  }),
650
810
  };
651
811
  }),
652
812
  };
653
813
  });
654
-
655
- return { ...customType, fields: newFields };
656
814
  }
657
815
 
658
816
  /**
@@ -721,7 +879,7 @@ export function updateSharedSliceContentRelationships(
721
879
 
722
880
  for (const { model: slice } of models) {
723
881
  const updateSlice = traverseSharedSlice({
724
- path: ["."],
882
+ path: [],
725
883
  slice,
726
884
  onField: ({ field }) => {
727
885
  return updateFieldContentRelationships({
@@ -738,6 +896,35 @@ export function updateSharedSliceContentRelationships(
738
896
  }
739
897
  }
740
898
 
899
+ interface CrUpdatePathIds {
900
+ customTypeId: string;
901
+ groupId: string | undefined;
902
+ fieldId: string;
903
+ }
904
+
905
+ function getPathIds(path: PathWithCustomType): CrUpdatePathIds {
906
+ if (path.length < 2) {
907
+ throw new Error(
908
+ `Unexpected path length ${
909
+ path.length
910
+ }. Expected at least 2 segments (got: ${path.join(".")}).`,
911
+ );
912
+ }
913
+
914
+ const [customTypeId, groupOrFieldId, fieldId] = path;
915
+
916
+ return {
917
+ customTypeId,
918
+ /**
919
+ * Id of a changed group. If it's defined, it means that a group or a field
920
+ * inside a group had its API ID renamed. It's defined when the path has a
921
+ * third element (e.g. `["customtypeA", "groupA", "fieldA"]`).
922
+ */
923
+ groupId: fieldId ? groupOrFieldId : undefined,
924
+ fieldId: fieldId || groupOrFieldId,
925
+ };
926
+ }
927
+
741
928
  function isEqualModel<T extends CustomType | SharedSlice>(
742
929
  modelA: T,
743
930
  modelB: T,