@slicemachine/manager 0.1.1-dev-plugins-validation.1 → 0.1.1-dev-plugins-m1-validation.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/constants/API_ENDPOINTS.cjs +6 -5
  2. package/dist/constants/API_ENDPOINTS.cjs.map +1 -1
  3. package/dist/constants/API_ENDPOINTS.js +6 -5
  4. package/dist/constants/API_ENDPOINTS.js.map +1 -1
  5. package/dist/lib/addTrailingSlash.cjs +7 -0
  6. package/dist/lib/addTrailingSlash.cjs.map +1 -0
  7. package/dist/lib/addTrailingSlash.d.ts +1 -0
  8. package/dist/lib/addTrailingSlash.js +7 -0
  9. package/dist/lib/addTrailingSlash.js.map +1 -0
  10. package/dist/lib/decodeSliceMachineConfig.cjs +0 -1
  11. package/dist/lib/decodeSliceMachineConfig.cjs.map +1 -1
  12. package/dist/lib/decodeSliceMachineConfig.js +0 -1
  13. package/dist/lib/decodeSliceMachineConfig.js.map +1 -1
  14. package/dist/lib/locateFileUpward.cjs.map +1 -1
  15. package/dist/lib/locateFileUpward.js.map +1 -1
  16. package/dist/managers/SliceMachineManager.cjs +7 -7
  17. package/dist/managers/SliceMachineManager.cjs.map +1 -1
  18. package/dist/managers/SliceMachineManager.d.ts +0 -4
  19. package/dist/managers/SliceMachineManager.js +7 -7
  20. package/dist/managers/SliceMachineManager.js.map +1 -1
  21. package/dist/managers/prismicRepository/PrismicRepositoryManager.cjs +18 -2
  22. package/dist/managers/prismicRepository/PrismicRepositoryManager.cjs.map +1 -1
  23. package/dist/managers/prismicRepository/PrismicRepositoryManager.js +18 -2
  24. package/dist/managers/prismicRepository/PrismicRepositoryManager.js.map +1 -1
  25. package/dist/managers/project/ProjectManager.cjs.map +1 -1
  26. package/dist/managers/project/ProjectManager.js.map +1 -1
  27. package/dist/managers/screenshots/ScreenshotsManager.cjs +7 -1
  28. package/dist/managers/screenshots/ScreenshotsManager.cjs.map +1 -1
  29. package/dist/managers/screenshots/ScreenshotsManager.js +7 -1
  30. package/dist/managers/screenshots/ScreenshotsManager.js.map +1 -1
  31. package/dist/managers/slices/SlicesManager.cjs +27 -19
  32. package/dist/managers/slices/SlicesManager.cjs.map +1 -1
  33. package/dist/managers/slices/SlicesManager.d.ts +5 -1
  34. package/dist/managers/slices/SlicesManager.js +27 -19
  35. package/dist/managers/slices/SlicesManager.js.map +1 -1
  36. package/dist/managers/telemetry/TelemetryManager.cjs +39 -12
  37. package/dist/managers/telemetry/TelemetryManager.cjs.map +1 -1
  38. package/dist/managers/telemetry/TelemetryManager.d.ts +14 -1
  39. package/dist/managers/telemetry/TelemetryManager.js +39 -12
  40. package/dist/managers/telemetry/TelemetryManager.js.map +1 -1
  41. package/dist/managers/telemetry/types.cjs +0 -4
  42. package/dist/managers/telemetry/types.cjs.map +1 -1
  43. package/dist/managers/telemetry/types.d.ts +5 -30
  44. package/dist/managers/telemetry/types.js +0 -4
  45. package/dist/managers/telemetry/types.js.map +1 -1
  46. package/dist/types.d.ts +0 -1
  47. package/package.json +5 -4
  48. package/src/constants/API_ENDPOINTS.ts +8 -5
  49. package/src/lib/addTrailingSlash.ts +5 -0
  50. package/src/lib/decodeSliceMachineConfig.ts +0 -1
  51. package/src/lib/locateFileUpward.ts +0 -1
  52. package/src/managers/SliceMachineManager.ts +9 -9
  53. package/src/managers/prismicRepository/PrismicRepositoryManager.ts +24 -2
  54. package/src/managers/project/ProjectManager.ts +0 -1
  55. package/src/managers/screenshots/ScreenshotsManager.ts +11 -1
  56. package/src/managers/slices/SlicesManager.ts +34 -29
  57. package/src/managers/telemetry/TelemetryManager.ts +77 -13
  58. package/src/managers/telemetry/types.ts +6 -32
  59. package/src/types.ts +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SlicesManager.cjs","sources":["../../../../src/managers/slices/SlicesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport fetch from \"node-fetch\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport { CustomTypes } from \"@prismicio/types-internal\";\nimport { SharedSliceContent } from \"@prismicio/types-internal/lib/content\";\nimport {\n\tCallHookReturnType,\n\tHookError,\n\tSliceAssetUpdateHook,\n\tSliceCreateHook,\n\tSliceCreateHookData,\n\tSliceDeleteHook,\n\tSliceDeleteHookData,\n\tSliceLibraryReadHookData,\n\tSliceReadHookData,\n\tSliceRenameHook,\n\tSliceRenameHookData,\n\tSliceUpdateHook,\n\tSliceUpdateHookData,\n} from \"@slicemachine/plugin-kit\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { bufferCodec } from \"../../lib/bufferCodec\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { DEFAULT_SLICE_SCREENSHOT_URL } from \"../../constants/DEFAULT_SLICE_SCREENSHOT_URL\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { UnauthenticatedError, UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype SlicesManagerReadSliceLibraryReturnType = {\n\tsliceIDs: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SlicesManagerReadAllSliceLibrariesReturnType = {\n\tlibraries: {\n\t\tlibraryID: string;\n\t\tsliceIDs: string[] | undefined;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryArgs = {\n\tlibraryID: string;\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\tmodels: { model: CustomTypes.Widgets.Slices.SharedSlice }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesReturnType = {\n\tmodels: {\n\t\tlibraryID: string;\n\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceReturnType = {\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushSliceArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\nexport type SliceMachineManagerPushSliceReturnType = {\n\t/**\n\t * A record of Slice variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tscreenshotURLs: Record<string, string> | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n};\n\ntype SliceMachineManagerReadSliceScreenshotReturnType = {\n\tdata: Buffer | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerUpdateSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n\tdata: Buffer;\n};\n\ntype SliceMachineManagerReadSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksReturnType = {\n\tmocks?: SharedSliceContent[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tmocks: SharedSliceContent[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgsReturnType = {\n\terrors: HookError[];\n};\n\ntype SlicesManagerUpsertHostedSliceScrenshotsArgs = {\n\tlibraryID: string;\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n};\n\nexport class SlicesManager extends BaseManager {\n\tasync readSliceLibrary(\n\t\targs: SliceLibraryReadHookData,\n\t): Promise<SlicesManagerReadSliceLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// TODO: Should validation happen at the `callHook` level?\n\t\t// Including validation at the hook level would ensure\n\t\t// hook-based actions are validated.\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice-library:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tid: t.string,\n\t\t\t\tsliceIDs: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tsliceIDs: data[0]?.sliceIDs ?? [],\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync readAllSliceLibraries(): Promise<SlicesManagerReadAllSliceLibrariesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SlicesManagerReadAllSliceLibrariesReturnType = {\n\t\t\tlibraries: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\tres.libraries.push({\n\t\t\t\tlibraryID,\n\t\t\t\tsliceIDs,\n\t\t\t});\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync readAllSlicesForLibrary(\n\t\targs: SliceMachineManagerReadAllSlicesForLibraryArgs,\n\t): Promise<SliceMachineManagerReadAllSlicesForLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\tlibraryID: args.libraryID,\n\t\t});\n\t\tres.errors.push(...errors);\n\n\t\tif (sliceIDs) {\n\t\t\tfor (const sliceID of sliceIDs) {\n\t\t\t\tconst { model, errors } = await this.readSlice({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID,\n\t\t\t\t});\n\t\t\t\tres.errors.push(...errors);\n\n\t\t\t\tif (model) {\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 readAllSlices(): Promise<SliceMachineManagerReadAllSlicesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SliceMachineManagerReadAllSlicesReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { models, errors } = await this.readAllSlicesForLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors.push(...errors);\n\n\t\t\tfor (const model of models) {\n\t\t\t\tres.models.push({\n\t\t\t\t\tlibraryID,\n\t\t\t\t\tmodel: model.model,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createSlice(\n\t\targs: SliceCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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 readSlice(\n\t\targs: SliceReadHookData,\n\t): Promise<SliceMachineManagerReadSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice,\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\tasync updateSlice(\n\t\targs: SliceUpdateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:update\",\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 renameSlice(\n\t\targs: SliceRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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\t// TODO: Disallow until Slices can be deleted.\n\tasync deleteSlice(\n\t\targs: SliceDeleteHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceDeleteHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:delete\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\t/**\n\t * @returns Record of variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tasync pushSlice(\n\t\targs: SliceMachineManagerPushSliceArgs,\n\t): Promise<SliceMachineManagerPushSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tif (!(await this.user.checkIsLoggedIn())) {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\n\t\tconst { model, errors: readSliceErrors } = await this.readSlice({\n\t\t\tlibraryID: args.libraryID,\n\t\t\tsliceID: args.sliceID,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst modelWithScreenshots =\n\t\t\t\tawait this._updateSliceModelScreenshotsInPlace({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tmodel,\n\t\t\t\t});\n\n\t\t\tconst { errors: updateSliceErrors } = await this.updateSlice({\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tmodel: modelWithScreenshots,\n\t\t\t});\n\n\t\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\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: sliceMachineConfig.repositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Slice already exists on the repository.\n\t\t\t\tawait client.getSharedSliceByID(args.sliceID);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateSharedSlice(modelWithScreenshots);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If the Slice doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertSharedSlice(modelWithScreenshots);\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 Slices to this Prismic repository.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Pass the error through if it isn't the one we were expecting.\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst screenshotURLs: Record<string, string> = {};\n\t\t\tfor (const variation of modelWithScreenshots.variations) {\n\t\t\t\tscreenshotURLs[variation.id] = variation.imageUrl;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tscreenshotURLs,\n\t\t\t\terrors: [...readSliceErrors, ...updateSliceErrors],\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tscreenshotURLs: undefined,\n\t\t\t\terrors: readSliceErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync readSliceScreenshot(\n\t\targs: SliceMachineManagerReadSliceScreenshotArgs,\n\t): Promise<SliceMachineManagerReadSliceScreenshotReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `screenshot-${args.variationID}.png`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: bufferCodec,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tdata: data[0]?.data,\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync updateSliceScreenshot(\n\t\targs: SliceMachineManagerUpdateSliceScreenshotArgs,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceAssetUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: `screenshot-${args.variationID}.png`,\n\t\t\t\t\tdata: args.data,\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 readSliceMocks(\n\t\targs: SliceMachineManagerReadSliceMocksArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `mocks.json`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: t.array(SharedSliceContent),\n\t\t\t}),\n\t\t\t{\n\t\t\t\t...hookResult,\n\t\t\t\t// Convert the asset data from a Buffer to JSON\n\t\t\t\t// to prepare it for validation.\n\t\t\t\tdata: hookResult.data.map((result) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...result,\n\t\t\t\t\t\t\tdata: JSON.parse(result.data.toString()),\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocks: data[0]?.data,\n\t\t\t\terrors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocks: [],\n\t\t\t\terrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync updateSliceMocks(\n\t\targs: SliceMachineManagerUpdateSliceMocksArgs,\n\t): Promise<SliceMachineManagerUpdateSliceMocksArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocks, 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\t// TODO: Remove\n\tasync readSliceMocksConfig(\n\t\targs: SliceMachineManagerReadSliceMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\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\tasync fetchRemoteSlices(): Promise<CustomTypes.Widgets.Slices.SharedSlice[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName: sliceMachineConfig.repositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t});\n\n\t\treturn await client.getAllSharedSlices();\n\t}\n\n\tprivate async _updateSliceModelScreenshotsInPlace(\n\t\targs: SlicesManagerUpsertHostedSliceScrenshotsArgs,\n\t): Promise<CustomTypes.Widgets.Slices.SharedSlice> {\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst variations = await Promise.all(\n\t\t\targs.model.variations.map(async (variation) => {\n\t\t\t\tconst updatedVariation: CustomTypes.Widgets.Slices.Variation = {\n\t\t\t\t\t...variation,\n\t\t\t\t\timageUrl: DEFAULT_SLICE_SCREENSHOT_URL,\n\t\t\t\t};\n\n\t\t\t\tconst screenshot = await this.readSliceScreenshot({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID: args.model.id,\n\t\t\t\t\tvariationID: variation.id,\n\t\t\t\t});\n\n\t\t\t\tif (screenshot.data) {\n\t\t\t\t\tconst keyPrefix = [\n\t\t\t\t\t\tsliceMachineConfig.repositoryName,\n\t\t\t\t\t\t\"shared-slices\",\n\t\t\t\t\t\targs.model.id,\n\t\t\t\t\t\tvariation.id,\n\t\t\t\t\t].join(\"/\");\n\n\t\t\t\t\t// TODO: If the existing imageUrl\n\t\t\t\t\t// property (not the prefilled efault\n\t\t\t\t\t// URL) is identical to the new image\n\t\t\t\t\t// (we'll need to get the image's full\n\t\t\t\t\t// URL before we upload it), then don't\n\t\t\t\t\t// upload anything.\n\n\t\t\t\t\tconst uploadedScreenshot = await this.screenshots.uploadScreenshot({\n\t\t\t\t\t\tdata: screenshot.data,\n\t\t\t\t\t\tkeyPrefix,\n\t\t\t\t\t});\n\n\t\t\t\t\tupdatedVariation.imageUrl = uploadedScreenshot.url;\n\t\t\t\t}\n\n\t\t\t\treturn updatedVariation;\n\t\t\t}),\n\t\t);\n\n\t\treturn {\n\t\t\t...args.model,\n\t\t\tvariations,\n\t\t};\n\t}\n}\n"],"names":["BaseManager","assertPluginsInitialized","errors","decodeHookResult","t","CustomTypes","UnauthenticatedError","prismicCustomTypesClient","API_ENDPOINTS","fetch","UnauthorizedError","bufferCodec","SharedSliceContent","DEFAULT_SLICE_SCREENSHOT_URL"],"mappings":"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"}
