@slicemachine/manager 0.24.16-beta.2 → 0.24.16-beta.3
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.
- package/dist/managers/customTypes/CustomTypesManager.cjs +113 -38
- package/dist/managers/customTypes/CustomTypesManager.cjs.map +1 -1
- package/dist/managers/customTypes/CustomTypesManager.d.ts +202 -75
- package/dist/managers/customTypes/CustomTypesManager.js +113 -38
- package/dist/managers/customTypes/CustomTypesManager.js.map +1 -1
- package/package.json +3 -3
- package/src/managers/customTypes/CustomTypesManager.ts +253 -70
@@ -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 PathWithoutCustomType = [string] | [string, string];\n\ntype SliceMachineManagerUpdateCustomTypeFieldIdChanged = {\n\t/**\n\t * Previous path of the changed field, excluding the custom type id. Can be\n\t * used to identify the field that had an API ID rename (e.g. [\"fieldA\"] or\n\t * [\"groupA\", \"fieldA\"])\n\t */\n\tpreviousPath: PathWithoutCustomType;\n\t/**\n\t * New path of the changed field, excluding the custom type id. Can be used to\n\t * identify the field that had an API ID rename (e.g. [\"fieldB\"] or [\"groupA\",\n\t * \"fieldB\"])\n\t */\n\tnewPath: PathWithoutCustomType;\n};\n\ntype SliceMachineManagerUpdateCustomTypeArgs = CustomTypeUpdateHookData & {\n\tupdateMeta?: {\n\t\tfieldIdChanged?: SliceMachineManagerUpdateCustomTypeFieldIdChanged;\n\t};\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\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.16-beta.
|
3
|
+
"version": "0.24.16-beta.3",
|
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.
|
71
|
+
"@prismicio/types-internal": "3.11.2",
|
72
72
|
"@segment/analytics-node": "^2.1.2",
|
73
|
-
"@slicemachine/plugin-kit": "0.4.78-beta.
|
73
|
+
"@slicemachine/plugin-kit": "0.4.78-beta.3",
|
74
74
|
"cookie": "^1.0.1",
|
75
75
|
"cors": "^2.8.5",
|
76
76
|
"execa": "^7.1.1",
|
@@ -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,
|
@@ -76,6 +77,30 @@ type SliceMachineManagerUpdateCustomTypeMocksConfigArgs = {
|
|
76
77
|
mocksConfig: Record<string, unknown>;
|
77
78
|
};
|
78
79
|
|
80
|
+
/** `[field]` or `[group, field]` – path **inside** the Custom Type */
|
81
|
+
type PathWithoutCustomType = [string] | [string, string];
|
82
|
+
|
83
|
+
type SliceMachineManagerUpdateCustomTypeFieldIdChanged = {
|
84
|
+
/**
|
85
|
+
* Previous path of the changed field, excluding the custom type id. Can be
|
86
|
+
* used to identify the field that had an API ID rename (e.g. ["fieldA"] or
|
87
|
+
* ["groupA", "fieldA"])
|
88
|
+
*/
|
89
|
+
previousPath: PathWithoutCustomType;
|
90
|
+
/**
|
91
|
+
* New path of the changed field, excluding the custom type id. Can be used to
|
92
|
+
* identify the field that had an API ID rename (e.g. ["fieldB"] or ["groupA",
|
93
|
+
* "fieldB"])
|
94
|
+
*/
|
95
|
+
newPath: PathWithoutCustomType;
|
96
|
+
};
|
97
|
+
|
98
|
+
type SliceMachineManagerUpdateCustomTypeArgs = CustomTypeUpdateHookData & {
|
99
|
+
updateMeta?: {
|
100
|
+
fieldIdChanged?: SliceMachineManagerUpdateCustomTypeFieldIdChanged;
|
101
|
+
};
|
102
|
+
};
|
103
|
+
|
79
104
|
type SliceMachineManagerUpdateCustomTypeMocksConfigArgsReturnType = {
|
80
105
|
errors: HookError[];
|
81
106
|
};
|
@@ -92,20 +117,15 @@ type CustomTypesMachineManagerUpdateCustomTypeReturnType = {
|
|
92
117
|
errors: (DecodeError | HookError)[];
|
93
118
|
};
|
94
119
|
|
120
|
+
/** `[ct, field]` or `[ct, group, field]` – path **with** Custom Type ID */
|
121
|
+
type PathWithCustomType = [string, string] | [string, string, string];
|
122
|
+
|
95
123
|
type CustomTypeFieldIdChangedMeta = {
|
96
|
-
previousPath:
|
97
|
-
newPath:
|
124
|
+
previousPath: PathWithCustomType;
|
125
|
+
newPath: PathWithCustomType;
|
98
126
|
};
|
99
127
|
|
100
|
-
type
|
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[] };
|
128
|
+
type LinkCustomType = NonNullable<LinkConfig["customtypes"]>[number];
|
109
129
|
|
110
130
|
export class CustomTypesManager extends BaseManager {
|
111
131
|
async readCustomTypeLibrary(): Promise<SliceMachineManagerReadCustomTypeLibraryReturnType> {
|
@@ -198,7 +218,9 @@ export class CustomTypesManager extends BaseManager {
|
|
198
218
|
* property.
|
199
219
|
*/
|
200
220
|
private async updateContentRelationships(
|
201
|
-
args: {
|
221
|
+
args: {
|
222
|
+
model: CustomType;
|
223
|
+
} & SliceMachineManagerUpdateCustomTypeFieldIdChanged,
|
202
224
|
): Promise<
|
203
225
|
OnlyHookErrors<CallHookReturnType<CustomTypeUpdateHook>> & {
|
204
226
|
rollback?: () => Promise<void>;
|
@@ -206,12 +228,16 @@ export class CustomTypesManager extends BaseManager {
|
|
206
228
|
> {
|
207
229
|
assertPluginsInitialized(this.sliceMachinePluginRunner);
|
208
230
|
|
209
|
-
const {
|
210
|
-
|
231
|
+
const {
|
232
|
+
model,
|
233
|
+
previousPath: previousFieldPath,
|
234
|
+
newPath: newFieldPath,
|
235
|
+
} = args;
|
211
236
|
|
212
|
-
if (
|
213
|
-
|
214
|
-
|
237
|
+
if (previousFieldPath.join(".") !== newFieldPath.join(".")) {
|
238
|
+
const { id: ctId } = model;
|
239
|
+
const previousPath: PathWithCustomType = [ctId, ...previousFieldPath];
|
240
|
+
const newPath: PathWithCustomType = [ctId, ...newFieldPath];
|
215
241
|
|
216
242
|
const crUpdates: {
|
217
243
|
updatePromise: Promise<{ errors: HookError[] }>;
|
@@ -294,7 +320,7 @@ export class CustomTypesManager extends BaseManager {
|
|
294
320
|
}
|
295
321
|
|
296
322
|
async updateCustomType(
|
297
|
-
args:
|
323
|
+
args: SliceMachineManagerUpdateCustomTypeArgs,
|
298
324
|
): Promise<CustomTypesMachineManagerUpdateCustomTypeReturnType> {
|
299
325
|
assertPluginsInitialized(this.sliceMachinePluginRunner);
|
300
326
|
const { model } = args;
|
@@ -560,99 +586,227 @@ const InferSliceResponse = z.object({
|
|
560
586
|
});
|
561
587
|
|
562
588
|
function updateCRCustomType(
|
563
|
-
args: { customType:
|
564
|
-
):
|
565
|
-
const
|
566
|
-
const
|
589
|
+
args: { customType: LinkCustomType } & CustomTypeFieldIdChangedMeta,
|
590
|
+
): LinkCustomType {
|
591
|
+
const previousPath = getPathIds(args.previousPath);
|
592
|
+
const newPath = getPathIds(args.newPath);
|
567
593
|
|
568
|
-
if (!
|
594
|
+
if (!previousPath.customTypeId || !newPath.customTypeId) {
|
569
595
|
throw new Error(
|
570
|
-
|
596
|
+
`Could not find a customtype id in previousPath (${args.previousPath.join(
|
597
|
+
".",
|
598
|
+
)}) and/or newPath (${args.newPath.join(
|
599
|
+
".",
|
600
|
+
)}), which should not be possible.`,
|
571
601
|
);
|
572
602
|
}
|
573
603
|
|
574
|
-
if (!
|
604
|
+
if (!previousPath.fieldId || !newPath.fieldId) {
|
575
605
|
throw new Error(
|
576
|
-
|
606
|
+
`Could not find a field id in previousPath (${args.previousPath.join(
|
607
|
+
".",
|
608
|
+
)}) and/or newPath (${args.newPath.join(
|
609
|
+
".",
|
610
|
+
)}), which should not be possible.`,
|
577
611
|
);
|
578
612
|
}
|
579
613
|
|
580
614
|
const customType = shallowCloneIfObject(args.customType);
|
581
615
|
|
582
|
-
if (typeof customType === "string"
|
616
|
+
if (typeof customType === "string") {
|
617
|
+
// Legacy format support, we don't have anything to update here.
|
583
618
|
return customType;
|
584
619
|
}
|
585
620
|
|
586
|
-
const matchedCustomTypeId = customType.id ===
|
621
|
+
const matchedCustomTypeId = customType.id === previousPath.customTypeId;
|
622
|
+
|
623
|
+
return {
|
624
|
+
...customType,
|
625
|
+
fields: customType.fields.map((fieldArg) => {
|
626
|
+
const customTypeField = shallowCloneIfObject(fieldArg);
|
627
|
+
|
628
|
+
// Regular field
|
629
|
+
if (typeof customTypeField === "string") {
|
630
|
+
if (
|
631
|
+
matchedCustomTypeId &&
|
632
|
+
customTypeField === previousPath.fieldId &&
|
633
|
+
customTypeField !== newPath.fieldId
|
634
|
+
) {
|
635
|
+
// The id of the field has changed.
|
636
|
+
return newPath.fieldId;
|
637
|
+
}
|
587
638
|
|
588
|
-
|
589
|
-
|
639
|
+
return customTypeField;
|
640
|
+
}
|
590
641
|
|
591
|
-
if (typeof customTypeField === "string") {
|
592
642
|
if (
|
593
643
|
matchedCustomTypeId &&
|
594
|
-
customTypeField ===
|
595
|
-
customTypeField !==
|
644
|
+
customTypeField.id === previousPath.fieldId &&
|
645
|
+
customTypeField.id !== newPath.fieldId
|
596
646
|
) {
|
597
|
-
//
|
598
|
-
//
|
599
|
-
//
|
600
|
-
|
647
|
+
// The id of the field has changed. We don't exit return because there
|
648
|
+
// might be other fields further down in nested custom types or groups
|
649
|
+
// that need to be updated.
|
650
|
+
customTypeField.id = newPath.fieldId;
|
601
651
|
}
|
602
652
|
|
603
|
-
|
604
|
-
|
653
|
+
// Group field
|
654
|
+
if ("fields" in customTypeField) {
|
655
|
+
if (
|
656
|
+
!previousPath.groupId &&
|
657
|
+
!newPath.groupId &&
|
658
|
+
customTypeField.id === previousPath.fieldId &&
|
659
|
+
customTypeField.id !== newPath.fieldId
|
660
|
+
) {
|
661
|
+
// Only the id of the group has changed. Group id is not defined, so
|
662
|
+
// we can return early.
|
663
|
+
return newPath.fieldId;
|
664
|
+
}
|
665
|
+
|
666
|
+
const matchedGroupId = customTypeField.id === previousPath.groupId;
|
667
|
+
|
668
|
+
if (
|
669
|
+
previousPath.groupId &&
|
670
|
+
newPath.groupId &&
|
671
|
+
matchedGroupId &&
|
672
|
+
customTypeField.id !== newPath.groupId
|
673
|
+
) {
|
674
|
+
// The id of the group field has changed, so we update it. We don't
|
675
|
+
// return because there are group fields that may need to be updated.
|
676
|
+
customTypeField.id = newPath.groupId;
|
677
|
+
}
|
678
|
+
|
679
|
+
return {
|
680
|
+
...customTypeField,
|
681
|
+
fields: customTypeField.fields.map((groupFieldArg) => {
|
682
|
+
const groupField = shallowCloneIfObject(groupFieldArg);
|
683
|
+
|
684
|
+
// Regular field inside a group field
|
685
|
+
if (typeof groupField === "string") {
|
686
|
+
if (
|
687
|
+
matchedGroupId &&
|
688
|
+
groupField === previousPath.fieldId &&
|
689
|
+
groupField !== newPath.fieldId
|
690
|
+
) {
|
691
|
+
// The id of the field inside the group has changed.
|
692
|
+
return newPath.fieldId;
|
693
|
+
}
|
694
|
+
|
695
|
+
return groupField;
|
696
|
+
}
|
697
|
+
|
698
|
+
// Content relationship field inside a group field
|
699
|
+
return {
|
700
|
+
...groupField,
|
701
|
+
fields: updateContentRelationshipFields({
|
702
|
+
customtypes: groupField.customtypes,
|
703
|
+
previousPath,
|
704
|
+
newPath,
|
705
|
+
}),
|
706
|
+
};
|
707
|
+
}),
|
708
|
+
};
|
709
|
+
}
|
710
|
+
|
711
|
+
// Content relationship field
|
712
|
+
return {
|
713
|
+
...customTypeField,
|
714
|
+
customtypes: updateContentRelationshipFields({
|
715
|
+
customtypes: customTypeField.customtypes,
|
716
|
+
previousPath,
|
717
|
+
newPath,
|
718
|
+
}),
|
719
|
+
};
|
720
|
+
}),
|
721
|
+
};
|
722
|
+
}
|
723
|
+
|
724
|
+
function updateContentRelationshipFields(args: {
|
725
|
+
customtypes: readonly (
|
726
|
+
| string
|
727
|
+
| {
|
728
|
+
id: string;
|
729
|
+
fields: readonly (string | { id: string; fields: readonly string[] })[];
|
730
|
+
}
|
731
|
+
)[];
|
732
|
+
previousPath: CrUpdatePathIds;
|
733
|
+
newPath: CrUpdatePathIds;
|
734
|
+
}) {
|
735
|
+
const { customtypes, previousPath, newPath } = args;
|
736
|
+
|
737
|
+
return customtypes.map((nestedCtArg) => {
|
738
|
+
const nestedCt = shallowCloneIfObject(nestedCtArg);
|
605
739
|
|
606
740
|
if (
|
607
|
-
|
608
|
-
|
609
|
-
|
741
|
+
typeof nestedCt === "string" ||
|
742
|
+
// Since we are entering a new custom type, if the previous id
|
743
|
+
// doesn't match, we can return early, because it's not the
|
744
|
+
// custom type we are looking for.
|
745
|
+
nestedCt.id !== previousPath.customTypeId
|
610
746
|
) {
|
611
|
-
|
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;
|
747
|
+
return nestedCt;
|
616
748
|
}
|
617
749
|
|
618
750
|
return {
|
619
|
-
...
|
620
|
-
|
621
|
-
const
|
751
|
+
...nestedCt,
|
752
|
+
fields: nestedCt.fields.map((nestedCtFieldArg) => {
|
753
|
+
const nestedCtField = shallowCloneIfObject(nestedCtFieldArg);
|
754
|
+
|
755
|
+
// Regular field
|
756
|
+
if (typeof nestedCtField === "string") {
|
757
|
+
if (
|
758
|
+
nestedCtField === previousPath.fieldId &&
|
759
|
+
nestedCtField !== newPath.fieldId
|
760
|
+
) {
|
761
|
+
// The id of the field has changed.
|
762
|
+
return newPath.fieldId;
|
763
|
+
}
|
764
|
+
|
765
|
+
return nestedCtField;
|
766
|
+
}
|
767
|
+
|
768
|
+
// Group field
|
622
769
|
|
623
770
|
if (
|
624
|
-
|
625
|
-
|
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
|
771
|
+
nestedCtField.id === previousPath.fieldId &&
|
772
|
+
nestedCtField.id !== newPath.fieldId
|
630
773
|
) {
|
631
|
-
|
774
|
+
// The id of the field has changed.
|
775
|
+
nestedCtField.id = newPath.fieldId;
|
632
776
|
}
|
633
777
|
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
778
|
+
// Further down the path, the field can only be a group field. So if we have
|
779
|
+
// no group id defined, no need to continue.
|
780
|
+
if (
|
781
|
+
!previousPath.groupId ||
|
782
|
+
!newPath.groupId ||
|
783
|
+
nestedCtField.id !== previousPath.groupId
|
784
|
+
) {
|
785
|
+
return nestedCtField;
|
786
|
+
}
|
787
|
+
|
788
|
+
if (nestedCtField.id !== newPath.groupId) {
|
789
|
+
// The id of the group has changed.
|
790
|
+
nestedCtField.id = newPath.groupId;
|
791
|
+
}
|
638
792
|
|
793
|
+
return {
|
794
|
+
...nestedCtField,
|
795
|
+
fields: nestedCtField.fields.map((nestedCtGroupFieldId) => {
|
639
796
|
if (
|
640
|
-
|
641
|
-
|
797
|
+
nestedCtGroupFieldId === previousPath.fieldId &&
|
798
|
+
nestedCtGroupFieldId !== newPath.fieldId
|
642
799
|
) {
|
643
|
-
//
|
644
|
-
|
645
|
-
return newFieldId;
|
800
|
+
// The id of the field inside the group has changed.
|
801
|
+
return newPath.fieldId;
|
646
802
|
}
|
647
803
|
|
648
|
-
return
|
804
|
+
return nestedCtGroupFieldId;
|
649
805
|
}),
|
650
806
|
};
|
651
807
|
}),
|
652
808
|
};
|
653
809
|
});
|
654
|
-
|
655
|
-
return { ...customType, fields: newFields };
|
656
810
|
}
|
657
811
|
|
658
812
|
/**
|
@@ -721,7 +875,7 @@ export function updateSharedSliceContentRelationships(
|
|
721
875
|
|
722
876
|
for (const { model: slice } of models) {
|
723
877
|
const updateSlice = traverseSharedSlice({
|
724
|
-
path: [
|
878
|
+
path: [],
|
725
879
|
slice,
|
726
880
|
onField: ({ field }) => {
|
727
881
|
return updateFieldContentRelationships({
|
@@ -738,6 +892,35 @@ export function updateSharedSliceContentRelationships(
|
|
738
892
|
}
|
739
893
|
}
|
740
894
|
|
895
|
+
interface CrUpdatePathIds {
|
896
|
+
customTypeId: string;
|
897
|
+
groupId: string | undefined;
|
898
|
+
fieldId: string;
|
899
|
+
}
|
900
|
+
|
901
|
+
function getPathIds(path: PathWithCustomType): CrUpdatePathIds {
|
902
|
+
if (path.length < 2) {
|
903
|
+
throw new Error(
|
904
|
+
`Unexpected path length ${
|
905
|
+
path.length
|
906
|
+
}. Expected at least 2 segments (got: ${path.join(".")}).`,
|
907
|
+
);
|
908
|
+
}
|
909
|
+
|
910
|
+
const [customTypeId, groupOrFieldId, fieldId] = path;
|
911
|
+
|
912
|
+
return {
|
913
|
+
customTypeId,
|
914
|
+
/**
|
915
|
+
* Id of a changed group. If it's defined, it means that a group or a field
|
916
|
+
* inside a group had its API ID renamed. It's defined when the path has a
|
917
|
+
* third element (e.g. `["customtypeA", "groupA", "fieldA"]`).
|
918
|
+
*/
|
919
|
+
groupId: fieldId ? groupOrFieldId : undefined,
|
920
|
+
fieldId: fieldId || groupOrFieldId,
|
921
|
+
};
|
922
|
+
}
|
923
|
+
|
741
924
|
function isEqualModel<T extends CustomType | SharedSlice>(
|
742
925
|
modelA: T,
|
743
926
|
modelB: T,
|