1
+ {"version":3,"file":"SlicesManager.cjs","sources":["../../../../src/managers/slices/SlicesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport fetch from \"node-fetch\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport { CustomTypes } from \"@prismicio/types-internal\";\nimport { SharedSliceContent } from \"@prismicio/types-internal/lib/content\";\nimport {\n\tCallHookReturnType,\n\tHookError,\n\tSliceAssetUpdateHook,\n\tSliceCreateHook,\n\tSliceCreateHookData,\n\tSliceDeleteHook,\n\tSliceDeleteHookData,\n\tSliceLibraryReadHookData,\n\tSliceReadHookData,\n\tSliceRenameHook,\n\tSliceRenameHookData,\n\tSliceUpdateHook,\n\tSliceUpdateHookData,\n} from \"@slicemachine/plugin-kit\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { bufferCodec } from \"../../lib/bufferCodec\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { DEFAULT_SLICE_SCREENSHOT_URL } from \"../../constants/DEFAULT_SLICE_SCREENSHOT_URL\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { UnauthenticatedError, UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\nimport { createContentDigest } from \"../../lib/createContentDigest\";\n\ntype SlicesManagerReadSliceLibraryReturnType = {\n\tsliceIDs: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SlicesManagerReadAllSliceLibrariesReturnType = {\n\tlibraries: {\n\t\tlibraryID: string;\n\t\tsliceIDs: string[] | undefined;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryArgs = {\n\tlibraryID: string;\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\tmodels: { model: CustomTypes.Widgets.Slices.SharedSlice }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesReturnType = {\n\tmodels: {\n\t\tlibraryID: string;\n\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceReturnType = {\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushSliceArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\nexport type SliceMachineManagerPushSliceReturnType = {\n\t/**\n\t * A record of Slice variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tscreenshotURLs: Record<string, string> | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n};\n\ntype SliceMachineManagerReadSliceScreenshotReturnType = {\n\tdata: Buffer | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerUpdateSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n\tdata: Buffer;\n};\n\ntype SliceMachineManagerReadSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksReturnType = {\n\tmocks?: SharedSliceContent[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tmocks: SharedSliceContent[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgsReturnType = {\n\terrors: HookError[];\n};\n\ntype SlicesManagerUpsertHostedSliceScrenshotsArgs = {\n\tlibraryID: string;\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n};\n\nexport class SlicesManager extends BaseManager {\n\tasync readSliceLibrary(\n\t\targs: SliceLibraryReadHookData,\n\t): Promise<SlicesManagerReadSliceLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// TODO: Should validation happen at the `callHook` level?\n\t\t// Including validation at the hook level would ensure\n\t\t// hook-based actions are validated.\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice-library:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tid: t.string,\n\t\t\t\tsliceIDs: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tsliceIDs: data[0]?.sliceIDs ?? [],\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync readAllSliceLibraries(): Promise<SlicesManagerReadAllSliceLibrariesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SlicesManagerReadAllSliceLibrariesReturnType = {\n\t\t\tlibraries: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\tres.libraries.push({\n\t\t\t\tlibraryID,\n\t\t\t\tsliceIDs,\n\t\t\t});\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync readAllSlicesForLibrary(\n\t\targs: SliceMachineManagerReadAllSlicesForLibraryArgs,\n\t): Promise<SliceMachineManagerReadAllSlicesForLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\tlibraryID: args.libraryID,\n\t\t});\n\t\tres.errors.push(...errors);\n\n\t\tif (sliceIDs) {\n\t\t\tfor (const sliceID of sliceIDs) {\n\t\t\t\tconst { model, errors } = await this.readSlice({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID,\n\t\t\t\t});\n\t\t\t\tres.errors.push(...errors);\n\n\t\t\t\tif (model) {\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 readAllSlices(): Promise<SliceMachineManagerReadAllSlicesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SliceMachineManagerReadAllSlicesReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { models, errors } = await this.readAllSlicesForLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors.push(...errors);\n\n\t\t\tfor (const model of models) {\n\t\t\t\tres.models.push({\n\t\t\t\t\tlibraryID,\n\t\t\t\t\tmodel: model.model,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createSlice(\n\t\targs: SliceCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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 readSlice(\n\t\targs: SliceReadHookData,\n\t): Promise<SliceMachineManagerReadSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice,\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\tasync updateSlice(\n\t\targs: SliceUpdateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:update\",\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 renameSlice(\n\t\targs: SliceRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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\t// TODO: Disallow until Slices can be deleted.\n\tasync deleteSlice(\n\t\targs: SliceDeleteHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceDeleteHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:delete\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\t/**\n\t * @returns Record of variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tasync pushSlice(\n\t\targs: SliceMachineManagerPushSliceArgs,\n\t): Promise<SliceMachineManagerPushSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tif (!(await this.user.checkIsLoggedIn())) {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\n\t\tconst { model, errors: readSliceErrors } = await this.readSlice({\n\t\t\tlibraryID: args.libraryID,\n\t\t\tsliceID: args.sliceID,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst modelWithScreenshots =\n\t\t\t\tawait this.updateSliceModelScreenshotsInPlace({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tmodel,\n\t\t\t\t});\n\n\t\t\tconst { errors: updateSliceErrors } = await this.updateSlice({\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tmodel: modelWithScreenshots,\n\t\t\t});\n\n\t\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\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: sliceMachineConfig.repositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Slice already exists on the repository.\n\t\t\t\tawait client.getSharedSliceByID(args.sliceID);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateSharedSlice(modelWithScreenshots);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If the Slice doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertSharedSlice(modelWithScreenshots);\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 Slices to this Prismic repository.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Pass the error through if it isn't the one we were expecting.\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst screenshotURLs: Record<string, string> = {};\n\t\t\tfor (const variation of modelWithScreenshots.variations) {\n\t\t\t\tscreenshotURLs[variation.id] = variation.imageUrl;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tscreenshotURLs,\n\t\t\t\terrors: [...readSliceErrors, ...updateSliceErrors],\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tscreenshotURLs: undefined,\n\t\t\t\terrors: readSliceErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync readSliceScreenshot(\n\t\targs: SliceMachineManagerReadSliceScreenshotArgs,\n\t): Promise<SliceMachineManagerReadSliceScreenshotReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `screenshot-${args.variationID}.png`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: bufferCodec,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tdata: data[0]?.data,\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync updateSliceScreenshot(\n\t\targs: SliceMachineManagerUpdateSliceScreenshotArgs,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceAssetUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: `screenshot-${args.variationID}.png`,\n\t\t\t\t\tdata: args.data,\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 readSliceMocks(\n\t\targs: SliceMachineManagerReadSliceMocksArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `mocks.json`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: t.array(SharedSliceContent),\n\t\t\t}),\n\t\t\t{\n\t\t\t\t...hookResult,\n\t\t\t\t// Convert the asset data from a Buffer to JSON\n\t\t\t\t// to prepare it for validation.\n\t\t\t\tdata: hookResult.data.map((result) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...result,\n\t\t\t\t\t\t\tdata: JSON.parse(result.data.toString()),\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocks: data[0]?.data,\n\t\t\t\terrors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocks: [],\n\t\t\t\terrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync updateSliceMocks(\n\t\targs: SliceMachineManagerUpdateSliceMocksArgs,\n\t): Promise<SliceMachineManagerUpdateSliceMocksArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocks, 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\t// TODO: Remove\n\tasync readSliceMocksConfig(\n\t\targs: SliceMachineManagerReadSliceMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\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\tasync fetchRemoteSlices(): Promise<CustomTypes.Widgets.Slices.SharedSlice[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName: sliceMachineConfig.repositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t});\n\n\t\treturn await client.getAllSharedSlices();\n\t}\n\n\tasync updateSliceModelScreenshotsInPlace(\n\t\targs: SlicesManagerUpsertHostedSliceScrenshotsArgs,\n\t): Promise<CustomTypes.Widgets.Slices.SharedSlice> {\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst variations = await Promise.all(\n\t\t\targs.model.variations.map(async (variation) => {\n\t\t\t\tconst screenshot = await this.readSliceScreenshot({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID: args.model.id,\n\t\t\t\t\tvariationID: variation.id,\n\t\t\t\t});\n\n\t\t\t\t// If there's no screenshot, delete it by replacing it with the default screenshot\n\t\t\t\tif (!screenshot.data) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...variation,\n\t\t\t\t\t\timageUrl: DEFAULT_SLICE_SCREENSHOT_URL,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst hasScreenshotChanged = !variation.imageUrl?.includes(\n\t\t\t\t\tcreateContentDigest(screenshot.data),\n\t\t\t\t);\n\n\t\t\t\t// If screenshot hasn't changed, do nothing\n\t\t\t\tif (!hasScreenshotChanged) {\n\t\t\t\t\treturn variation;\n\t\t\t\t}\n\n\t\t\t\tconst keyPrefix = [\n\t\t\t\t\tsliceMachineConfig.repositoryName,\n\t\t\t\t\t\"shared-slices\",\n\t\t\t\t\targs.model.id,\n\t\t\t\t\tvariation.id,\n\t\t\t\t].join(\"/\");\n\n\t\t\t\tconst uploadedScreenshot = await this.screenshots.uploadScreenshot({\n\t\t\t\t\tdata: screenshot.data,\n\t\t\t\t\tkeyPrefix,\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\t...variation,\n\t\t\t\t\timageUrl: uploadedScreenshot.url,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn {\n\t\t\t...args.model,\n\t\t\tvariations,\n\t\t};\n\t}\n}\n"],"names":["BaseManager","assertPluginsInitialized","errors","decodeHookResult","t","CustomTypes","UnauthenticatedError","prismicCustomTypesClient","API_ENDPOINTS","fetch","UnauthorizedError","bufferCodec","SharedSliceContent","DEFAULT_SLICE_SCREENSHOT_URL","createContentDigest"],"mappings":"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"}
@@ -86,6 +86,10 @@ type SliceMachineManagerUpdateSliceMocksArgs = {
86
86
  type SliceMachineManagerUpdateSliceMocksArgsReturnType = {
87
87
  errors: HookError[];
88
88
  };
89
+ type SlicesManagerUpsertHostedSliceScrenshotsArgs = {
90
+ libraryID: string;
91
+ model: CustomTypes.Widgets.Slices.SharedSlice;
92
+ };
89
93
  export declare class SlicesManager extends BaseManager {
90
94
  readSliceLibrary(args: SliceLibraryReadHookData): Promise<SlicesManagerReadSliceLibraryReturnType>;
91
95
  readAllSliceLibraries(): Promise<SlicesManagerReadAllSliceLibrariesReturnType>;
@@ -106,6 +110,6 @@ export declare class SlicesManager extends BaseManager {
106
110
  updateSliceMocks(args: SliceMachineManagerUpdateSliceMocksArgs): Promise<SliceMachineManagerUpdateSliceMocksArgsReturnType>;
107
111
  readSliceMocksConfig(args: SliceMachineManagerReadSliceMocksConfigArgs): Promise<SliceMachineManagerReadSliceMocksConfigArgsReturnType>;
108
112
  fetchRemoteSlices(): Promise<CustomTypes.Widgets.Slices.SharedSlice[]>;
109
- private _updateSliceModelScreenshotsInPlace;
113
+ updateSliceModelScreenshotsInPlace(args: SlicesManagerUpsertHostedSliceScrenshotsArgs): Promise<CustomTypes.Widgets.Slices.SharedSlice>;
110
114
  }
111
115
  export {};
@@ -10,6 +10,7 @@ import { DEFAULT_SLICE_SCREENSHOT_URL } from "../../constants/DEFAULT_SLICE_SCRE
10
10
  import { API_ENDPOINTS } from "../../constants/API_ENDPOINTS.js";
11
11
  import { UnauthenticatedError, UnauthorizedError } from "../../errors.js";
12
12
  import { BaseManager } from "../BaseManager.js";
13
+ import { createContentDigest } from "../../lib/createContentDigest.js";
13
14
  class SlicesManager extends BaseManager {
14
15
  async readSliceLibrary(args) {
15
16
  var _a;
@@ -144,7 +145,7 @@ class SlicesManager extends BaseManager {
144
145
  sliceID: args.sliceID
145
146
  });
146
147
  if (model) {
147
- const modelWithScreenshots = await this._updateSliceModelScreenshotsInPlace({
148
+ const modelWithScreenshots = await this.updateSliceModelScreenshotsInPlace({
148
149
  libraryID: args.libraryID,
149
150
  model
150
151
  });
@@ -301,32 +302,39 @@ class SlicesManager extends BaseManager {
301
302
  });
302
303
  return await client.getAllSharedSlices();
303
304
  }
304
- async _updateSliceModelScreenshotsInPlace(args) {
305
+ async updateSliceModelScreenshotsInPlace(args) {
305
306
  const sliceMachineConfig = await this.project.getSliceMachineConfig();
306
307
  const variations = await Promise.all(args.model.variations.map(async (variation) => {
307
- const updatedVariation = {
308
- ...variation,
309
- imageUrl: DEFAULT_SLICE_SCREENSHOT_URL
310
- };
308
+ var _a;
311
309
  const screenshot = await this.readSliceScreenshot({
312
310
  libraryID: args.libraryID,
313
311
  sliceID: args.model.id,
314
312
  variationID: variation.id
315
313
  });
316
- if (screenshot.data) {
317
- const keyPrefix = [
318
- sliceMachineConfig.repositoryName,
319
- "shared-slices",
320
- args.model.id,
321
- variation.id
322
- ].join("/");
323
- const uploadedScreenshot = await this.screenshots.uploadScreenshot({
324
- data: screenshot.data,
325
- keyPrefix
326
- });
327
- updatedVariation.imageUrl = uploadedScreenshot.url;
314
+ if (!screenshot.data) {
315
+ return {
316
+ ...variation,
317
+ imageUrl: DEFAULT_SLICE_SCREENSHOT_URL
318
+ };
319
+ }
320
+ const hasScreenshotChanged = !((_a = variation.imageUrl) == null ? void 0 : _a.includes(createContentDigest(screenshot.data)));
321
+ if (!hasScreenshotChanged) {
322
+ return variation;
328
323
  }
329
- return updatedVariation;
324
+ const keyPrefix = [
325
+ sliceMachineConfig.repositoryName,
326
+ "shared-slices",
327
+ args.model.id,
328
+ variation.id
329
+ ].join("/");
330
+ const uploadedScreenshot = await this.screenshots.uploadScreenshot({
331
+ data: screenshot.data,
332
+ keyPrefix
333
+ });
334
+ return {
335
+ ...variation,
336
+ imageUrl: uploadedScreenshot.url
337
+ };
330
338
  }));
331
339
  return {
332
340
  ...args.model,
@@ -1 +1 @@
1
- {"version":3,"file":"SlicesManager.js","sources":["../../../../src/managers/slices/SlicesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport fetch from \"node-fetch\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport { CustomTypes } from \"@prismicio/types-internal\";\nimport { SharedSliceContent } from \"@prismicio/types-internal/lib/content\";\nimport {\n\tCallHookReturnType,\n\tHookError,\n\tSliceAssetUpdateHook,\n\tSliceCreateHook,\n\tSliceCreateHookData,\n\tSliceDeleteHook,\n\tSliceDeleteHookData,\n\tSliceLibraryReadHookData,\n\tSliceReadHookData,\n\tSliceRenameHook,\n\tSliceRenameHookData,\n\tSliceUpdateHook,\n\tSliceUpdateHookData,\n} from \"@slicemachine/plugin-kit\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { bufferCodec } from \"../../lib/bufferCodec\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { DEFAULT_SLICE_SCREENSHOT_URL } from \"../../constants/DEFAULT_SLICE_SCREENSHOT_URL\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { UnauthenticatedError, UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype SlicesManagerReadSliceLibraryReturnType = {\n\tsliceIDs: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SlicesManagerReadAllSliceLibrariesReturnType = {\n\tlibraries: {\n\t\tlibraryID: string;\n\t\tsliceIDs: string[] | undefined;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryArgs = {\n\tlibraryID: string;\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\tmodels: { model: CustomTypes.Widgets.Slices.SharedSlice }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesReturnType = {\n\tmodels: {\n\t\tlibraryID: string;\n\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceReturnType = {\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushSliceArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\nexport type SliceMachineManagerPushSliceReturnType = {\n\t/**\n\t * A record of Slice variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tscreenshotURLs: Record<string, string> | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n};\n\ntype SliceMachineManagerReadSliceScreenshotReturnType = {\n\tdata: Buffer | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerUpdateSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n\tdata: Buffer;\n};\n\ntype SliceMachineManagerReadSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksReturnType = {\n\tmocks?: SharedSliceContent[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tmocks: SharedSliceContent[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgsReturnType = {\n\terrors: HookError[];\n};\n\ntype SlicesManagerUpsertHostedSliceScrenshotsArgs = {\n\tlibraryID: string;\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n};\n\nexport class SlicesManager extends BaseManager {\n\tasync readSliceLibrary(\n\t\targs: SliceLibraryReadHookData,\n\t): Promise<SlicesManagerReadSliceLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// TODO: Should validation happen at the `callHook` level?\n\t\t// Including validation at the hook level would ensure\n\t\t// hook-based actions are validated.\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice-library:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tid: t.string,\n\t\t\t\tsliceIDs: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tsliceIDs: data[0]?.sliceIDs ?? [],\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync readAllSliceLibraries(): Promise<SlicesManagerReadAllSliceLibrariesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SlicesManagerReadAllSliceLibrariesReturnType = {\n\t\t\tlibraries: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\tres.libraries.push({\n\t\t\t\tlibraryID,\n\t\t\t\tsliceIDs,\n\t\t\t});\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync readAllSlicesForLibrary(\n\t\targs: SliceMachineManagerReadAllSlicesForLibraryArgs,\n\t): Promise<SliceMachineManagerReadAllSlicesForLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\tlibraryID: args.libraryID,\n\t\t});\n\t\tres.errors.push(...errors);\n\n\t\tif (sliceIDs) {\n\t\t\tfor (const sliceID of sliceIDs) {\n\t\t\t\tconst { model, errors } = await this.readSlice({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID,\n\t\t\t\t});\n\t\t\t\tres.errors.push(...errors);\n\n\t\t\t\tif (model) {\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 readAllSlices(): Promise<SliceMachineManagerReadAllSlicesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SliceMachineManagerReadAllSlicesReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { models, errors } = await this.readAllSlicesForLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors.push(...errors);\n\n\t\t\tfor (const model of models) {\n\t\t\t\tres.models.push({\n\t\t\t\t\tlibraryID,\n\t\t\t\t\tmodel: model.model,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createSlice(\n\t\targs: SliceCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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 readSlice(\n\t\targs: SliceReadHookData,\n\t): Promise<SliceMachineManagerReadSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice,\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\tasync updateSlice(\n\t\targs: SliceUpdateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:update\",\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 renameSlice(\n\t\targs: SliceRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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\t// TODO: Disallow until Slices can be deleted.\n\tasync deleteSlice(\n\t\targs: SliceDeleteHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceDeleteHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:delete\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\t/**\n\t * @returns Record of variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tasync pushSlice(\n\t\targs: SliceMachineManagerPushSliceArgs,\n\t): Promise<SliceMachineManagerPushSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tif (!(await this.user.checkIsLoggedIn())) {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\n\t\tconst { model, errors: readSliceErrors } = await this.readSlice({\n\t\t\tlibraryID: args.libraryID,\n\t\t\tsliceID: args.sliceID,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst modelWithScreenshots =\n\t\t\t\tawait this._updateSliceModelScreenshotsInPlace({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tmodel,\n\t\t\t\t});\n\n\t\t\tconst { errors: updateSliceErrors } = await this.updateSlice({\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tmodel: modelWithScreenshots,\n\t\t\t});\n\n\t\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\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: sliceMachineConfig.repositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Slice already exists on the repository.\n\t\t\t\tawait client.getSharedSliceByID(args.sliceID);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateSharedSlice(modelWithScreenshots);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If the Slice doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertSharedSlice(modelWithScreenshots);\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 Slices to this Prismic repository.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Pass the error through if it isn't the one we were expecting.\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst screenshotURLs: Record<string, string> = {};\n\t\t\tfor (const variation of modelWithScreenshots.variations) {\n\t\t\t\tscreenshotURLs[variation.id] = variation.imageUrl;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tscreenshotURLs,\n\t\t\t\terrors: [...readSliceErrors, ...updateSliceErrors],\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tscreenshotURLs: undefined,\n\t\t\t\terrors: readSliceErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync readSliceScreenshot(\n\t\targs: SliceMachineManagerReadSliceScreenshotArgs,\n\t): Promise<SliceMachineManagerReadSliceScreenshotReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `screenshot-${args.variationID}.png`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: bufferCodec,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tdata: data[0]?.data,\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync updateSliceScreenshot(\n\t\targs: SliceMachineManagerUpdateSliceScreenshotArgs,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceAssetUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: `screenshot-${args.variationID}.png`,\n\t\t\t\t\tdata: args.data,\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 readSliceMocks(\n\t\targs: SliceMachineManagerReadSliceMocksArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `mocks.json`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: t.array(SharedSliceContent),\n\t\t\t}),\n\t\t\t{\n\t\t\t\t...hookResult,\n\t\t\t\t// Convert the asset data from a Buffer to JSON\n\t\t\t\t// to prepare it for validation.\n\t\t\t\tdata: hookResult.data.map((result) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...result,\n\t\t\t\t\t\t\tdata: JSON.parse(result.data.toString()),\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocks: data[0]?.data,\n\t\t\t\terrors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocks: [],\n\t\t\t\terrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync updateSliceMocks(\n\t\targs: SliceMachineManagerUpdateSliceMocksArgs,\n\t): Promise<SliceMachineManagerUpdateSliceMocksArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocks, 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\t// TODO: Remove\n\tasync readSliceMocksConfig(\n\t\targs: SliceMachineManagerReadSliceMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\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\tasync fetchRemoteSlices(): Promise<CustomTypes.Widgets.Slices.SharedSlice[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName: sliceMachineConfig.repositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t});\n\n\t\treturn await client.getAllSharedSlices();\n\t}\n\n\tprivate async _updateSliceModelScreenshotsInPlace(\n\t\targs: SlicesManagerUpsertHostedSliceScrenshotsArgs,\n\t): Promise<CustomTypes.Widgets.Slices.SharedSlice> {\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst variations = await Promise.all(\n\t\t\targs.model.variations.map(async (variation) => {\n\t\t\t\tconst updatedVariation: CustomTypes.Widgets.Slices.Variation = {\n\t\t\t\t\t...variation,\n\t\t\t\t\timageUrl: DEFAULT_SLICE_SCREENSHOT_URL,\n\t\t\t\t};\n\n\t\t\t\tconst screenshot = await this.readSliceScreenshot({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID: args.model.id,\n\t\t\t\t\tvariationID: variation.id,\n\t\t\t\t});\n\n\t\t\t\tif (screenshot.data) {\n\t\t\t\t\tconst keyPrefix = [\n\t\t\t\t\t\tsliceMachineConfig.repositoryName,\n\t\t\t\t\t\t\"shared-slices\",\n\t\t\t\t\t\targs.model.id,\n\t\t\t\t\t\tvariation.id,\n\t\t\t\t\t].join(\"/\");\n\n\t\t\t\t\t// TODO: If the existing imageUrl\n\t\t\t\t\t// property (not the prefilled efault\n\t\t\t\t\t// URL) is identical to the new image\n\t\t\t\t\t// (we'll need to get the image's full\n\t\t\t\t\t// URL before we upload it), then don't\n\t\t\t\t\t// upload anything.\n\n\t\t\t\t\tconst uploadedScreenshot = await this.screenshots.uploadScreenshot({\n\t\t\t\t\t\tdata: screenshot.data,\n\t\t\t\t\t\tkeyPrefix,\n\t\t\t\t\t});\n\n\t\t\t\t\tupdatedVariation.imageUrl = uploadedScreenshot.url;\n\t\t\t\t}\n\n\t\t\t\treturn updatedVariation;\n\t\t\t}),\n\t\t);\n\n\t\treturn {\n\t\t\t...args.model,\n\t\t\tvariations,\n\t\t};\n\t}\n}\n"],"names":["errors"],"mappings":"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"}
1
+ {"version":3,"file":"SlicesManager.js","sources":["../../../../src/managers/slices/SlicesManager.ts"],"sourcesContent":["import * as t from \"io-ts\";\nimport fetch from \"node-fetch\";\nimport * as prismicCustomTypesClient from \"@prismicio/custom-types-client\";\nimport { CustomTypes } from \"@prismicio/types-internal\";\nimport { SharedSliceContent } from \"@prismicio/types-internal/lib/content\";\nimport {\n\tCallHookReturnType,\n\tHookError,\n\tSliceAssetUpdateHook,\n\tSliceCreateHook,\n\tSliceCreateHookData,\n\tSliceDeleteHook,\n\tSliceDeleteHookData,\n\tSliceLibraryReadHookData,\n\tSliceReadHookData,\n\tSliceRenameHook,\n\tSliceRenameHookData,\n\tSliceUpdateHook,\n\tSliceUpdateHookData,\n} from \"@slicemachine/plugin-kit\";\n\nimport { DecodeError } from \"../../lib/DecodeError\";\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { bufferCodec } from \"../../lib/bufferCodec\";\nimport { decodeHookResult } from \"../../lib/decodeHookResult\";\n\nimport { OnlyHookErrors } from \"../../types\";\nimport { DEFAULT_SLICE_SCREENSHOT_URL } from \"../../constants/DEFAULT_SLICE_SCREENSHOT_URL\";\nimport { API_ENDPOINTS } from \"../../constants/API_ENDPOINTS\";\nimport { UnauthenticatedError, UnauthorizedError } from \"../../errors\";\n\nimport { BaseManager } from \"../BaseManager\";\nimport { createContentDigest } from \"../../lib/createContentDigest\";\n\ntype SlicesManagerReadSliceLibraryReturnType = {\n\tsliceIDs: string[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SlicesManagerReadAllSliceLibrariesReturnType = {\n\tlibraries: {\n\t\tlibraryID: string;\n\t\tsliceIDs: string[] | undefined;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryArgs = {\n\tlibraryID: string;\n};\n\ntype SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\tmodels: { model: CustomTypes.Widgets.Slices.SharedSlice }[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadAllSlicesReturnType = {\n\tmodels: {\n\t\tlibraryID: string;\n\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n\t}[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceReturnType = {\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerPushSliceArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\nexport type SliceMachineManagerPushSliceReturnType = {\n\t/**\n\t * A record of Slice variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tscreenshotURLs: Record<string, string> | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n};\n\ntype SliceMachineManagerReadSliceScreenshotReturnType = {\n\tdata: Buffer | undefined;\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerUpdateSliceScreenshotArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tvariationID: string;\n\tdata: Buffer;\n};\n\ntype SliceMachineManagerReadSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksReturnType = {\n\tmocks?: SharedSliceContent[];\n\terrors: (DecodeError | HookError)[];\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n};\n\ntype SliceMachineManagerReadSliceMocksConfigArgsReturnType = {\n\t// TODO\n\tmocksConfig?: Record<string, unknown>;\n\terrors: HookError[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgs = {\n\tlibraryID: string;\n\tsliceID: string;\n\tmocks: SharedSliceContent[];\n};\n\ntype SliceMachineManagerUpdateSliceMocksArgsReturnType = {\n\terrors: HookError[];\n};\n\ntype SlicesManagerUpsertHostedSliceScrenshotsArgs = {\n\tlibraryID: string;\n\tmodel: CustomTypes.Widgets.Slices.SharedSlice;\n};\n\nexport class SlicesManager extends BaseManager {\n\tasync readSliceLibrary(\n\t\targs: SliceLibraryReadHookData,\n\t): Promise<SlicesManagerReadSliceLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// TODO: Should validation happen at the `callHook` level?\n\t\t// Including validation at the hook level would ensure\n\t\t// hook-based actions are validated.\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice-library:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tid: t.string,\n\t\t\t\tsliceIDs: t.array(t.string),\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tsliceIDs: data[0]?.sliceIDs ?? [],\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync readAllSliceLibraries(): Promise<SlicesManagerReadAllSliceLibrariesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SlicesManagerReadAllSliceLibrariesReturnType = {\n\t\t\tlibraries: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors = [...res.errors, ...errors];\n\n\t\t\tres.libraries.push({\n\t\t\t\tlibraryID,\n\t\t\t\tsliceIDs,\n\t\t\t});\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync readAllSlicesForLibrary(\n\t\targs: SliceMachineManagerReadAllSlicesForLibraryArgs,\n\t): Promise<SliceMachineManagerReadAllSlicesForLibraryReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst res: SliceMachineManagerReadAllSlicesForLibraryReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tconst { sliceIDs, errors } = await this.readSliceLibrary({\n\t\t\tlibraryID: args.libraryID,\n\t\t});\n\t\tres.errors.push(...errors);\n\n\t\tif (sliceIDs) {\n\t\t\tfor (const sliceID of sliceIDs) {\n\t\t\t\tconst { model, errors } = await this.readSlice({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID,\n\t\t\t\t});\n\t\t\t\tres.errors.push(...errors);\n\n\t\t\t\tif (model) {\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 readAllSlices(): Promise<SliceMachineManagerReadAllSlicesReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\t\tconst libraryIDs = sliceMachineConfig.libraries || [];\n\n\t\tconst res: SliceMachineManagerReadAllSlicesReturnType = {\n\t\t\tmodels: [],\n\t\t\terrors: [],\n\t\t};\n\n\t\tfor (const libraryID of libraryIDs) {\n\t\t\tconst { models, errors } = await this.readAllSlicesForLibrary({\n\t\t\t\tlibraryID,\n\t\t\t});\n\t\t\tres.errors.push(...errors);\n\n\t\t\tfor (const model of models) {\n\t\t\t\tres.models.push({\n\t\t\t\t\tlibraryID,\n\t\t\t\t\tmodel: model.model,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn res;\n\t}\n\n\tasync createSlice(\n\t\targs: SliceCreateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceCreateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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 readSlice(\n\t\targs: SliceReadHookData,\n\t): Promise<SliceMachineManagerReadSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:read\",\n\t\t\targs,\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tmodel: CustomTypes.Widgets.Slices.SharedSlice,\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\tasync updateSlice(\n\t\targs: SliceUpdateHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:update\",\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 renameSlice(\n\t\targs: SliceRenameHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceRenameHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice: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\t// TODO: Disallow until Slices can be deleted.\n\tasync deleteSlice(\n\t\targs: SliceDeleteHookData,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceDeleteHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:delete\",\n\t\t\targs,\n\t\t);\n\n\t\treturn {\n\t\t\terrors: hookResult.errors,\n\t\t};\n\t}\n\n\t/**\n\t * @returns Record of variation IDs mapped to uploaded screenshot URLs.\n\t */\n\tasync pushSlice(\n\t\targs: SliceMachineManagerPushSliceArgs,\n\t): Promise<SliceMachineManagerPushSliceReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tif (!(await this.user.checkIsLoggedIn())) {\n\t\t\tthrow new UnauthenticatedError();\n\t\t}\n\n\t\tconst { model, errors: readSliceErrors } = await this.readSlice({\n\t\t\tlibraryID: args.libraryID,\n\t\t\tsliceID: args.sliceID,\n\t\t});\n\n\t\tif (model) {\n\t\t\tconst modelWithScreenshots =\n\t\t\t\tawait this.updateSliceModelScreenshotsInPlace({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tmodel,\n\t\t\t\t});\n\n\t\t\tconst { errors: updateSliceErrors } = await this.updateSlice({\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tmodel: modelWithScreenshots,\n\t\t\t});\n\n\t\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\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: sliceMachineConfig.repositoryName,\n\t\t\t\ttoken: authenticationToken,\n\t\t\t\tfetch,\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\t// Check if Slice already exists on the repository.\n\t\t\t\tawait client.getSharedSliceByID(args.sliceID);\n\n\t\t\t\t// If it exists on the repository, update it.\n\t\t\t\tawait client.updateSharedSlice(modelWithScreenshots);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof prismicCustomTypesClient.NotFoundError) {\n\t\t\t\t\t// If the Slice doesn't exist on the repository, insert it.\n\t\t\t\t\tawait client.insertSharedSlice(modelWithScreenshots);\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 Slices to this Prismic repository.\",\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Pass the error through if it isn't the one we were expecting.\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst screenshotURLs: Record<string, string> = {};\n\t\t\tfor (const variation of modelWithScreenshots.variations) {\n\t\t\t\tscreenshotURLs[variation.id] = variation.imageUrl;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tscreenshotURLs,\n\t\t\t\terrors: [...readSliceErrors, ...updateSliceErrors],\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tscreenshotURLs: undefined,\n\t\t\t\terrors: readSliceErrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync readSliceScreenshot(\n\t\targs: SliceMachineManagerReadSliceScreenshotArgs,\n\t): Promise<SliceMachineManagerReadSliceScreenshotReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `screenshot-${args.variationID}.png`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: bufferCodec,\n\t\t\t}),\n\t\t\thookResult,\n\t\t);\n\n\t\treturn {\n\t\t\tdata: data[0]?.data,\n\t\t\terrors: errors,\n\t\t};\n\t}\n\n\tasync updateSliceScreenshot(\n\t\targs: SliceMachineManagerUpdateSliceScreenshotArgs,\n\t): Promise<OnlyHookErrors<CallHookReturnType<SliceAssetUpdateHook>>> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: `screenshot-${args.variationID}.png`,\n\t\t\t\t\tdata: args.data,\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 readSliceMocks(\n\t\targs: SliceMachineManagerReadSliceMocksArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tassetID: `mocks.json`,\n\t\t\t},\n\t\t);\n\t\tconst { data, errors } = decodeHookResult(\n\t\t\tt.type({\n\t\t\t\tdata: t.array(SharedSliceContent),\n\t\t\t}),\n\t\t\t{\n\t\t\t\t...hookResult,\n\t\t\t\t// Convert the asset data from a Buffer to JSON\n\t\t\t\t// to prepare it for validation.\n\t\t\t\tdata: hookResult.data.map((result) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t...result,\n\t\t\t\t\t\t\tdata: JSON.parse(result.data.toString()),\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn result;\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t},\n\t\t);\n\n\t\tif (data) {\n\t\t\treturn {\n\t\t\t\tmocks: data[0]?.data,\n\t\t\t\terrors,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tmocks: [],\n\t\t\t\terrors,\n\t\t\t};\n\t\t}\n\t}\n\n\tasync updateSliceMocks(\n\t\targs: SliceMachineManagerUpdateSliceMocksArgs,\n\t): Promise<SliceMachineManagerUpdateSliceMocksArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:update\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\n\t\t\t\tasset: {\n\t\t\t\t\tid: \"mocks.json\",\n\t\t\t\t\tdata: Buffer.from(JSON.stringify(args.mocks, 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\t// TODO: Remove\n\tasync readSliceMocksConfig(\n\t\targs: SliceMachineManagerReadSliceMocksConfigArgs,\n\t): Promise<SliceMachineManagerReadSliceMocksConfigArgsReturnType> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\tconst hookResult = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"slice:asset:read\",\n\t\t\t{\n\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\tsliceID: args.sliceID,\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\tasync fetchRemoteSlices(): Promise<CustomTypes.Widgets.Slices.SharedSlice[]> {\n\t\tconst authenticationToken = await this.user.getAuthenticationToken();\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst client = prismicCustomTypesClient.createClient({\n\t\t\tendpoint: API_ENDPOINTS.PrismicModels,\n\t\t\trepositoryName: sliceMachineConfig.repositoryName,\n\t\t\ttoken: authenticationToken,\n\t\t\tfetch,\n\t\t});\n\n\t\treturn await client.getAllSharedSlices();\n\t}\n\n\tasync updateSliceModelScreenshotsInPlace(\n\t\targs: SlicesManagerUpsertHostedSliceScrenshotsArgs,\n\t): Promise<CustomTypes.Widgets.Slices.SharedSlice> {\n\t\tconst sliceMachineConfig = await this.project.getSliceMachineConfig();\n\n\t\tconst variations = await Promise.all(\n\t\t\targs.model.variations.map(async (variation) => {\n\t\t\t\tconst screenshot = await this.readSliceScreenshot({\n\t\t\t\t\tlibraryID: args.libraryID,\n\t\t\t\t\tsliceID: args.model.id,\n\t\t\t\t\tvariationID: variation.id,\n\t\t\t\t});\n\n\t\t\t\t// If there's no screenshot, delete it by replacing it with the default screenshot\n\t\t\t\tif (!screenshot.data) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\t...variation,\n\t\t\t\t\t\timageUrl: DEFAULT_SLICE_SCREENSHOT_URL,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\tconst hasScreenshotChanged = !variation.imageUrl?.includes(\n\t\t\t\t\tcreateContentDigest(screenshot.data),\n\t\t\t\t);\n\n\t\t\t\t// If screenshot hasn't changed, do nothing\n\t\t\t\tif (!hasScreenshotChanged) {\n\t\t\t\t\treturn variation;\n\t\t\t\t}\n\n\t\t\t\tconst keyPrefix = [\n\t\t\t\t\tsliceMachineConfig.repositoryName,\n\t\t\t\t\t\"shared-slices\",\n\t\t\t\t\targs.model.id,\n\t\t\t\t\tvariation.id,\n\t\t\t\t].join(\"/\");\n\n\t\t\t\tconst uploadedScreenshot = await this.screenshots.uploadScreenshot({\n\t\t\t\t\tdata: screenshot.data,\n\t\t\t\t\tkeyPrefix,\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\t...variation,\n\t\t\t\t\timageUrl: uploadedScreenshot.url,\n\t\t\t\t};\n\t\t\t}),\n\t\t);\n\n\t\treturn {\n\t\t\t...args.model,\n\t\t\tvariations,\n\t\t};\n\t}\n}\n"],"names":["errors"],"mappings":"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"}
@@ -23,8 +23,9 @@ class TelemetryManager extends BaseManager.BaseManager {
23
23
  __publicField(this, "_segmentClient");
24
24
  __publicField(this, "_anonymousID");
25
25
  __publicField(this, "_userID");
26
+ __publicField(this, "_context");
26
27
  }
27
- async initTelemetry() {
28
+ async initTelemetry(args) {
28
29
  if (this._segmentClient) {
29
30
  return;
30
31
  }
@@ -37,6 +38,7 @@ class TelemetryManager extends BaseManager.BaseManager {
37
38
  }
38
39
  });
39
40
  this._anonymousID = crypto.randomUUID();
41
+ this._context = { app: { name: args.appName, version: args.appVersion } };
40
42
  }
41
43
  // TODO: Should `userId` be automatically populated by the logged in
42
44
  // user? We already have their info via UserRepository.
@@ -46,9 +48,11 @@ class TelemetryManager extends BaseManager.BaseManager {
46
48
  const payload = {
47
49
  event: types.HumanSegmentEventType[event],
48
50
  properties: {
51
+ nodeVersion: process.versions.node,
49
52
  repo: repository,
50
53
  ...properties
51
- }
54
+ },
55
+ context: { ...this._context }
52
56
  };
53
57
  if (this._userID) {
54
58
  payload.userId = this._userID;
@@ -74,18 +78,19 @@ class TelemetryManager extends BaseManager.BaseManager {
74
78
  // by the logged in user? We already have their info via
75
79
  // UserRepository.
76
80
  identify(args) {
81
+ const payload = {
82
+ userId: args.userID,
83
+ anonymousId: this._anonymousID,
84
+ integrations: {
85
+ Intercom: {
86
+ user_hash: args.intercomHash
87
+ }
88
+ },
89
+ context: { ...this._context }
90
+ };
91
+ this._userID = args.userID;
77
92
  return new Promise((resolve) => {
78
93
  assertTelemetryInitialized(this._segmentClient);
79
- const payload = {
80
- userId: args.userID,
81
- anonymousId: this._anonymousID,
82
- integrations: {
83
- Intercom: {
84
- user_hash: args.intercomHash
85
- }
86
- }
87
- };
88
- this._userID = args.userID;
89
94
  this._segmentClient.identify(payload, (maybeError) => {
90
95
  if (maybeError) {
91
96
  console.warn(`An error occurred during Segment identify`, maybeError);
@@ -94,6 +99,28 @@ class TelemetryManager extends BaseManager.BaseManager {
94
99
  });
95
100
  });
96
101
  }
102
+ group(args) {
103
+ const { repositoryName, ...traits } = args;
104
+ const payload = {
105
+ groupId: repositoryName,
106
+ traits,
107
+ context: { ...this._context }
108
+ };
109
+ if (this._userID) {
110
+ payload.userId = this._userID;
111
+ } else {
112
+ payload.anonymousId = this._anonymousID;
113
+ }
114
+ return new Promise((resolve) => {
115
+ assertTelemetryInitialized(this._segmentClient);
116
+ this._segmentClient.group(payload, (maybeError) => {
117
+ if (maybeError) {
118
+ console.warn(`An error occurred during Segment group`, maybeError);
119
+ }
120
+ resolve();
121
+ });
122
+ });
123
+ }
97
124
  async checkIsTelemetryEnabled() {
98
125
  let root;
99
126
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"TelemetryManager.cjs","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\n\tasync initTelemetry(): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tconst payload = {\n\t\t\t\tuserId: args.userID,\n\t\t\t\tanonymousId: this._anonymousID,\n\t\t\t\tintegrations: {\n\t\t\t\t\tIntercom: {\n\t\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis._userID = args.userID;\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":["BaseManager","API_TOKENS","randomUUID","HumanSegmentEventType","readPrismicrc"],"mappings":";;;;;;;;;;;;;;AAuBA,SAAS,2BACR,eAAwC;AAExC,MAAI,iBAAiB,QAAW;AACzB,UAAA,IAAI,MACT,kIAAkI;AAAA,EAEnI;AACF;AAEM,MAAO,yBAAyBA,YAAAA,YAAW;AAAA,EAA3C;AAAA;AACG;AACA;AACA;AAAA;AAAA,EAER,MAAM,gBAAa;AAClB,QAAI,KAAK,gBAAgB;AAExB;AAAA,IACA;AAED,SAAK,iBAAiB,IAAI,cAAcC,WAAAA,WAAW,YAAY;AAAA;AAAA,MAE9D,SAAS;AAAA;AAAA,MAET,QAAQ,MAAM,KAAK,wBAAyB;AAAA,MAC5C,cAAc,MAAK;AAAA,MAKnB;AAAA,IAAA,CACA;AACD,SAAK,eAAeC,OAAAA;EACrB;AAAA;AAAA;AAAA,EAIA,MAAM,MAA+B;;AACpC,UAAM,EAAE,OAAO,YAAY,GAAG,eAAe;AAE7C,UAAM,UAUF;AAAA,MACH,OAAOC,4BAAsB,KAAK;AAAA,MAClC,YAAY;AAAA,QACX,MAAM;AAAA,QACN,GAAG;AAAA,MACH;AAAA,IAAA;AAGF,QAAI,KAAK,SAAS;AACjB,cAAQ,SAAS,KAAK;AAAA,IAAA,OAChB;AACN,cAAQ,cAAc,KAAK;AAAA,IAC3B;AAED,QAAI,KAAK,YAAY;AACpB,cAAQ,YAAR,QAAQ,UAAY;AACZ,oBAAA,SAAQ,YAAR,GAAQ,UAAY;AACpB,cAAA,QAAQ,QAAQ,aAAa;AAAA,IACrC;AAEM,WAAA,IAAI,QAAQ,CAAC,YAAW;AAC9B,iCAA2B,KAAK,cAAc;AAG9C,WAAK,eAAe,MACnB,SACA,CAAC,eAAsB;AACtB,YAAI,YAAY;AAEP,kBAAA,KACP,6CACA,UAAU;AAAA,QAEX;;OAGD;AAAA,IAAA,CAEF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAkC;AACnC,WAAA,IAAI,QAAQ,CAAC,YAAW;AAC9B,iCAA2B,KAAK,cAAc;AAE9C,YAAM,UAAU;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK;AAAA,QAClB,cAAc;AAAA,UACb,UAAU;AAAA,YACT,WAAW,KAAK;AAAA,UAChB;AAAA,QACD;AAAA,MAAA;AAEF,WAAK,UAAU,KAAK;AAGpB,WAAK,eAAe,SAAS,SAAS,CAAC,eAAsB;AAC5D,YAAI,YAAY;AAEP,kBAAA,KAAK,6CAA6C,UAAU;AAAA,QACpE;;OAGD;AAAA,IAAA,CACD;AAAA,EACF;AAAA,EAEA,MAAM,0BAAuB;AACxB,QAAA;AACA,QAAA;AACI,aAAA,MAAM,KAAK,QAAQ;YACzB;AACM,aAAA,MAAM,KAAK,QAAQ;IAC1B;AAEM,WAAAC,wBAAc,IAAI,EAAE,cAAc;AAAA,EAC1C;AACA;;"}
1
+ {"version":3,"file":"TelemetryManager.cjs","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\trepositoryName: string;\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tgroup(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tconst { repositoryName, ...traits } = args;\n\n\t\tconst payload: {\n\t\t\tgroupId: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext>;\n\t\t} = {\n\t\t\tgroupId: repositoryName,\n\t\t\ttraits,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":["BaseManager","API_TOKENS","randomUUID","HumanSegmentEventType","readPrismicrc"],"mappings":"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"}
@@ -1,17 +1,30 @@
1
1
  import { BaseManager } from "../BaseManager";
2
2
  import { SegmentEvents } from "./types";
3
+ type TelemetryManagerInitTelemetryArgs = {
4
+ appName: string;
5
+ appVersion: string;
6
+ };
3
7
  type TelemetryManagerTrackArgs = SegmentEvents;
4
8
  type TelemetryManagerIdentifyArgs = {
5
9
  userID: string;
6
10
  intercomHash: string;
7
11
  };
12
+ type TelemetryManagerGroupArgs = {
13
+ repositoryName: string;
14
+ manualLibsCount: number;
15
+ downloadedLibsCount: number;
16
+ npmLibsCount: number;
17
+ downloadedLibs: string[];
18
+ };
8
19
  export declare class TelemetryManager extends BaseManager {
9
20
  private _segmentClient;
10
21
  private _anonymousID;
11
22
  private _userID;
12
- initTelemetry(): Promise<void>;
23
+ private _context;
24
+ initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void>;
13
25
  track(args: TelemetryManagerTrackArgs): Promise<void>;
14
26
  identify(args: TelemetryManagerIdentifyArgs): Promise<void>;
27
+ group(args: TelemetryManagerGroupArgs): Promise<void>;
15
28
  checkIsTelemetryEnabled(): Promise<boolean>;
16
29
  }
17
30
  export {};
@@ -21,8 +21,9 @@ class TelemetryManager extends BaseManager {
21
21
  __publicField(this, "_segmentClient");
22
22
  __publicField(this, "_anonymousID");
23
23
  __publicField(this, "_userID");
24
+ __publicField(this, "_context");
24
25
  }
25
- async initTelemetry() {
26
+ async initTelemetry(args) {
26
27
  if (this._segmentClient) {
27
28
  return;
28
29
  }
@@ -35,6 +36,7 @@ class TelemetryManager extends BaseManager {
35
36
  }
36
37
  });
37
38
  this._anonymousID = randomUUID();
39
+ this._context = { app: { name: args.appName, version: args.appVersion } };
38
40
  }
39
41
  // TODO: Should `userId` be automatically populated by the logged in
40
42
  // user? We already have their info via UserRepository.
@@ -44,9 +46,11 @@ class TelemetryManager extends BaseManager {
44
46
  const payload = {
45
47
  event: HumanSegmentEventType[event],
46
48
  properties: {
49
+ nodeVersion: process.versions.node,
47
50
  repo: repository,
48
51
  ...properties
49
- }
52
+ },
53
+ context: { ...this._context }
50
54
  };
51
55
  if (this._userID) {
52
56
  payload.userId = this._userID;
@@ -72,18 +76,19 @@ class TelemetryManager extends BaseManager {
72
76
  // by the logged in user? We already have their info via
73
77
  // UserRepository.
74
78
  identify(args) {
79
+ const payload = {
80
+ userId: args.userID,
81
+ anonymousId: this._anonymousID,
82
+ integrations: {
83
+ Intercom: {
84
+ user_hash: args.intercomHash
85
+ }
86
+ },
87
+ context: { ...this._context }
88
+ };
89
+ this._userID = args.userID;
75
90
  return new Promise((resolve) => {
76
91
  assertTelemetryInitialized(this._segmentClient);
77
- const payload = {
78
- userId: args.userID,
79
- anonymousId: this._anonymousID,
80
- integrations: {
81
- Intercom: {
82
- user_hash: args.intercomHash
83
- }
84
- }
85
- };
86
- this._userID = args.userID;
87
92
  this._segmentClient.identify(payload, (maybeError) => {
88
93
  if (maybeError) {
89
94
  console.warn(`An error occurred during Segment identify`, maybeError);
@@ -92,6 +97,28 @@ class TelemetryManager extends BaseManager {
92
97
  });
93
98
  });
94
99
  }
100
+ group(args) {
101
+ const { repositoryName, ...traits } = args;
102
+ const payload = {
103
+ groupId: repositoryName,
104
+ traits,
105
+ context: { ...this._context }
106
+ };
107
+ if (this._userID) {
108
+ payload.userId = this._userID;
109
+ } else {
110
+ payload.anonymousId = this._anonymousID;
111
+ }
112
+ return new Promise((resolve) => {
113
+ assertTelemetryInitialized(this._segmentClient);
114
+ this._segmentClient.group(payload, (maybeError) => {
115
+ if (maybeError) {
116
+ console.warn(`An error occurred during Segment group`, maybeError);
117
+ }
118
+ resolve();
119
+ });
120
+ });
121
+ }
95
122
  async checkIsTelemetryEnabled() {
96
123
  let root;
97
124
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"TelemetryManager.js","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\n\tasync initTelemetry(): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tconst payload = {\n\t\t\t\tuserId: args.userID,\n\t\t\t\tanonymousId: this._anonymousID,\n\t\t\t\tintegrations: {\n\t\t\t\t\tIntercom: {\n\t\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t\tthis._userID = args.userID;\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AAuBA,SAAS,2BACR,eAAwC;AAExC,MAAI,iBAAiB,QAAW;AACzB,UAAA,IAAI,MACT,kIAAkI;AAAA,EAEnI;AACF;AAEM,MAAO,yBAAyB,YAAW;AAAA,EAA3C;AAAA;AACG;AACA;AACA;AAAA;AAAA,EAER,MAAM,gBAAa;AAClB,QAAI,KAAK,gBAAgB;AAExB;AAAA,IACA;AAED,SAAK,iBAAiB,IAAI,cAAc,WAAW,YAAY;AAAA;AAAA,MAE9D,SAAS;AAAA;AAAA,MAET,QAAQ,MAAM,KAAK,wBAAyB;AAAA,MAC5C,cAAc,MAAK;AAAA,MAKnB;AAAA,IAAA,CACA;AACD,SAAK,eAAe;EACrB;AAAA;AAAA;AAAA,EAIA,MAAM,MAA+B;;AACpC,UAAM,EAAE,OAAO,YAAY,GAAG,eAAe;AAE7C,UAAM,UAUF;AAAA,MACH,OAAO,sBAAsB,KAAK;AAAA,MAClC,YAAY;AAAA,QACX,MAAM;AAAA,QACN,GAAG;AAAA,MACH;AAAA,IAAA;AAGF,QAAI,KAAK,SAAS;AACjB,cAAQ,SAAS,KAAK;AAAA,IAAA,OAChB;AACN,cAAQ,cAAc,KAAK;AAAA,IAC3B;AAED,QAAI,KAAK,YAAY;AACpB,cAAQ,YAAR,QAAQ,UAAY;AACZ,oBAAA,SAAQ,YAAR,GAAQ,UAAY;AACpB,cAAA,QAAQ,QAAQ,aAAa;AAAA,IACrC;AAEM,WAAA,IAAI,QAAQ,CAAC,YAAW;AAC9B,iCAA2B,KAAK,cAAc;AAG9C,WAAK,eAAe,MACnB,SACA,CAAC,eAAsB;AACtB,YAAI,YAAY;AAEP,kBAAA,KACP,6CACA,UAAU;AAAA,QAEX;;OAGD;AAAA,IAAA,CAEF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,MAAkC;AACnC,WAAA,IAAI,QAAQ,CAAC,YAAW;AAC9B,iCAA2B,KAAK,cAAc;AAE9C,YAAM,UAAU;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK;AAAA,QAClB,cAAc;AAAA,UACb,UAAU;AAAA,YACT,WAAW,KAAK;AAAA,UAChB;AAAA,QACD;AAAA,MAAA;AAEF,WAAK,UAAU,KAAK;AAGpB,WAAK,eAAe,SAAS,SAAS,CAAC,eAAsB;AAC5D,YAAI,YAAY;AAEP,kBAAA,KAAK,6CAA6C,UAAU;AAAA,QACpE;;OAGD;AAAA,IAAA,CACD;AAAA,EACF;AAAA,EAEA,MAAM,0BAAuB;AACxB,QAAA;AACA,QAAA;AACI,aAAA,MAAM,KAAK,QAAQ;YACzB;AACM,aAAA,MAAM,KAAK,QAAQ;IAC1B;AAEM,WAAA,cAAc,IAAI,EAAE,cAAc;AAAA,EAC1C;AACA;"}
1
+ {"version":3,"file":"TelemetryManager.js","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\trepositoryName: string;\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tgroup(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tconst { repositoryName, ...traits } = args;\n\n\t\tconst payload: {\n\t\t\tgroupId: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext>;\n\t\t} = {\n\t\t\tgroupId: repositoryName,\n\t\t\ttraits,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":[],"mappings":"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"}