@elek-io/core 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/service/AssetService.ts","../src/error/RequiredParameterMissingError.ts","../src/util/index.ts","../src/service/AbstractCrudService.ts","../src/service/GitService.ts","../src/error/GitError.ts","../src/error/NoCurrentUserError.ts","../src/service/GitTagService.ts","../src/service/UserService.ts","../src/service/JsonFileService.ts","../src/service/CollectionService.ts","../src/service/EntryService.ts","../src/service/ValueService.ts","../src/service/ProjectService.ts","../src/error/ProjectUpgradeError.ts","../src/service/SearchService.ts"],"sourcesContent":["import {\n constructorElekIoCoreSchema,\n type ConstructorElekIoCoreProps,\n type ElekIoCoreOptions,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport AssetService from './service/AssetService.js';\nimport CollectionService from './service/CollectionService.js';\nimport EntryService from './service/EntryService.js';\nimport GitService from './service/GitService.js';\nimport JsonFileService from './service/JsonFileService.js';\nimport ProjectService from './service/ProjectService.js';\nimport SearchService from './service/SearchService.js';\nimport UserService from './service/UserService.js';\nimport ValueService from './service/ValueService.js';\nimport * as CoreUtil from './util/index.js';\n\n/**\n * elek.io Core\n *\n * Provides access to all services Core is offering\n */\nexport default class ElekIoCore {\n private readonly options: ElekIoCoreOptions;\n private readonly userService: UserService;\n private readonly gitService: GitService;\n private readonly jsonFileService: JsonFileService;\n private readonly assetService: AssetService;\n private readonly searchService: SearchService;\n private readonly projectService: ProjectService;\n private readonly collectionService: CollectionService;\n private readonly entryService: EntryService;\n private readonly valueService: ValueService;\n\n constructor(props?: ConstructorElekIoCoreProps) {\n const parsedProps = constructorElekIoCoreSchema.parse(props);\n\n const defaults: ElekIoCoreOptions = {\n environment: 'production',\n version: '0.0.0',\n file: {\n json: {\n indentation: 2,\n },\n },\n };\n this.options = Object.assign({}, defaults, parsedProps);\n\n this.jsonFileService = new JsonFileService(this.options);\n this.userService = new UserService(this.jsonFileService);\n this.gitService = new GitService(this.options, this.userService);\n // this.gitService.getVersion(); // @todo currently throws an \"Error: Unable to find path to repository on disk.\"\n this.assetService = new AssetService(\n this.options,\n this.jsonFileService,\n this.gitService\n );\n this.valueService = new ValueService(\n this.options,\n this.jsonFileService,\n this.gitService,\n this.assetService\n );\n this.collectionService = new CollectionService(\n this.options,\n this.jsonFileService,\n this.gitService\n );\n this.entryService = new EntryService(\n this.options,\n this.jsonFileService,\n this.gitService,\n this.collectionService,\n this.valueService\n );\n this.searchService = new SearchService(\n this.options,\n this.assetService,\n this.collectionService\n );\n this.projectService = new ProjectService(\n this.options,\n this.jsonFileService,\n this.userService,\n this.gitService,\n this.searchService,\n this.assetService,\n this.collectionService,\n this.entryService,\n this.valueService\n );\n\n if (this.options.environment !== 'production') {\n console.info(\n `Initializing inside an \"${this.options.environment}\" environment`,\n {\n ...this.options,\n }\n );\n }\n\n Fs.mkdirpSync(CoreUtil.pathTo.projects);\n Fs.mkdirpSync(CoreUtil.pathTo.tmp);\n Fs.emptyDirSync(CoreUtil.pathTo.tmp);\n }\n\n /**\n * Utility / helper functions\n */\n public get util() {\n return CoreUtil;\n }\n\n /**\n *\n */\n public get user(): UserService {\n return this.userService;\n }\n\n /**\n * CRUD methods to work with Projects\n */\n public get projects(): ProjectService {\n return this.projectService;\n }\n\n /**\n * CRUD methods to work with Assets\n */\n public get assets(): AssetService {\n return this.assetService;\n }\n\n /**\n * CRUD methods to work with Collections\n */\n public get collections(): CollectionService {\n return this.collectionService;\n }\n\n /**\n * CRUD methods to work with Entries\n */\n public get entries(): EntryService {\n return this.entryService;\n }\n\n /**\n * CRUD methods to work with Values\n */\n public get values(): ValueService {\n return this.valueService;\n }\n}\n","import {\n assetFileSchema,\n assetSchema,\n countAssetsSchema,\n createAssetSchema,\n currentTimestamp,\n deleteAssetSchema,\n fileTypeSchema,\n listAssetsSchema,\n readAssetSchema,\n serviceTypeSchema,\n supportedExtensionSchema,\n supportedFileTypeSchema,\n supportedMimeTypeSchema,\n updateAssetSchema,\n uuid,\n type Asset,\n type AssetFile,\n type BaseFile,\n type CountAssetsProps,\n type CreateAssetProps,\n type DeleteAssetProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListAssetsProps,\n type PaginatedList,\n type ReadAssetProps,\n type UpdateAssetProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport IsSvg from 'is-svg';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport default class AssetService\n extends AbstractCrudService\n implements ExtendedCrudService<Asset>\n{\n private readonly jsonFileService: JsonFileService;\n private readonly gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.Enum.Asset, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new Asset\n */\n public async create(props: CreateAssetProps): Promise<Asset> {\n createAssetSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const fileType = await this.getSupportedFileTypeOrThrow(props.filePath);\n const size = await this.getAssetSize(props.filePath);\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n id,\n props.language,\n fileType.extension\n );\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n id,\n props.language\n );\n\n const assetFile: AssetFile = {\n ...props,\n fileType: 'asset',\n id,\n created: currentTimestamp(),\n extension: fileType.extension,\n mimeType: fileType.mimeType,\n size,\n };\n\n try {\n await Fs.copyFile(props.filePath, assetPath);\n await this.jsonFileService.create(\n assetFile,\n assetFilePath,\n assetFileSchema\n );\n } catch (error) {\n // To avoid partial data being added to the repository / git status reporting uncommitted files\n await this.delete({ ...assetFile, projectId: props.projectId });\n throw error;\n }\n\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Returns an Asset by ID and language\n */\n public async read(props: ReadAssetProps): Promise<Asset> {\n readAssetSchema.parse(props);\n\n const assetFile = await this.jsonFileService.read(\n CoreUtil.pathTo.assetFile(props.projectId, props.id, props.language),\n assetFileSchema\n );\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Updates given Asset\n *\n * Use the optional \"newFilePath\" prop to update the Asset itself\n */\n public async update(props: UpdateAssetProps): Promise<Asset> {\n updateAssetSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n props.id,\n props.language\n );\n const prevAssetFile = await this.read(props);\n\n // Overwrite old data with new\n // It's ok to have projectId inside props, since the prevAssetFile is read with the same data\n const assetFile: AssetFile = {\n ...prevAssetFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n if (props.newFilePath) {\n // Overwrite the file itself (in LFS folder)...\n\n const fileType = await this.getSupportedFileTypeOrThrow(\n props.newFilePath\n );\n const size = await this.getAssetSize(props.newFilePath);\n const prevAssetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n prevAssetFile.extension\n );\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n fileType.extension\n );\n\n // @todo use try catch to handle FS error and restore previous state\n await Fs.remove(prevAssetPath); // Need to explicitly remove old Asset, because it could have a different extension\n await Fs.copyFile(props.newFilePath, assetPath);\n\n // ...and update meta information\n assetFile.extension = fileType.extension;\n assetFile.mimeType = fileType.mimeType;\n assetFile.size = size;\n }\n\n await this.jsonFileService.update(\n assetFile,\n assetFilePath,\n assetFileSchema\n );\n await this.gitService.add(projectPath, [assetFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Deletes given Asset\n */\n public async delete(props: DeleteAssetProps): Promise<void> {\n deleteAssetSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n props.id,\n props.language\n );\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n props.extension\n );\n await Fs.remove(assetPath);\n await Fs.remove(assetFilePath);\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(props: ListAssetsProps): Promise<PaginatedList<Asset>> {\n listAssetsSchema.parse(props);\n\n const assetReferences = await this.listReferences(\n fileTypeSchema.Enum.asset,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n assetReferences.map((assetReference) => {\n if (!assetReference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n id: assetReference.id,\n language: assetReference.language,\n });\n })\n );\n\n const paginatedResult = this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n\n return paginatedResult;\n }\n\n public async count(props: CountAssetsProps): Promise<number> {\n countAssetsSchema.parse(props);\n\n const count = (\n await this.listReferences(fileTypeSchema.Enum.asset, props.projectId)\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is of type Asset\n */\n public isAsset(obj: BaseFile | unknown): obj is Asset {\n return assetSchema.safeParse(obj).success;\n }\n\n /**\n * Returns the size of an Asset in bytes\n *\n * @param path Path of the Asset to get the size from\n */\n private async getAssetSize(path: string) {\n return (await Fs.stat(path)).size;\n }\n\n /**\n * Creates an Asset from given AssetFile\n *\n * @param projectId The project's ID\n * @param assetFile The AssetFile to convert\n */\n private async toAsset(\n projectId: string,\n assetFile: AssetFile\n ): Promise<Asset> {\n const assetPath = CoreUtil.pathTo.asset(\n projectId,\n assetFile.id,\n assetFile.language,\n assetFile.extension\n );\n\n const asset: Asset = {\n ...assetFile,\n absolutePath: assetPath,\n };\n\n return asset;\n }\n\n /**\n * Returns the found and supported extension as well as mime type,\n * otherwise throws an error\n *\n * @param filePath Path to the file to check\n */\n private async getSupportedFileTypeOrThrow(filePath: string) {\n const fileSize = (await Fs.stat(filePath)).size;\n\n // Only try to parse potential SVG's\n // that are smaller than 500 kB\n if (fileSize / 1000 <= 500) {\n const fileBuffer = await Fs.readFile(filePath);\n if (IsSvg(fileBuffer.toString()) === true) {\n return {\n extension: supportedExtensionSchema.Enum.svg,\n mimeType: supportedMimeTypeSchema.Enum['image/svg+xml'],\n };\n }\n }\n\n // We do not use fileBuffer here again because fromFile() is recommended\n const { fileTypeFromFile } = await import('file-type');\n const fileType = await fileTypeFromFile(filePath);\n\n const result = supportedFileTypeSchema.parse({\n extension: fileType?.ext,\n mimeType: fileType?.mime,\n });\n\n return result;\n }\n}\n","export default class RequiredParameterMissingError extends Error {\n constructor(parameter: string) {\n super(`Missing required parameter \"${parameter}\"`);\n\n this.name = 'RequiredParameterMissingError';\n }\n}\n","import { projectFolderSchema, uuidSchema } from '@elek-io/shared';\nimport { spawn, type SpawnOptionsWithoutStdio } from 'child_process';\nimport Fs from 'fs-extra';\nimport { filter, flatten, groupBy, uniq } from 'lodash-es';\nimport Os from 'os';\nimport Path from 'path';\n\n/**\n * The directory in which everything is stored and will be worked in\n *\n * @todo make the workingDirectory an elek option to be set via app.getPath('home') (electron instead of node)?\n */\nexport const workingDirectory = Path.join(Os.homedir(), 'elek.io');\n\n/**\n * A collection of often used paths\n */\nexport const pathTo = {\n tmp: Path.join(workingDirectory, 'tmp'),\n userFile: Path.join(workingDirectory, 'user.json'),\n // logs: Path.join(workingDirectory, 'logs'),\n\n projects: Path.join(workingDirectory, 'projects'),\n project: (projectId: string): string => {\n return Path.join(pathTo.projects, projectId);\n },\n projectFile: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), 'project.json');\n },\n // projectLogs: (projectId: string): string => {\n // return Path.join(pathTo.project(projectId), projectFolderSchema.Enum.logs);\n // },\n\n // public: (projectId: string): string => {\n // return Path.join(pathTo.project(projectId), 'public');\n // },\n\n lfs: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), projectFolderSchema.Enum.lfs);\n },\n\n collections: (projectId: string): string => {\n return Path.join(\n pathTo.project(projectId),\n projectFolderSchema.Enum.collections\n );\n },\n collection: (projectId: string, id: string) => {\n return Path.join(pathTo.collections(projectId), id);\n },\n collectionFile: (projectId: string, id: string) => {\n return Path.join(pathTo.collection(projectId, id), 'collection.json');\n },\n\n entries: (projectId: string, collectionId: string): string => {\n return Path.join(pathTo.collection(projectId, collectionId));\n },\n entryFile: (\n projectId: string,\n collectionId: string,\n id: string,\n language: string\n ) => {\n return Path.join(\n pathTo.entries(projectId, collectionId),\n `${id}.${language}.json`\n );\n },\n\n values: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), 'values');\n },\n valueFile: (projectId: string, id: string, language: string) => {\n return Path.join(pathTo.values(projectId), `${id}.${language}.json`);\n },\n\n assets: (projectId: string): string => {\n return Path.join(\n pathTo.project(projectId),\n projectFolderSchema.Enum.assets\n );\n },\n assetFile: (projectId: string, id: string, language: string): string => {\n return Path.join(pathTo.assets(projectId), `${id}.${language}.json`);\n },\n asset: (\n projectId: string,\n id: string,\n language: string,\n extension: string\n ): string => {\n return Path.join(pathTo.lfs(projectId), `${id}.${language}.${extension}`);\n },\n};\n\n/**\n * Searches for a potential project ID in given path string and returns it\n *\n * Mainly used for logging inside the GitService, where we don't have a project ID,\n * but always have a path which could contain one. The ID is then used,\n * to log to the current project log, instead of logging to the main log file.\n *\n * @todo I really dont like this and I do not know how much performance we loose here\n */\nexport const fromPath = {\n projectId: (path: string): string | undefined => {\n const startsWith = 'projects/';\n const endsWith = '/';\n const start = path.indexOf(startsWith) + startsWith.length;\n // Return early\n if (start === -1) {\n return undefined;\n }\n const end = path.indexOf(endsWith, start);\n // Use path length if there is no ending \"/\"\n const result = path.substring(start, end === -1 ? path.length : end);\n if (result && uuidSchema.safeParse(result).success) {\n return result;\n }\n return undefined;\n },\n};\n\n/**\n * Returns a complete default type, hydrated with the partials of value\n */\nexport function assignDefaultIfMissing<T extends {}>(\n value: Partial<T> | undefined | null,\n defaultsTo: T\n): T {\n return Object.assign(defaultsTo, value);\n}\n\n/**\n * Used as parameter for filter() methods to assure,\n * only values not null, undefined or empty strings are returned\n *\n * @param value Value to check\n */\nexport function notEmpty<T>(value: T | null | undefined): value is T {\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === 'string') {\n if (value.trim() === '') {\n return false;\n }\n }\n return true;\n}\n\nexport function isNoError<T>(item: T | Error): item is T {\n return item instanceof Error !== true;\n}\n\n/**\n * Basically a Promise.all() without rejecting if one promise fails to resolve\n */\nexport async function returnResolved<T>(promises: Promise<T>[]) {\n const toCheck: Promise<T | Error>[] = [];\n for (let index = 0; index < promises.length; index++) {\n const promise = promises[index];\n if (!promise) {\n throw new Error(`No promise found at index \"${index}\"`);\n }\n // Here comes the trick:\n // By using \"then\" and \"catch\" we are able to create an array of Project and Error types\n // without throwing and stopping the later Promise.all() call prematurely\n toCheck.push(\n promise\n .then((result) => {\n return result;\n })\n .catch((error) => {\n // Because the error parameter could be anything,\n // we need to specifically call an Error\n return new Error(error);\n })\n );\n }\n // Resolve all promises\n // Here we do not expect any error to fail the call to Promise.all()\n // because we caught it earlier and returning an Error type instead of throwing it\n const checked = await Promise.all(toCheck);\n // This way we can easily filter out any Errors by type\n // Note that we also need to use a User-Defined Type Guard here,\n // because otherwise TS does not recognize we are filtering the errors out\n // > | <\n return checked.filter(isNoError);\n}\n\n/**\n * Custom async typescript ready implementation of Node.js child_process\n *\n * @see https://nodejs.org/api/child_process.html\n * @see https://github.com/ralphtheninja/await-spawn\n */\nexport function spawnChildProcess(\n command: string,\n args: ReadonlyArray<string>,\n options?: SpawnOptionsWithoutStdio\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const childProcess = spawn(command, args, options);\n let log = '';\n\n childProcess.stdout.on('data', (data) => {\n log += data;\n });\n\n childProcess.stderr.on('data', (data) => {\n log += data;\n });\n\n childProcess.on('error', (error) => {\n throw error;\n });\n\n childProcess.on('exit', (code) => {\n if (code === 0) {\n return resolve(log);\n }\n return reject(log);\n });\n });\n}\n\n/**\n * Returns all folders of given path\n */\nexport async function folders(path: string): Promise<Fs.Dirent[]> {\n const dirent = await Fs.readdir(path, { withFileTypes: true });\n return dirent.filter((dirent) => {\n return dirent.isDirectory();\n });\n}\n\n/**\n * Returns all files of given path which can be filtered by extension\n */\nexport async function files(\n path: string,\n extension?: string\n): Promise<Fs.Dirent[]> {\n const dirent = await Fs.readdir(path, { withFileTypes: true });\n return dirent.filter((dirent) => {\n if (extension && dirent.isFile() === true) {\n if (dirent.name.endsWith(extension)) {\n return true;\n }\n return false;\n }\n return dirent.isFile();\n });\n}\n\n/**\n * Returns the relative path for given path\n * by stripping out everything up to the working directory\n */\nexport function getRelativePath(path: string): string {\n let relativePath = path.replace(workingDirectory, '');\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substr(1);\n }\n return relativePath;\n}\n\n/**\n * Searches given array of objects for duplicates of given key and returns them\n *\n * @param arr Array with possible duplicate values\n * @param key Key of object T to get duplicates of\n */\nexport function getDuplicates<T>(arr: T[], key: keyof T) {\n const grouped = groupBy(arr, (item) => {\n return item[key];\n });\n return uniq(\n flatten(\n filter(grouped, (item) => {\n return item.length > 1;\n })\n )\n );\n}\n","import {\n fileReferenceSchema,\n fileTypeSchema,\n gitCommitIconSchema,\n type BaseFile,\n type ElekIoCoreOptions,\n type FileReference,\n type FileType,\n type GitTag,\n type PaginatedList,\n type ServiceType,\n type Sort,\n type SupportedExtension,\n type SupportedLanguage,\n} from '@elek-io/shared';\nimport { orderBy, remove } from 'lodash-es';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\n\n/**\n * A base service that provides properties for most other services\n */\nexport default abstract class AbstractCrudService {\n public readonly type: ServiceType;\n public readonly options: ElekIoCoreOptions;\n\n /**\n * Dynamically generated git messages for operations\n */\n public readonly gitMessage: {\n create: string;\n update: string;\n delete: string;\n };\n\n /**\n * Do not instantiate directly as this is an abstract class\n */\n protected constructor(type: ServiceType, options: ElekIoCoreOptions) {\n this.type = type;\n this.options = options;\n this.gitMessage = {\n create: `${gitCommitIconSchema.enum.CREATE} Created ${this.type}`,\n update: `${gitCommitIconSchema.enum.UPDATE} Updated ${this.type}`,\n delete: `${gitCommitIconSchema.enum.DELETE} Deleted ${this.type}`,\n };\n }\n\n /**\n * Returns the filtered, sorted and paginated version of given list\n *\n * @todo Sorting and filtering requires all models to be loaded\n * from disk. This results in a huge memory spike before the\n * filtering and pagination takes effect - removing most of it again.\n * This approach is still better than returning everything and\n * letting the frontend handle it, since the memory usage would then be constant.\n * But this still could fill the memory limit of node.js (default 1,4 GB).\n *\n * @param list Array to filter, sort and paginate\n * @param sort Array of sort objects containing information about what to sort and how\n * @param filter Filter all object values of `list` by this string\n * @param limit Limit the result to this amount. If 0 is given, no limit is applied\n * @param offset Start at this index instead of 0\n */\n protected async paginate<T extends BaseFile | GitTag>(\n list: T[],\n sort: Sort<T>[] = [],\n filter = '',\n limit = 15,\n offset = 0\n ): Promise<PaginatedList<T>> {\n let result = list;\n const total = list.length;\n const normalizedFilter = filter.trim().toLowerCase();\n\n // Filter\n if (normalizedFilter !== '') {\n remove(result, (model) => {\n let key: keyof T;\n for (key in model) {\n const value = model[key];\n if (String(value).toLowerCase().includes(normalizedFilter)) {\n return false;\n }\n }\n return true;\n });\n }\n\n // Sort\n if (sort.length !== 0) {\n const keys = sort.map((value) => value.by);\n const orders = sort.map((value) => value.order);\n result = orderBy(result, keys, orders);\n }\n\n // Paginate\n if (limit !== 0) {\n result = result.slice(offset, offset + limit);\n }\n\n return {\n total,\n limit,\n offset,\n list: result,\n };\n }\n\n /**\n * Returns a list of all file references of given project and type\n *\n * @param type File type of the references wanted\n * @param projectId Project to get all asset references from\n * @param collectionId Only needed when requesting files of type \"Entry\"\n */\n protected async listReferences(\n type: FileType,\n projectId?: string,\n collectionId?: string\n ): Promise<FileReference[]> {\n switch (type) {\n case fileTypeSchema.Enum.asset:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(CoreUtil.pathTo.lfs(projectId)); // LFS folder is correct, since we want the extension of the file itself, not the AssetFile (.json)\n\n case fileTypeSchema.Enum.project:\n return this.getFolderReferences(CoreUtil.pathTo.projects);\n\n case fileTypeSchema.Enum.collection:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFolderReferences(CoreUtil.pathTo.collections(projectId));\n\n case fileTypeSchema.Enum.entry:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n if (!collectionId) {\n throw new RequiredParameterMissingError('collectionId');\n }\n return this.getFileReferences(\n CoreUtil.pathTo.collection(projectId, collectionId)\n );\n\n case fileTypeSchema.Enum.value:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(CoreUtil.pathTo.values(projectId));\n\n default:\n throw new Error(`Trying to list files of unsupported type \"${type}\"`);\n }\n }\n\n private async getFolderReferences(path: string): Promise<FileReference[]> {\n const possibleFolders = await CoreUtil.folders(path);\n const results = possibleFolders.map((possibleFolder) => {\n const folderReference: FileReference = {\n id: possibleFolder.name,\n };\n\n try {\n return fileReferenceSchema.parse(folderReference);\n } catch (error) {\n return null;\n }\n });\n\n return results.filter(CoreUtil.notEmpty);\n }\n\n /**\n * Searches for all files inside given folder,\n * parses their names and returns them as FileReference\n *\n * Ignores files not matching the [id].[language].[extension]\n * or [id].[extension] format for their names\n */\n private async getFileReferences(path: string): Promise<FileReference[]> {\n const possibleFiles = await CoreUtil.files(path);\n\n const results = await Promise.all(\n possibleFiles.map(async (possibleFile) => {\n const fileNameArray = possibleFile.name.split('.');\n\n const fileReference: FileReference = {\n id: fileNameArray[0],\n language:\n fileNameArray.length === 3\n ? (fileNameArray[1] as SupportedLanguage)\n : undefined,\n extension:\n fileNameArray.length === 2\n ? (fileNameArray[1] as SupportedExtension)\n : (fileNameArray[2] as SupportedExtension),\n };\n\n try {\n return fileReferenceSchema.parse(fileReference);\n } catch (error) {\n return null;\n }\n })\n );\n\n return results.filter(CoreUtil.notEmpty);\n }\n}\n","import {\n gitCommitSchema,\n uuidSchema,\n type ElekIoCoreOptions,\n type GitCloneOptions,\n type GitCommit,\n type GitInitOptions,\n type GitLogOptions,\n type GitSwitchOptions,\n} from '@elek-io/shared';\nimport { GitProcess, type IGitResult } from 'dugite';\nimport PQueue from 'p-queue';\nimport GitError from '../error/GitError.js';\nimport NoCurrentUserError from '../error/NoCurrentUserError.js';\nimport GitTagService from './GitTagService.js';\nimport UserService from './UserService.js';\n\n/**\n * Service that manages Git functionality\n *\n * Uses dugite Node.js bindings for Git to be fully compatible\n * and be able to leverage Git LFS functionality\n * @see https://github.com/desktop/dugite\n *\n * Heavily inspired by the GitHub Desktop app\n * @see https://github.com/desktop/desktop\n *\n * Git operations are sequential!\n * We use a FIFO queue to translate async calls\n * into a sequence of git operations\n */\nexport default class GitService {\n private version: string | undefined;\n private queue: PQueue;\n private gitTagService: GitTagService;\n private userService: UserService;\n\n public constructor(options: ElekIoCoreOptions, userService: UserService) {\n this.version = undefined;\n this.queue = new PQueue({\n concurrency: 1, // No concurrency because git operations are sequencial\n });\n this.gitTagService = new GitTagService(options, this.git);\n this.userService = userService;\n }\n\n /**\n * CRUD methods to work with git tags\n */\n public get tags(): GitTagService {\n return this.gitTagService;\n }\n\n /**\n * Reads the currently used version of Git\n */\n public async getVersion(): Promise<void> {\n const result = await this.git('', ['--version']);\n this.version = result.stdout.replace('git version', '').trim();\n }\n\n /**\n * Create an empty Git repository or reinitialize an existing one\n *\n * @see https://git-scm.com/docs/git-init\n *\n * @param path Path to initialize in. Fails if path does not exist\n * @param options Options specific to the init operation\n */\n public async init(\n path: string,\n options?: Partial<GitInitOptions>\n ): Promise<void> {\n let args = ['init'];\n\n if (options?.initialBranch) {\n args = [...args, `--initial-branch=${options.initialBranch}`];\n }\n\n await this.git(path, args);\n await this.setLocalConfig(path);\n await this.installLfs(path);\n }\n\n /**\n * Clone a repository into a directory\n *\n * @see https://git-scm.com/docs/git-clone\n *\n * @todo Implement progress callback / events\n *\n * @param url The remote repository URL to clone from\n * @param path The destination path for the cloned repository.\n * Which is only working if the directory is existing and empty.\n * @param options Options specific to the clone operation\n */\n public async clone(\n url: string,\n path: string,\n options?: Partial<GitCloneOptions>\n ): Promise<void> {\n let args = ['clone', '--progress'];\n\n if (options?.branch) {\n args = [...args, '--branch', options.branch];\n }\n\n if (options?.depth) {\n args = [...args, '--depth', options.depth.toString()];\n }\n\n if (options?.singleBranch === true) {\n args = [...args, '--single-branch'];\n }\n\n await this.git(path, [...args, url, '.']);\n await this.setLocalConfig(path);\n }\n\n /**\n * Add file contents to the index\n *\n * @see https://git-scm.com/docs/git-add\n *\n * @param path Path to the repository\n * @param files Files to add\n */\n public async add(path: string, files: string[]): Promise<void> {\n const args = ['add', '--', ...files];\n\n await this.git(path, args);\n }\n\n /**\n * Switch branches\n *\n * @see https://git-scm.com/docs/git-switch/\n *\n * @param path Path to the repository\n * @param name Name of the branch to switch to\n * @param options Options specific to the switch operation\n */\n public async switch(\n path: string,\n name: string,\n options?: Partial<GitSwitchOptions>\n ): Promise<void> {\n await this.checkBranchOrTagName(path, name);\n\n let args = ['switch'];\n\n if (options?.isNew === true) {\n args = [...args, '--create', name];\n } else {\n args = [...args, name];\n }\n\n await this.git(path, args);\n }\n\n /**\n * Reset current HEAD to the specified state\n *\n * @todo maybe add more options\n * @see https://git-scm.com/docs/git-reset\n *\n * @param path Path to the repository\n * @param mode Modifies the working tree depending on given mode\n * @param commit Resets the current branch head to this commit / tag\n */\n public async reset(path: string, mode: 'soft' | 'hard', commit: string) {\n const args = ['reset', `--${mode}`, commit];\n await this.git(path, args);\n }\n\n /**\n * Restore working tree files\n *\n * @see https://git-scm.com/docs/git-restore/\n *\n * @todo It's probably a good idea to not use restore\n * for a use case where someone just wants to have a look\n * and maybe copy something from a deleted file.\n * We should use `checkout` without `add .` and `commit` for that\n *\n * @param path Path to the repository\n * @param source Git commit SHA or tag name to restore to\n * @param files Files to restore\n */\n // public async restore(\n // path: string,\n // source: string,\n // files: string[]\n // ): Promise<void> {\n // const args = ['restore', `--source=${source}`, ...files];\n // await this.git(path, args);\n // }\n\n /**\n * Fetch from and integrate with another repository or a local branch\n *\n * @see https://git-scm.com/docs/git-pull\n *\n * @param path Path to the repository\n */\n public async pull(path: string): Promise<void> {\n const args = ['pull'];\n await this.git(path, args);\n }\n\n /**\n * Record changes to the repository\n *\n * @see https://git-scm.com/docs/git-commit\n *\n * @param path Path to the repository\n * @param message A message that describes the changes\n */\n public async commit(path: string, message: string): Promise<void> {\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const args = [\n 'commit',\n `--message=${message}`,\n `--author=${user.name} <${user.email}>`,\n ];\n await this.git(path, args);\n }\n\n /**\n * Gets local commit history\n *\n * @see https://git-scm.com/docs/git-log\n *\n * @todo Check if there is a need to trim the git commit message of chars\n * @todo Use this method in a service. Decide if we need a HistoryService for example\n *\n * @param path Path to the repository\n * @param options Options specific to the log operation\n */\n public async log(\n path: string,\n options?: Partial<GitLogOptions>\n ): Promise<GitCommit[]> {\n let args = ['log'];\n\n if (options?.between?.from) {\n args = [\n ...args,\n `${options.between.from}...${options.between.to || 'HEAD'}`,\n ];\n }\n\n if (options?.limit) {\n args = [...args, `--max-count=${options.limit}`];\n }\n\n const result = await this.git(path, [\n ...args,\n '--format=%H|%s|%an|%ae|%at|%D',\n ]);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n return {\n hash: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n timestamp: parseInt(lineArray[4]),\n tag: this.refNameToTagName(lineArray[5]),\n };\n });\n\n return lineObjArr.filter(this.isGitCommit.bind(this));\n }\n\n public refNameToTagName(refName: string) {\n let tagName: string | undefined = '';\n\n // Strip tag key\n tagName = refName.replace('tag: ', '');\n // Return undefined for anything else than UUIDs (tag names are UUIDs)\n if (\n tagName.trim() === '' ||\n uuidSchema.safeParse(tagName).success === false\n ) {\n tagName = undefined;\n }\n\n return tagName;\n }\n\n /**\n * Returns a timestamp of given files creation\n *\n * Git only returns the timestamp the file was added,\n * which could be different from the file being created.\n * But since file operations will always be committed\n * immediately, this is practically the same.\n *\n * @param path Path to the repository\n * @param file File to get timestamp from\n */\n public async getFileCreatedTimestamp(path: string, file: string) {\n const result = await this.git(path, [\n 'log',\n '--diff-filter=A',\n '--follow',\n '--format=%at',\n '--max-count=1',\n '--',\n file,\n ]);\n return parseInt(result.stdout);\n }\n\n /**\n * Returns a timestamp of the files last modification\n *\n * @param path Path to the repository\n * @param file File to get timestamp from\n */\n public async getFileLastUpdatedTimestamp(path: string, file: string) {\n const result = await this.git(path, [\n 'log',\n '--follow',\n '--format=%at',\n '--max-count=1',\n '--',\n file,\n ]);\n return parseInt(result.stdout);\n }\n\n /**\n * Returns created and updated timestamps from given file\n *\n * @param path Path to the project\n * @param file Path to the file\n */\n public async getFileCreatedUpdatedMeta(path: string, file: string) {\n const meta = await Promise.all([\n this.getFileCreatedTimestamp(path, file),\n this.getFileLastUpdatedTimestamp(path, file),\n ]);\n return {\n created: meta[0],\n updated: meta[1],\n };\n }\n\n /**\n * A reference is used in Git to specify branches and tags.\n * This method checks if given name matches the required format\n *\n * @see https://git-scm.com/docs/git-check-ref-format\n *\n * @param path Path to the repository\n * @param name Name to check\n */\n private async checkBranchOrTagName(path: string, name: string) {\n await this.git(path, ['check-ref-format', '--allow-onelevel', name]);\n }\n\n /**\n * Installs LFS support and starts tracking\n * all files inside the lfs folder\n *\n * @param path Path to the repository\n */\n private async installLfs(path: string): Promise<void> {\n await this.git(path, ['lfs', 'install']);\n await this.git(path, ['lfs', 'track', 'lfs/*']);\n }\n\n /**\n * Sets the git config of given local repository from ElekIoCoreOptions\n *\n * @param path Path to the repository\n */\n private async setLocalConfig(path: string) {\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const userNameArgs = ['config', '--local', 'user.name', user.name];\n const userEmailArgs = ['config', '--local', 'user.email', user.email];\n await this.git(path, userNameArgs);\n await this.git(path, userEmailArgs);\n }\n\n /**\n * Type guard for GitCommit\n *\n * @param obj The object to check\n */\n private isGitCommit(obj: unknown): obj is GitCommit {\n return gitCommitSchema.safeParse(obj).success;\n }\n\n /**\n * Wraps the execution of any git command\n * to use a FIFO queue for sequential processing\n *\n * @param path Path to the repository\n * @param args Arguments to append after the `git` command\n */\n private async git(path: string, args: string[]): Promise<IGitResult> {\n const result = await this.queue.add(() => GitProcess.exec(args, path));\n if (!result) {\n throw new GitError(\n `Git (${this.version}) command \"git ${args.join(\n ' '\n )}\" failed to return a result`\n );\n }\n\n return result;\n }\n}\n","export default class GitError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'GitError';\n }\n}\n","export default class NoCurrentUserError extends Error {\n constructor() {\n super('Make sure to set a User via Core before using other methods');\n\n this.name = 'NoCurrentUserError';\n }\n}\n","import {\n countGitTagsSchema,\n createGitTagSchema,\n deleteGitTagSchema,\n gitTagSchema,\n listGitTagsSchema,\n readGitTagSchema,\n serviceTypeSchema,\n uuid,\n type CountGitTagsProps,\n type CreateGitTagProps,\n type DeleteGitTagProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type GitTag,\n type ListGitTagsProps,\n type PaginatedList,\n type ReadGitTagProps,\n} from '@elek-io/shared';\nimport GitError from '../error/GitError.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\n\n/**\n * Service that manages CRUD functionality for GitTags\n */\nexport default class GitTagService\n extends AbstractCrudService\n implements ExtendedCrudService<GitTag>\n{\n private git: GitService['git'];\n\n public constructor(options: ElekIoCoreOptions, git: GitService['git']) {\n super(serviceTypeSchema.Enum.GitTag, options);\n\n this.git = git;\n }\n\n /**\n * Creates a new tag\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---annotate\n */\n public async create(props: CreateGitTagProps): Promise<GitTag> {\n createGitTagSchema.parse(props);\n\n const id = uuid();\n let args = ['tag', '--annotate', id];\n\n if (props.hash) {\n args = [...args, props.hash];\n }\n\n args = [...args, '-m', props.message];\n\n await this.git(props.path, args);\n const tag = await this.read({ path: props.path, id });\n\n return tag;\n }\n\n /**\n * Returns a tag by ID\n *\n * Internally uses list() with id as pattern.\n */\n public async read(props: ReadGitTagProps): Promise<GitTag> {\n readGitTagSchema.parse(props);\n\n const tags = await this.list({ path: props.path, filter: props.id });\n\n if (tags.total === 0) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" did not match any known tags`\n );\n }\n if (tags.total > 1) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" matched multiple known tags`\n );\n }\n\n return tags.list[0];\n }\n\n /**\n * Updating a git tag is not supported.\n * Please delete the old and create a new one\n *\n * @see https://git-scm.com/docs/git-tag#_on_re_tagging\n */\n public async update(): Promise<never> {\n throw new Error(\n 'Updating a git tag is not supported. Please delete the old and create a new one'\n );\n }\n\n /**\n * Deletes a tag\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---delete\n *\n * @param path Path to the repository\n * @param id UUID of the tag to delete\n */\n public async delete(props: DeleteGitTagProps): Promise<void> {\n deleteGitTagSchema.parse(props);\n\n const args = ['tag', '--delete', props.id];\n await this.git(props.path, args);\n }\n\n /**\n * Gets all local tags or filter them by pattern\n *\n * They are sorted by authordate of the commit, not the timestamp the tag is created.\n * This ensures tags are sorted correctly in the timeline of their commits.\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---list\n */\n public async list(props: ListGitTagsProps): Promise<PaginatedList<GitTag>> {\n listGitTagsSchema.parse(props);\n\n let args = ['tag', '--list'];\n\n args = [\n ...args,\n '--sort=-*authordate',\n '--format=%(refname:short)|%(subject)|%(*authorname)|%(*authoremail)|%(*authordate:unix)',\n ];\n const result = await this.git(props.path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n return {\n id: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n timestamp:\n typeof lineArray[4] === 'string' ? parseInt(lineArray[4]) : undefined,\n };\n });\n\n const gitTags = lineObjArr.filter(this.isGitTag.bind(this));\n\n return this.paginate(\n gitTags,\n props?.sort,\n props?.filter,\n props?.limit,\n props?.offset\n );\n }\n\n /**\n * Returns the total number of tags inside given repository\n *\n * Internally uses list(), so do not use count()\n * in conjuncion with it to avoid multiple git calls.\n *\n * @param path Path to the repository\n */\n public async count(props: CountGitTagsProps): Promise<number> {\n countGitTagsSchema.parse(props);\n\n const gitTags = await this.list({ path: props.path });\n return gitTags.total;\n }\n\n /**\n * Type guard for GitTag\n *\n * @param obj The object to check\n */\n private isGitTag(obj: unknown): obj is GitTag {\n return gitTagSchema.safeParse(obj).success;\n }\n}\n","import {\n UserTypeSchema,\n setUserSchema,\n userFileSchema,\n type SetUserProps,\n type User,\n type UserFile,\n} from '@elek-io/shared';\nimport * as CoreUtil from '../util/index.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport default class UserService {\n private readonly jsonFileService: JsonFileService;\n\n constructor(jsonFileService: JsonFileService) {\n this.jsonFileService = jsonFileService;\n }\n\n /**\n * Returns the User currently working with Core\n */\n public async get(): Promise<User | undefined> {\n try {\n return await this.jsonFileService.read(\n CoreUtil.pathTo.userFile,\n userFileSchema\n );\n } catch (error) {\n // Should probably be logged in some way or another\n return undefined;\n }\n }\n\n /**\n * Sets the User currently working with Core\n *\n * By doing so all git operations are done with the signature of this User\n */\n public async set(props: SetUserProps): Promise<User> {\n setUserSchema.parse(props);\n\n const userFilePath = CoreUtil.pathTo.userFile;\n\n const userFile: UserFile = {\n ...props,\n };\n\n if (userFile.userType === UserTypeSchema.Enum.cloud) {\n // Try logging in the user\n // Throw on Error\n }\n\n await this.jsonFileService.update(userFile, userFilePath, userFileSchema);\n\n return userFile;\n }\n}\n","import {\n serviceTypeSchema,\n type BaseFile,\n type ElekIoCoreOptions,\n type UserFile,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport type { z } from 'zod';\nimport AbstractCrudService from './AbstractCrudService.js';\n\n/**\n * Service that manages CRUD functionality for JSON files on disk\n */\nexport default class JsonFileService extends AbstractCrudService {\n private cache: Map<string, any> = new Map();\n\n constructor(options: ElekIoCoreOptions) {\n super(serviceTypeSchema.Enum.JsonFile, options);\n }\n\n /**\n * Creates a new file on disk. Fails if path already exists\n *\n * @param data Data to write into the file\n * @param path Path to write the file to\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async create<T extends z.ZodType<BaseFile>>(\n data: unknown,\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n const parsedData = schema.parse(data);\n const string = this.serialize(parsedData);\n await Fs.writeFile(path, string, {\n flag: 'wx',\n encoding: 'utf8',\n });\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n /**\n * Reads the content of a file on disk. Fails if path does not exist\n *\n * @param path Path to read the file from\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async read<T extends z.ZodType<BaseFile | UserFile>>(\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n if (this.cache.has(path)) {\n // console.log(`Cache hit for \"${path}\"`);\n return this.cache.get(path);\n }\n\n // console.log(`Cache miss for \"${path}\"`);\n const data = await Fs.readFile(path, {\n flag: 'r',\n encoding: 'utf8',\n });\n const json = this.deserialize(data);\n const parsedData = schema.parse(json);\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n /**\n * Overwrites an existing file on disk\n *\n * @todo Check how to error out if the file does not exist already\n *\n * @param data Data to write into the file\n * @param path Path to the file to overwrite\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async update<T extends z.ZodType<BaseFile | UserFile>>(\n data: unknown,\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n const parsedData = schema.parse(data);\n const string = this.serialize(parsedData);\n await Fs.writeFile(path, string, {\n flag: 'w',\n encoding: 'utf8',\n });\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n private serialize(data: unknown): string {\n return JSON.stringify(data, null, this.options.file.json.indentation);\n }\n\n private deserialize(data: string): unknown {\n return JSON.parse(data);\n }\n}\n","import {\n collectionFileSchema,\n countCollectionsSchema,\n createCollectionSchema,\n currentTimestamp,\n deleteCollectionSchema,\n fileTypeSchema,\n listCollectionsSchema,\n readCollectionSchema,\n serviceTypeSchema,\n slug,\n updateCollectionSchema,\n uuid,\n type BaseFile,\n type Collection,\n type CollectionFile,\n type CountCollectionsProps,\n type CreateCollectionProps,\n type DeleteCollectionProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListCollectionsProps,\n type PaginatedList,\n type ReadCollectionProps,\n type UpdateCollectionProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Collection files on disk\n */\nexport default class CollectionService\n extends AbstractCrudService\n implements ExtendedCrudService<Collection>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.Enum.Collection, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new Collection\n */\n public async create(props: CreateCollectionProps): Promise<Collection> {\n createCollectionSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionPath = CoreUtil.pathTo.collection(props.projectId, id);\n const collectionFilePath = CoreUtil.pathTo.collectionFile(\n props.projectId,\n id\n );\n\n const collectionFile: CollectionFile = {\n ...props,\n fileType: 'collection',\n id,\n slug: {\n singular: slug(props.slug.singular),\n plural: slug(props.slug.plural),\n },\n created: currentTimestamp(),\n };\n\n await Fs.ensureDir(collectionPath);\n await this.jsonFileService.create(\n collectionFile,\n collectionFilePath,\n collectionFileSchema\n );\n await this.gitService.add(projectPath, [collectionFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return collectionFile;\n }\n\n /**\n * Returns a Collection by ID\n */\n public async read(props: ReadCollectionProps): Promise<Collection> {\n readCollectionSchema.parse(props);\n\n const collection = await this.jsonFileService.read(\n CoreUtil.pathTo.collectionFile(props.projectId, props.id),\n collectionFileSchema\n );\n\n return collection;\n }\n\n /**\n * Updates given Collection\n *\n * @todo finish implementing checks for FieldDefinitions and extract methods\n *\n * @param projectId Project ID of the collection to update\n * @param collection Collection to write to disk\n * @returns An object containing information about the actions needed to be taken,\n * before given update can be executed or void if the update was executed successfully\n */\n public async update(props: UpdateCollectionProps): Promise<Collection> {\n updateCollectionSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionFilePath = CoreUtil.pathTo.collectionFile(\n props.projectId,\n props.id\n );\n const prevCollectionFile = await this.read(props);\n\n const collectionFile: CollectionFile = {\n ...prevCollectionFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n // @todo Collection Service has to check if any of the updated fieldDefinitions do not validate against the used Fields in each CollectionItem of the Collection\n // and return a list of mismatches, so the user can choose what to do in the UI / a wizard\n // For that:\n // - Iterate over all CollectionItems inside Collection\n // - Create an array with all FieldReferences of those CollectionItems\n // - Load all Fields by those references and check if the Field still complies with the new definition\n\n // const result: CollectionUpdateResult = {\n // create: [],\n // update: [],\n // delete: [],\n // };\n\n // const currentCollection = await this.read(props);\n // Iterate over all FieldDefinitions and check each for changes\n // for (let index = 0; index < collection.fieldDefinitions.length; index++) {\n // const nextFieldDefinition = collection.fieldDefinitions[index];\n // if (!nextFieldDefinition) {\n // throw new Error('Could not find any field definition');\n // }\n // // Get the correct FieldDefinition by ID\n // const currentFieldDefinition = currentCollection.fieldDefinitions.find(\n // (current) => {\n // return current.id === nextFieldDefinition.id;\n // }\n // );\n // if (currentFieldDefinition) {\n // if (\n // currentFieldDefinition.isRequired === false &&\n // nextFieldDefinition.isRequired === true\n // ) {\n // // Case 1.\n // // A FieldDefinition was not required to be filled, but is now\n // // -> Check if all CollectionItems have a FieldReference to this definition (if not create)\n // // -> Check all values of referenced fields of this definition for null (if not update)\n // // -> If the value is null, this is a violation\n // const collectionItems = (\n // await this.collectionItemService.list(\n // projectId,\n // collection.id,\n // undefined,\n // undefined,\n // 0,\n // 0\n // )\n // ).list;\n // for (let index = 0; index < collectionItems.length; index++) {\n // const collectionItem = collectionItems[index];\n // if (!collectionItem) {\n // throw new Error('Blaa');\n // }\n // const fieldReference = collectionItem.fieldReferences.find(\n // (fieldReference) => {\n // return (\n // fieldReference.fieldDefinitionId === nextFieldDefinition.id\n // );\n // }\n // );\n // if (!fieldReference) {\n // result.create.push({\n // violation: Violation.FIELD_REQUIRED_BUT_UNDEFINED,\n // collectionItem,\n // fieldDefinition: nextFieldDefinition,\n // });\n // } else {\n // const field = await this.fieldService.read(\n // projectId,\n // fieldReference.field.id,\n // fieldReference.field.language\n // );\n // if (field.value === null) {\n // result.update.push({\n // violation: Violation.FIELD_VALUE_REQUIRED_BUT_NULL,\n // collectionItem,\n // fieldReference,\n // });\n // }\n // }\n // }\n // }\n // if (\n // currentFieldDefinition.isUnique !== nextFieldDefinition.isUnique &&\n // nextFieldDefinition.isUnique === true\n // ) {\n // // Case 2.\n // // A FieldDefinition was not required to be unique, but is now\n // // -> Check all current values of referenced fields\n // // -> If a value is not unique, this is a violation\n // // const fieldReferences = await this.collectionItemService.getAllFieldReferences(project, currentCollection, currentFieldDefinition.id);\n // // const fields = await this.fieldService.readAll(project, fieldReferences);\n // // const duplicates = Util.getDuplicates(fields, 'value');\n // // for (let index = 0; index < duplicates.length; index++) {\n // // const duplicate = duplicates[index];\n // // result.update.push({\n // // violation: Violation.FIELD_VALUE_NOT_UNIQUE,\n // // collectionItem: ,\n // // fieldReference\n // // });\n // // }\n // }\n // if (\n // isEqual(currentFieldDefinition.input, nextFieldDefinition.input) ===\n // false\n // ) {\n // // Case 3.\n // // A FieldDefinition has a new input specification\n // // -> Check if this input is valid for given FieldType\n // // -> If not, this is a violation\n // }\n // } else {\n // // It's a new FieldDefinition that was not existing before\n // if (nextFieldDefinition.isRequired) {\n // // Case 4.\n // // A FieldDefinition is new and a field (with value) required\n // // -> The user needs to add a field reference (either through a new or existing field)\n // // for every CollectionItem of this Collection\n // const collectionItems = (\n // await this.collectionItemService.list(\n // projectId,\n // collection.id,\n // undefined,\n // undefined,\n // 0,\n // 0\n // )\n // ).list;\n // collectionItems.forEach((collectionItem) => {\n // result.create.push({\n // violation: Violation.FIELD_REQUIRED_BUT_UNDEFINED,\n // collectionItem,\n // fieldDefinition: nextFieldDefinition,\n // });\n // });\n // }\n // }\n // }\n\n // // Return early to notify the user of changes he has to do before this update is working\n // if (\n // result.create.length !== 0 ||\n // result.update.length !== 0 ||\n // result.delete.length !== 0\n // ) {\n // return result;\n // }\n\n await this.jsonFileService.update(\n collectionFile,\n collectionFilePath,\n collectionFileSchema\n );\n await this.gitService.add(projectPath, [collectionFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n return collectionFile;\n }\n\n /**\n * Deletes given Collection (folder), including it's items\n *\n * The Fields that Collection used are not deleted.\n */\n public async delete(props: DeleteCollectionProps): Promise<void> {\n deleteCollectionSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionPath = CoreUtil.pathTo.collection(\n props.projectId,\n props.id\n );\n\n await Fs.remove(collectionPath);\n await this.gitService.add(projectPath, [collectionPath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(\n props: ListCollectionsProps\n ): Promise<PaginatedList<Collection>> {\n listCollectionsSchema.parse(props);\n\n const references = await this.listReferences(\n fileTypeSchema.Enum.collection,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountCollectionsProps): Promise<number> {\n countCollectionsSchema.parse(props);\n\n const count = (\n await this.listReferences(fileTypeSchema.Enum.collection, props.projectId)\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is of type Collection\n */\n public isCollection(obj: BaseFile | unknown): obj is Collection {\n return collectionFileSchema.safeParse(obj).success;\n }\n}\n","import {\n countEntriesSchema,\n createEntrySchema,\n currentTimestamp,\n deleteEntrySchema,\n entryFileSchema,\n entrySchema,\n fileTypeSchema,\n getValueSchemaFromDefinition,\n listEntriesSchema,\n readEntrySchema,\n serviceTypeSchema,\n updateEntrySchema,\n uuid,\n type BaseFile,\n type CountEntriesProps,\n type CreateEntryProps,\n type DeleteEntryProps,\n type ElekIoCoreOptions,\n type Entry,\n type EntryFile,\n type ExtendedCrudService,\n type ListEntriesProps,\n type ReadEntryProps,\n type UpdateEntryProps,\n type ValueDefinition,\n type ValueReference,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport CollectionService from './CollectionService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\nimport ValueService from './ValueService.js';\n\n/**\n * Service that manages CRUD functionality for Entry files on disk\n */\nexport default class EntryService\n extends AbstractCrudService\n implements ExtendedCrudService<Entry>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private collectionService: CollectionService;\n private valueService: ValueService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService,\n collectionService: CollectionService,\n valueService: ValueService\n ) {\n super(serviceTypeSchema.Enum.Entry, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n this.collectionService = collectionService;\n this.valueService = valueService;\n }\n\n /**\n * Creates a new Entry\n */\n public async create(props: CreateEntryProps): Promise<Entry> {\n createEntrySchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n id,\n props.language\n );\n const collection = await this.collectionService.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n await this.validateValueReferences(\n props.projectId,\n props.collectionId,\n props.valueReferences,\n collection.valueDefinitions\n );\n\n /**\n * Entry saves references to the Values it's using\n */\n const entryFile: EntryFile = {\n fileType: 'entry',\n id,\n language: props.language,\n valueReferences: props.valueReferences,\n created: currentTimestamp(),\n };\n\n await this.jsonFileService.create(\n entryFile,\n entryFilePath,\n entryFileSchema\n );\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return entryFile;\n }\n\n /**\n * Returns an Entry by ID and language\n */\n public async read(props: ReadEntryProps): Promise<Entry> {\n readEntrySchema.parse(props);\n\n const entryFile = await this.jsonFileService.read(\n CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n ),\n entryFileSchema\n );\n\n return entryFile;\n }\n\n /**\n * Updates Entry with given ValueReferences\n */\n public async update(props: UpdateEntryProps): Promise<Entry> {\n updateEntrySchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n );\n const collection = await this.collectionService.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n await this.validateValueReferences(\n props.projectId,\n props.collectionId,\n props.valueReferences,\n collection.valueDefinitions\n );\n\n const prevEntryFile = await this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: props.id,\n language: props.language,\n });\n\n const entryFile: EntryFile = {\n ...prevEntryFile,\n valueReferences: props.valueReferences,\n updated: currentTimestamp(),\n };\n\n await this.jsonFileService.update(\n entryFile,\n entryFilePath,\n entryFileSchema\n );\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return entryFile;\n }\n\n /**\n * Deletes given Entry\n */\n public async delete(props: DeleteEntryProps): Promise<void> {\n deleteEntrySchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n );\n\n await Fs.remove(entryFilePath);\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(props: ListEntriesProps) {\n listEntriesSchema.parse(props);\n\n const references = await this.listReferences(\n fileTypeSchema.Enum.entry,\n props.projectId,\n props.collectionId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n if (!reference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: reference.id,\n language: reference.language,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountEntriesProps): Promise<number> {\n countEntriesSchema.parse(props);\n\n return (\n await this.listReferences(\n fileTypeSchema.Enum.entry,\n props.projectId,\n props.collectionId\n )\n ).length;\n }\n\n /**\n * Checks if given object of Collection, CollectionItem,\n * Field, Project or Asset is of type CollectionItem\n */\n public isEntry(obj: BaseFile | unknown): obj is Entry {\n return entrySchema.safeParse(obj).success;\n }\n\n /**\n * Validates referenced Values against the Collections definition\n *\n * @todo should probably return all errors occurring during parsing instead of throwing\n */\n private async validateValueReferences(\n projectId: string,\n collectionId: string,\n valueReferences: ValueReference[],\n valueDefinitions: ValueDefinition[]\n ) {\n await Promise.all(\n valueReferences.map(async (reference) => {\n const definition = valueDefinitions.find((def) => {\n if (def.id === reference.definitionId) {\n return true;\n }\n return false;\n });\n\n if (!definition) {\n throw new Error(\n `No definition with ID \"${reference.definitionId}\" found in Collection \"${collectionId}\" for given Value reference`\n );\n }\n\n const schema = getValueSchemaFromDefinition(definition);\n const value = await this.valueService.read({\n ...reference.references,\n projectId,\n });\n schema.parse(value.content);\n })\n );\n }\n}\n","import {\n countValuesSchema,\n createValueSchema,\n currentTimestamp,\n deleteValueSchema,\n fileTypeSchema,\n getValueSchemaFromDefinition,\n listValuesSchema,\n readValueSchema,\n serviceTypeSchema,\n updateValueSchema,\n uuid,\n validateValueSchema,\n valueFileSchema,\n type BaseFile,\n type CountValuesProps,\n type CreateValueProps,\n type DeleteValueProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListValuesProps,\n type PaginatedList,\n type ReadValueProps,\n type UpdateValueProps,\n type ValidateValueProps,\n type Value,\n type ValueFile,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Value files on disk\n */\nexport default class ValueService\n extends AbstractCrudService\n implements ExtendedCrudService<Value>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService,\n assetService: AssetService\n ) {\n super(serviceTypeSchema.Enum.Value, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new Value\n */\n public async create(props: CreateValueProps): Promise<Value> {\n createValueSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const valueFilePath = CoreUtil.pathTo.valueFile(\n props.projectId,\n id,\n props.language\n );\n\n const valueFile: ValueFile = {\n ...props,\n fileType: 'value',\n id,\n created: currentTimestamp(),\n };\n\n await this.jsonFileService.create(\n valueFile,\n valueFilePath,\n valueFileSchema\n );\n await this.gitService.add(projectPath, [valueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return valueFile;\n }\n\n /**\n * Returns a Value by ID and language\n */\n public async read(props: ReadValueProps): Promise<Value> {\n readValueSchema.parse(props);\n\n const valueFile = await this.jsonFileService.read(\n CoreUtil.pathTo.valueFile(props.projectId, props.id, props.language),\n valueFileSchema\n );\n\n return valueFile;\n }\n\n /**\n * Updates given Value\n */\n public async update(props: UpdateValueProps): Promise<Value> {\n updateValueSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const valueFilePath = CoreUtil.pathTo.valueFile(\n props.projectId,\n props.id,\n props.language\n );\n const prevValueFile = await this.read(props);\n\n const valueFile: ValueFile = {\n ...prevValueFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n await this.jsonFileService.update(\n valueFile,\n valueFilePath,\n valueFileSchema\n );\n await this.gitService.add(projectPath, [valueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return valueFile;\n }\n\n /**\n * Deletes given Value\n */\n public async delete(props: DeleteValueProps): Promise<void> {\n deleteValueSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const valueFilePath = CoreUtil.pathTo.valueFile(\n props.projectId,\n props.id,\n props.language\n );\n\n await Fs.remove(valueFilePath);\n await this.gitService.add(projectPath, [valueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(props: ListValuesProps): Promise<PaginatedList<Value>> {\n listValuesSchema.parse(props);\n\n const references = await this.listReferences(\n fileTypeSchema.Enum.value,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n if (!reference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n language: reference.language,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountValuesProps): Promise<number> {\n countValuesSchema.parse(props);\n\n const count = (\n await this.listReferences(fileTypeSchema.Enum.value, props.projectId)\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is of type Value\n */\n public isValue(obj: BaseFile | unknown): obj is Value {\n return valueFileSchema.safeParse(obj).success;\n }\n\n /**\n * Reads the given Value from disk and validates it against the ValueDefinition\n */\n public async validate(props: ValidateValueProps) {\n validateValueSchema.parse(props);\n\n const value = await this.read(props);\n const valueSchema = getValueSchemaFromDefinition(props.definition);\n // @todo for isUnique = true we need to iterate through all values of this collection\n // const fieldsOfCollection = await Promise.all(\n // props.fieldRefsOfCollection.map((fieldRefOfCollection) => {\n // return this.read({\n // ...fieldRefOfCollection.field,\n // projectId: props.projectId,\n // });\n // })\n // );\n\n return valueSchema.safeParse(value.content);\n }\n}\n","import {\n createProjectSchema,\n currentTimestamp,\n deleteProjectSchema,\n fileTypeSchema,\n gitCommitIconSchema,\n listProjectsSchema,\n projectFileSchema,\n projectFolderSchema,\n readProjectSchema,\n serviceTypeSchema,\n updateProjectSchema,\n upgradeProjectSchema,\n uuid,\n type BaseFile,\n type CollectionExport,\n type CreateProjectProps,\n type DeleteProjectProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type FileType,\n type ListProjectsProps,\n type PaginatedList,\n type Project,\n type ProjectExport,\n type ProjectFile,\n type ProjectSettings,\n type ReadProjectProps,\n type UpdateProjectProps,\n type UpgradeProjectProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport Os from 'os';\nimport Path from 'path';\nimport Semver from 'semver';\nimport NoCurrentUserError from '../error/NoCurrentUserError.js';\nimport ProjectUpgradeError from '../error/ProjectUpgradeError.js';\nimport type { ProjectUpgradeImport } from '../upgrade/example.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport CollectionService from './CollectionService.js';\nimport type EntryService from './EntryService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\nimport SearchService from './SearchService.js';\nimport UserService from './UserService.js';\nimport type ValueService from './ValueService.js';\n\n/**\n * Service that manages CRUD functionality for Project files on disk\n */\nexport default class ProjectService\n extends AbstractCrudService\n implements ExtendedCrudService<Project>\n{\n private jsonFileService: JsonFileService;\n private userService: UserService;\n private gitService: GitService;\n private searchService: SearchService;\n private assetService: AssetService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n private valueService: ValueService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n userService: UserService,\n gitService: GitService,\n searchService: SearchService,\n assetService: AssetService,\n collectionService: CollectionService,\n entryService: EntryService,\n valueService: ValueService\n ) {\n super(serviceTypeSchema.Enum.Project, options);\n\n this.jsonFileService = jsonFileService;\n this.userService = userService;\n this.gitService = gitService;\n this.searchService = searchService;\n this.assetService = assetService;\n this.collectionService = collectionService;\n this.entryService = entryService;\n this.valueService = valueService;\n }\n\n /**\n * Creates a new Project\n */\n public async create(props: CreateProjectProps): Promise<Project> {\n createProjectSchema.parse(props);\n\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const id = uuid();\n const defaultSettings: ProjectSettings = {\n locale: {\n default: user.locale,\n supported: [user.locale],\n },\n };\n\n const projectFile: ProjectFile = {\n ...props,\n fileType: 'project',\n id,\n description: props.description || '',\n settings: Object.assign({}, defaultSettings, props.settings),\n created: currentTimestamp(),\n coreVersion: this.options.version, // @todo should be read from package.json to avoid duplicates\n status: 'todo',\n version: '0.0.1',\n };\n\n const projectPath = CoreUtil.pathTo.project(id);\n\n await Fs.ensureDir(projectPath);\n\n try {\n await this.createFolderStructure(projectPath);\n await this.createGitignore(projectPath);\n await this.gitService.init(projectPath, { initialBranch: 'main' });\n await this.jsonFileService.create(\n projectFile,\n CoreUtil.pathTo.projectFile(id),\n projectFileSchema\n );\n await this.gitService.add(projectPath, ['.']);\n await this.gitService.commit(\n projectPath,\n `${gitCommitIconSchema.enum.INIT} Created this new elek.io project`\n );\n await this.gitService.switch(projectPath, 'stage', { isNew: true });\n } catch (error) {\n // To avoid partial data being added to the repository / git status reporting uncommitted files\n await this.delete({\n id,\n });\n throw error;\n }\n\n return projectFile;\n }\n\n /**\n * Returns a Project by ID\n */\n public async read(props: ReadProjectProps): Promise<Project> {\n readProjectSchema.parse(props);\n\n const projectFile = await this.jsonFileService.read(\n CoreUtil.pathTo.projectFile(props.id),\n projectFileSchema\n );\n\n return projectFile;\n }\n\n /**\n * Updates given Project\n */\n public async update(props: UpdateProjectProps): Promise<Project> {\n updateProjectSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.id);\n const filePath = CoreUtil.pathTo.projectFile(props.id);\n const prevProjectFile = await this.read(props);\n\n const projectFile: ProjectFile = {\n ...prevProjectFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n await this.jsonFileService.update(projectFile, filePath, projectFileSchema);\n await this.gitService.add(projectPath, [filePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return projectFile;\n }\n\n /**\n * Upgrades given Project to the latest version of this client\n *\n * Needed when a new core version is requiring changes to existing files or structure.\n *\n * @todo Find out why using this.snapshotService is throwing isObjWithKeyAndValueOfString of undefined error in gitService (maybe binding issue)\n */\n public async upgrade(props: UpgradeProjectProps): Promise<void> {\n upgradeProjectSchema.parse(props);\n\n const project = await this.read(props);\n const projectPath = CoreUtil.pathTo.project(project.id);\n\n if (Semver.gt(project.coreVersion, this.options.version)) {\n // Upgrade of the client needed before the project can be upgraded\n throw new Error(\n `Failed upgrading project. The projects core version \"${project.coreVersion}\" is higher than the current core version \"${this.options.version}\" of this client. A client upgrade is needed beforehand.`\n );\n }\n\n if (Semver.eq(project.coreVersion, this.options.version)) {\n // Nothing, since both are equal\n return;\n }\n\n // Get all available upgrade scripts\n const upgradeFiles = await CoreUtil.files(\n Path.resolve(__dirname, '../upgrade'),\n 'ts'\n );\n\n // Import all objects\n const upgrades = (\n await Promise.all(\n upgradeFiles.map((file) => {\n return import(\n Path.join('../upgrade', file.name)\n ) as Promise<ProjectUpgradeImport>;\n })\n )\n ).map((upgradeImport) => {\n return upgradeImport.default;\n });\n\n // Sort them by core version and filter out the example one\n const sortedUpgrades = upgrades\n .sort((a, b) => {\n return Semver.compare(a.to, b.to);\n })\n .filter((upgrade) => {\n if (upgrade.to !== '0.0.0') {\n return upgrade;\n }\n });\n\n for (let index = 0; index < sortedUpgrades.length; index++) {\n const upgrade = sortedUpgrades[index];\n if (!upgrade) {\n throw new Error('Expected ProjectUpgrade but got undefined');\n }\n\n // Make a tag to revert to on failure\n const failsafeTag = await this.gitService.tags.create({\n path: projectPath,\n message: `Attempting to upgrade Project to Core version \"${upgrade.to}\"`,\n });\n\n try {\n await upgrade.run(project);\n\n // Override the projects core version\n project.coreVersion = upgrade.to;\n await this.update(project);\n\n // And create another tag to show successfull upgrade in git log\n await this.gitService.tags.create({\n path: projectPath,\n message: `Upgraded Project to Core version \"${upgrade.to}\"`,\n });\n\n // Done, remove the failsafe tag again\n await this.gitService.tags.delete({\n path: projectPath,\n id: failsafeTag.id,\n });\n } catch (error) {\n // Reset Project to the tag made before\n await this.gitService.reset(projectPath, 'hard', failsafeTag.id);\n\n throw new ProjectUpgradeError(\n `Failed to upgrade Project to Core version \"${upgrade.to}\"`\n );\n }\n }\n }\n\n /**\n * Deletes given Project\n *\n * Deletes the whole Project folder including the history, not only the config file.\n * Use with caution, since a Project that is only available locally could be lost forever.\n * Or changes that are not pushed to a remote yet, will be lost too.\n */\n public async delete(props: DeleteProjectProps): Promise<void> {\n deleteProjectSchema.parse(props);\n\n await Fs.remove(CoreUtil.pathTo.project(props.id));\n }\n\n public async list(\n props?: ListProjectsProps\n ): Promise<PaginatedList<Project>> {\n if (props) {\n listProjectsSchema.parse(props);\n }\n\n const references = await this.listReferences(fileTypeSchema.Enum.project);\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n return this.read({ id: reference.id });\n })\n );\n\n return this.paginate(\n list,\n props?.sort,\n props?.filter,\n props?.limit,\n props?.offset\n );\n }\n\n public async count(): Promise<number> {\n return (await this.listReferences(fileTypeSchema.Enum.project)).length;\n }\n\n /**\n * Search all models inside the project for given query\n *\n * @param projectId Project ID to search in\n * @param query Query to search for\n * @param type (Optional) specify the type to search for\n */\n public async search(projectId: string, query: string, type?: FileType) {\n return this.searchService.search(projectId, query, type);\n }\n\n /**\n * Checks if given object is of type Project\n */\n public isProject(obj: BaseFile | unknown): obj is Project {\n return projectFileSchema.safeParse(obj).success;\n }\n\n /**\n * Exports given Project to JSON\n *\n * @todo performance tests\n * @todo add progress callback\n */\n public async exportToJson(projectId: string): Promise<ProjectExport> {\n const project = await this.read({ id: projectId });\n const assets = (await this.assetService.list({ projectId, limit: 0 })).list;\n const collections = (\n await this.collectionService.list({ projectId, limit: 0 })\n ).list;\n\n const collectionExport: CollectionExport[] = await Promise.all(\n collections.map(async (collection) => {\n const entries = (\n await this.entryService.list({\n projectId,\n collectionId: collection.id,\n limit: 0,\n })\n ).list;\n const entryExport = await Promise.all(\n entries.map(async (entry) => {\n const valueExport = await Promise.all(\n entry.valueReferences.map(async (valueReference) => {\n return this.valueService.read({\n projectId,\n id: valueReference.references.id,\n language: valueReference.references.language,\n });\n })\n );\n\n return {\n ...entry,\n values: valueExport,\n };\n })\n );\n\n return {\n ...collection,\n entries: entryExport,\n };\n })\n );\n\n return {\n ...project,\n assets,\n collections: collectionExport,\n };\n }\n\n /**\n * Creates the projects folder structure and makes sure to\n * write empty .gitkeep files inside them to ensure they are\n * committed\n */\n private async createFolderStructure(path: string): Promise<void> {\n const folders = Object.values(projectFolderSchema.Values);\n\n await Promise.all(\n folders.map(async (folder) => {\n await Fs.mkdirp(Path.join(path, folder));\n await Fs.writeFile(Path.join(path, folder, '.gitkeep'), '');\n })\n );\n }\n\n /**\n * Writes the Projects main .gitignore file to disk\n *\n * @todo Add general things to ignore\n * @see https://github.com/github/gitignore/tree/master/Global\n */\n private async createGitignore(path: string): Promise<void> {\n const lines = [\n '# Ignore all hidden files and folders...',\n '.*',\n '# ...but these',\n '!/.gitignore',\n '!/.gitattributes',\n '!/**/.gitkeep',\n '',\n '# elek.io related ignores',\n // projectFolderSchema.Enum.theme + '/',\n // projectFolderSchema.Enum.public + '/',\n // projectFolderSchema.Enum.logs + '/',\n ];\n await Fs.writeFile(Path.join(path, '.gitignore'), lines.join(Os.EOL));\n }\n}\n","export default class ProjectUpgradeError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'ProjectUpgradeError';\n }\n}\n","import {\n serviceTypeSchema,\n type ElekIoCoreOptions,\n type FileType,\n type SearchResult,\n} from '@elek-io/shared';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport CollectionService from './CollectionService.js';\n\n/**\n * Service that queries other services for data to search\n *\n * @todo refactor for the new Services\n */\nexport default class SearchService extends AbstractCrudService {\n private assetService: AssetService;\n private collectionService: CollectionService;\n\n constructor(\n options: ElekIoCoreOptions,\n assetService: AssetService,\n collectionService: CollectionService\n ) {\n super(serviceTypeSchema.enum.Search, options);\n\n this.assetService = assetService;\n this.collectionService = collectionService;\n }\n\n /**\n * Search all models inside the project for given query\n *\n * @todo Implement SearchOptions parameter\n *\n * @param project Project to search in\n * @param query Query to search for\n */\n public async search(projectId: string, query: string, fileType?: FileType) {\n const results: SearchResult[] = [];\n const normalizedQuery = query.trim();\n\n if (normalizedQuery === '') {\n return results;\n }\n\n const paginatedLists = (\n await Promise.all([this.assetService.list({ projectId, filter: query })])\n ).flat();\n\n paginatedLists.forEach((paginatedList) => {\n paginatedList.list.flat().forEach((file) => {\n const result: SearchResult = {\n id: file.id,\n language: file.language,\n name: file.name,\n type: file.fileType,\n matches: [],\n };\n\n for (const [key, value] of Object.entries(file)) {\n const valueString = String(value);\n if (\n valueString.toLowerCase().includes(normalizedQuery.toLowerCase())\n ) {\n const matchStart = valueString\n .toLowerCase()\n .indexOf(normalizedQuery.toLowerCase());\n const matchEnd = matchStart + normalizedQuery.length;\n\n result.matches.push({\n key,\n prefix: this.truncate(\n valueString.substring(0, matchStart),\n 'start'\n ),\n match: valueString.substring(matchStart, matchEnd),\n suffix: this.truncate(\n valueString.substring(matchEnd, valueString.length),\n 'end'\n ),\n });\n }\n }\n\n if (result.matches.length > 0) {\n results.push(result);\n }\n });\n });\n\n return results;\n }\n\n private truncate(value: string, at: 'start' | 'end', limit = 15) {\n if (at === 'start') {\n return `${value.substring(value.length - limit, value.length)}`;\n } else {\n return `${value.substring(0, limit)}`;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,kBAIO;AACP,IAAAC,mBAAe;;;ACLf,IAAAC,iBA4BO;AACP,IAAAC,mBAAe;AACf,oBAAkB;;;AC9BlB,IAAqB,gCAArB,cAA2D,MAAM;AAAA,EAC/D,YAAY,WAAmB;AAC7B,UAAM,+BAA+B,SAAS,GAAG;AAEjD,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgD;AAChD,2BAAqD;AACrD,sBAAe;AACf,uBAA+C;AAC/C,gBAAe;AACf,kBAAiB;AAOV,IAAM,mBAAmB,YAAAC,QAAK,KAAK,UAAAC,QAAG,QAAQ,GAAG,SAAS;AAK1D,IAAM,SAAS;AAAA,EACpB,KAAK,YAAAD,QAAK,KAAK,kBAAkB,KAAK;AAAA,EACtC,UAAU,YAAAA,QAAK,KAAK,kBAAkB,WAAW;AAAA;AAAA,EAGjD,UAAU,YAAAA,QAAK,KAAK,kBAAkB,UAAU;AAAA,EAChD,SAAS,CAAC,cAA8B;AACtC,WAAO,YAAAA,QAAK,KAAK,OAAO,UAAU,SAAS;AAAA,EAC7C;AAAA,EACA,aAAa,CAAC,cAA8B;AAC1C,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,cAAc;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,CAAC,cAA8B;AAClC,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,kCAAoB,KAAK,GAAG;AAAA,EAC1E;AAAA,EAEA,aAAa,CAAC,cAA8B;AAC1C,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,SAAS;AAAA,MACxB,kCAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,YAAY,CAAC,WAAmB,OAAe;AAC7C,WAAO,YAAAA,QAAK,KAAK,OAAO,YAAY,SAAS,GAAG,EAAE;AAAA,EACpD;AAAA,EACA,gBAAgB,CAAC,WAAmB,OAAe;AACjD,WAAO,YAAAA,QAAK,KAAK,OAAO,WAAW,WAAW,EAAE,GAAG,iBAAiB;AAAA,EACtE;AAAA,EAEA,SAAS,CAAC,WAAmB,iBAAiC;AAC5D,WAAO,YAAAA,QAAK,KAAK,OAAO,WAAW,WAAW,YAAY,CAAC;AAAA,EAC7D;AAAA,EACA,WAAW,CACT,WACA,cACA,IACA,aACG;AACH,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,WAAW,YAAY;AAAA,MACtC,GAAG,EAAE,IAAI,QAAQ;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,QAAQ,CAAC,cAA8B;AACrC,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,QAAQ;AAAA,EACtD;AAAA,EACA,WAAW,CAAC,WAAmB,IAAY,aAAqB;AAC9D,WAAO,YAAAA,QAAK,KAAK,OAAO,OAAO,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,OAAO;AAAA,EACrE;AAAA,EAEA,QAAQ,CAAC,cAA8B;AACrC,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,SAAS;AAAA,MACxB,kCAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,WAAW,CAAC,WAAmB,IAAY,aAA6B;AACtE,WAAO,YAAAA,QAAK,KAAK,OAAO,OAAO,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,OAAO;AAAA,EACrE;AAAA,EACA,OAAO,CACL,WACA,IACA,UACA,cACW;AACX,WAAO,YAAAA,QAAK,KAAK,OAAO,IAAI,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,IAAI,SAAS,EAAE;AAAA,EAC1E;AACF;AAWO,IAAM,WAAW;AAAA,EACtB,WAAW,CAAC,SAAqC;AAC/C,UAAM,aAAa;AACnB,UAAM,WAAW;AACjB,UAAM,QAAQ,KAAK,QAAQ,UAAU,IAAI,WAAW;AAEpD,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AACA,UAAM,MAAM,KAAK,QAAQ,UAAU,KAAK;AAExC,UAAM,SAAS,KAAK,UAAU,OAAO,QAAQ,KAAK,KAAK,SAAS,GAAG;AACnE,QAAI,UAAU,yBAAW,UAAU,MAAM,EAAE,SAAS;AAClD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;AAKO,SAAS,uBACd,OACA,YACG;AACH,SAAO,OAAO,OAAO,YAAY,KAAK;AACxC;AAQO,SAAS,SAAY,OAAyC;AACnE,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,MAAM,KAAK,MAAM,IAAI;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,UAAa,MAA4B;AACvD,SAAO,gBAAgB,UAAU;AACnC;AAKA,eAAsB,eAAkB,UAAwB;AAC9D,QAAM,UAAgC,CAAC;AACvC,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AACpD,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,8BAA8B,KAAK,GAAG;AAAA,IACxD;AAIA,YAAQ;AAAA,MACN,QACG,KAAK,CAAC,WAAW;AAChB,eAAO;AAAA,MACT,CAAC,EACA,MAAM,CAAC,UAAU;AAGhB,eAAO,IAAI,MAAM,KAAK;AAAA,MACxB,CAAC;AAAA,IACL;AAAA,EACF;AAIA,QAAM,UAAU,MAAM,QAAQ,IAAI,OAAO;AAKzC,SAAO,QAAQ,OAAO,SAAS;AACjC;AAQO,SAAS,kBACd,SACA,MACA,SACiB;AACjB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,mBAAe,4BAAM,SAAS,MAAM,OAAO;AACjD,QAAI,MAAM;AAEV,iBAAa,OAAO,GAAG,QAAQ,CAAC,SAAS;AACvC,aAAO;AAAA,IACT,CAAC;AAED,iBAAa,OAAO,GAAG,QAAQ,CAAC,SAAS;AACvC,aAAO;AAAA,IACT,CAAC;AAED,iBAAa,GAAG,SAAS,CAAC,UAAU;AAClC,YAAM;AAAA,IACR,CAAC;AAED,iBAAa,GAAG,QAAQ,CAAC,SAAS;AAChC,UAAI,SAAS,GAAG;AACd,eAAO,QAAQ,GAAG;AAAA,MACpB;AACA,aAAO,OAAO,GAAG;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAsB,QAAQ,MAAoC;AAChE,QAAM,SAAS,MAAM,gBAAAE,QAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC7D,SAAO,OAAO,OAAO,CAACC,YAAW;AAC/B,WAAOA,QAAO,YAAY;AAAA,EAC5B,CAAC;AACH;AAKA,eAAsB,MACpB,MACA,WACsB;AACtB,QAAM,SAAS,MAAM,gBAAAD,QAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC7D,SAAO,OAAO,OAAO,CAACC,YAAW;AAC/B,QAAI,aAAaA,QAAO,OAAO,MAAM,MAAM;AACzC,UAAIA,QAAO,KAAK,SAAS,SAAS,GAAG;AACnC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAOA,QAAO,OAAO;AAAA,EACvB,CAAC;AACH;AAMO,SAAS,gBAAgB,MAAsB;AACpD,MAAI,eAAe,KAAK,QAAQ,kBAAkB,EAAE;AACpD,MAAI,aAAa,WAAW,GAAG,GAAG;AAChC,mBAAe,aAAa,OAAO,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAQO,SAAS,cAAiB,KAAU,KAAc;AACvD,QAAM,cAAU,0BAAQ,KAAK,CAAC,SAAS;AACrC,WAAO,KAAK,GAAG;AAAA,EACjB,CAAC;AACD,aAAO;AAAA,QACL;AAAA,UACE,yBAAO,SAAS,CAAC,SAAS;AACxB,eAAO,KAAK,SAAS;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7RA,IAAAC,iBAcO;AACP,IAAAC,oBAAgC;AAOhC,IAA8B,sBAA9B,MAAkD;AAAA;AAAA;AAAA;AAAA,EAgBtC,YAAY,MAAmB,SAA4B;AACnE,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,MAChB,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,MAC/D,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,MAC/D,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAgB,SACd,MACA,OAAkB,CAAC,GACnBC,UAAS,IACT,QAAQ,IACR,SAAS,GACkB;AAC3B,QAAI,SAAS;AACb,UAAM,QAAQ,KAAK;AACnB,UAAM,mBAAmBA,QAAO,KAAK,EAAE,YAAY;AAGnD,QAAI,qBAAqB,IAAI;AAC3B,oCAAO,QAAQ,CAAC,UAAU;AACxB,YAAI;AACJ,aAAK,OAAO,OAAO;AACjB,gBAAM,QAAQ,MAAM,GAAG;AACvB,cAAI,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,gBAAgB,GAAG;AAC1D,mBAAO;AAAA,UACT;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,OAAO,KAAK,IAAI,CAAC,UAAU,MAAM,EAAE;AACzC,YAAM,SAAS,KAAK,IAAI,CAAC,UAAU,MAAM,KAAK;AAC9C,mBAAS,2BAAQ,QAAQ,MAAM,MAAM;AAAA,IACvC;AAGA,QAAI,UAAU,GAAG;AACf,eAAS,OAAO,MAAM,QAAQ,SAAS,KAAK;AAAA,IAC9C;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,eACd,MACA,WACA,cAC0B;AAC1B,YAAQ,MAAM;AAAA,MACZ,KAAK,8BAAe,KAAK;AACvB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,kBAA2B,OAAO,IAAI,SAAS,CAAC;AAAA,MAE9D,KAAK,8BAAe,KAAK;AACvB,eAAO,KAAK,oBAA6B,OAAO,QAAQ;AAAA,MAE1D,KAAK,8BAAe,KAAK;AACvB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,oBAA6B,OAAO,YAAY,SAAS,CAAC;AAAA,MAExE,KAAK,8BAAe,KAAK;AACvB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI,8BAA8B,cAAc;AAAA,QACxD;AACA,eAAO,KAAK;AAAA,UACD,OAAO,WAAW,WAAW,YAAY;AAAA,QACpD;AAAA,MAEF,KAAK,8BAAe,KAAK;AACvB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,kBAA2B,OAAO,OAAO,SAAS,CAAC;AAAA,MAEjE;AACE,cAAM,IAAI,MAAM,6CAA6C,IAAI,GAAG;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,MAAwC;AACxE,UAAM,kBAAkB,MAAe,QAAQ,IAAI;AACnD,UAAM,UAAU,gBAAgB,IAAI,CAAC,mBAAmB;AACtD,YAAM,kBAAiC;AAAA,QACrC,IAAI,eAAe;AAAA,MACrB;AAEA,UAAI;AACF,eAAO,mCAAoB,MAAM,eAAe;AAAA,MAClD,SAAS,OAAO;AACd,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,QAAQ,OAAgB,QAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBAAkB,MAAwC;AACtE,UAAM,gBAAgB,MAAe,MAAM,IAAI;AAE/C,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,cAAc,IAAI,OAAO,iBAAiB;AACxC,cAAM,gBAAgB,aAAa,KAAK,MAAM,GAAG;AAEjD,cAAM,gBAA+B;AAAA,UACnC,IAAI,cAAc,CAAC;AAAA,UACnB,UACE,cAAc,WAAW,IACpB,cAAc,CAAC,IAChB;AAAA,UACN,WACE,cAAc,WAAW,IACpB,cAAc,CAAC,IACf,cAAc,CAAC;AAAA,QACxB;AAEA,YAAI;AACF,iBAAO,mCAAoB,MAAM,aAAa;AAAA,QAChD,SAAS,OAAO;AACd,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,QAAQ,OAAgB,QAAQ;AAAA,EACzC;AACF;;;ACpNA,IAAAC,iBASO;AACP,oBAA4C;AAC5C,qBAAmB;;;ACXnB,IAAqB,WAArB,cAAsC,MAAM;AAAA,EAC1C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAqB,qBAArB,cAAgD,MAAM;AAAA,EACpD,cAAc;AACZ,UAAM,6DAA6D;AAEnE,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAAC,iBAkBO;AAQP,IAAqB,gBAArB,cACU,oBAEV;AAAA,EAGS,YAAY,SAA4B,KAAwB;AACrE,UAAM,iCAAkB,KAAK,QAAQ,OAAO;AAE5C,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAA2C;AAC7D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,SAAK,qBAAK;AAChB,QAAI,OAAO,CAAC,OAAO,cAAc,EAAE;AAEnC,QAAI,MAAM,MAAM;AACd,aAAO,CAAC,GAAG,MAAM,MAAM,IAAI;AAAA,IAC7B;AAEA,WAAO,CAAC,GAAG,MAAM,MAAM,MAAM,OAAO;AAEpC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAC/B,UAAM,MAAM,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,CAAC;AAEpD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,KAAK,OAAyC;AACzD,oCAAiB,MAAM,KAAK;AAE5B,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,GAAG,CAAC;AAEnE,QAAI,KAAK,UAAU,GAAG;AACpB,YAAM,IAAI;AAAA,QACR,2BAA2B,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,GAAG;AAClB,YAAM,IAAI;AAAA,QACR,2BAA2B,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AAEA,WAAO,KAAK,KAAK,CAAC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,SAAyB;AACpC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OAAO,OAAyC;AAC3D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,OAAO,CAAC,OAAO,YAAY,MAAM,EAAE;AACzC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,KAAK,OAAyD;AACzE,qCAAkB,MAAM,KAAK;AAE7B,QAAI,OAAO,CAAC,OAAO,QAAQ;AAE3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAE9C,UAAM,kBAAkB,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,CAAC,SAAS;AACjE,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,UAAM,aAAa,gBAAgB,IAAI,CAAC,SAAS;AAC/C,YAAM,YAAY,KAAK,MAAM,GAAG;AAChC,aAAO;AAAA,QACL,IAAI,UAAU,CAAC;AAAA,QACf,SAAS,UAAU,CAAC;AAAA,QACpB,QAAQ;AAAA,UACN,MAAM,UAAU,CAAC;AAAA,UACjB,OAAO,UAAU,CAAC;AAAA,QACpB;AAAA,QACA,WACE,OAAO,UAAU,CAAC,MAAM,WAAW,SAAS,UAAU,CAAC,CAAC,IAAI;AAAA,MAChE;AAAA,IACF,CAAC;AAED,UAAM,UAAU,WAAW,OAAO,KAAK,SAAS,KAAK,IAAI,CAAC;AAE1D,WAAO,KAAK;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,MAAM,OAA2C;AAC5D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,UAAU,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,KAAK,CAAC;AACpD,WAAO,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,SAAS,KAA6B;AAC5C,WAAO,4BAAa,UAAU,GAAG,EAAE;AAAA,EACrC;AACF;;;ACxLA,IAAAC,iBAOO;;;ACPP,IAAAC,iBAKO;AACP,IAAAC,mBAAe;AAOf,IAAqB,kBAArB,cAA6C,oBAAoB;AAAA,EAG/D,YAAY,SAA4B;AACtC,UAAM,iCAAkB,KAAK,UAAU,OAAO;AAHhD,SAAQ,QAA0B,oBAAI,IAAI;AAAA,EAI1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OACX,MACA,MACA,QACsB;AACtB,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,UAAM,SAAS,KAAK,UAAU,UAAU;AACxC,UAAM,iBAAAC,QAAG,UAAU,MAAM,QAAQ;AAAA,MAC/B,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,KACX,MACA,QACsB;AACtB,QAAI,KAAK,MAAM,IAAI,IAAI,GAAG;AAExB,aAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IAC5B;AAGA,UAAM,OAAO,MAAM,iBAAAA,QAAG,SAAS,MAAM;AAAA,MACnC,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,OAAO,KAAK,YAAY,IAAI;AAClC,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,OACX,MACA,MACA,QACsB;AACtB,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,UAAM,SAAS,KAAK,UAAU,UAAU;AACxC,UAAM,iBAAAA,QAAG,UAAU,MAAM,QAAQ;AAAA,MAC/B,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,MAAuB;AACvC,WAAO,KAAK,UAAU,MAAM,MAAM,KAAK,QAAQ,KAAK,KAAK,WAAW;AAAA,EACtE;AAAA,EAEQ,YAAY,MAAuB;AACzC,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AACF;;;AD3FA,IAAqB,cAArB,MAAiC;AAAA,EAG/B,YAAY,iBAAkC;AAC5C,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,MAAiC;AAC5C,QAAI;AACF,aAAO,MAAM,KAAK,gBAAgB;AAAA,QACvB,OAAO;AAAA,QAChB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,IAAI,OAAoC;AACnD,iCAAc,MAAM,KAAK;AAEzB,UAAM,eAAwB,OAAO;AAErC,UAAM,WAAqB;AAAA,MACzB,GAAG;AAAA,IACL;AAEA,QAAI,SAAS,aAAa,8BAAe,KAAK,OAAO;AAAA,IAGrD;AAEA,UAAM,KAAK,gBAAgB,OAAO,UAAU,cAAc,6BAAc;AAExE,WAAO;AAAA,EACT;AACF;;;AJ5BA,IAAqBC,cAArB,MAAgC;AAAA,EAMvB,YAAY,SAA4B,aAA0B;AACvE,SAAK,UAAU;AACf,SAAK,QAAQ,IAAI,eAAAC,QAAO;AAAA,MACtB,aAAa;AAAA;AAAA,IACf,CAAC;AACD,SAAK,gBAAgB,IAAI,cAAc,SAAS,KAAK,GAAG;AACxD,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAsB;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,aAA4B;AACvC,UAAM,SAAS,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC;AAC/C,SAAK,UAAU,OAAO,OAAO,QAAQ,eAAe,EAAE,EAAE,KAAK;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,KACX,MACA,SACe;AACf,QAAI,OAAO,CAAC,MAAM;AAElB,QAAI,SAAS,eAAe;AAC1B,aAAO,CAAC,GAAG,MAAM,oBAAoB,QAAQ,aAAa,EAAE;AAAA,IAC9D;AAEA,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,eAAe,IAAI;AAC9B,UAAM,KAAK,WAAW,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAa,MACX,KACA,MACA,SACe;AACf,QAAI,OAAO,CAAC,SAAS,YAAY;AAEjC,QAAI,SAAS,QAAQ;AACnB,aAAO,CAAC,GAAG,MAAM,YAAY,QAAQ,MAAM;AAAA,IAC7C;AAEA,QAAI,SAAS,OAAO;AAClB,aAAO,CAAC,GAAG,MAAM,WAAW,QAAQ,MAAM,SAAS,CAAC;AAAA,IACtD;AAEA,QAAI,SAAS,iBAAiB,MAAM;AAClC,aAAO,CAAC,GAAG,MAAM,iBAAiB;AAAA,IACpC;AAEA,UAAM,KAAK,IAAI,MAAM,CAAC,GAAG,MAAM,KAAK,GAAG,CAAC;AACxC,UAAM,KAAK,eAAe,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,IAAI,MAAcC,QAAgC;AAC7D,UAAM,OAAO,CAAC,OAAO,MAAM,GAAGA,MAAK;AAEnC,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,OACX,MACA,MACA,SACe;AACf,UAAM,KAAK,qBAAqB,MAAM,IAAI;AAE1C,QAAI,OAAO,CAAC,QAAQ;AAEpB,QAAI,SAAS,UAAU,MAAM;AAC3B,aAAO,CAAC,GAAG,MAAM,YAAY,IAAI;AAAA,IACnC,OAAO;AACL,aAAO,CAAC,GAAG,MAAM,IAAI;AAAA,IACvB;AAEA,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,MAAM,MAAc,MAAuB,QAAgB;AACtE,UAAM,OAAO,CAAC,SAAS,KAAK,IAAI,IAAI,MAAM;AAC1C,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAa,KAAK,MAA6B;AAC7C,UAAM,OAAO,CAAC,MAAM;AACpB,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OAAO,MAAc,SAAgC;AAChE,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,OAAO;AAAA,MACX;AAAA,MACA,aAAa,OAAO;AAAA,MACpB,YAAY,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,IACtC;AACA,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,IACX,MACA,SACsB;AACtB,QAAI,OAAO,CAAC,KAAK;AAEjB,QAAI,SAAS,SAAS,MAAM;AAC1B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,QAAQ,QAAQ,IAAI,MAAM,QAAQ,QAAQ,MAAM,MAAM;AAAA,MAC3D;AAAA,IACF;AAEA,QAAI,SAAS,OAAO;AAClB,aAAO,CAAC,GAAG,MAAM,eAAe,QAAQ,KAAK,EAAE;AAAA,IACjD;AAEA,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAED,UAAM,kBAAkB,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,CAAC,SAAS;AACjE,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,UAAM,aAAa,gBAAgB,IAAI,CAAC,SAAS;AAC/C,YAAM,YAAY,KAAK,MAAM,GAAG;AAChC,aAAO;AAAA,QACL,MAAM,UAAU,CAAC;AAAA,QACjB,SAAS,UAAU,CAAC;AAAA,QACpB,QAAQ;AAAA,UACN,MAAM,UAAU,CAAC;AAAA,UACjB,OAAO,UAAU,CAAC;AAAA,QACpB;AAAA,QACA,WAAW,SAAS,UAAU,CAAC,CAAC;AAAA,QAChC,KAAK,KAAK,iBAAiB,UAAU,CAAC,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAED,WAAO,WAAW,OAAO,KAAK,YAAY,KAAK,IAAI,CAAC;AAAA,EACtD;AAAA,EAEO,iBAAiB,SAAiB;AACvC,QAAI,UAA8B;AAGlC,cAAU,QAAQ,QAAQ,SAAS,EAAE;AAErC,QACE,QAAQ,KAAK,MAAM,MACnB,0BAAW,UAAU,OAAO,EAAE,YAAY,OAC1C;AACA,gBAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,wBAAwB,MAAc,MAAc;AAC/D,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,4BAA4B,MAAc,MAAc;AACnE,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,0BAA0B,MAAc,MAAc;AACjE,UAAM,OAAO,MAAM,QAAQ,IAAI;AAAA,MAC7B,KAAK,wBAAwB,MAAM,IAAI;AAAA,MACvC,KAAK,4BAA4B,MAAM,IAAI;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,MACL,SAAS,KAAK,CAAC;AAAA,MACf,SAAS,KAAK,CAAC;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,qBAAqB,MAAc,MAAc;AAC7D,UAAM,KAAK,IAAI,MAAM,CAAC,oBAAoB,oBAAoB,IAAI,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,WAAW,MAA6B;AACpD,UAAM,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,CAAC;AACvC,UAAM,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,OAAO,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,eAAe,MAAc;AACzC,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,eAAe,CAAC,UAAU,WAAW,aAAa,KAAK,IAAI;AACjE,UAAM,gBAAgB,CAAC,UAAU,WAAW,cAAc,KAAK,KAAK;AACpE,UAAM,KAAK,IAAI,MAAM,YAAY;AACjC,UAAM,KAAK,IAAI,MAAM,aAAa;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAY,KAAgC;AAClD,WAAO,+BAAgB,UAAU,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,IAAI,MAAc,MAAqC;AACnE,UAAM,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,yBAAW,KAAK,MAAM,IAAI,CAAC;AACrE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,QAAQ,KAAK,OAAO,kBAAkB,KAAK;AAAA,UACzC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AJtYA,IAAqB,eAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA;AACA,UAAM,iCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,WAAW,MAAM,KAAK,4BAA4B,MAAM,QAAQ;AACtE,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM,QAAQ;AACnD,UAAM,YAAqB,OAAO;AAAA,MAChC,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AACA,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AAEA,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,MACA,aAAS,iCAAiB;AAAA,MAC1B,WAAW,SAAS;AAAA,MACpB,UAAU,SAAS;AAAA,MACnB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,iBAAAC,QAAG,SAAS,MAAM,UAAU,SAAS;AAC3C,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,YAAM,KAAK,OAAO,EAAE,GAAG,WAAW,WAAW,MAAM,UAAU,CAAC;AAC9D,YAAM;AAAA,IACR;AAEA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,eAAe,SAAS,CAAC;AACjE,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAuC;AACvD,mCAAgB,MAAM,KAAK;AAE3B,UAAM,YAAY,MAAM,KAAK,gBAAgB;AAAA,MAClC,OAAO,UAAU,MAAM,WAAW,MAAM,IAAI,MAAM,QAAQ;AAAA,MACnE;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,gBAAgB,MAAM,KAAK,KAAK,KAAK;AAI3C,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,iCAAiB;AAAA,IAC5B;AAEA,QAAI,MAAM,aAAa;AAGrB,YAAM,WAAW,MAAM,KAAK;AAAA,QAC1B,MAAM;AAAA,MACR;AACA,YAAM,OAAO,MAAM,KAAK,aAAa,MAAM,WAAW;AACtD,YAAM,gBAAyB,OAAO;AAAA,QACpC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AACA,YAAM,YAAqB,OAAO;AAAA,QAChC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAGA,YAAM,iBAAAA,QAAG,OAAO,aAAa;AAC7B,YAAM,iBAAAA,QAAG,SAAS,MAAM,aAAa,SAAS;AAG9C,gBAAU,YAAY,SAAS;AAC/B,gBAAU,WAAW,SAAS;AAC9B,gBAAU,OAAO;AAAA,IACnB;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAwC;AAC1D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,YAAqB,OAAO;AAAA,MAChC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,iBAAAA,QAAG,OAAO,SAAS;AACzB,UAAM,iBAAAA,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,eAAe,SAAS,CAAC;AACjE,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KAAK,OAAuD;AACvE,oCAAiB,MAAM,KAAK;AAE5B,UAAM,kBAAkB,MAAM,KAAK;AAAA,MACjC,8BAAe,KAAK;AAAA,MACpB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,gBAAgB,IAAI,CAAC,mBAAmB;AACtC,YAAI,CAAC,eAAe,UAAU;AAC5B,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,eAAe;AAAA,UACnB,UAAU,eAAe;AAAA,QAC3B,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB,KAAK;AAAA,MAC3B;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,MAAM,OAA0C;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SACJ,MAAM,KAAK,eAAe,8BAAe,KAAK,OAAO,MAAM,SAAS,GACpE;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,KAAuC;AACpD,WAAO,2BAAY,UAAU,GAAG,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,aAAa,MAAc;AACvC,YAAQ,MAAM,iBAAAA,QAAG,KAAK,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,QACZ,WACA,WACgB;AAChB,UAAM,YAAqB,OAAO;AAAA,MAChC;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAEA,UAAM,QAAe;AAAA,MACnB,GAAG;AAAA,MACH,cAAc;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,4BAA4B,UAAkB;AAC1D,UAAM,YAAY,MAAM,iBAAAA,QAAG,KAAK,QAAQ,GAAG;AAI3C,QAAI,WAAW,OAAQ,KAAK;AAC1B,YAAM,aAAa,MAAM,iBAAAA,QAAG,SAAS,QAAQ;AAC7C,cAAI,cAAAC,SAAM,WAAW,SAAS,CAAC,MAAM,MAAM;AACzC,eAAO;AAAA,UACL,WAAW,wCAAyB,KAAK;AAAA,UACzC,UAAU,uCAAwB,KAAK,eAAe;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAGA,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,WAAW;AACrD,UAAM,WAAW,MAAM,iBAAiB,QAAQ;AAEhD,UAAM,SAAS,uCAAwB,MAAM;AAAA,MAC3C,WAAW,UAAU;AAAA,MACrB,UAAU,UAAU;AAAA,IACtB,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AUtUA,IAAAC,iBAyBO;AACP,IAAAC,mBAAe;AASf,IAAqB,oBAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA;AACA,UAAM,iCAAkB,KAAK,YAAY,OAAO;AAEhD,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAmD;AACrE,0CAAuB,MAAM,KAAK;AAElC,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,iBAA0B,OAAO,WAAW,MAAM,WAAW,EAAE;AACrE,UAAM,qBAA8B,OAAO;AAAA,MACzC,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,iBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,MACA,MAAM;AAAA,QACJ,cAAU,qBAAK,MAAM,KAAK,QAAQ;AAAA,QAClC,YAAQ,qBAAK,MAAM,KAAK,MAAM;AAAA,MAChC;AAAA,MACA,aAAS,iCAAiB;AAAA,IAC5B;AAEA,UAAM,iBAAAC,QAAG,UAAU,cAAc;AACjC,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,kBAAkB,CAAC;AAC3D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAiD;AACjE,wCAAqB,MAAM,KAAK;AAEhC,UAAM,aAAa,MAAM,KAAK,gBAAgB;AAAA,MACnC,OAAO,eAAe,MAAM,WAAW,MAAM,EAAE;AAAA,MACxD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,OAAO,OAAmD;AACrE,0CAAuB,MAAM,KAAK;AAElC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,qBAA8B,OAAO;AAAA,MACzC,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,qBAAqB,MAAM,KAAK,KAAK,KAAK;AAEhD,UAAM,iBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,iCAAiB;AAAA,IAC5B;AAoJA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,kBAAkB,CAAC;AAC3D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAChE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAA6C;AAC/D,0CAAuB,MAAM,KAAK;AAElC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,iBAA0B,OAAO;AAAA,MACrC,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAA,QAAG,OAAO,cAAc;AAC9B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,cAAc,CAAC;AACvD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KACX,OACoC;AACpC,yCAAsB,MAAM,KAAK;AAEjC,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,8BAAe,KAAK;AAAA,MACpB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,UAAU;AAAA,QAChB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA+C;AAChE,0CAAuB,MAAM,KAAK;AAElC,UAAM,SACJ,MAAM,KAAK,eAAe,8BAAe,KAAK,YAAY,MAAM,SAAS,GACzE;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,KAA4C;AAC9D,WAAO,oCAAqB,UAAU,GAAG,EAAE;AAAA,EAC7C;AACF;;;AC5VA,IAAAC,kBA2BO;AACP,IAAAC,mBAAe;;;AC5Bf,IAAAC,iBA2BO;AACP,IAAAC,mBAAe;AAWf,IAAqB,eAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA,cACA;AACA,UAAM,iCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AAEA,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,MACA,aAAS,iCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAuC;AACvD,mCAAgB,MAAM,KAAK;AAE3B,UAAM,YAAY,MAAM,KAAK,gBAAgB;AAAA,MAClC,OAAO,UAAU,MAAM,WAAW,MAAM,IAAI,MAAM,QAAQ;AAAA,MACnE;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,gBAAgB,MAAM,KAAK,KAAK,KAAK;AAE3C,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,iCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAwC;AAC1D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAC,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KAAK,OAAuD;AACvE,oCAAiB,MAAM,KAAK;AAE5B,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,8BAAe,KAAK;AAAA,MACpB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,YAAI,CAAC,UAAU,UAAU;AACvB,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,UAAU;AAAA,UACd,UAAU,UAAU;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA0C;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SACJ,MAAM,KAAK,eAAe,8BAAe,KAAK,OAAO,MAAM,SAAS,GACpE;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,KAAuC;AACpD,WAAO,+BAAgB,UAAU,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,SAAS,OAA2B;AAC/C,uCAAoB,MAAM,KAAK;AAE/B,UAAM,QAAQ,MAAM,KAAK,KAAK,KAAK;AACnC,UAAM,kBAAc,6CAA6B,MAAM,UAAU;AAWjE,WAAO,YAAY,UAAU,MAAM,OAAO;AAAA,EAC5C;AACF;;;ADnLA,IAAqB,eAArB,cACU,oBAEV;AAAA,EAME,YACE,SACA,iBACA,YACA,mBACA,cACA;AACA,UAAM,kCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,SAAK,sBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AACA,UAAM,aAAa,MAAM,KAAK,kBAAkB,KAAK;AAAA,MACnD,WAAW,MAAM;AAAA,MACjB,IAAI,MAAM;AAAA,IACZ,CAAC;AAED,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAKA,UAAM,YAAuB;AAAA,MAC3B,UAAU;AAAA,MACV;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,iBAAiB,MAAM;AAAA,MACvB,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAuC;AACvD,oCAAgB,MAAM,KAAK;AAE3B,UAAM,YAAY,MAAM,KAAK,gBAAgB;AAAA,MAClC,OAAO;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,aAAa,MAAM,KAAK,kBAAkB,KAAK;AAAA,MACnD,WAAW,MAAM;AAAA,MACjB,IAAI,MAAM;AAAA,IACZ,CAAC;AAED,UAAM,KAAK;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAEA,UAAM,gBAAgB,MAAM,KAAK,KAAK;AAAA,MACpC,WAAW,MAAM;AAAA,MACjB,cAAc,MAAM;AAAA,MACpB,IAAI,MAAM;AAAA,MACV,UAAU,MAAM;AAAA,IAClB,CAAC;AAED,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,iBAAiB,MAAM;AAAA,MACvB,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAwC;AAC1D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAC,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KAAK,OAAyB;AACzC,sCAAkB,MAAM,KAAK;AAE7B,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,+BAAe,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,YAAI,CAAC,UAAU,UAAU;AACvB,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,cAAc,MAAM;AAAA,UACpB,IAAI,UAAU;AAAA,UACd,UAAU,UAAU;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA2C;AAC5D,uCAAmB,MAAM,KAAK;AAE9B,YACE,MAAM,KAAK;AAAA,MACT,+BAAe,KAAK;AAAA,MACpB,MAAM;AAAA,MACN,MAAM;AAAA,IACR,GACA;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,QAAQ,KAAuC;AACpD,WAAO,4BAAY,UAAU,GAAG,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,wBACZ,WACA,cACA,iBACA,kBACA;AACA,UAAM,QAAQ;AAAA,MACZ,gBAAgB,IAAI,OAAO,cAAc;AACvC,cAAM,aAAa,iBAAiB,KAAK,CAAC,QAAQ;AAChD,cAAI,IAAI,OAAO,UAAU,cAAc;AACrC,mBAAO;AAAA,UACT;AACA,iBAAO;AAAA,QACT,CAAC;AAED,YAAI,CAAC,YAAY;AACf,gBAAM,IAAI;AAAA,YACR,0BAA0B,UAAU,YAAY,0BAA0B,YAAY;AAAA,UACxF;AAAA,QACF;AAEA,cAAM,aAAS,8CAA6B,UAAU;AACtD,cAAM,QAAQ,MAAM,KAAK,aAAa,KAAK;AAAA,UACzC,GAAG,UAAU;AAAA,UACb;AAAA,QACF,CAAC;AACD,eAAO,MAAM,MAAM,OAAO;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AE7RA,IAAAC,kBA8BO;AACP,IAAAC,mBAAe;AACf,IAAAC,aAAe;AACf,IAAAC,eAAiB;AACjB,oBAAmB;;;AClCnB,IAAqB,sBAArB,cAAiD,MAAM;AAAA,EACrD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAAC,kBAKO;AAUP,IAAqB,gBAArB,cAA2C,oBAAoB;AAAA,EAI7D,YACE,SACA,cACA,mBACA;AACA,UAAM,kCAAkB,KAAK,QAAQ,OAAO;AAE5C,SAAK,eAAe;AACpB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OAAO,WAAmB,OAAe,UAAqB;AACzE,UAAM,UAA0B,CAAC;AACjC,UAAM,kBAAkB,MAAM,KAAK;AAEnC,QAAI,oBAAoB,IAAI;AAC1B,aAAO;AAAA,IACT;AAEA,UAAM,kBACJ,MAAM,QAAQ,IAAI,CAAC,KAAK,aAAa,KAAK,EAAE,WAAW,QAAQ,MAAM,CAAC,CAAC,CAAC,GACxE,KAAK;AAEP,mBAAe,QAAQ,CAAC,kBAAkB;AACxC,oBAAc,KAAK,KAAK,EAAE,QAAQ,CAAC,SAAS;AAC1C,cAAM,SAAuB;AAAA,UAC3B,IAAI,KAAK;AAAA,UACT,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,UACX,SAAS,CAAC;AAAA,QACZ;AAEA,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,gBAAM,cAAc,OAAO,KAAK;AAChC,cACE,YAAY,YAAY,EAAE,SAAS,gBAAgB,YAAY,CAAC,GAChE;AACA,kBAAM,aAAa,YAChB,YAAY,EACZ,QAAQ,gBAAgB,YAAY,CAAC;AACxC,kBAAM,WAAW,aAAa,gBAAgB;AAE9C,mBAAO,QAAQ,KAAK;AAAA,cAClB;AAAA,cACA,QAAQ,KAAK;AAAA,gBACX,YAAY,UAAU,GAAG,UAAU;AAAA,gBACnC;AAAA,cACF;AAAA,cACA,OAAO,YAAY,UAAU,YAAY,QAAQ;AAAA,cACjD,QAAQ,KAAK;AAAA,gBACX,YAAY,UAAU,UAAU,YAAY,MAAM;AAAA,gBAClD;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAEA,YAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,kBAAQ,KAAK,MAAM;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,OAAe,IAAqB,QAAQ,IAAI;AAC/D,QAAI,OAAO,SAAS;AAClB,aAAO,GAAG,MAAM,UAAU,MAAM,SAAS,OAAO,MAAM,MAAM,CAAC;AAAA,IAC/D,OAAO;AACL,aAAO,GAAG,MAAM,UAAU,GAAG,KAAK,CAAC;AAAA,IACrC;AAAA,EACF;AACF;;;AFjDA,IAAqB,iBAArB,cACU,oBAEV;AAAA,EAUE,YACE,SACA,iBACA,aACA,YACA,eACA,cACA,mBACA,cACA,cACA;AACA,UAAM,kCAAkB,KAAK,SAAS,OAAO;AAE7C,SAAK,kBAAkB;AACvB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,oBAAoB;AACzB,SAAK,eAAe;AACpB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAA6C;AAC/D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,SAAK,sBAAK;AAChB,UAAM,kBAAmC;AAAA,MACvC,QAAQ;AAAA,QACN,SAAS,KAAK;AAAA,QACd,WAAW,CAAC,KAAK,MAAM;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,cAA2B;AAAA,MAC/B,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,MACA,aAAa,MAAM,eAAe;AAAA,MAClC,UAAU,OAAO,OAAO,CAAC,GAAG,iBAAiB,MAAM,QAAQ;AAAA,MAC3D,aAAS,kCAAiB;AAAA,MAC1B,aAAa,KAAK,QAAQ;AAAA;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAEA,UAAM,cAAuB,OAAO,QAAQ,EAAE;AAE9C,UAAM,iBAAAC,QAAG,UAAU,WAAW;AAE9B,QAAI;AACF,YAAM,KAAK,sBAAsB,WAAW;AAC5C,YAAM,KAAK,gBAAgB,WAAW;AACtC,YAAM,KAAK,WAAW,KAAK,aAAa,EAAE,eAAe,OAAO,CAAC;AACjE,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACS,OAAO,YAAY,EAAE;AAAA,QAC9B;AAAA,MACF;AACA,YAAM,KAAK,WAAW,IAAI,aAAa,CAAC,GAAG,CAAC;AAC5C,YAAM,KAAK,WAAW;AAAA,QACpB;AAAA,QACA,GAAG,oCAAoB,KAAK,IAAI;AAAA,MAClC;AACA,YAAM,KAAK,WAAW,OAAO,aAAa,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IACpE,SAAS,OAAO;AAEd,YAAM,KAAK,OAAO;AAAA,QAChB;AAAA,MACF,CAAC;AACD,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAA2C;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAAA,MACpC,OAAO,YAAY,MAAM,EAAE;AAAA,MACpC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAA6C;AAC/D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,cAAuB,OAAO,QAAQ,MAAM,EAAE;AACpD,UAAM,WAAoB,OAAO,YAAY,MAAM,EAAE;AACrD,UAAM,kBAAkB,MAAM,KAAK,KAAK,KAAK;AAE7C,UAAM,cAA2B;AAAA,MAC/B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB,OAAO,aAAa,UAAU,iCAAiB;AAC1E,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,QAAQ,CAAC;AACjD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,QAAQ,OAA2C;AAC9D,yCAAqB,MAAM,KAAK;AAEhC,UAAM,UAAU,MAAM,KAAK,KAAK,KAAK;AACrC,UAAM,cAAuB,OAAO,QAAQ,QAAQ,EAAE;AAEtD,QAAI,cAAAC,QAAO,GAAG,QAAQ,aAAa,KAAK,QAAQ,OAAO,GAAG;AAExD,YAAM,IAAI;AAAA,QACR,wDAAwD,QAAQ,WAAW,8CAA8C,KAAK,QAAQ,OAAO;AAAA,MAC/I;AAAA,IACF;AAEA,QAAI,cAAAA,QAAO,GAAG,QAAQ,aAAa,KAAK,QAAQ,OAAO,GAAG;AAExD;AAAA,IACF;AAGA,UAAM,eAAe,MAAe;AAAA,MAClC,aAAAC,QAAK,QAAQ,WAAW,YAAY;AAAA,MACpC;AAAA,IACF;AAGA,UAAM,YACJ,MAAM,QAAQ;AAAA,MACZ,aAAa,IAAI,CAAC,SAAS;AACzB,eAAO,OACL,aAAAA,QAAK,KAAK,cAAc,KAAK,IAAI;AAAA,MAErC,CAAC;AAAA,IACH,GACA,IAAI,CAAC,kBAAkB;AACvB,aAAO,cAAc;AAAA,IACvB,CAAC;AAGD,UAAM,iBAAiB,SACpB,KAAK,CAAC,GAAG,MAAM;AACd,aAAO,cAAAD,QAAO,QAAQ,EAAE,IAAI,EAAE,EAAE;AAAA,IAClC,CAAC,EACA,OAAO,CAAC,YAAY;AACnB,UAAI,QAAQ,OAAO,SAAS;AAC1B,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAEH,aAAS,QAAQ,GAAG,QAAQ,eAAe,QAAQ,SAAS;AAC1D,YAAM,UAAU,eAAe,KAAK;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAGA,YAAM,cAAc,MAAM,KAAK,WAAW,KAAK,OAAO;AAAA,QACpD,MAAM;AAAA,QACN,SAAS,kDAAkD,QAAQ,EAAE;AAAA,MACvE,CAAC;AAED,UAAI;AACF,cAAM,QAAQ,IAAI,OAAO;AAGzB,gBAAQ,cAAc,QAAQ;AAC9B,cAAM,KAAK,OAAO,OAAO;AAGzB,cAAM,KAAK,WAAW,KAAK,OAAO;AAAA,UAChC,MAAM;AAAA,UACN,SAAS,qCAAqC,QAAQ,EAAE;AAAA,QAC1D,CAAC;AAGD,cAAM,KAAK,WAAW,KAAK,OAAO;AAAA,UAChC,MAAM;AAAA,UACN,IAAI,YAAY;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,OAAO;AAEd,cAAM,KAAK,WAAW,MAAM,aAAa,QAAQ,YAAY,EAAE;AAE/D,cAAM,IAAI;AAAA,UACR,8CAA8C,QAAQ,EAAE;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,OAAO,OAA0C;AAC5D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,iBAAAD,QAAG,OAAgB,OAAO,QAAQ,MAAM,EAAE,CAAC;AAAA,EACnD;AAAA,EAEA,MAAa,KACX,OACiC;AACjC,QAAI,OAAO;AACT,yCAAmB,MAAM,KAAK;AAAA,IAChC;AAEA,UAAM,aAAa,MAAM,KAAK,eAAe,+BAAe,KAAK,OAAO;AACxE,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,eAAO,KAAK,KAAK,EAAE,IAAI,UAAU,GAAG,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAa,QAAyB;AACpC,YAAQ,MAAM,KAAK,eAAe,+BAAe,KAAK,OAAO,GAAG;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,OAAO,WAAmB,OAAe,MAAiB;AACrE,WAAO,KAAK,cAAc,OAAO,WAAW,OAAO,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,KAAyC;AACxD,WAAO,kCAAkB,UAAU,GAAG,EAAE;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,aAAa,WAA2C;AACnE,UAAM,UAAU,MAAM,KAAK,KAAK,EAAE,IAAI,UAAU,CAAC;AACjD,UAAM,UAAU,MAAM,KAAK,aAAa,KAAK,EAAE,WAAW,OAAO,EAAE,CAAC,GAAG;AACvE,UAAM,eACJ,MAAM,KAAK,kBAAkB,KAAK,EAAE,WAAW,OAAO,EAAE,CAAC,GACzD;AAEF,UAAM,mBAAuC,MAAM,QAAQ;AAAA,MACzD,YAAY,IAAI,OAAO,eAAe;AACpC,cAAM,WACJ,MAAM,KAAK,aAAa,KAAK;AAAA,UAC3B;AAAA,UACA,cAAc,WAAW;AAAA,UACzB,OAAO;AAAA,QACT,CAAC,GACD;AACF,cAAM,cAAc,MAAM,QAAQ;AAAA,UAChC,QAAQ,IAAI,OAAO,UAAU;AAC3B,kBAAM,cAAc,MAAM,QAAQ;AAAA,cAChC,MAAM,gBAAgB,IAAI,OAAO,mBAAmB;AAClD,uBAAO,KAAK,aAAa,KAAK;AAAA,kBAC5B;AAAA,kBACA,IAAI,eAAe,WAAW;AAAA,kBAC9B,UAAU,eAAe,WAAW;AAAA,gBACtC,CAAC;AAAA,cACH,CAAC;AAAA,YACH;AAEA,mBAAO;AAAA,cACL,GAAG;AAAA,cACH,QAAQ;AAAA,YACV;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,UACL,GAAG;AAAA,UACH,SAAS;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,sBAAsB,MAA6B;AAC/D,UAAMG,WAAU,OAAO,OAAO,oCAAoB,MAAM;AAExD,UAAM,QAAQ;AAAA,MACZA,SAAQ,IAAI,OAAO,WAAW;AAC5B,cAAM,iBAAAH,QAAG,OAAO,aAAAE,QAAK,KAAK,MAAM,MAAM,CAAC;AACvC,cAAM,iBAAAF,QAAG,UAAU,aAAAE,QAAK,KAAK,MAAM,QAAQ,UAAU,GAAG,EAAE;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,gBAAgB,MAA6B;AACzD,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,IAIF;AACA,UAAM,iBAAAF,QAAG,UAAU,aAAAE,QAAK,KAAK,MAAM,YAAY,GAAG,MAAM,KAAK,WAAAE,QAAG,GAAG,CAAC;AAAA,EACtE;AACF;;;Ad3ZA,IAAqB,aAArB,MAAgC;AAAA,EAY9B,YAAY,OAAoC;AAC9C,UAAM,cAAc,4CAA4B,MAAM,KAAK;AAE3D,UAAM,WAA8B;AAAA,MAClC,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,MAAM;AAAA,UACJ,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU,OAAO,OAAO,CAAC,GAAG,UAAU,WAAW;AAEtD,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,OAAO;AACvD,SAAK,cAAc,IAAI,YAAY,KAAK,eAAe;AACvD,SAAK,aAAa,IAAIC,YAAW,KAAK,SAAS,KAAK,WAAW;AAE/D,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,oBAAoB,IAAI;AAAA,MAC3B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,gBAAgB,IAAI;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,QAAI,KAAK,QAAQ,gBAAgB,cAAc;AAC7C,cAAQ;AAAA,QACN,2BAA2B,KAAK,QAAQ,WAAW;AAAA,QACnD;AAAA,UACE,GAAG,KAAK;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,qBAAAC,QAAG,WAAoB,OAAO,QAAQ;AACtC,qBAAAA,QAAG,WAAoB,OAAO,GAAG;AACjC,qBAAAA,QAAG,aAAsB,OAAO,GAAG;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAO;AAChB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAoB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,WAA2B;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAAuB;AAChC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,cAAiC;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAwB;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAAuB;AAChC,WAAO,KAAK;AAAA,EACd;AACF;","names":["import_shared","import_fs_extra","import_shared","import_fs_extra","Path","Os","Fs","dirent","import_shared","import_lodash_es","filter","import_shared","import_shared","import_shared","import_shared","import_fs_extra","Fs","GitService","PQueue","files","Fs","IsSvg","import_shared","import_fs_extra","Fs","import_shared","import_fs_extra","import_shared","import_fs_extra","Fs","Fs","import_shared","import_fs_extra","import_os","import_path","import_shared","Fs","Semver","Path","folders","Os","GitService","Fs"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/service/AssetService.ts","../src/error/RequiredParameterMissingError.ts","../src/util/index.ts","../src/service/AbstractCrudService.ts","../src/service/GitService.ts","../src/error/GitError.ts","../src/error/NoCurrentUserError.ts","../src/service/GitTagService.ts","../src/service/UserService.ts","../src/service/JsonFileService.ts","../src/service/CollectionService.ts","../src/service/EntryService.ts","../src/service/SharedValueService.ts","../src/service/ProjectService.ts","../src/error/ProjectUpgradeError.ts","../src/service/SearchService.ts"],"sourcesContent":["import {\n constructorElekIoCoreSchema,\n type ConstructorElekIoCoreProps,\n type ElekIoCoreOptions,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport AssetService from './service/AssetService.js';\nimport CollectionService from './service/CollectionService.js';\nimport EntryService from './service/EntryService.js';\nimport GitService from './service/GitService.js';\nimport JsonFileService from './service/JsonFileService.js';\nimport ProjectService from './service/ProjectService.js';\nimport SearchService from './service/SearchService.js';\nimport SharedValueService from './service/SharedValueService.js';\nimport UserService from './service/UserService.js';\nimport * as CoreUtil from './util/index.js';\n\n/**\n * elek.io Core\n *\n * Provides access to all services Core is offering\n */\nexport default class ElekIoCore {\n private readonly options: ElekIoCoreOptions;\n private readonly userService: UserService;\n private readonly gitService: GitService;\n private readonly jsonFileService: JsonFileService;\n private readonly assetService: AssetService;\n private readonly searchService: SearchService;\n private readonly projectService: ProjectService;\n private readonly collectionService: CollectionService;\n private readonly entryService: EntryService;\n private readonly sharedValueService: SharedValueService;\n\n constructor(props?: ConstructorElekIoCoreProps) {\n const parsedProps = constructorElekIoCoreSchema.parse(props);\n\n const defaults: ElekIoCoreOptions = {\n environment: 'production',\n version: '0.0.0',\n file: {\n json: {\n indentation: 2,\n },\n },\n };\n this.options = Object.assign({}, defaults, parsedProps);\n\n this.jsonFileService = new JsonFileService(this.options);\n this.userService = new UserService(this.jsonFileService);\n this.gitService = new GitService(this.options, this.userService);\n // this.gitService.getVersion(); // @todo currently throws an \"Error: Unable to find path to repository on disk.\"\n this.assetService = new AssetService(\n this.options,\n this.jsonFileService,\n this.gitService\n );\n this.collectionService = new CollectionService(\n this.options,\n this.jsonFileService,\n this.gitService\n );\n this.sharedValueService = new SharedValueService(\n this.options,\n this.jsonFileService,\n this.gitService,\n this.assetService\n );\n this.entryService = new EntryService(\n this.options,\n this.jsonFileService,\n this.gitService,\n this.collectionService,\n this.assetService,\n this.sharedValueService\n );\n this.searchService = new SearchService(\n this.options,\n this.assetService,\n this.collectionService\n );\n this.projectService = new ProjectService(\n this.options,\n this.jsonFileService,\n this.userService,\n this.gitService,\n this.searchService,\n this.assetService,\n this.collectionService,\n this.entryService\n );\n\n if (this.options.environment !== 'production') {\n console.info(\n `Initializing inside an \"${this.options.environment}\" environment`,\n {\n ...this.options,\n }\n );\n }\n\n Fs.mkdirpSync(CoreUtil.pathTo.projects);\n Fs.mkdirpSync(CoreUtil.pathTo.tmp);\n Fs.emptyDirSync(CoreUtil.pathTo.tmp);\n }\n\n /**\n * Utility / helper functions\n */\n public get util() {\n return CoreUtil;\n }\n\n /**\n *\n */\n public get user(): UserService {\n return this.userService;\n }\n\n /**\n * CRUD methods to work with Projects\n */\n public get projects(): ProjectService {\n return this.projectService;\n }\n\n /**\n * CRUD methods to work with Assets\n */\n public get assets(): AssetService {\n return this.assetService;\n }\n\n /**\n * CRUD methods to work with Collections\n */\n public get collections(): CollectionService {\n return this.collectionService;\n }\n\n /**\n * CRUD methods to work with Entries\n */\n public get entries(): EntryService {\n return this.entryService;\n }\n\n /**\n * CRUD methods to work with Values\n */\n public get sharedValues(): SharedValueService {\n return this.sharedValueService;\n }\n}\n","import {\n assetFileSchema,\n assetSchema,\n countAssetsSchema,\n createAssetSchema,\n currentTimestamp,\n deleteAssetSchema,\n listAssetsSchema,\n objectTypeSchema,\n readAssetSchema,\n serviceTypeSchema,\n supportedAssetExtensionSchema,\n supportedAssetMimeTypeSchema,\n supportedAssetTypeSchema,\n updateAssetSchema,\n uuid,\n type Asset,\n type AssetFile,\n type BaseFile,\n type CountAssetsProps,\n type CreateAssetProps,\n type DeleteAssetProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListAssetsProps,\n type PaginatedList,\n type ReadAssetProps,\n type UpdateAssetProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport IsSvg from 'is-svg';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport default class AssetService\n extends AbstractCrudService\n implements ExtendedCrudService<Asset>\n{\n private readonly jsonFileService: JsonFileService;\n private readonly gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.Enum.Asset, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new Asset\n */\n public async create(props: CreateAssetProps): Promise<Asset> {\n createAssetSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const fileType = await this.getSupportedFileTypeOrThrow(props.filePath);\n const size = await this.getAssetSize(props.filePath);\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n id,\n props.language,\n fileType.extension\n );\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n id,\n props.language\n );\n\n const assetFile: AssetFile = {\n ...props,\n objectType: 'asset',\n id,\n created: currentTimestamp(),\n extension: fileType.extension,\n mimeType: fileType.mimeType,\n size,\n };\n\n try {\n await Fs.copyFile(props.filePath, assetPath);\n await this.jsonFileService.create(\n assetFile,\n assetFilePath,\n assetFileSchema\n );\n } catch (error) {\n // To avoid partial data being added to the repository / git status reporting uncommitted files\n await this.delete({ ...assetFile, projectId: props.projectId });\n throw error;\n }\n\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Returns an Asset by ID and language\n */\n public async read(props: ReadAssetProps): Promise<Asset> {\n readAssetSchema.parse(props);\n\n const assetFile = await this.jsonFileService.read(\n CoreUtil.pathTo.assetFile(props.projectId, props.id, props.language),\n assetFileSchema\n );\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Updates given Asset\n *\n * Use the optional \"newFilePath\" prop to update the Asset itself\n */\n public async update(props: UpdateAssetProps): Promise<Asset> {\n updateAssetSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n props.id,\n props.language\n );\n const prevAssetFile = await this.read(props);\n\n // Overwrite old data with new\n // It's ok to have projectId inside props, since the prevAssetFile is read with the same data\n const assetFile: AssetFile = {\n ...prevAssetFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n if (props.newFilePath) {\n // Overwrite the file itself (in LFS folder)...\n\n const fileType = await this.getSupportedFileTypeOrThrow(\n props.newFilePath\n );\n const size = await this.getAssetSize(props.newFilePath);\n const prevAssetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n prevAssetFile.extension\n );\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n fileType.extension\n );\n\n // @todo use try catch to handle FS error and restore previous state\n await Fs.remove(prevAssetPath); // Need to explicitly remove old Asset, because it could have a different extension\n await Fs.copyFile(props.newFilePath, assetPath);\n\n // ...and update meta information\n assetFile.extension = fileType.extension;\n assetFile.mimeType = fileType.mimeType;\n assetFile.size = size;\n }\n\n await this.jsonFileService.update(\n assetFile,\n assetFilePath,\n assetFileSchema\n );\n await this.gitService.add(projectPath, [assetFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Deletes given Asset\n */\n public async delete(props: DeleteAssetProps): Promise<void> {\n deleteAssetSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const assetFilePath = CoreUtil.pathTo.assetFile(\n props.projectId,\n props.id,\n props.language\n );\n const assetPath = CoreUtil.pathTo.asset(\n props.projectId,\n props.id,\n props.language,\n props.extension\n );\n await Fs.remove(assetPath);\n await Fs.remove(assetFilePath);\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(props: ListAssetsProps): Promise<PaginatedList<Asset>> {\n listAssetsSchema.parse(props);\n\n const assetReferences = await this.listReferences(\n objectTypeSchema.Enum.asset,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n assetReferences.map((assetReference) => {\n if (!assetReference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n id: assetReference.id,\n language: assetReference.language,\n });\n })\n );\n\n const paginatedResult = this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n\n return paginatedResult;\n }\n\n public async count(props: CountAssetsProps): Promise<number> {\n countAssetsSchema.parse(props);\n\n const count = (\n await this.listReferences(objectTypeSchema.Enum.asset, props.projectId)\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is of type Asset\n */\n public isAsset(obj: BaseFile | unknown): obj is Asset {\n return assetSchema.safeParse(obj).success;\n }\n\n /**\n * Returns the size of an Asset in bytes\n *\n * @param path Path of the Asset to get the size from\n */\n private async getAssetSize(path: string) {\n return (await Fs.stat(path)).size;\n }\n\n /**\n * Creates an Asset from given AssetFile\n *\n * @param projectId The project's ID\n * @param assetFile The AssetFile to convert\n */\n private async toAsset(\n projectId: string,\n assetFile: AssetFile\n ): Promise<Asset> {\n const assetPath = CoreUtil.pathTo.asset(\n projectId,\n assetFile.id,\n assetFile.language,\n assetFile.extension\n );\n\n const asset: Asset = {\n ...assetFile,\n absolutePath: assetPath,\n };\n\n return asset;\n }\n\n /**\n * Returns the found and supported extension as well as mime type,\n * otherwise throws an error\n *\n * @param filePath Path to the file to check\n */\n private async getSupportedFileTypeOrThrow(filePath: string) {\n const fileSize = (await Fs.stat(filePath)).size;\n\n // Only try to parse potential SVG's\n // that are smaller than 500 kB\n if (fileSize / 1000 <= 500) {\n const fileBuffer = await Fs.readFile(filePath);\n if (IsSvg(fileBuffer.toString()) === true) {\n return {\n extension: supportedAssetExtensionSchema.Enum.svg,\n mimeType: supportedAssetMimeTypeSchema.Enum['image/svg+xml'],\n };\n }\n }\n\n // We do not use fileBuffer here again because fromFile() is recommended\n const { fileTypeFromFile } = await import('file-type');\n const fileType = await fileTypeFromFile(filePath);\n\n const result = supportedAssetTypeSchema.parse({\n extension: fileType?.ext,\n mimeType: fileType?.mime,\n });\n\n return result;\n }\n}\n","export default class RequiredParameterMissingError extends Error {\n constructor(parameter: string) {\n super(`Missing required parameter \"${parameter}\"`);\n\n this.name = 'RequiredParameterMissingError';\n }\n}\n","import { projectFolderSchema, uuidSchema } from '@elek-io/shared';\nimport { spawn, type SpawnOptionsWithoutStdio } from 'child_process';\nimport Fs from 'fs-extra';\nimport { filter, flatten, groupBy, uniq } from 'lodash-es';\nimport Os from 'os';\nimport Path from 'path';\n\n/**\n * The directory in which everything is stored and will be worked in\n *\n * @todo make the workingDirectory an elek option to be set via app.getPath('home') (electron instead of node)?\n */\nexport const workingDirectory = Path.join(Os.homedir(), 'elek.io');\n\n/**\n * A collection of often used paths\n */\nexport const pathTo = {\n tmp: Path.join(workingDirectory, 'tmp'),\n userFile: Path.join(workingDirectory, 'user.json'),\n // logs: Path.join(workingDirectory, 'logs'),\n\n projects: Path.join(workingDirectory, 'projects'),\n project: (projectId: string): string => {\n return Path.join(pathTo.projects, projectId);\n },\n projectFile: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), 'project.json');\n },\n // projectLogs: (projectId: string): string => {\n // return Path.join(pathTo.project(projectId), projectFolderSchema.Enum.logs);\n // },\n\n // public: (projectId: string): string => {\n // return Path.join(pathTo.project(projectId), 'public');\n // },\n\n lfs: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), projectFolderSchema.Enum.lfs);\n },\n\n collections: (projectId: string): string => {\n return Path.join(\n pathTo.project(projectId),\n projectFolderSchema.Enum.collections\n );\n },\n collection: (projectId: string, id: string) => {\n return Path.join(pathTo.collections(projectId), id);\n },\n collectionFile: (projectId: string, id: string) => {\n return Path.join(pathTo.collection(projectId, id), 'collection.json');\n },\n\n entries: (projectId: string, collectionId: string): string => {\n return Path.join(pathTo.collection(projectId, collectionId));\n },\n entryFile: (\n projectId: string,\n collectionId: string,\n id: string,\n language: string\n ) => {\n return Path.join(\n pathTo.entries(projectId, collectionId),\n `${id}.${language}.json`\n );\n },\n\n sharedValues: (projectId: string): string => {\n return Path.join(pathTo.project(projectId), 'shared-values');\n },\n sharedValueFile: (projectId: string, id: string, language: string) => {\n return Path.join(pathTo.sharedValues(projectId), `${id}.${language}.json`);\n },\n\n assets: (projectId: string): string => {\n return Path.join(\n pathTo.project(projectId),\n projectFolderSchema.Enum.assets\n );\n },\n assetFile: (projectId: string, id: string, language: string): string => {\n return Path.join(pathTo.assets(projectId), `${id}.${language}.json`);\n },\n asset: (\n projectId: string,\n id: string,\n language: string,\n extension: string\n ): string => {\n return Path.join(pathTo.lfs(projectId), `${id}.${language}.${extension}`);\n },\n};\n\n/**\n * Searches for a potential project ID in given path string and returns it\n *\n * Mainly used for logging inside the GitService, where we don't have a project ID,\n * but always have a path which could contain one. The ID is then used,\n * to log to the current project log, instead of logging to the main log file.\n *\n * @todo I really dont like this and I do not know how much performance we loose here\n */\nexport const fromPath = {\n projectId: (path: string): string | undefined => {\n const startsWith = 'projects/';\n const endsWith = '/';\n const start = path.indexOf(startsWith) + startsWith.length;\n // Return early\n if (start === -1) {\n return undefined;\n }\n const end = path.indexOf(endsWith, start);\n // Use path length if there is no ending \"/\"\n const result = path.substring(start, end === -1 ? path.length : end);\n if (result && uuidSchema.safeParse(result).success) {\n return result;\n }\n return undefined;\n },\n};\n\n/**\n * Returns a complete default type, hydrated with the partials of value\n */\nexport function assignDefaultIfMissing<T extends {}>(\n value: Partial<T> | undefined | null,\n defaultsTo: T\n): T {\n return Object.assign(defaultsTo, value);\n}\n\n/**\n * Used as parameter for filter() methods to assure,\n * only values not null, undefined or empty strings are returned\n *\n * @param value Value to check\n */\nexport function notEmpty<T>(value: T | null | undefined): value is T {\n if (value === null || value === undefined) {\n return false;\n }\n if (typeof value === 'string') {\n if (value.trim() === '') {\n return false;\n }\n }\n return true;\n}\n\nexport function isNoError<T>(item: T | Error): item is T {\n return item instanceof Error !== true;\n}\n\n/**\n * Basically a Promise.all() without rejecting if one promise fails to resolve\n */\nexport async function returnResolved<T>(promises: Promise<T>[]) {\n const toCheck: Promise<T | Error>[] = [];\n for (let index = 0; index < promises.length; index++) {\n const promise = promises[index];\n if (!promise) {\n throw new Error(`No promise found at index \"${index}\"`);\n }\n // Here comes the trick:\n // By using \"then\" and \"catch\" we are able to create an array of Project and Error types\n // without throwing and stopping the later Promise.all() call prematurely\n toCheck.push(\n promise\n .then((result) => {\n return result;\n })\n .catch((error) => {\n // Because the error parameter could be anything,\n // we need to specifically call an Error\n return new Error(error);\n })\n );\n }\n // Resolve all promises\n // Here we do not expect any error to fail the call to Promise.all()\n // because we caught it earlier and returning an Error type instead of throwing it\n const checked = await Promise.all(toCheck);\n // This way we can easily filter out any Errors by type\n // Note that we also need to use a User-Defined Type Guard here,\n // because otherwise TS does not recognize we are filtering the errors out\n // > | <\n return checked.filter(isNoError);\n}\n\n/**\n * Custom async typescript ready implementation of Node.js child_process\n *\n * @see https://nodejs.org/api/child_process.html\n * @see https://github.com/ralphtheninja/await-spawn\n */\nexport function spawnChildProcess(\n command: string,\n args: ReadonlyArray<string>,\n options?: SpawnOptionsWithoutStdio\n): Promise<string> {\n return new Promise((resolve, reject) => {\n const childProcess = spawn(command, args, options);\n let log = '';\n\n childProcess.stdout.on('data', (data) => {\n log += data;\n });\n\n childProcess.stderr.on('data', (data) => {\n log += data;\n });\n\n childProcess.on('error', (error) => {\n throw error;\n });\n\n childProcess.on('exit', (code) => {\n if (code === 0) {\n return resolve(log);\n }\n return reject(log);\n });\n });\n}\n\n/**\n * Returns all folders of given path\n */\nexport async function folders(path: string): Promise<Fs.Dirent[]> {\n const dirent = await Fs.readdir(path, { withFileTypes: true });\n return dirent.filter((dirent) => {\n return dirent.isDirectory();\n });\n}\n\n/**\n * Returns all files of given path which can be filtered by extension\n */\nexport async function files(\n path: string,\n extension?: string\n): Promise<Fs.Dirent[]> {\n const dirent = await Fs.readdir(path, { withFileTypes: true });\n return dirent.filter((dirent) => {\n if (extension && dirent.isFile() === true) {\n if (dirent.name.endsWith(extension)) {\n return true;\n }\n return false;\n }\n return dirent.isFile();\n });\n}\n\n/**\n * Returns the relative path for given path\n * by stripping out everything up to the working directory\n */\nexport function getRelativePath(path: string): string {\n let relativePath = path.replace(workingDirectory, '');\n if (relativePath.startsWith('/')) {\n relativePath = relativePath.substr(1);\n }\n return relativePath;\n}\n\n/**\n * Searches given array of objects for duplicates of given key and returns them\n *\n * @param arr Array with possible duplicate values\n * @param key Key of object T to get duplicates of\n */\nexport function getDuplicates<T>(arr: T[], key: keyof T) {\n const grouped = groupBy(arr, (item) => {\n return item[key];\n });\n return uniq(\n flatten(\n filter(grouped, (item) => {\n return item.length > 1;\n })\n )\n );\n}\n","import {\n fileReferenceSchema,\n gitCommitIconSchema,\n objectTypeSchema,\n type BaseFile,\n type ElekIoCoreOptions,\n type FileReference,\n type GitTag,\n type ObjectType,\n type PaginatedList,\n type ServiceType,\n type Sort,\n type SupportedAssetExtension,\n type SupportedLanguage,\n} from '@elek-io/shared';\nimport { orderBy, remove } from 'lodash-es';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\n\n/**\n * A base service that provides properties for most other services\n */\nexport default abstract class AbstractCrudService {\n public readonly type: ServiceType;\n public readonly options: ElekIoCoreOptions;\n\n /**\n * Dynamically generated git messages for operations\n */\n public readonly gitMessage: {\n create: string;\n update: string;\n delete: string;\n };\n\n /**\n * Do not instantiate directly as this is an abstract class\n */\n protected constructor(type: ServiceType, options: ElekIoCoreOptions) {\n this.type = type;\n this.options = options;\n this.gitMessage = {\n create: `${gitCommitIconSchema.enum.CREATE} Created ${this.type}`,\n update: `${gitCommitIconSchema.enum.UPDATE} Updated ${this.type}`,\n delete: `${gitCommitIconSchema.enum.DELETE} Deleted ${this.type}`,\n };\n }\n\n /**\n * Returns the filtered, sorted and paginated version of given list\n *\n * @todo Sorting and filtering requires all models to be loaded\n * from disk. This results in a huge memory spike before the\n * filtering and pagination takes effect - removing most of it again.\n * This approach is still better than returning everything and\n * letting the frontend handle it, since the memory usage would then be constant.\n * But this still could fill the memory limit of node.js (default 1,4 GB).\n *\n * @param list Array to filter, sort and paginate\n * @param sort Array of sort objects containing information about what to sort and how\n * @param filter Filter all object values of `list` by this string\n * @param limit Limit the result to this amount. If 0 is given, no limit is applied\n * @param offset Start at this index instead of 0\n */\n protected async paginate<T extends BaseFile | GitTag>(\n list: T[],\n sort: Sort<T>[] = [],\n filter = '',\n limit = 15,\n offset = 0\n ): Promise<PaginatedList<T>> {\n let result = list;\n const total = list.length;\n const normalizedFilter = filter.trim().toLowerCase();\n\n // Filter\n if (normalizedFilter !== '') {\n remove(result, (model) => {\n let key: keyof T;\n for (key in model) {\n const value = model[key];\n if (String(value).toLowerCase().includes(normalizedFilter)) {\n return false;\n }\n }\n return true;\n });\n }\n\n // Sort\n if (sort.length !== 0) {\n const keys = sort.map((value) => value.by);\n const orders = sort.map((value) => value.order);\n result = orderBy(result, keys, orders);\n }\n\n // Paginate\n if (limit !== 0) {\n result = result.slice(offset, offset + limit);\n }\n\n return {\n total,\n limit,\n offset,\n list: result,\n };\n }\n\n /**\n * Returns a list of all file references of given project and type\n *\n * @param type File type of the references wanted\n * @param projectId Project to get all asset references from\n * @param collectionId Only needed when requesting files of type \"Entry\"\n */\n protected async listReferences(\n type: ObjectType,\n projectId?: string,\n collectionId?: string\n ): Promise<FileReference[]> {\n switch (type) {\n case objectTypeSchema.Enum.asset:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(CoreUtil.pathTo.lfs(projectId)); // LFS folder is correct, since we want the extension of the file itself, not the AssetFile (.json)\n\n case objectTypeSchema.Enum.project:\n return this.getFolderReferences(CoreUtil.pathTo.projects);\n\n case objectTypeSchema.Enum.collection:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFolderReferences(CoreUtil.pathTo.collections(projectId));\n\n case objectTypeSchema.Enum.entry:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n if (!collectionId) {\n throw new RequiredParameterMissingError('collectionId');\n }\n return this.getFileReferences(\n CoreUtil.pathTo.collection(projectId, collectionId)\n );\n\n case objectTypeSchema.Enum.sharedValue:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(CoreUtil.pathTo.sharedValues(projectId));\n\n default:\n throw new Error(`Trying to list files of unsupported type \"${type}\"`);\n }\n }\n\n private async getFolderReferences(path: string): Promise<FileReference[]> {\n const possibleFolders = await CoreUtil.folders(path);\n const results = possibleFolders.map((possibleFolder) => {\n const folderReference: FileReference = {\n id: possibleFolder.name,\n };\n\n try {\n return fileReferenceSchema.parse(folderReference);\n } catch (error) {\n return null;\n }\n });\n\n return results.filter(CoreUtil.notEmpty);\n }\n\n /**\n * Searches for all files inside given folder,\n * parses their names and returns them as FileReference\n *\n * Ignores files not matching the [id].[language].[extension]\n * or [id].[extension] format for their names\n */\n private async getFileReferences(path: string): Promise<FileReference[]> {\n const possibleFiles = await CoreUtil.files(path);\n\n const results = await Promise.all(\n possibleFiles.map(async (possibleFile) => {\n const fileNameArray = possibleFile.name.split('.');\n\n const fileReference: FileReference = {\n id: fileNameArray[0],\n language:\n fileNameArray.length === 3\n ? (fileNameArray[1] as SupportedLanguage)\n : undefined,\n extension:\n fileNameArray.length === 2\n ? (fileNameArray[1] as SupportedAssetExtension)\n : (fileNameArray[2] as SupportedAssetExtension),\n };\n\n try {\n return fileReferenceSchema.parse(fileReference);\n } catch (error) {\n return null;\n }\n })\n );\n\n return results.filter(CoreUtil.notEmpty);\n }\n}\n","import {\n gitCommitSchema,\n uuidSchema,\n type ElekIoCoreOptions,\n type GitCloneOptions,\n type GitCommit,\n type GitInitOptions,\n type GitLogOptions,\n type GitSwitchOptions,\n} from '@elek-io/shared';\nimport { GitProcess, type IGitResult } from 'dugite';\nimport PQueue from 'p-queue';\nimport GitError from '../error/GitError.js';\nimport NoCurrentUserError from '../error/NoCurrentUserError.js';\nimport GitTagService from './GitTagService.js';\nimport UserService from './UserService.js';\n\n/**\n * Service that manages Git functionality\n *\n * Uses dugite Node.js bindings for Git to be fully compatible\n * and be able to leverage Git LFS functionality\n * @see https://github.com/desktop/dugite\n *\n * Heavily inspired by the GitHub Desktop app\n * @see https://github.com/desktop/desktop\n *\n * Git operations are sequential!\n * We use a FIFO queue to translate async calls\n * into a sequence of git operations\n */\nexport default class GitService {\n private version: string | undefined;\n private queue: PQueue;\n private gitTagService: GitTagService;\n private userService: UserService;\n\n public constructor(options: ElekIoCoreOptions, userService: UserService) {\n this.version = undefined;\n this.queue = new PQueue({\n concurrency: 1, // No concurrency because git operations are sequencial\n });\n this.gitTagService = new GitTagService(options, this.git);\n this.userService = userService;\n }\n\n /**\n * CRUD methods to work with git tags\n */\n public get tags(): GitTagService {\n return this.gitTagService;\n }\n\n /**\n * Reads the currently used version of Git\n */\n public async getVersion(): Promise<void> {\n const result = await this.git('', ['--version']);\n this.version = result.stdout.replace('git version', '').trim();\n }\n\n /**\n * Create an empty Git repository or reinitialize an existing one\n *\n * @see https://git-scm.com/docs/git-init\n *\n * @param path Path to initialize in. Fails if path does not exist\n * @param options Options specific to the init operation\n */\n public async init(\n path: string,\n options?: Partial<GitInitOptions>\n ): Promise<void> {\n let args = ['init'];\n\n if (options?.initialBranch) {\n args = [...args, `--initial-branch=${options.initialBranch}`];\n }\n\n await this.git(path, args);\n await this.setLocalConfig(path);\n await this.installLfs(path);\n }\n\n /**\n * Clone a repository into a directory\n *\n * @see https://git-scm.com/docs/git-clone\n *\n * @todo Implement progress callback / events\n *\n * @param url The remote repository URL to clone from\n * @param path The destination path for the cloned repository.\n * Which is only working if the directory is existing and empty.\n * @param options Options specific to the clone operation\n */\n public async clone(\n url: string,\n path: string,\n options?: Partial<GitCloneOptions>\n ): Promise<void> {\n let args = ['clone', '--progress'];\n\n if (options?.branch) {\n args = [...args, '--branch', options.branch];\n }\n\n if (options?.depth) {\n args = [...args, '--depth', options.depth.toString()];\n }\n\n if (options?.singleBranch === true) {\n args = [...args, '--single-branch'];\n }\n\n await this.git(path, [...args, url, '.']);\n await this.setLocalConfig(path);\n }\n\n /**\n * Add file contents to the index\n *\n * @see https://git-scm.com/docs/git-add\n *\n * @param path Path to the repository\n * @param files Files to add\n */\n public async add(path: string, files: string[]): Promise<void> {\n const args = ['add', '--', ...files];\n\n await this.git(path, args);\n }\n\n /**\n * Switch branches\n *\n * @see https://git-scm.com/docs/git-switch/\n *\n * @param path Path to the repository\n * @param name Name of the branch to switch to\n * @param options Options specific to the switch operation\n */\n public async switch(\n path: string,\n name: string,\n options?: Partial<GitSwitchOptions>\n ): Promise<void> {\n await this.checkBranchOrTagName(path, name);\n\n let args = ['switch'];\n\n if (options?.isNew === true) {\n args = [...args, '--create', name];\n } else {\n args = [...args, name];\n }\n\n await this.git(path, args);\n }\n\n /**\n * Reset current HEAD to the specified state\n *\n * @todo maybe add more options\n * @see https://git-scm.com/docs/git-reset\n *\n * @param path Path to the repository\n * @param mode Modifies the working tree depending on given mode\n * @param commit Resets the current branch head to this commit / tag\n */\n public async reset(path: string, mode: 'soft' | 'hard', commit: string) {\n const args = ['reset', `--${mode}`, commit];\n await this.git(path, args);\n }\n\n /**\n * Restore working tree files\n *\n * @see https://git-scm.com/docs/git-restore/\n *\n * @todo It's probably a good idea to not use restore\n * for a use case where someone just wants to have a look\n * and maybe copy something from a deleted file.\n * We should use `checkout` without `add .` and `commit` for that\n *\n * @param path Path to the repository\n * @param source Git commit SHA or tag name to restore to\n * @param files Files to restore\n */\n // public async restore(\n // path: string,\n // source: string,\n // files: string[]\n // ): Promise<void> {\n // const args = ['restore', `--source=${source}`, ...files];\n // await this.git(path, args);\n // }\n\n /**\n * Fetch from and integrate with another repository or a local branch\n *\n * @see https://git-scm.com/docs/git-pull\n *\n * @param path Path to the repository\n */\n public async pull(path: string): Promise<void> {\n const args = ['pull'];\n await this.git(path, args);\n }\n\n /**\n * Record changes to the repository\n *\n * @see https://git-scm.com/docs/git-commit\n *\n * @param path Path to the repository\n * @param message A message that describes the changes\n */\n public async commit(path: string, message: string): Promise<void> {\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const args = [\n 'commit',\n `--message=${message}`,\n `--author=${user.name} <${user.email}>`,\n ];\n await this.git(path, args);\n }\n\n /**\n * Gets local commit history\n *\n * @see https://git-scm.com/docs/git-log\n *\n * @todo Check if there is a need to trim the git commit message of chars\n * @todo Use this method in a service. Decide if we need a HistoryService for example\n *\n * @param path Path to the repository\n * @param options Options specific to the log operation\n */\n public async log(\n path: string,\n options?: Partial<GitLogOptions>\n ): Promise<GitCommit[]> {\n let args = ['log'];\n\n if (options?.between?.from) {\n args = [\n ...args,\n `${options.between.from}...${options.between.to || 'HEAD'}`,\n ];\n }\n\n if (options?.limit) {\n args = [...args, `--max-count=${options.limit}`];\n }\n\n const result = await this.git(path, [\n ...args,\n '--format=%H|%s|%an|%ae|%at|%D',\n ]);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n return {\n hash: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n timestamp: parseInt(lineArray[4]),\n tag: this.refNameToTagName(lineArray[5]),\n };\n });\n\n return lineObjArr.filter(this.isGitCommit.bind(this));\n }\n\n public refNameToTagName(refName: string) {\n let tagName: string | undefined = '';\n\n // Strip tag key\n tagName = refName.replace('tag: ', '');\n // Return undefined for anything else than UUIDs (tag names are UUIDs)\n if (\n tagName.trim() === '' ||\n uuidSchema.safeParse(tagName).success === false\n ) {\n tagName = undefined;\n }\n\n return tagName;\n }\n\n /**\n * Returns a timestamp of given files creation\n *\n * Git only returns the timestamp the file was added,\n * which could be different from the file being created.\n * But since file operations will always be committed\n * immediately, this is practically the same.\n *\n * @param path Path to the repository\n * @param file File to get timestamp from\n */\n public async getFileCreatedTimestamp(path: string, file: string) {\n const result = await this.git(path, [\n 'log',\n '--diff-filter=A',\n '--follow',\n '--format=%at',\n '--max-count=1',\n '--',\n file,\n ]);\n return parseInt(result.stdout);\n }\n\n /**\n * Returns a timestamp of the files last modification\n *\n * @param path Path to the repository\n * @param file File to get timestamp from\n */\n public async getFileLastUpdatedTimestamp(path: string, file: string) {\n const result = await this.git(path, [\n 'log',\n '--follow',\n '--format=%at',\n '--max-count=1',\n '--',\n file,\n ]);\n return parseInt(result.stdout);\n }\n\n /**\n * Returns created and updated timestamps from given file\n *\n * @param path Path to the project\n * @param file Path to the file\n */\n public async getFileCreatedUpdatedMeta(path: string, file: string) {\n const meta = await Promise.all([\n this.getFileCreatedTimestamp(path, file),\n this.getFileLastUpdatedTimestamp(path, file),\n ]);\n return {\n created: meta[0],\n updated: meta[1],\n };\n }\n\n /**\n * A reference is used in Git to specify branches and tags.\n * This method checks if given name matches the required format\n *\n * @see https://git-scm.com/docs/git-check-ref-format\n *\n * @param path Path to the repository\n * @param name Name to check\n */\n private async checkBranchOrTagName(path: string, name: string) {\n await this.git(path, ['check-ref-format', '--allow-onelevel', name]);\n }\n\n /**\n * Installs LFS support and starts tracking\n * all files inside the lfs folder\n *\n * @param path Path to the repository\n */\n private async installLfs(path: string): Promise<void> {\n await this.git(path, ['lfs', 'install']);\n await this.git(path, ['lfs', 'track', 'lfs/*']);\n }\n\n /**\n * Sets the git config of given local repository from ElekIoCoreOptions\n *\n * @param path Path to the repository\n */\n private async setLocalConfig(path: string) {\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const userNameArgs = ['config', '--local', 'user.name', user.name];\n const userEmailArgs = ['config', '--local', 'user.email', user.email];\n await this.git(path, userNameArgs);\n await this.git(path, userEmailArgs);\n }\n\n /**\n * Type guard for GitCommit\n *\n * @param obj The object to check\n */\n private isGitCommit(obj: unknown): obj is GitCommit {\n return gitCommitSchema.safeParse(obj).success;\n }\n\n /**\n * Wraps the execution of any git command\n * to use a FIFO queue for sequential processing\n *\n * @param path Path to the repository\n * @param args Arguments to append after the `git` command\n */\n private async git(path: string, args: string[]): Promise<IGitResult> {\n const result = await this.queue.add(() => GitProcess.exec(args, path));\n if (!result) {\n throw new GitError(\n `Git (${this.version}) command \"git ${args.join(\n ' '\n )}\" failed to return a result`\n );\n }\n\n return result;\n }\n}\n","export default class GitError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'GitError';\n }\n}\n","export default class NoCurrentUserError extends Error {\n constructor() {\n super('Make sure to set a User via Core before using other methods');\n\n this.name = 'NoCurrentUserError';\n }\n}\n","import {\n countGitTagsSchema,\n createGitTagSchema,\n deleteGitTagSchema,\n gitTagSchema,\n listGitTagsSchema,\n readGitTagSchema,\n serviceTypeSchema,\n uuid,\n type CountGitTagsProps,\n type CreateGitTagProps,\n type DeleteGitTagProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type GitTag,\n type ListGitTagsProps,\n type PaginatedList,\n type ReadGitTagProps,\n} from '@elek-io/shared';\nimport GitError from '../error/GitError.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\n\n/**\n * Service that manages CRUD functionality for GitTags\n */\nexport default class GitTagService\n extends AbstractCrudService\n implements ExtendedCrudService<GitTag>\n{\n private git: GitService['git'];\n\n public constructor(options: ElekIoCoreOptions, git: GitService['git']) {\n super(serviceTypeSchema.Enum.GitTag, options);\n\n this.git = git;\n }\n\n /**\n * Creates a new tag\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---annotate\n */\n public async create(props: CreateGitTagProps): Promise<GitTag> {\n createGitTagSchema.parse(props);\n\n const id = uuid();\n let args = ['tag', '--annotate', id];\n\n if (props.hash) {\n args = [...args, props.hash];\n }\n\n args = [...args, '-m', props.message];\n\n await this.git(props.path, args);\n const tag = await this.read({ path: props.path, id });\n\n return tag;\n }\n\n /**\n * Returns a tag by ID\n *\n * Internally uses list() with id as pattern.\n */\n public async read(props: ReadGitTagProps): Promise<GitTag> {\n readGitTagSchema.parse(props);\n\n const tags = await this.list({ path: props.path, filter: props.id });\n\n if (tags.total === 0) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" did not match any known tags`\n );\n }\n if (tags.total > 1) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" matched multiple known tags`\n );\n }\n\n return tags.list[0];\n }\n\n /**\n * Updating a git tag is not supported.\n * Please delete the old and create a new one\n *\n * @see https://git-scm.com/docs/git-tag#_on_re_tagging\n */\n public async update(): Promise<never> {\n throw new Error(\n 'Updating a git tag is not supported. Please delete the old and create a new one'\n );\n }\n\n /**\n * Deletes a tag\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---delete\n *\n * @param path Path to the repository\n * @param id UUID of the tag to delete\n */\n public async delete(props: DeleteGitTagProps): Promise<void> {\n deleteGitTagSchema.parse(props);\n\n const args = ['tag', '--delete', props.id];\n await this.git(props.path, args);\n }\n\n /**\n * Gets all local tags or filter them by pattern\n *\n * They are sorted by authordate of the commit, not the timestamp the tag is created.\n * This ensures tags are sorted correctly in the timeline of their commits.\n *\n * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---list\n */\n public async list(props: ListGitTagsProps): Promise<PaginatedList<GitTag>> {\n listGitTagsSchema.parse(props);\n\n let args = ['tag', '--list'];\n\n args = [\n ...args,\n '--sort=-*authordate',\n '--format=%(refname:short)|%(subject)|%(*authorname)|%(*authoremail)|%(*authordate:unix)',\n ];\n const result = await this.git(props.path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n return {\n id: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n timestamp:\n typeof lineArray[4] === 'string' ? parseInt(lineArray[4]) : undefined,\n };\n });\n\n const gitTags = lineObjArr.filter(this.isGitTag.bind(this));\n\n return this.paginate(\n gitTags,\n props?.sort,\n props?.filter,\n props?.limit,\n props?.offset\n );\n }\n\n /**\n * Returns the total number of tags inside given repository\n *\n * Internally uses list(), so do not use count()\n * in conjuncion with it to avoid multiple git calls.\n *\n * @param path Path to the repository\n */\n public async count(props: CountGitTagsProps): Promise<number> {\n countGitTagsSchema.parse(props);\n\n const gitTags = await this.list({ path: props.path });\n return gitTags.total;\n }\n\n /**\n * Type guard for GitTag\n *\n * @param obj The object to check\n */\n private isGitTag(obj: unknown): obj is GitTag {\n return gitTagSchema.safeParse(obj).success;\n }\n}\n","import {\n UserTypeSchema,\n setUserSchema,\n userFileSchema,\n type SetUserProps,\n type User,\n type UserFile,\n} from '@elek-io/shared';\nimport * as CoreUtil from '../util/index.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport default class UserService {\n private readonly jsonFileService: JsonFileService;\n\n constructor(jsonFileService: JsonFileService) {\n this.jsonFileService = jsonFileService;\n }\n\n /**\n * Returns the User currently working with Core\n */\n public async get(): Promise<User | undefined> {\n try {\n return await this.jsonFileService.read(\n CoreUtil.pathTo.userFile,\n userFileSchema\n );\n } catch (error) {\n // Should probably be logged in some way or another\n return undefined;\n }\n }\n\n /**\n * Sets the User currently working with Core\n *\n * By doing so all git operations are done with the signature of this User\n */\n public async set(props: SetUserProps): Promise<User> {\n setUserSchema.parse(props);\n\n const userFilePath = CoreUtil.pathTo.userFile;\n\n const userFile: UserFile = {\n ...props,\n };\n\n if (userFile.userType === UserTypeSchema.Enum.cloud) {\n // Try logging in the user\n // Throw on Error\n }\n\n await this.jsonFileService.update(userFile, userFilePath, userFileSchema);\n\n return userFile;\n }\n}\n","import {\n serviceTypeSchema,\n type BaseFile,\n type ElekIoCoreOptions,\n type UserFile,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport type { z } from 'zod';\nimport AbstractCrudService from './AbstractCrudService.js';\n\n/**\n * Service that manages CRUD functionality for JSON files on disk\n */\nexport default class JsonFileService extends AbstractCrudService {\n private cache: Map<string, any> = new Map();\n\n constructor(options: ElekIoCoreOptions) {\n super(serviceTypeSchema.Enum.JsonFile, options);\n }\n\n /**\n * Creates a new file on disk. Fails if path already exists\n *\n * @param data Data to write into the file\n * @param path Path to write the file to\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async create<T extends z.ZodType<BaseFile>>(\n data: unknown,\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n const parsedData = schema.parse(data);\n const string = this.serialize(parsedData);\n await Fs.writeFile(path, string, {\n flag: 'wx',\n encoding: 'utf8',\n });\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n /**\n * Reads the content of a file on disk. Fails if path does not exist\n *\n * @param path Path to read the file from\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async read<T extends z.ZodType<BaseFile | UserFile>>(\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n if (this.cache.has(path)) {\n // console.log(`Cache hit for \"${path}\"`);\n return this.cache.get(path);\n }\n\n // console.log(`Cache miss for \"${path}\"`);\n const data = await Fs.readFile(path, {\n flag: 'r',\n encoding: 'utf8',\n });\n const json = this.deserialize(data);\n const parsedData = schema.parse(json);\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n /**\n * Overwrites an existing file on disk\n *\n * @todo Check how to error out if the file does not exist already\n *\n * @param data Data to write into the file\n * @param path Path to the file to overwrite\n * @param schema Schema of the file to validate against\n * @returns Validated content of the file from disk\n */\n public async update<T extends z.ZodType<BaseFile | UserFile>>(\n data: unknown,\n path: string,\n schema: T\n ): Promise<z.output<T>> {\n const parsedData = schema.parse(data);\n const string = this.serialize(parsedData);\n await Fs.writeFile(path, string, {\n flag: 'w',\n encoding: 'utf8',\n });\n this.cache.set(path, parsedData);\n\n return parsedData;\n }\n\n private serialize(data: unknown): string {\n return JSON.stringify(data, null, this.options.file.json.indentation);\n }\n\n private deserialize(data: string): unknown {\n return JSON.parse(data);\n }\n}\n","import {\n collectionFileSchema,\n countCollectionsSchema,\n createCollectionSchema,\n currentTimestamp,\n deleteCollectionSchema,\n listCollectionsSchema,\n objectTypeSchema,\n readCollectionSchema,\n serviceTypeSchema,\n slug,\n updateCollectionSchema,\n uuid,\n type BaseFile,\n type Collection,\n type CollectionFile,\n type CountCollectionsProps,\n type CreateCollectionProps,\n type DeleteCollectionProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListCollectionsProps,\n type PaginatedList,\n type ReadCollectionProps,\n type UpdateCollectionProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for Collection files on disk\n */\nexport default class CollectionService\n extends AbstractCrudService\n implements ExtendedCrudService<Collection>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.Enum.Collection, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new Collection\n */\n public async create(props: CreateCollectionProps): Promise<Collection> {\n createCollectionSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionPath = CoreUtil.pathTo.collection(props.projectId, id);\n const collectionFilePath = CoreUtil.pathTo.collectionFile(\n props.projectId,\n id\n );\n\n const collectionFile: CollectionFile = {\n ...props,\n objectType: 'collection',\n id,\n slug: {\n singular: slug(props.slug.singular),\n plural: slug(props.slug.plural),\n },\n created: currentTimestamp(),\n };\n\n await Fs.ensureDir(collectionPath);\n await this.jsonFileService.create(\n collectionFile,\n collectionFilePath,\n collectionFileSchema\n );\n await this.gitService.add(projectPath, [collectionFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return collectionFile;\n }\n\n /**\n * Returns a Collection by ID\n */\n public async read(props: ReadCollectionProps): Promise<Collection> {\n readCollectionSchema.parse(props);\n\n const collection = await this.jsonFileService.read(\n CoreUtil.pathTo.collectionFile(props.projectId, props.id),\n collectionFileSchema\n );\n\n return collection;\n }\n\n /**\n * Updates given Collection\n *\n * @todo finish implementing checks for FieldDefinitions and extract methods\n *\n * @param projectId Project ID of the collection to update\n * @param collection Collection to write to disk\n * @returns An object containing information about the actions needed to be taken,\n * before given update can be executed or void if the update was executed successfully\n */\n public async update(props: UpdateCollectionProps): Promise<Collection> {\n updateCollectionSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionFilePath = CoreUtil.pathTo.collectionFile(\n props.projectId,\n props.id\n );\n const prevCollectionFile = await this.read(props);\n\n const collectionFile: CollectionFile = {\n ...prevCollectionFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n // @todo Collection Service has to check if any of the updated fieldDefinitions do not validate against the used Fields in each CollectionItem of the Collection\n // and return a list of mismatches, so the user can choose what to do in the UI / a wizard\n // For that:\n // - Iterate over all CollectionItems inside Collection\n // - Create an array with all FieldReferences of those CollectionItems\n // - Load all Fields by those references and check if the Field still complies with the new definition\n\n // const result: CollectionUpdateResult = {\n // create: [],\n // update: [],\n // delete: [],\n // };\n\n // const currentCollection = await this.read(props);\n // Iterate over all FieldDefinitions and check each for changes\n // for (let index = 0; index < collection.fieldDefinitions.length; index++) {\n // const nextFieldDefinition = collection.fieldDefinitions[index];\n // if (!nextFieldDefinition) {\n // throw new Error('Could not find any field definition');\n // }\n // // Get the correct FieldDefinition by ID\n // const currentFieldDefinition = currentCollection.fieldDefinitions.find(\n // (current) => {\n // return current.id === nextFieldDefinition.id;\n // }\n // );\n // if (currentFieldDefinition) {\n // if (\n // currentFieldDefinition.isRequired === false &&\n // nextFieldDefinition.isRequired === true\n // ) {\n // // Case 1.\n // // A FieldDefinition was not required to be filled, but is now\n // // -> Check if all CollectionItems have a FieldReference to this definition (if not create)\n // // -> Check all values of referenced fields of this definition for null (if not update)\n // // -> If the value is null, this is a violation\n // const collectionItems = (\n // await this.collectionItemService.list(\n // projectId,\n // collection.id,\n // undefined,\n // undefined,\n // 0,\n // 0\n // )\n // ).list;\n // for (let index = 0; index < collectionItems.length; index++) {\n // const collectionItem = collectionItems[index];\n // if (!collectionItem) {\n // throw new Error('Blaa');\n // }\n // const fieldReference = collectionItem.fieldReferences.find(\n // (fieldReference) => {\n // return (\n // fieldReference.fieldDefinitionId === nextFieldDefinition.id\n // );\n // }\n // );\n // if (!fieldReference) {\n // result.create.push({\n // violation: Violation.FIELD_REQUIRED_BUT_UNDEFINED,\n // collectionItem,\n // fieldDefinition: nextFieldDefinition,\n // });\n // } else {\n // const field = await this.fieldService.read(\n // projectId,\n // fieldReference.field.id,\n // fieldReference.field.language\n // );\n // if (field.value === null) {\n // result.update.push({\n // violation: Violation.FIELD_VALUE_REQUIRED_BUT_NULL,\n // collectionItem,\n // fieldReference,\n // });\n // }\n // }\n // }\n // }\n // if (\n // currentFieldDefinition.isUnique !== nextFieldDefinition.isUnique &&\n // nextFieldDefinition.isUnique === true\n // ) {\n // // Case 2.\n // // A FieldDefinition was not required to be unique, but is now\n // // -> Check all current values of referenced fields\n // // -> If a value is not unique, this is a violation\n // // const fieldReferences = await this.collectionItemService.getAllFieldReferences(project, currentCollection, currentFieldDefinition.id);\n // // const fields = await this.fieldService.readAll(project, fieldReferences);\n // // const duplicates = Util.getDuplicates(fields, 'value');\n // // for (let index = 0; index < duplicates.length; index++) {\n // // const duplicate = duplicates[index];\n // // result.update.push({\n // // violation: Violation.FIELD_VALUE_NOT_UNIQUE,\n // // collectionItem: ,\n // // fieldReference\n // // });\n // // }\n // }\n // if (\n // isEqual(currentFieldDefinition.input, nextFieldDefinition.input) ===\n // false\n // ) {\n // // Case 3.\n // // A FieldDefinition has a new input specification\n // // -> Check if this input is valid for given FieldType\n // // -> If not, this is a violation\n // }\n // } else {\n // // It's a new FieldDefinition that was not existing before\n // if (nextFieldDefinition.isRequired) {\n // // Case 4.\n // // A FieldDefinition is new and a field (with value) required\n // // -> The user needs to add a field reference (either through a new or existing field)\n // // for every CollectionItem of this Collection\n // const collectionItems = (\n // await this.collectionItemService.list(\n // projectId,\n // collection.id,\n // undefined,\n // undefined,\n // 0,\n // 0\n // )\n // ).list;\n // collectionItems.forEach((collectionItem) => {\n // result.create.push({\n // violation: Violation.FIELD_REQUIRED_BUT_UNDEFINED,\n // collectionItem,\n // fieldDefinition: nextFieldDefinition,\n // });\n // });\n // }\n // }\n // }\n\n // // Return early to notify the user of changes he has to do before this update is working\n // if (\n // result.create.length !== 0 ||\n // result.update.length !== 0 ||\n // result.delete.length !== 0\n // ) {\n // return result;\n // }\n\n await this.jsonFileService.update(\n collectionFile,\n collectionFilePath,\n collectionFileSchema\n );\n await this.gitService.add(projectPath, [collectionFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n return collectionFile;\n }\n\n /**\n * Deletes given Collection (folder), including it's items\n *\n * The Fields that Collection used are not deleted.\n */\n public async delete(props: DeleteCollectionProps): Promise<void> {\n deleteCollectionSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const collectionPath = CoreUtil.pathTo.collection(\n props.projectId,\n props.id\n );\n\n await Fs.remove(collectionPath);\n await this.gitService.add(projectPath, [collectionPath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(\n props: ListCollectionsProps\n ): Promise<PaginatedList<Collection>> {\n listCollectionsSchema.parse(props);\n\n const references = await this.listReferences(\n objectTypeSchema.Enum.collection,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountCollectionsProps): Promise<number> {\n countCollectionsSchema.parse(props);\n\n const count = (\n await this.listReferences(\n objectTypeSchema.Enum.collection,\n props.projectId\n )\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is of type Collection\n */\n public isCollection(obj: BaseFile | unknown): obj is Collection {\n return collectionFileSchema.safeParse(obj).success;\n }\n}\n","import {\n ValueTypeSchema,\n countEntriesSchema,\n createEntrySchema,\n currentTimestamp,\n deleteEntrySchema,\n entryFileSchema,\n entrySchema,\n getValueContentSchemaFromDefinition,\n listEntriesSchema,\n objectTypeSchema,\n readEntrySchema,\n serviceTypeSchema,\n updateEntrySchema,\n uuid,\n type BaseFile,\n type CountEntriesProps,\n type CreateEntryProps,\n type DeleteEntryProps,\n type ElekIoCoreOptions,\n type Entry,\n type EntryFile,\n type ExtendedCrudService,\n type ListEntriesProps,\n type ReadEntryProps,\n type ResolvedValueContentReference,\n type ResolvedValueContentReferenceToAsset,\n type ResolvedValueContentReferenceToSharedValue,\n type UpdateEntryProps,\n type Value,\n type ValueContentReference,\n type ValueContentReferenceToAsset,\n type ValueContentReferenceToSharedValue,\n type ValueDefinition,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport type AssetService from './AssetService.js';\nimport CollectionService from './CollectionService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\nimport SharedValueService from './SharedValueService.js';\n\n/**\n * Service that manages CRUD functionality for Entry files on disk\n */\nexport default class EntryService\n extends AbstractCrudService\n implements ExtendedCrudService<Entry>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private collectionService: CollectionService;\n private assetService: AssetService;\n private sharedValueService: SharedValueService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService,\n collectionService: CollectionService,\n assetService: AssetService,\n sharedValueService: SharedValueService\n ) {\n super(serviceTypeSchema.Enum.Entry, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n this.collectionService = collectionService;\n this.assetService = assetService;\n this.sharedValueService = sharedValueService;\n }\n\n /**\n * Creates a new Entry for given Collection\n */\n public async create(props: CreateEntryProps): Promise<Entry> {\n createEntrySchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n id,\n props.language\n );\n const collection = await this.collectionService.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n const entryFile: EntryFile = {\n objectType: 'entry',\n id,\n language: props.language,\n values: props.values,\n created: currentTimestamp(),\n };\n\n const entry: Entry = await this.toEntry({\n projectId: props.projectId,\n entryFile,\n });\n\n this.validateValues({\n collectionId: props.collectionId,\n valueDefinitions: collection.valueDefinitions,\n values: entry.values,\n });\n\n await this.jsonFileService.create(\n entryFile,\n entryFilePath,\n entryFileSchema\n );\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return entry;\n }\n\n /**\n * Returns an Entry from given Collection by ID and language\n */\n public async read(props: ReadEntryProps): Promise<Entry> {\n readEntrySchema.parse(props);\n\n const entryFile: EntryFile = await this.jsonFileService.read(\n CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n ),\n entryFileSchema\n );\n\n return await this.toEntry({ projectId: props.projectId, entryFile });\n }\n\n /**\n * Updates an Entry of given Collection with new Values and shared Values\n */\n public async update(props: UpdateEntryProps): Promise<Entry> {\n updateEntrySchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n );\n const collection = await this.collectionService.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n const prevEntryFile = await this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: props.id,\n language: props.language,\n });\n\n const entryFile: EntryFile = {\n ...prevEntryFile,\n values: props.values,\n updated: currentTimestamp(),\n };\n\n const entry: Entry = await this.toEntry({\n projectId: props.projectId,\n entryFile,\n });\n\n this.validateValues({\n collectionId: props.collectionId,\n valueDefinitions: collection.valueDefinitions,\n values: entry.values,\n });\n\n await this.jsonFileService.update(\n entryFile,\n entryFilePath,\n entryFileSchema\n );\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return entry;\n }\n\n /**\n * Deletes given Entry from it's Collection\n */\n public async delete(props: DeleteEntryProps): Promise<void> {\n deleteEntrySchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const entryFilePath = CoreUtil.pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id,\n props.language\n );\n\n await Fs.remove(entryFilePath);\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(props: ListEntriesProps) {\n listEntriesSchema.parse(props);\n\n const references = await this.listReferences(\n objectTypeSchema.Enum.entry,\n props.projectId,\n props.collectionId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n if (!reference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: reference.id,\n language: reference.language,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountEntriesProps): Promise<number> {\n countEntriesSchema.parse(props);\n\n return (\n await this.listReferences(\n objectTypeSchema.Enum.entry,\n props.projectId,\n props.collectionId\n )\n ).length;\n }\n\n /**\n * Checks if given object is of type Entry\n */\n public isEntry(obj: BaseFile | unknown): obj is Entry {\n return entrySchema.safeParse(obj).success;\n }\n\n /**\n * Returns a Value definition by ID\n */\n private getValueDefinitionById(props: {\n valueDefinitions: ValueDefinition[];\n id: string;\n collectionId: string;\n }) {\n const definition = props.valueDefinitions.find((def) => {\n if (def.id === props.id) {\n return true;\n }\n return false;\n });\n\n if (!definition) {\n throw new Error(\n `No definition with ID \"${props.id}\" found in Collection \"${props.collectionId}\" for given Value reference`\n );\n }\n\n return definition;\n }\n\n /**\n * Validates given Values against it's Collections definitions\n */\n private validateValues(props: {\n collectionId: string;\n valueDefinitions: ValueDefinition[];\n values: Value[];\n }) {\n props.values.map((value) => {\n const definition = this.getValueDefinitionById({\n collectionId: props.collectionId,\n valueDefinitions: props.valueDefinitions,\n id: value.definitionId,\n });\n const schema = getValueContentSchemaFromDefinition(definition);\n\n try {\n schema.parse(value.content);\n } catch (error) {\n console.log('Definition:', definition);\n console.log('Value:', value);\n throw error;\n }\n });\n }\n\n /**\n * Validates given shared Value references against it's Collections definitions\n */\n // private validateResolvedSharedValues(props: {\n // collectionId: string;\n // valueDefinitions: ValueDefinition[];\n // resolvedSharedValues: ResolvedSharedValueReference[];\n // }) {\n // props.resolvedSharedValues.map((value) => {\n // const definition = this.getValueDefinitionById({\n // collectionId: props.collectionId,\n // valueDefinitions: props.valueDefinitions,\n // id: value.definitionId,\n // });\n // const schema = getValueSchemaFromDefinition(definition);\n // schema.parse(value.resolved.content);\n // });\n // }\n\n private async resolveValueContentReference(props: {\n projectId: string;\n valueContentReference: ValueContentReference;\n }): Promise<ResolvedValueContentReference> {\n switch (props.valueContentReference.referenceObjectType) {\n case objectTypeSchema.Enum.asset:\n return this.resolveValueContentReferenceToAsset({\n projectId: props.projectId,\n valueContentReferenceToAsset: props.valueContentReference,\n });\n case objectTypeSchema.Enum.sharedValue:\n return this.resolveValueContentReferenceToSharedValue({\n projectId: props.projectId,\n valueContentReferenceToSharedValue: props.valueContentReference,\n });\n\n default:\n throw new Error(\n // @ts-ignore\n `Tried to resolve unsupported Value reference \"${props.valueContentReference.referenceObjectType}\"`\n );\n }\n }\n\n private async resolveValueContentReferenceToAsset(props: {\n projectId: string;\n valueContentReferenceToAsset: ValueContentReferenceToAsset;\n }): Promise<ResolvedValueContentReferenceToAsset> {\n const resolvedReferences = await Promise.all(\n props.valueContentReferenceToAsset.references.map(async (reference) => {\n const resolvedAsset = await this.assetService.read({\n projectId: props.projectId,\n id: reference.id,\n language: reference.language,\n });\n return {\n ...reference,\n resolved: resolvedAsset,\n };\n })\n );\n\n return {\n ...props.valueContentReferenceToAsset,\n references: resolvedReferences,\n };\n }\n\n private async resolveValueContentReferenceToSharedValue(props: {\n projectId: string;\n valueContentReferenceToSharedValue: ValueContentReferenceToSharedValue;\n }): Promise<ResolvedValueContentReferenceToSharedValue> {\n const resolvedSharedValue = await this.sharedValueService.read({\n projectId: props.projectId,\n id: props.valueContentReferenceToSharedValue.references.id,\n language: props.valueContentReferenceToSharedValue.references.language,\n });\n\n return {\n ...props.valueContentReferenceToSharedValue,\n references: {\n ...props.valueContentReferenceToSharedValue.references,\n resolved: resolvedSharedValue,\n },\n };\n }\n\n /**\n * Creates an Entry from given EntryFile by resolving it's Values\n */\n private async toEntry(props: {\n projectId: string;\n entryFile: EntryFile;\n }): Promise<Entry> {\n const entry: Entry = {\n ...props.entryFile,\n values: await Promise.all(\n props.entryFile.values.map(async (value) => {\n if (value.valueType === ValueTypeSchema.Enum.reference) {\n const resolvedValueContentReference =\n await this.resolveValueContentReference({\n projectId: props.projectId,\n valueContentReference: value.content,\n });\n\n return {\n ...value,\n content: resolvedValueContentReference,\n };\n }\n\n return value;\n })\n ),\n };\n\n return entry;\n }\n}\n","import {\n ValueTypeSchema,\n countValuesSchema,\n createSharedValueSchema,\n currentTimestamp,\n deleteSharedValueSchema,\n listSharedValuesSchema,\n objectTypeSchema,\n readSharedValueSchema,\n serviceTypeSchema,\n sharedValueFileSchema,\n sharedValueSchema,\n updateSharedValueSchema,\n uuid,\n z,\n type BaseFile,\n type CountValuesProps,\n type CreateSharedValueProps,\n type DeleteSharedValueProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListSharedValuesProps,\n type PaginatedList,\n type ReadSharedValueProps,\n type SharedValue,\n type SharedValueFile,\n type UpdateSharedValueProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport RequiredParameterMissingError from '../error/RequiredParameterMissingError.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\n\n/**\n * Service that manages CRUD functionality for shared Value files on disk\n */\nexport default class SharedValueService\n extends AbstractCrudService\n implements ExtendedCrudService<SharedValue>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n gitService: GitService,\n assetService: AssetService\n ) {\n super(serviceTypeSchema.Enum.Value, options);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n }\n\n /**\n * Creates a new shared Value\n */\n public async create(props: CreateSharedValueProps): Promise<SharedValue> {\n createSharedValueSchema.parse(props);\n\n const id = uuid();\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const sharedValueFilePath = CoreUtil.pathTo.sharedValueFile(\n props.projectId,\n id,\n props.language\n );\n\n const sharedValueFile: SharedValueFile = {\n ...props,\n objectType: 'sharedValue',\n id,\n created: currentTimestamp(),\n };\n\n this.validate(sharedValueFile);\n\n await this.jsonFileService.create(\n sharedValueFile,\n sharedValueFilePath,\n sharedValueFileSchema\n );\n await this.gitService.add(projectPath, [sharedValueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.create);\n\n return sharedValueFile;\n }\n\n /**\n * Returns a shared Value by ID and language\n */\n public async read(props: ReadSharedValueProps): Promise<SharedValue> {\n readSharedValueSchema.parse(props);\n\n const sharedValueFile = await this.jsonFileService.read(\n CoreUtil.pathTo.sharedValueFile(\n props.projectId,\n props.id,\n props.language\n ),\n sharedValueFileSchema\n );\n\n return sharedValueFile;\n }\n\n /**\n * Updates given shared Values content\n *\n * The valueType cannot be changed after creating the shared Value\n */\n public async update(props: UpdateSharedValueProps): Promise<SharedValue> {\n updateSharedValueSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const sharedValueFilePath = CoreUtil.pathTo.sharedValueFile(\n props.projectId,\n props.id,\n props.language\n );\n const prevSharedValueFile = await this.read(props);\n\n const sharedValueFile: SharedValueFile = {\n ...prevSharedValueFile,\n content: props.content,\n updated: currentTimestamp(),\n };\n\n this.validate(sharedValueFile);\n\n await this.jsonFileService.update(\n sharedValueFile,\n sharedValueFilePath,\n sharedValueFileSchema\n );\n await this.gitService.add(projectPath, [sharedValueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return sharedValueFile;\n }\n\n /**\n * Deletes given shared Value\n */\n public async delete(props: DeleteSharedValueProps): Promise<void> {\n deleteSharedValueSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.projectId);\n const valueFilePath = CoreUtil.pathTo.sharedValueFile(\n props.projectId,\n props.id,\n props.language\n );\n\n await Fs.remove(valueFilePath);\n await this.gitService.add(projectPath, [valueFilePath]);\n await this.gitService.commit(projectPath, this.gitMessage.delete);\n }\n\n public async list(\n props: ListSharedValuesProps\n ): Promise<PaginatedList<SharedValue>> {\n listSharedValuesSchema.parse(props);\n\n const references = await this.listReferences(\n objectTypeSchema.Enum.sharedValue,\n props.projectId\n );\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n if (!reference.language) {\n throw new RequiredParameterMissingError('language');\n }\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n language: reference.language,\n });\n })\n );\n\n return this.paginate(\n list,\n props.sort,\n props.filter,\n props.limit,\n props.offset\n );\n }\n\n public async count(props: CountValuesProps): Promise<number> {\n countValuesSchema.parse(props);\n\n const count = (\n await this.listReferences(\n objectTypeSchema.Enum.sharedValue,\n props.projectId\n )\n ).length;\n\n return count;\n }\n\n /**\n * Checks if given object is a shared Value\n */\n public isSharedValue(obj: BaseFile | unknown): obj is SharedValue {\n return sharedValueSchema.safeParse(obj).success;\n }\n\n /**\n * Reads the given shared Values content based on it's ValueType\n */\n private validate(sharedValue: SharedValueFile) {\n switch (sharedValue.valueType) {\n case ValueTypeSchema.Enum.boolean:\n z.boolean().parse(sharedValue.content);\n break;\n case ValueTypeSchema.Enum.number:\n z.number().parse(sharedValue.content);\n break;\n case ValueTypeSchema.Enum.string:\n z.string().parse(sharedValue.content);\n break;\n default:\n throw new Error(\n `Error validating content of unsupported shared Value with ValueType \"${sharedValue.valueType}\"`\n );\n }\n }\n}\n","import {\n createProjectSchema,\n currentTimestamp,\n deleteProjectSchema,\n gitCommitIconSchema,\n listProjectsSchema,\n objectTypeSchema,\n projectFileSchema,\n projectFolderSchema,\n readProjectSchema,\n serviceTypeSchema,\n updateProjectSchema,\n upgradeProjectSchema,\n uuid,\n type BaseFile,\n type CollectionExport,\n type CreateProjectProps,\n type DeleteProjectProps,\n type ElekIoCoreOptions,\n type ExtendedCrudService,\n type ListProjectsProps,\n type ObjectType,\n type PaginatedList,\n type Project,\n type ProjectExport,\n type ProjectFile,\n type ProjectSettings,\n type ReadProjectProps,\n type UpdateProjectProps,\n type UpgradeProjectProps,\n} from '@elek-io/shared';\nimport Fs from 'fs-extra';\nimport Os from 'os';\nimport Path from 'path';\nimport Semver from 'semver';\nimport NoCurrentUserError from '../error/NoCurrentUserError.js';\nimport ProjectUpgradeError from '../error/ProjectUpgradeError.js';\nimport type { ProjectUpgradeImport } from '../upgrade/example.js';\nimport * as CoreUtil from '../util/index.js';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport CollectionService from './CollectionService.js';\nimport type EntryService from './EntryService.js';\nimport GitService from './GitService.js';\nimport JsonFileService from './JsonFileService.js';\nimport SearchService from './SearchService.js';\nimport UserService from './UserService.js';\n\n/**\n * Service that manages CRUD functionality for Project files on disk\n */\nexport default class ProjectService\n extends AbstractCrudService\n implements ExtendedCrudService<Project>\n{\n private jsonFileService: JsonFileService;\n private userService: UserService;\n private gitService: GitService;\n private searchService: SearchService;\n private assetService: AssetService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n\n constructor(\n options: ElekIoCoreOptions,\n jsonFileService: JsonFileService,\n userService: UserService,\n gitService: GitService,\n searchService: SearchService,\n assetService: AssetService,\n collectionService: CollectionService,\n entryService: EntryService\n ) {\n super(serviceTypeSchema.Enum.Project, options);\n\n this.jsonFileService = jsonFileService;\n this.userService = userService;\n this.gitService = gitService;\n this.searchService = searchService;\n this.assetService = assetService;\n this.collectionService = collectionService;\n this.entryService = entryService;\n }\n\n /**\n * Creates a new Project\n */\n public async create(props: CreateProjectProps): Promise<Project> {\n createProjectSchema.parse(props);\n\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const id = uuid();\n const defaultSettings: ProjectSettings = {\n language: {\n default: user.language,\n supported: [user.language],\n },\n };\n\n const projectFile: ProjectFile = {\n ...props,\n objectType: 'project',\n id,\n description: props.description || '',\n settings: Object.assign({}, defaultSettings, props.settings),\n created: currentTimestamp(),\n coreVersion: this.options.version, // @todo should be read from package.json to avoid duplicates\n status: 'todo',\n version: '0.0.1',\n };\n\n const projectPath = CoreUtil.pathTo.project(id);\n\n await Fs.ensureDir(projectPath);\n\n try {\n await this.createFolderStructure(projectPath);\n await this.createGitignore(projectPath);\n await this.gitService.init(projectPath, { initialBranch: 'main' });\n await this.jsonFileService.create(\n projectFile,\n CoreUtil.pathTo.projectFile(id),\n projectFileSchema\n );\n await this.gitService.add(projectPath, ['.']);\n await this.gitService.commit(\n projectPath,\n `${gitCommitIconSchema.enum.INIT} Created this new elek.io project`\n );\n await this.gitService.switch(projectPath, 'stage', { isNew: true });\n } catch (error) {\n // To avoid partial data being added to the repository / git status reporting uncommitted files\n await this.delete({\n id,\n });\n throw error;\n }\n\n return projectFile;\n }\n\n /**\n * Returns a Project by ID\n */\n public async read(props: ReadProjectProps): Promise<Project> {\n readProjectSchema.parse(props);\n\n const projectFile = await this.jsonFileService.read(\n CoreUtil.pathTo.projectFile(props.id),\n projectFileSchema\n );\n\n return projectFile;\n }\n\n /**\n * Updates given Project\n */\n public async update(props: UpdateProjectProps): Promise<Project> {\n updateProjectSchema.parse(props);\n\n const projectPath = CoreUtil.pathTo.project(props.id);\n const filePath = CoreUtil.pathTo.projectFile(props.id);\n const prevProjectFile = await this.read(props);\n\n const projectFile: ProjectFile = {\n ...prevProjectFile,\n ...props,\n updated: currentTimestamp(),\n };\n\n await this.jsonFileService.update(projectFile, filePath, projectFileSchema);\n await this.gitService.add(projectPath, [filePath]);\n await this.gitService.commit(projectPath, this.gitMessage.update);\n\n return projectFile;\n }\n\n /**\n * Upgrades given Project to the latest version of this client\n *\n * Needed when a new core version is requiring changes to existing files or structure.\n *\n * @todo Find out why using this.snapshotService is throwing isObjWithKeyAndValueOfString of undefined error in gitService (maybe binding issue)\n */\n public async upgrade(props: UpgradeProjectProps): Promise<void> {\n upgradeProjectSchema.parse(props);\n\n const project = await this.read(props);\n const projectPath = CoreUtil.pathTo.project(project.id);\n\n if (Semver.gt(project.coreVersion, this.options.version)) {\n // Upgrade of the client needed before the project can be upgraded\n throw new Error(\n `Failed upgrading project. The projects core version \"${project.coreVersion}\" is higher than the current core version \"${this.options.version}\" of this client. A client upgrade is needed beforehand.`\n );\n }\n\n if (Semver.eq(project.coreVersion, this.options.version)) {\n // Nothing, since both are equal\n return;\n }\n\n // Get all available upgrade scripts\n const upgradeFiles = await CoreUtil.files(\n Path.resolve(__dirname, '../upgrade'),\n 'ts'\n );\n\n // Import all objects\n const upgrades = (\n await Promise.all(\n upgradeFiles.map((file) => {\n return import(\n Path.join('../upgrade', file.name)\n ) as Promise<ProjectUpgradeImport>;\n })\n )\n ).map((upgradeImport) => {\n return upgradeImport.default;\n });\n\n // Sort them by core version and filter out the example one\n const sortedUpgrades = upgrades\n .sort((a, b) => {\n return Semver.compare(a.to, b.to);\n })\n .filter((upgrade) => {\n if (upgrade.to !== '0.0.0') {\n return upgrade;\n }\n });\n\n for (let index = 0; index < sortedUpgrades.length; index++) {\n const upgrade = sortedUpgrades[index];\n if (!upgrade) {\n throw new Error('Expected ProjectUpgrade but got undefined');\n }\n\n // Make a tag to revert to on failure\n const failsafeTag = await this.gitService.tags.create({\n path: projectPath,\n message: `Attempting to upgrade Project to Core version \"${upgrade.to}\"`,\n });\n\n try {\n await upgrade.run(project);\n\n // Override the projects core version\n project.coreVersion = upgrade.to;\n await this.update(project);\n\n // And create another tag to show successfull upgrade in git log\n await this.gitService.tags.create({\n path: projectPath,\n message: `Upgraded Project to Core version \"${upgrade.to}\"`,\n });\n\n // Done, remove the failsafe tag again\n await this.gitService.tags.delete({\n path: projectPath,\n id: failsafeTag.id,\n });\n } catch (error) {\n // Reset Project to the tag made before\n await this.gitService.reset(projectPath, 'hard', failsafeTag.id);\n\n throw new ProjectUpgradeError(\n `Failed to upgrade Project to Core version \"${upgrade.to}\"`\n );\n }\n }\n }\n\n /**\n * Deletes given Project\n *\n * Deletes the whole Project folder including the history, not only the config file.\n * Use with caution, since a Project that is only available locally could be lost forever.\n * Or changes that are not pushed to a remote yet, will be lost too.\n */\n public async delete(props: DeleteProjectProps): Promise<void> {\n deleteProjectSchema.parse(props);\n\n await Fs.remove(CoreUtil.pathTo.project(props.id));\n }\n\n public async list(\n props?: ListProjectsProps\n ): Promise<PaginatedList<Project>> {\n if (props) {\n listProjectsSchema.parse(props);\n }\n\n const references = await this.listReferences(objectTypeSchema.Enum.project);\n const list = await CoreUtil.returnResolved(\n references.map((reference) => {\n return this.read({ id: reference.id });\n })\n );\n\n return this.paginate(\n list,\n props?.sort,\n props?.filter,\n props?.limit,\n props?.offset\n );\n }\n\n public async count(): Promise<number> {\n return (await this.listReferences(objectTypeSchema.Enum.project)).length;\n }\n\n /**\n * Search all models inside the project for given query\n *\n * @param projectId Project ID to search in\n * @param query Query to search for\n * @param type (Optional) specify the type to search for\n */\n public async search(projectId: string, query: string, type?: ObjectType) {\n return this.searchService.search(projectId, query, type);\n }\n\n /**\n * Checks if given object is of type Project\n */\n public isProject(obj: BaseFile | unknown): obj is Project {\n return projectFileSchema.safeParse(obj).success;\n }\n\n /**\n * Exports given Project to JSON\n *\n * @todo do not read everything before writing to disk -> stream into file given via props\n * @todo performance tests\n * @todo add progress callback\n */\n public async exportToJson(projectId: string): Promise<ProjectExport> {\n const project = await this.read({ id: projectId });\n const assets = (await this.assetService.list({ projectId, limit: 0 })).list;\n const collections = (\n await this.collectionService.list({ projectId, limit: 0 })\n ).list;\n\n const collectionExport: CollectionExport[] = await Promise.all(\n collections.map(async (collection) => {\n const entries = (\n await this.entryService.list({\n projectId,\n collectionId: collection.id,\n limit: 0,\n })\n ).list;\n\n return {\n ...collection,\n entries,\n };\n })\n );\n\n return {\n ...project,\n assets,\n collections: collectionExport,\n };\n }\n\n /**\n * Creates the projects folder structure and makes sure to\n * write empty .gitkeep files inside them to ensure they are\n * committed\n */\n private async createFolderStructure(path: string): Promise<void> {\n const folders = Object.values(projectFolderSchema.Values);\n\n await Promise.all(\n folders.map(async (folder) => {\n await Fs.mkdirp(Path.join(path, folder));\n await Fs.writeFile(Path.join(path, folder, '.gitkeep'), '');\n })\n );\n }\n\n /**\n * Writes the Projects main .gitignore file to disk\n *\n * @todo Add general things to ignore\n * @see https://github.com/github/gitignore/tree/master/Global\n */\n private async createGitignore(path: string): Promise<void> {\n const lines = [\n '# Ignore all hidden files and folders...',\n '.*',\n '# ...but these',\n '!/.gitignore',\n '!/.gitattributes',\n '!/**/.gitkeep',\n '',\n '# elek.io related ignores',\n // projectFolderSchema.Enum.theme + '/',\n // projectFolderSchema.Enum.public + '/',\n // projectFolderSchema.Enum.logs + '/',\n ];\n await Fs.writeFile(Path.join(path, '.gitignore'), lines.join(Os.EOL));\n }\n}\n","export default class ProjectUpgradeError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'ProjectUpgradeError';\n }\n}\n","import {\n serviceTypeSchema,\n type ElekIoCoreOptions,\n type ObjectType,\n type SearchResult,\n} from '@elek-io/shared';\nimport AbstractCrudService from './AbstractCrudService.js';\nimport AssetService from './AssetService.js';\nimport CollectionService from './CollectionService.js';\n\n/**\n * Service that queries other services for data to search\n *\n * @todo refactor for the new Services\n */\nexport default class SearchService extends AbstractCrudService {\n private assetService: AssetService;\n private collectionService: CollectionService;\n\n constructor(\n options: ElekIoCoreOptions,\n assetService: AssetService,\n collectionService: CollectionService\n ) {\n super(serviceTypeSchema.enum.Search, options);\n\n this.assetService = assetService;\n this.collectionService = collectionService;\n }\n\n /**\n * Search all models inside the project for given query\n *\n * @todo Implement SearchOptions parameter\n *\n * @param project Project to search in\n * @param query Query to search for\n */\n public async search(\n projectId: string,\n query: string,\n objectType?: ObjectType\n ) {\n const results: SearchResult[] = [];\n const normalizedQuery = query.trim();\n\n if (normalizedQuery === '') {\n return results;\n }\n\n const paginatedLists = (\n await Promise.all([this.assetService.list({ projectId, filter: query })])\n ).flat();\n\n paginatedLists.forEach((paginatedList) => {\n paginatedList.list.flat().forEach((file) => {\n const result: SearchResult = {\n id: file.id,\n language: file.language,\n name: file.name,\n type: file.objectType,\n matches: [],\n };\n\n for (const [key, value] of Object.entries(file)) {\n const valueString = String(value);\n if (\n valueString.toLowerCase().includes(normalizedQuery.toLowerCase())\n ) {\n const matchStart = valueString\n .toLowerCase()\n .indexOf(normalizedQuery.toLowerCase());\n const matchEnd = matchStart + normalizedQuery.length;\n\n result.matches.push({\n key,\n prefix: this.truncate(\n valueString.substring(0, matchStart),\n 'start'\n ),\n match: valueString.substring(matchStart, matchEnd),\n suffix: this.truncate(\n valueString.substring(matchEnd, valueString.length),\n 'end'\n ),\n });\n }\n }\n\n if (result.matches.length > 0) {\n results.push(result);\n }\n });\n });\n\n return results;\n }\n\n private truncate(value: string, at: 'start' | 'end', limit = 15) {\n if (at === 'start') {\n return `${value.substring(value.length - limit, value.length)}`;\n } else {\n return `${value.substring(0, limit)}`;\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,kBAIO;AACP,IAAAC,mBAAe;;;ACLf,IAAAC,iBA4BO;AACP,IAAAC,mBAAe;AACf,oBAAkB;;;AC9BlB,IAAqB,gCAArB,cAA2D,MAAM;AAAA,EAC/D,YAAY,WAAmB;AAC7B,UAAM,+BAA+B,SAAS,GAAG;AAEjD,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAgD;AAChD,2BAAqD;AACrD,sBAAe;AACf,uBAA+C;AAC/C,gBAAe;AACf,kBAAiB;AAOV,IAAM,mBAAmB,YAAAC,QAAK,KAAK,UAAAC,QAAG,QAAQ,GAAG,SAAS;AAK1D,IAAM,SAAS;AAAA,EACpB,KAAK,YAAAD,QAAK,KAAK,kBAAkB,KAAK;AAAA,EACtC,UAAU,YAAAA,QAAK,KAAK,kBAAkB,WAAW;AAAA;AAAA,EAGjD,UAAU,YAAAA,QAAK,KAAK,kBAAkB,UAAU;AAAA,EAChD,SAAS,CAAC,cAA8B;AACtC,WAAO,YAAAA,QAAK,KAAK,OAAO,UAAU,SAAS;AAAA,EAC7C;AAAA,EACA,aAAa,CAAC,cAA8B;AAC1C,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,cAAc;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,CAAC,cAA8B;AAClC,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,kCAAoB,KAAK,GAAG;AAAA,EAC1E;AAAA,EAEA,aAAa,CAAC,cAA8B;AAC1C,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,SAAS;AAAA,MACxB,kCAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,YAAY,CAAC,WAAmB,OAAe;AAC7C,WAAO,YAAAA,QAAK,KAAK,OAAO,YAAY,SAAS,GAAG,EAAE;AAAA,EACpD;AAAA,EACA,gBAAgB,CAAC,WAAmB,OAAe;AACjD,WAAO,YAAAA,QAAK,KAAK,OAAO,WAAW,WAAW,EAAE,GAAG,iBAAiB;AAAA,EACtE;AAAA,EAEA,SAAS,CAAC,WAAmB,iBAAiC;AAC5D,WAAO,YAAAA,QAAK,KAAK,OAAO,WAAW,WAAW,YAAY,CAAC;AAAA,EAC7D;AAAA,EACA,WAAW,CACT,WACA,cACA,IACA,aACG;AACH,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,WAAW,YAAY;AAAA,MACtC,GAAG,EAAE,IAAI,QAAQ;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,cAAc,CAAC,cAA8B;AAC3C,WAAO,YAAAA,QAAK,KAAK,OAAO,QAAQ,SAAS,GAAG,eAAe;AAAA,EAC7D;AAAA,EACA,iBAAiB,CAAC,WAAmB,IAAY,aAAqB;AACpE,WAAO,YAAAA,QAAK,KAAK,OAAO,aAAa,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,OAAO;AAAA,EAC3E;AAAA,EAEA,QAAQ,CAAC,cAA8B;AACrC,WAAO,YAAAA,QAAK;AAAA,MACV,OAAO,QAAQ,SAAS;AAAA,MACxB,kCAAoB,KAAK;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,WAAW,CAAC,WAAmB,IAAY,aAA6B;AACtE,WAAO,YAAAA,QAAK,KAAK,OAAO,OAAO,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,OAAO;AAAA,EACrE;AAAA,EACA,OAAO,CACL,WACA,IACA,UACA,cACW;AACX,WAAO,YAAAA,QAAK,KAAK,OAAO,IAAI,SAAS,GAAG,GAAG,EAAE,IAAI,QAAQ,IAAI,SAAS,EAAE;AAAA,EAC1E;AACF;AAWO,IAAM,WAAW;AAAA,EACtB,WAAW,CAAC,SAAqC;AAC/C,UAAM,aAAa;AACnB,UAAM,WAAW;AACjB,UAAM,QAAQ,KAAK,QAAQ,UAAU,IAAI,WAAW;AAEpD,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AACA,UAAM,MAAM,KAAK,QAAQ,UAAU,KAAK;AAExC,UAAM,SAAS,KAAK,UAAU,OAAO,QAAQ,KAAK,KAAK,SAAS,GAAG;AACnE,QAAI,UAAU,yBAAW,UAAU,MAAM,EAAE,SAAS;AAClD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AACF;AAKO,SAAS,uBACd,OACA,YACG;AACH,SAAO,OAAO,OAAO,YAAY,KAAK;AACxC;AAQO,SAAS,SAAY,OAAyC;AACnE,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,MAAM,KAAK,MAAM,IAAI;AACvB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,UAAa,MAA4B;AACvD,SAAO,gBAAgB,UAAU;AACnC;AAKA,eAAsB,eAAkB,UAAwB;AAC9D,QAAM,UAAgC,CAAC;AACvC,WAAS,QAAQ,GAAG,QAAQ,SAAS,QAAQ,SAAS;AACpD,UAAM,UAAU,SAAS,KAAK;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,8BAA8B,KAAK,GAAG;AAAA,IACxD;AAIA,YAAQ;AAAA,MACN,QACG,KAAK,CAAC,WAAW;AAChB,eAAO;AAAA,MACT,CAAC,EACA,MAAM,CAAC,UAAU;AAGhB,eAAO,IAAI,MAAM,KAAK;AAAA,MACxB,CAAC;AAAA,IACL;AAAA,EACF;AAIA,QAAM,UAAU,MAAM,QAAQ,IAAI,OAAO;AAKzC,SAAO,QAAQ,OAAO,SAAS;AACjC;AAQO,SAAS,kBACd,SACA,MACA,SACiB;AACjB,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,mBAAe,4BAAM,SAAS,MAAM,OAAO;AACjD,QAAI,MAAM;AAEV,iBAAa,OAAO,GAAG,QAAQ,CAAC,SAAS;AACvC,aAAO;AAAA,IACT,CAAC;AAED,iBAAa,OAAO,GAAG,QAAQ,CAAC,SAAS;AACvC,aAAO;AAAA,IACT,CAAC;AAED,iBAAa,GAAG,SAAS,CAAC,UAAU;AAClC,YAAM;AAAA,IACR,CAAC;AAED,iBAAa,GAAG,QAAQ,CAAC,SAAS;AAChC,UAAI,SAAS,GAAG;AACd,eAAO,QAAQ,GAAG;AAAA,MACpB;AACA,aAAO,OAAO,GAAG;AAAA,IACnB,CAAC;AAAA,EACH,CAAC;AACH;AAKA,eAAsB,QAAQ,MAAoC;AAChE,QAAM,SAAS,MAAM,gBAAAE,QAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC7D,SAAO,OAAO,OAAO,CAACC,YAAW;AAC/B,WAAOA,QAAO,YAAY;AAAA,EAC5B,CAAC;AACH;AAKA,eAAsB,MACpB,MACA,WACsB;AACtB,QAAM,SAAS,MAAM,gBAAAD,QAAG,QAAQ,MAAM,EAAE,eAAe,KAAK,CAAC;AAC7D,SAAO,OAAO,OAAO,CAACC,YAAW;AAC/B,QAAI,aAAaA,QAAO,OAAO,MAAM,MAAM;AACzC,UAAIA,QAAO,KAAK,SAAS,SAAS,GAAG;AACnC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAOA,QAAO,OAAO;AAAA,EACvB,CAAC;AACH;AAMO,SAAS,gBAAgB,MAAsB;AACpD,MAAI,eAAe,KAAK,QAAQ,kBAAkB,EAAE;AACpD,MAAI,aAAa,WAAW,GAAG,GAAG;AAChC,mBAAe,aAAa,OAAO,CAAC;AAAA,EACtC;AACA,SAAO;AACT;AAQO,SAAS,cAAiB,KAAU,KAAc;AACvD,QAAM,cAAU,0BAAQ,KAAK,CAAC,SAAS;AACrC,WAAO,KAAK,GAAG;AAAA,EACjB,CAAC;AACD,aAAO;AAAA,QACL;AAAA,UACE,yBAAO,SAAS,CAAC,SAAS;AACxB,eAAO,KAAK,SAAS;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC7RA,IAAAC,iBAcO;AACP,IAAAC,oBAAgC;AAOhC,IAA8B,sBAA9B,MAAkD;AAAA;AAAA;AAAA;AAAA,EAgBtC,YAAY,MAAmB,SAA4B;AACnE,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,aAAa;AAAA,MAChB,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,MAC/D,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,MAC/D,QAAQ,GAAG,mCAAoB,KAAK,MAAM,YAAY,KAAK,IAAI;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAgB,SACd,MACA,OAAkB,CAAC,GACnBC,UAAS,IACT,QAAQ,IACR,SAAS,GACkB;AAC3B,QAAI,SAAS;AACb,UAAM,QAAQ,KAAK;AACnB,UAAM,mBAAmBA,QAAO,KAAK,EAAE,YAAY;AAGnD,QAAI,qBAAqB,IAAI;AAC3B,oCAAO,QAAQ,CAAC,UAAU;AACxB,YAAI;AACJ,aAAK,OAAO,OAAO;AACjB,gBAAM,QAAQ,MAAM,GAAG;AACvB,cAAI,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,gBAAgB,GAAG;AAC1D,mBAAO;AAAA,UACT;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAGA,QAAI,KAAK,WAAW,GAAG;AACrB,YAAM,OAAO,KAAK,IAAI,CAAC,UAAU,MAAM,EAAE;AACzC,YAAM,SAAS,KAAK,IAAI,CAAC,UAAU,MAAM,KAAK;AAC9C,mBAAS,2BAAQ,QAAQ,MAAM,MAAM;AAAA,IACvC;AAGA,QAAI,UAAU,GAAG;AACf,eAAS,OAAO,MAAM,QAAQ,SAAS,KAAK;AAAA,IAC9C;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAgB,eACd,MACA,WACA,cAC0B;AAC1B,YAAQ,MAAM;AAAA,MACZ,KAAK,gCAAiB,KAAK;AACzB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,kBAA2B,OAAO,IAAI,SAAS,CAAC;AAAA,MAE9D,KAAK,gCAAiB,KAAK;AACzB,eAAO,KAAK,oBAA6B,OAAO,QAAQ;AAAA,MAE1D,KAAK,gCAAiB,KAAK;AACzB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,oBAA6B,OAAO,YAAY,SAAS,CAAC;AAAA,MAExE,KAAK,gCAAiB,KAAK;AACzB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI,8BAA8B,cAAc;AAAA,QACxD;AACA,eAAO,KAAK;AAAA,UACD,OAAO,WAAW,WAAW,YAAY;AAAA,QACpD;AAAA,MAEF,KAAK,gCAAiB,KAAK;AACzB,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,8BAA8B,WAAW;AAAA,QACrD;AACA,eAAO,KAAK,kBAA2B,OAAO,aAAa,SAAS,CAAC;AAAA,MAEvE;AACE,cAAM,IAAI,MAAM,6CAA6C,IAAI,GAAG;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,MAAwC;AACxE,UAAM,kBAAkB,MAAe,QAAQ,IAAI;AACnD,UAAM,UAAU,gBAAgB,IAAI,CAAC,mBAAmB;AACtD,YAAM,kBAAiC;AAAA,QACrC,IAAI,eAAe;AAAA,MACrB;AAEA,UAAI;AACF,eAAO,mCAAoB,MAAM,eAAe;AAAA,MAClD,SAAS,OAAO;AACd,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,WAAO,QAAQ,OAAgB,QAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBAAkB,MAAwC;AACtE,UAAM,gBAAgB,MAAe,MAAM,IAAI;AAE/C,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,cAAc,IAAI,OAAO,iBAAiB;AACxC,cAAM,gBAAgB,aAAa,KAAK,MAAM,GAAG;AAEjD,cAAM,gBAA+B;AAAA,UACnC,IAAI,cAAc,CAAC;AAAA,UACnB,UACE,cAAc,WAAW,IACpB,cAAc,CAAC,IAChB;AAAA,UACN,WACE,cAAc,WAAW,IACpB,cAAc,CAAC,IACf,cAAc,CAAC;AAAA,QACxB;AAEA,YAAI;AACF,iBAAO,mCAAoB,MAAM,aAAa;AAAA,QAChD,SAAS,OAAO;AACd,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO,QAAQ,OAAgB,QAAQ;AAAA,EACzC;AACF;;;ACpNA,IAAAC,iBASO;AACP,oBAA4C;AAC5C,qBAAmB;;;ACXnB,IAAqB,WAArB,cAAsC,MAAM;AAAA,EAC1C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAqB,qBAArB,cAAgD,MAAM;AAAA,EACpD,cAAc;AACZ,UAAM,6DAA6D;AAEnE,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAAC,iBAkBO;AAQP,IAAqB,gBAArB,cACU,oBAEV;AAAA,EAGS,YAAY,SAA4B,KAAwB;AACrE,UAAM,iCAAkB,KAAK,QAAQ,OAAO;AAE5C,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAA2C;AAC7D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,SAAK,qBAAK;AAChB,QAAI,OAAO,CAAC,OAAO,cAAc,EAAE;AAEnC,QAAI,MAAM,MAAM;AACd,aAAO,CAAC,GAAG,MAAM,MAAM,IAAI;AAAA,IAC7B;AAEA,WAAO,CAAC,GAAG,MAAM,MAAM,MAAM,OAAO;AAEpC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAC/B,UAAM,MAAM,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM,GAAG,CAAC;AAEpD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,KAAK,OAAyC;AACzD,oCAAiB,MAAM,KAAK;AAE5B,UAAM,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,GAAG,CAAC;AAEnE,QAAI,KAAK,UAAU,GAAG;AACpB,YAAM,IAAI;AAAA,QACR,2BAA2B,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,GAAG;AAClB,YAAM,IAAI;AAAA,QACR,2BAA2B,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AAEA,WAAO,KAAK,KAAK,CAAC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,SAAyB;AACpC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OAAO,OAAyC;AAC3D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,OAAO,CAAC,OAAO,YAAY,MAAM,EAAE;AACzC,UAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,KAAK,OAAyD;AACzE,qCAAkB,MAAM,KAAK;AAE7B,QAAI,OAAO,CAAC,OAAO,QAAQ;AAE3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF;AACA,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM,MAAM,IAAI;AAE9C,UAAM,kBAAkB,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,CAAC,SAAS;AACjE,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,UAAM,aAAa,gBAAgB,IAAI,CAAC,SAAS;AAC/C,YAAM,YAAY,KAAK,MAAM,GAAG;AAChC,aAAO;AAAA,QACL,IAAI,UAAU,CAAC;AAAA,QACf,SAAS,UAAU,CAAC;AAAA,QACpB,QAAQ;AAAA,UACN,MAAM,UAAU,CAAC;AAAA,UACjB,OAAO,UAAU,CAAC;AAAA,QACpB;AAAA,QACA,WACE,OAAO,UAAU,CAAC,MAAM,WAAW,SAAS,UAAU,CAAC,CAAC,IAAI;AAAA,MAChE;AAAA,IACF,CAAC;AAED,UAAM,UAAU,WAAW,OAAO,KAAK,SAAS,KAAK,IAAI,CAAC;AAE1D,WAAO,KAAK;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,MAAM,OAA2C;AAC5D,sCAAmB,MAAM,KAAK;AAE9B,UAAM,UAAU,MAAM,KAAK,KAAK,EAAE,MAAM,MAAM,KAAK,CAAC;AACpD,WAAO,QAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,SAAS,KAA6B;AAC5C,WAAO,4BAAa,UAAU,GAAG,EAAE;AAAA,EACrC;AACF;;;ACxLA,IAAAC,iBAOO;;;ACPP,IAAAC,iBAKO;AACP,IAAAC,mBAAe;AAOf,IAAqB,kBAArB,cAA6C,oBAAoB;AAAA,EAG/D,YAAY,SAA4B;AACtC,UAAM,iCAAkB,KAAK,UAAU,OAAO;AAHhD,SAAQ,QAA0B,oBAAI,IAAI;AAAA,EAI1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OACX,MACA,MACA,QACsB;AACtB,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,UAAM,SAAS,KAAK,UAAU,UAAU;AACxC,UAAM,iBAAAC,QAAG,UAAU,MAAM,QAAQ;AAAA,MAC/B,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,KACX,MACA,QACsB;AACtB,QAAI,KAAK,MAAM,IAAI,IAAI,GAAG;AAExB,aAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IAC5B;AAGA,UAAM,OAAO,MAAM,iBAAAA,QAAG,SAAS,MAAM;AAAA,MACnC,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,UAAM,OAAO,KAAK,YAAY,IAAI;AAClC,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,OACX,MACA,MACA,QACsB;AACtB,UAAM,aAAa,OAAO,MAAM,IAAI;AACpC,UAAM,SAAS,KAAK,UAAU,UAAU;AACxC,UAAM,iBAAAA,QAAG,UAAU,MAAM,QAAQ;AAAA,MAC/B,MAAM;AAAA,MACN,UAAU;AAAA,IACZ,CAAC;AACD,SAAK,MAAM,IAAI,MAAM,UAAU;AAE/B,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,MAAuB;AACvC,WAAO,KAAK,UAAU,MAAM,MAAM,KAAK,QAAQ,KAAK,KAAK,WAAW;AAAA,EACtE;AAAA,EAEQ,YAAY,MAAuB;AACzC,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB;AACF;;;AD3FA,IAAqB,cAArB,MAAiC;AAAA,EAG/B,YAAY,iBAAkC;AAC5C,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,MAAiC;AAC5C,QAAI;AACF,aAAO,MAAM,KAAK,gBAAgB;AAAA,QACvB,OAAO;AAAA,QAChB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,IAAI,OAAoC;AACnD,iCAAc,MAAM,KAAK;AAEzB,UAAM,eAAwB,OAAO;AAErC,UAAM,WAAqB;AAAA,MACzB,GAAG;AAAA,IACL;AAEA,QAAI,SAAS,aAAa,8BAAe,KAAK,OAAO;AAAA,IAGrD;AAEA,UAAM,KAAK,gBAAgB,OAAO,UAAU,cAAc,6BAAc;AAExE,WAAO;AAAA,EACT;AACF;;;AJ5BA,IAAqBC,cAArB,MAAgC;AAAA,EAMvB,YAAY,SAA4B,aAA0B;AACvE,SAAK,UAAU;AACf,SAAK,QAAQ,IAAI,eAAAC,QAAO;AAAA,MACtB,aAAa;AAAA;AAAA,IACf,CAAC;AACD,SAAK,gBAAgB,IAAI,cAAc,SAAS,KAAK,GAAG;AACxD,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAsB;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,aAA4B;AACvC,UAAM,SAAS,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC;AAC/C,SAAK,UAAU,OAAO,OAAO,QAAQ,eAAe,EAAE,EAAE,KAAK;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,KACX,MACA,SACe;AACf,QAAI,OAAO,CAAC,MAAM;AAElB,QAAI,SAAS,eAAe;AAC1B,aAAO,CAAC,GAAG,MAAM,oBAAoB,QAAQ,aAAa,EAAE;AAAA,IAC9D;AAEA,UAAM,KAAK,IAAI,MAAM,IAAI;AACzB,UAAM,KAAK,eAAe,IAAI;AAC9B,UAAM,KAAK,WAAW,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAa,MACX,KACA,MACA,SACe;AACf,QAAI,OAAO,CAAC,SAAS,YAAY;AAEjC,QAAI,SAAS,QAAQ;AACnB,aAAO,CAAC,GAAG,MAAM,YAAY,QAAQ,MAAM;AAAA,IAC7C;AAEA,QAAI,SAAS,OAAO;AAClB,aAAO,CAAC,GAAG,MAAM,WAAW,QAAQ,MAAM,SAAS,CAAC;AAAA,IACtD;AAEA,QAAI,SAAS,iBAAiB,MAAM;AAClC,aAAO,CAAC,GAAG,MAAM,iBAAiB;AAAA,IACpC;AAEA,UAAM,KAAK,IAAI,MAAM,CAAC,GAAG,MAAM,KAAK,GAAG,CAAC;AACxC,UAAM,KAAK,eAAe,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,IAAI,MAAcC,QAAgC;AAC7D,UAAM,OAAO,CAAC,OAAO,MAAM,GAAGA,MAAK;AAEnC,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,OACX,MACA,MACA,SACe;AACf,UAAM,KAAK,qBAAqB,MAAM,IAAI;AAE1C,QAAI,OAAO,CAAC,QAAQ;AAEpB,QAAI,SAAS,UAAU,MAAM;AAC3B,aAAO,CAAC,GAAG,MAAM,YAAY,IAAI;AAAA,IACnC,OAAO;AACL,aAAO,CAAC,GAAG,MAAM,IAAI;AAAA,IACvB;AAEA,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,MAAM,MAAc,MAAuB,QAAgB;AACtE,UAAM,OAAO,CAAC,SAAS,KAAK,IAAI,IAAI,MAAM;AAC1C,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAa,KAAK,MAA6B;AAC7C,UAAM,OAAO,CAAC,MAAM;AACpB,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OAAO,MAAc,SAAgC;AAChE,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,OAAO;AAAA,MACX;AAAA,MACA,aAAa,OAAO;AAAA,MACpB,YAAY,KAAK,IAAI,KAAK,KAAK,KAAK;AAAA,IACtC;AACA,UAAM,KAAK,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,IACX,MACA,SACsB;AACtB,QAAI,OAAO,CAAC,KAAK;AAEjB,QAAI,SAAS,SAAS,MAAM;AAC1B,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,QAAQ,QAAQ,IAAI,MAAM,QAAQ,QAAQ,MAAM,MAAM;AAAA,MAC3D;AAAA,IACF;AAEA,QAAI,SAAS,OAAO;AAClB,aAAO,CAAC,GAAG,MAAM,eAAe,QAAQ,KAAK,EAAE;AAAA,IACjD;AAEA,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AAED,UAAM,kBAAkB,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,CAAC,SAAS;AACjE,aAAO,SAAS;AAAA,IAClB,CAAC;AAED,UAAM,aAAa,gBAAgB,IAAI,CAAC,SAAS;AAC/C,YAAM,YAAY,KAAK,MAAM,GAAG;AAChC,aAAO;AAAA,QACL,MAAM,UAAU,CAAC;AAAA,QACjB,SAAS,UAAU,CAAC;AAAA,QACpB,QAAQ;AAAA,UACN,MAAM,UAAU,CAAC;AAAA,UACjB,OAAO,UAAU,CAAC;AAAA,QACpB;AAAA,QACA,WAAW,SAAS,UAAU,CAAC,CAAC;AAAA,QAChC,KAAK,KAAK,iBAAiB,UAAU,CAAC,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAED,WAAO,WAAW,OAAO,KAAK,YAAY,KAAK,IAAI,CAAC;AAAA,EACtD;AAAA,EAEO,iBAAiB,SAAiB;AACvC,QAAI,UAA8B;AAGlC,cAAU,QAAQ,QAAQ,SAAS,EAAE;AAErC,QACE,QAAQ,KAAK,MAAM,MACnB,0BAAW,UAAU,OAAO,EAAE,YAAY,OAC1C;AACA,gBAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAa,wBAAwB,MAAc,MAAc;AAC/D,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,4BAA4B,MAAc,MAAc;AACnE,UAAM,SAAS,MAAM,KAAK,IAAI,MAAM;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,WAAO,SAAS,OAAO,MAAM;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,0BAA0B,MAAc,MAAc;AACjE,UAAM,OAAO,MAAM,QAAQ,IAAI;AAAA,MAC7B,KAAK,wBAAwB,MAAM,IAAI;AAAA,MACvC,KAAK,4BAA4B,MAAM,IAAI;AAAA,IAC7C,CAAC;AACD,WAAO;AAAA,MACL,SAAS,KAAK,CAAC;AAAA,MACf,SAAS,KAAK,CAAC;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,qBAAqB,MAAc,MAAc;AAC7D,UAAM,KAAK,IAAI,MAAM,CAAC,oBAAoB,oBAAoB,IAAI,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,WAAW,MAA6B;AACpD,UAAM,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,CAAC;AACvC,UAAM,KAAK,IAAI,MAAM,CAAC,OAAO,SAAS,OAAO,CAAC;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,eAAe,MAAc;AACzC,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,eAAe,CAAC,UAAU,WAAW,aAAa,KAAK,IAAI;AACjE,UAAM,gBAAgB,CAAC,UAAU,WAAW,cAAc,KAAK,KAAK;AACpE,UAAM,KAAK,IAAI,MAAM,YAAY;AACjC,UAAM,KAAK,IAAI,MAAM,aAAa;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,YAAY,KAAgC;AAClD,WAAO,+BAAgB,UAAU,GAAG,EAAE;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,IAAI,MAAc,MAAqC;AACnE,UAAM,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,yBAAW,KAAK,MAAM,IAAI,CAAC;AACrE,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,QAAQ,KAAK,OAAO,kBAAkB,KAAK;AAAA,UACzC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AJtYA,IAAqB,eAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA;AACA,UAAM,iCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,WAAW,MAAM,KAAK,4BAA4B,MAAM,QAAQ;AACtE,UAAM,OAAO,MAAM,KAAK,aAAa,MAAM,QAAQ;AACnD,UAAM,YAAqB,OAAO;AAAA,MAChC,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AACA,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AAEA,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,YAAY;AAAA,MACZ;AAAA,MACA,aAAS,iCAAiB;AAAA,MAC1B,WAAW,SAAS;AAAA,MACpB,UAAU,SAAS;AAAA,MACnB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,iBAAAC,QAAG,SAAS,MAAM,UAAU,SAAS;AAC3C,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,YAAM,KAAK,OAAO,EAAE,GAAG,WAAW,WAAW,MAAM,UAAU,CAAC;AAC9D,YAAM;AAAA,IACR;AAEA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,eAAe,SAAS,CAAC;AACjE,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAuC;AACvD,mCAAgB,MAAM,KAAK;AAE3B,UAAM,YAAY,MAAM,KAAK,gBAAgB;AAAA,MAClC,OAAO,UAAU,MAAM,WAAW,MAAM,IAAI,MAAM,QAAQ;AAAA,MACnE;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAAyC;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,gBAAgB,MAAM,KAAK,KAAK,KAAK;AAI3C,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,iCAAiB;AAAA,IAC5B;AAEA,QAAI,MAAM,aAAa;AAGrB,YAAM,WAAW,MAAM,KAAK;AAAA,QAC1B,MAAM;AAAA,MACR;AACA,YAAM,OAAO,MAAM,KAAK,aAAa,MAAM,WAAW;AACtD,YAAM,gBAAyB,OAAO;AAAA,QACpC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,cAAc;AAAA,MAChB;AACA,YAAM,YAAqB,OAAO;AAAA,QAChC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAGA,YAAM,iBAAAA,QAAG,OAAO,aAAa;AAC7B,YAAM,iBAAAA,QAAG,SAAS,MAAM,aAAa,SAAS;AAG9C,gBAAU,YAAY,SAAS;AAC/B,gBAAU,WAAW,SAAS;AAC9B,gBAAU,OAAO;AAAA,IACnB;AAEA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO,KAAK,QAAQ,MAAM,WAAW,SAAS;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAwC;AAC1D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,YAAqB,OAAO;AAAA,MAChC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,iBAAAA,QAAG,OAAO,SAAS;AACzB,UAAM,iBAAAA,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,eAAe,SAAS,CAAC;AACjE,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KAAK,OAAuD;AACvE,oCAAiB,MAAM,KAAK;AAE5B,UAAM,kBAAkB,MAAM,KAAK;AAAA,MACjC,gCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,gBAAgB,IAAI,CAAC,mBAAmB;AACtC,YAAI,CAAC,eAAe,UAAU;AAC5B,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,eAAe;AAAA,UACnB,UAAU,eAAe;AAAA,QAC3B,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,UAAM,kBAAkB,KAAK;AAAA,MAC3B;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,MAAM,OAA0C;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SACJ,MAAM,KAAK,eAAe,gCAAiB,KAAK,OAAO,MAAM,SAAS,GACtE;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,KAAuC;AACpD,WAAO,2BAAY,UAAU,GAAG,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,aAAa,MAAc;AACvC,YAAQ,MAAM,iBAAAA,QAAG,KAAK,IAAI,GAAG;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,QACZ,WACA,WACgB;AAChB,UAAM,YAAqB,OAAO;AAAA,MAChC;AAAA,MACA,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAEA,UAAM,QAAe;AAAA,MACnB,GAAG;AAAA,MACH,cAAc;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,4BAA4B,UAAkB;AAC1D,UAAM,YAAY,MAAM,iBAAAA,QAAG,KAAK,QAAQ,GAAG;AAI3C,QAAI,WAAW,OAAQ,KAAK;AAC1B,YAAM,aAAa,MAAM,iBAAAA,QAAG,SAAS,QAAQ;AAC7C,cAAI,cAAAC,SAAM,WAAW,SAAS,CAAC,MAAM,MAAM;AACzC,eAAO;AAAA,UACL,WAAW,6CAA8B,KAAK;AAAA,UAC9C,UAAU,4CAA6B,KAAK,eAAe;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAGA,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,WAAW;AACrD,UAAM,WAAW,MAAM,iBAAiB,QAAQ;AAEhD,UAAM,SAAS,wCAAyB,MAAM;AAAA,MAC5C,WAAW,UAAU;AAAA,MACrB,UAAU,UAAU;AAAA,IACtB,CAAC;AAED,WAAO;AAAA,EACT;AACF;;;AUtUA,IAAAC,iBAyBO;AACP,IAAAC,mBAAe;AASf,IAAqB,oBAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA;AACA,UAAM,iCAAkB,KAAK,YAAY,OAAO;AAEhD,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAmD;AACrE,0CAAuB,MAAM,KAAK;AAElC,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,iBAA0B,OAAO,WAAW,MAAM,WAAW,EAAE;AACrE,UAAM,qBAA8B,OAAO;AAAA,MACzC,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,iBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,YAAY;AAAA,MACZ;AAAA,MACA,MAAM;AAAA,QACJ,cAAU,qBAAK,MAAM,KAAK,QAAQ;AAAA,QAClC,YAAQ,qBAAK,MAAM,KAAK,MAAM;AAAA,MAChC;AAAA,MACA,aAAS,iCAAiB;AAAA,IAC5B;AAEA,UAAM,iBAAAC,QAAG,UAAU,cAAc;AACjC,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,kBAAkB,CAAC;AAC3D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAiD;AACjE,wCAAqB,MAAM,KAAK;AAEhC,UAAM,aAAa,MAAM,KAAK,gBAAgB;AAAA,MACnC,OAAO,eAAe,MAAM,WAAW,MAAM,EAAE;AAAA,MACxD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAa,OAAO,OAAmD;AACrE,0CAAuB,MAAM,KAAK;AAElC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,qBAA8B,OAAO;AAAA,MACzC,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,qBAAqB,MAAM,KAAK,KAAK,KAAK;AAEhD,UAAM,iBAAiC;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,iCAAiB;AAAA,IAC5B;AAoJA,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,kBAAkB,CAAC;AAC3D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAChE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAA6C;AAC/D,0CAAuB,MAAM,KAAK;AAElC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,iBAA0B,OAAO;AAAA,MACrC,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAA,QAAG,OAAO,cAAc;AAC9B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,cAAc,CAAC;AACvD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KACX,OACoC;AACpC,yCAAsB,MAAM,KAAK;AAEjC,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,gCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,UAAU;AAAA,QAChB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA+C;AAChE,0CAAuB,MAAM,KAAK;AAElC,UAAM,SACJ,MAAM,KAAK;AAAA,MACT,gCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,IACR,GACA;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,KAA4C;AAC9D,WAAO,oCAAqB,UAAU,GAAG,EAAE;AAAA,EAC7C;AACF;;;AC/VA,IAAAC,kBAkCO;AACP,IAAAC,mBAAe;;;ACnCf,IAAAC,iBA2BO;AACP,IAAAC,mBAAe;AAWf,IAAqB,qBAArB,cACU,oBAEV;AAAA,EAIE,YACE,SACA,iBACA,YACA,cACA;AACA,UAAM,iCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAqD;AACvE,2CAAwB,MAAM,KAAK;AAEnC,UAAM,SAAK,qBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,sBAA+B,OAAO;AAAA,MAC1C,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AAEA,UAAM,kBAAmC;AAAA,MACvC,GAAG;AAAA,MACH,YAAY;AAAA,MACZ;AAAA,MACA,aAAS,iCAAiB;AAAA,IAC5B;AAEA,SAAK,SAAS,eAAe;AAE7B,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,mBAAmB,CAAC;AAC5D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAmD;AACnE,yCAAsB,MAAM,KAAK;AAEjC,UAAM,kBAAkB,MAAM,KAAK,gBAAgB;AAAA,MACxC,OAAO;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,OAAO,OAAqD;AACvE,2CAAwB,MAAM,KAAK;AAEnC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,sBAA+B,OAAO;AAAA,MAC1C,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,sBAAsB,MAAM,KAAK,KAAK,KAAK;AAEjD,UAAM,kBAAmC;AAAA,MACvC,GAAG;AAAA,MACH,SAAS,MAAM;AAAA,MACf,aAAS,iCAAiB;AAAA,IAC5B;AAEA,SAAK,SAAS,eAAe;AAE7B,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,mBAAmB,CAAC;AAC5D,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAA8C;AAChE,2CAAwB,MAAM,KAAK;AAEnC,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAC,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KACX,OACqC;AACrC,0CAAuB,MAAM,KAAK;AAElC,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,gCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,YAAI,CAAC,UAAU,UAAU;AACvB,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,IAAI,UAAU;AAAA,UACd,UAAU,UAAU;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA0C;AAC3D,qCAAkB,MAAM,KAAK;AAE7B,UAAM,SACJ,MAAM,KAAK;AAAA,MACT,gCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,IACR,GACA;AAEF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,cAAc,KAA6C;AAChE,WAAO,iCAAkB,UAAU,GAAG,EAAE;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKQ,SAAS,aAA8B;AAC7C,YAAQ,YAAY,WAAW;AAAA,MAC7B,KAAK,+BAAgB,KAAK;AACxB,yBAAE,QAAQ,EAAE,MAAM,YAAY,OAAO;AACrC;AAAA,MACF,KAAK,+BAAgB,KAAK;AACxB,yBAAE,OAAO,EAAE,MAAM,YAAY,OAAO;AACpC;AAAA,MACF,KAAK,+BAAgB,KAAK;AACxB,yBAAE,OAAO,EAAE,MAAM,YAAY,OAAO;AACpC;AAAA,MACF;AACE,cAAM,IAAI;AAAA,UACR,wEAAwE,YAAY,SAAS;AAAA,QAC/F;AAAA,IACJ;AAAA,EACF;AACF;;;AD1LA,IAAqB,eAArB,cACU,oBAEV;AAAA,EAOE,YACE,SACA,iBACA,YACA,mBACA,cACA,oBACA;AACA,UAAM,kCAAkB,KAAK,OAAO,OAAO;AAE3C,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,SAAK,eAAe;AACpB,SAAK,qBAAqB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,SAAK,sBAAK;AAChB,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,IACR;AACA,UAAM,aAAa,MAAM,KAAK,kBAAkB,KAAK;AAAA,MACnD,WAAW,MAAM;AAAA,MACjB,IAAI,MAAM;AAAA,IACZ,CAAC;AAED,UAAM,YAAuB;AAAA,MAC3B,YAAY;AAAA,MACZ;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,QAAQ,MAAM;AAAA,MACd,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,QAAe,MAAM,KAAK,QAAQ;AAAA,MACtC,WAAW,MAAM;AAAA,MACjB;AAAA,IACF,CAAC;AAED,SAAK,eAAe;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,kBAAkB,WAAW;AAAA,MAC7B,QAAQ,MAAM;AAAA,IAChB,CAAC;AAED,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAAuC;AACvD,oCAAgB,MAAM,KAAK;AAE3B,UAAM,YAAuB,MAAM,KAAK,gBAAgB;AAAA,MAC7C,OAAO;AAAA,QACd,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,QAAQ,EAAE,WAAW,MAAM,WAAW,UAAU,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAyC;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,aAAa,MAAM,KAAK,kBAAkB,KAAK;AAAA,MACnD,WAAW,MAAM;AAAA,MACjB,IAAI,MAAM;AAAA,IACZ,CAAC;AAED,UAAM,gBAAgB,MAAM,KAAK,KAAK;AAAA,MACpC,WAAW,MAAM;AAAA,MACjB,cAAc,MAAM;AAAA,MACpB,IAAI,MAAM;AAAA,MACV,UAAU,MAAM;AAAA,IAClB,CAAC;AAED,UAAM,YAAuB;AAAA,MAC3B,GAAG;AAAA,MACH,QAAQ,MAAM;AAAA,MACd,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,QAAe,MAAM,KAAK,QAAQ;AAAA,MACtC,WAAW,MAAM;AAAA,MACjB;AAAA,IACF,CAAC;AAED,SAAK,eAAe;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,kBAAkB,WAAW;AAAA,MAC7B,QAAQ,MAAM;AAAA,IAChB,CAAC;AAED,UAAM,KAAK,gBAAgB;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAAwC;AAC1D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAuB,OAAO,QAAQ,MAAM,SAAS;AAC3D,UAAM,gBAAyB,OAAO;AAAA,MACpC,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAEA,UAAM,iBAAAC,QAAG,OAAO,aAAa;AAC7B,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,aAAa,CAAC;AACtD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAAA,EAClE;AAAA,EAEA,MAAa,KAAK,OAAyB;AACzC,sCAAkB,MAAM,KAAK;AAE7B,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5B,iCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AACA,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,YAAI,CAAC,UAAU,UAAU;AACvB,gBAAM,IAAI,8BAA8B,UAAU;AAAA,QACpD;AACA,eAAO,KAAK,KAAK;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,cAAc,MAAM;AAAA,UACpB,IAAI,UAAU;AAAA,UACd,UAAU,UAAU;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,MAAM,OAA2C;AAC5D,uCAAmB,MAAM,KAAK;AAE9B,YACE,MAAM,KAAK;AAAA,MACT,iCAAiB,KAAK;AAAA,MACtB,MAAM;AAAA,MACN,MAAM;AAAA,IACR,GACA;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,KAAuC;AACpD,WAAO,4BAAY,UAAU,GAAG,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAAuB,OAI5B;AACD,UAAM,aAAa,MAAM,iBAAiB,KAAK,CAAC,QAAQ;AACtD,UAAI,IAAI,OAAO,MAAM,IAAI;AACvB,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAED,QAAI,CAAC,YAAY;AACf,YAAM,IAAI;AAAA,QACR,0BAA0B,MAAM,EAAE,0BAA0B,MAAM,YAAY;AAAA,MAChF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,OAIpB;AACD,UAAM,OAAO,IAAI,CAAC,UAAU;AAC1B,YAAM,aAAa,KAAK,uBAAuB;AAAA,QAC7C,cAAc,MAAM;AAAA,QACpB,kBAAkB,MAAM;AAAA,QACxB,IAAI,MAAM;AAAA,MACZ,CAAC;AACD,YAAM,aAAS,qDAAoC,UAAU;AAE7D,UAAI;AACF,eAAO,MAAM,MAAM,OAAO;AAAA,MAC5B,SAAS,OAAO;AACd,gBAAQ,IAAI,eAAe,UAAU;AACrC,gBAAQ,IAAI,UAAU,KAAK;AAC3B,cAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,MAAc,6BAA6B,OAGA;AACzC,YAAQ,MAAM,sBAAsB,qBAAqB;AAAA,MACvD,KAAK,iCAAiB,KAAK;AACzB,eAAO,KAAK,oCAAoC;AAAA,UAC9C,WAAW,MAAM;AAAA,UACjB,8BAA8B,MAAM;AAAA,QACtC,CAAC;AAAA,MACH,KAAK,iCAAiB,KAAK;AACzB,eAAO,KAAK,0CAA0C;AAAA,UACpD,WAAW,MAAM;AAAA,UACjB,oCAAoC,MAAM;AAAA,QAC5C,CAAC;AAAA,MAEH;AACE,cAAM,IAAI;AAAA;AAAA,UAER,iDAAiD,MAAM,sBAAsB,mBAAmB;AAAA,QAClG;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAc,oCAAoC,OAGA;AAChD,UAAM,qBAAqB,MAAM,QAAQ;AAAA,MACvC,MAAM,6BAA6B,WAAW,IAAI,OAAO,cAAc;AACrE,cAAM,gBAAgB,MAAM,KAAK,aAAa,KAAK;AAAA,UACjD,WAAW,MAAM;AAAA,UACjB,IAAI,UAAU;AAAA,UACd,UAAU,UAAU;AAAA,QACtB,CAAC;AACD,eAAO;AAAA,UACL,GAAG;AAAA,UACH,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,GAAG,MAAM;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EAEA,MAAc,0CAA0C,OAGA;AACtD,UAAM,sBAAsB,MAAM,KAAK,mBAAmB,KAAK;AAAA,MAC7D,WAAW,MAAM;AAAA,MACjB,IAAI,MAAM,mCAAmC,WAAW;AAAA,MACxD,UAAU,MAAM,mCAAmC,WAAW;AAAA,IAChE,CAAC;AAED,WAAO;AAAA,MACL,GAAG,MAAM;AAAA,MACT,YAAY;AAAA,QACV,GAAG,MAAM,mCAAmC;AAAA,QAC5C,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,QAAQ,OAGH;AACjB,UAAM,QAAe;AAAA,MACnB,GAAG,MAAM;AAAA,MACT,QAAQ,MAAM,QAAQ;AAAA,QACpB,MAAM,UAAU,OAAO,IAAI,OAAO,UAAU;AAC1C,cAAI,MAAM,cAAc,gCAAgB,KAAK,WAAW;AACtD,kBAAM,gCACJ,MAAM,KAAK,6BAA6B;AAAA,cACtC,WAAW,MAAM;AAAA,cACjB,uBAAuB,MAAM;AAAA,YAC/B,CAAC;AAEH,mBAAO;AAAA,cACL,GAAG;AAAA,cACH,SAAS;AAAA,YACX;AAAA,UACF;AAEA,iBAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;;;AEhbA,IAAAC,kBA8BO;AACP,IAAAC,mBAAe;AACf,IAAAC,aAAe;AACf,IAAAC,eAAiB;AACjB,oBAAmB;;;AClCnB,IAAqB,sBAArB,cAAiD,MAAM;AAAA,EACrD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AAEb,SAAK,OAAO;AAAA,EACd;AACF;;;ACNA,IAAAC,kBAKO;AAUP,IAAqB,gBAArB,cAA2C,oBAAoB;AAAA,EAI7D,YACE,SACA,cACA,mBACA;AACA,UAAM,kCAAkB,KAAK,QAAQ,OAAO;AAE5C,SAAK,eAAe;AACpB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,OACX,WACA,OACA,YACA;AACA,UAAM,UAA0B,CAAC;AACjC,UAAM,kBAAkB,MAAM,KAAK;AAEnC,QAAI,oBAAoB,IAAI;AAC1B,aAAO;AAAA,IACT;AAEA,UAAM,kBACJ,MAAM,QAAQ,IAAI,CAAC,KAAK,aAAa,KAAK,EAAE,WAAW,QAAQ,MAAM,CAAC,CAAC,CAAC,GACxE,KAAK;AAEP,mBAAe,QAAQ,CAAC,kBAAkB;AACxC,oBAAc,KAAK,KAAK,EAAE,QAAQ,CAAC,SAAS;AAC1C,cAAM,SAAuB;AAAA,UAC3B,IAAI,KAAK;AAAA,UACT,UAAU,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,UACX,SAAS,CAAC;AAAA,QACZ;AAEA,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,gBAAM,cAAc,OAAO,KAAK;AAChC,cACE,YAAY,YAAY,EAAE,SAAS,gBAAgB,YAAY,CAAC,GAChE;AACA,kBAAM,aAAa,YAChB,YAAY,EACZ,QAAQ,gBAAgB,YAAY,CAAC;AACxC,kBAAM,WAAW,aAAa,gBAAgB;AAE9C,mBAAO,QAAQ,KAAK;AAAA,cAClB;AAAA,cACA,QAAQ,KAAK;AAAA,gBACX,YAAY,UAAU,GAAG,UAAU;AAAA,gBACnC;AAAA,cACF;AAAA,cACA,OAAO,YAAY,UAAU,YAAY,QAAQ;AAAA,cACjD,QAAQ,KAAK;AAAA,gBACX,YAAY,UAAU,UAAU,YAAY,MAAM;AAAA,gBAClD;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAEA,YAAI,OAAO,QAAQ,SAAS,GAAG;AAC7B,kBAAQ,KAAK,MAAM;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,SAAS,OAAe,IAAqB,QAAQ,IAAI;AAC/D,QAAI,OAAO,SAAS;AAClB,aAAO,GAAG,MAAM,UAAU,MAAM,SAAS,OAAO,MAAM,MAAM,CAAC;AAAA,IAC/D,OAAO;AACL,aAAO,GAAG,MAAM,UAAU,GAAG,KAAK,CAAC;AAAA,IACrC;AAAA,EACF;AACF;;;AFtDA,IAAqB,iBAArB,cACU,oBAEV;AAAA,EASE,YACE,SACA,iBACA,aACA,YACA,eACA,cACA,mBACA,cACA;AACA,UAAM,kCAAkB,KAAK,SAAS,OAAO;AAE7C,SAAK,kBAAkB;AACvB,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,oBAAoB;AACzB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAA6C;AAC/D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,OAAO,MAAM,KAAK,YAAY,IAAI;AACxC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,mBAAmB;AAAA,IAC/B;AAEA,UAAM,SAAK,sBAAK;AAChB,UAAM,kBAAmC;AAAA,MACvC,UAAU;AAAA,QACR,SAAS,KAAK;AAAA,QACd,WAAW,CAAC,KAAK,QAAQ;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,cAA2B;AAAA,MAC/B,GAAG;AAAA,MACH,YAAY;AAAA,MACZ;AAAA,MACA,aAAa,MAAM,eAAe;AAAA,MAClC,UAAU,OAAO,OAAO,CAAC,GAAG,iBAAiB,MAAM,QAAQ;AAAA,MAC3D,aAAS,kCAAiB;AAAA,MAC1B,aAAa,KAAK,QAAQ;AAAA;AAAA,MAC1B,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAEA,UAAM,cAAuB,OAAO,QAAQ,EAAE;AAE9C,UAAM,iBAAAC,QAAG,UAAU,WAAW;AAE9B,QAAI;AACF,YAAM,KAAK,sBAAsB,WAAW;AAC5C,YAAM,KAAK,gBAAgB,WAAW;AACtC,YAAM,KAAK,WAAW,KAAK,aAAa,EAAE,eAAe,OAAO,CAAC;AACjE,YAAM,KAAK,gBAAgB;AAAA,QACzB;AAAA,QACS,OAAO,YAAY,EAAE;AAAA,QAC9B;AAAA,MACF;AACA,YAAM,KAAK,WAAW,IAAI,aAAa,CAAC,GAAG,CAAC;AAC5C,YAAM,KAAK,WAAW;AAAA,QACpB;AAAA,QACA,GAAG,oCAAoB,KAAK,IAAI;AAAA,MAClC;AACA,YAAM,KAAK,WAAW,OAAO,aAAa,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IACpE,SAAS,OAAO;AAEd,YAAM,KAAK,OAAO;AAAA,QAChB;AAAA,MACF,CAAC;AACD,YAAM;AAAA,IACR;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,KAAK,OAA2C;AAC3D,sCAAkB,MAAM,KAAK;AAE7B,UAAM,cAAc,MAAM,KAAK,gBAAgB;AAAA,MACpC,OAAO,YAAY,MAAM,EAAE;AAAA,MACpC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO,OAA6C;AAC/D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,cAAuB,OAAO,QAAQ,MAAM,EAAE;AACpD,UAAM,WAAoB,OAAO,YAAY,MAAM,EAAE;AACrD,UAAM,kBAAkB,MAAM,KAAK,KAAK,KAAK;AAE7C,UAAM,cAA2B;AAAA,MAC/B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,aAAS,kCAAiB;AAAA,IAC5B;AAEA,UAAM,KAAK,gBAAgB,OAAO,aAAa,UAAU,iCAAiB;AAC1E,UAAM,KAAK,WAAW,IAAI,aAAa,CAAC,QAAQ,CAAC;AACjD,UAAM,KAAK,WAAW,OAAO,aAAa,KAAK,WAAW,MAAM;AAEhE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,QAAQ,OAA2C;AAC9D,yCAAqB,MAAM,KAAK;AAEhC,UAAM,UAAU,MAAM,KAAK,KAAK,KAAK;AACrC,UAAM,cAAuB,OAAO,QAAQ,QAAQ,EAAE;AAEtD,QAAI,cAAAC,QAAO,GAAG,QAAQ,aAAa,KAAK,QAAQ,OAAO,GAAG;AAExD,YAAM,IAAI;AAAA,QACR,wDAAwD,QAAQ,WAAW,8CAA8C,KAAK,QAAQ,OAAO;AAAA,MAC/I;AAAA,IACF;AAEA,QAAI,cAAAA,QAAO,GAAG,QAAQ,aAAa,KAAK,QAAQ,OAAO,GAAG;AAExD;AAAA,IACF;AAGA,UAAM,eAAe,MAAe;AAAA,MAClC,aAAAC,QAAK,QAAQ,WAAW,YAAY;AAAA,MACpC;AAAA,IACF;AAGA,UAAM,YACJ,MAAM,QAAQ;AAAA,MACZ,aAAa,IAAI,CAAC,SAAS;AACzB,eAAO,OACL,aAAAA,QAAK,KAAK,cAAc,KAAK,IAAI;AAAA,MAErC,CAAC;AAAA,IACH,GACA,IAAI,CAAC,kBAAkB;AACvB,aAAO,cAAc;AAAA,IACvB,CAAC;AAGD,UAAM,iBAAiB,SACpB,KAAK,CAAC,GAAG,MAAM;AACd,aAAO,cAAAD,QAAO,QAAQ,EAAE,IAAI,EAAE,EAAE;AAAA,IAClC,CAAC,EACA,OAAO,CAAC,YAAY;AACnB,UAAI,QAAQ,OAAO,SAAS;AAC1B,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAEH,aAAS,QAAQ,GAAG,QAAQ,eAAe,QAAQ,SAAS;AAC1D,YAAM,UAAU,eAAe,KAAK;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAGA,YAAM,cAAc,MAAM,KAAK,WAAW,KAAK,OAAO;AAAA,QACpD,MAAM;AAAA,QACN,SAAS,kDAAkD,QAAQ,EAAE;AAAA,MACvE,CAAC;AAED,UAAI;AACF,cAAM,QAAQ,IAAI,OAAO;AAGzB,gBAAQ,cAAc,QAAQ;AAC9B,cAAM,KAAK,OAAO,OAAO;AAGzB,cAAM,KAAK,WAAW,KAAK,OAAO;AAAA,UAChC,MAAM;AAAA,UACN,SAAS,qCAAqC,QAAQ,EAAE;AAAA,QAC1D,CAAC;AAGD,cAAM,KAAK,WAAW,KAAK,OAAO;AAAA,UAChC,MAAM;AAAA,UACN,IAAI,YAAY;AAAA,QAClB,CAAC;AAAA,MACH,SAAS,OAAO;AAEd,cAAM,KAAK,WAAW,MAAM,aAAa,QAAQ,YAAY,EAAE;AAE/D,cAAM,IAAI;AAAA,UACR,8CAA8C,QAAQ,EAAE;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,OAAO,OAA0C;AAC5D,wCAAoB,MAAM,KAAK;AAE/B,UAAM,iBAAAD,QAAG,OAAgB,OAAO,QAAQ,MAAM,EAAE,CAAC;AAAA,EACnD;AAAA,EAEA,MAAa,KACX,OACiC;AACjC,QAAI,OAAO;AACT,yCAAmB,MAAM,KAAK;AAAA,IAChC;AAEA,UAAM,aAAa,MAAM,KAAK,eAAe,iCAAiB,KAAK,OAAO;AAC1E,UAAM,OAAO,MAAe;AAAA,MAC1B,WAAW,IAAI,CAAC,cAAc;AAC5B,eAAO,KAAK,KAAK,EAAE,IAAI,UAAU,GAAG,CAAC;AAAA,MACvC,CAAC;AAAA,IACH;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAa,QAAyB;AACpC,YAAQ,MAAM,KAAK,eAAe,iCAAiB,KAAK,OAAO,GAAG;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,OAAO,WAAmB,OAAe,MAAmB;AACvE,WAAO,KAAK,cAAc,OAAO,WAAW,OAAO,IAAI;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,KAAyC;AACxD,WAAO,kCAAkB,UAAU,GAAG,EAAE;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,aAAa,WAA2C;AACnE,UAAM,UAAU,MAAM,KAAK,KAAK,EAAE,IAAI,UAAU,CAAC;AACjD,UAAM,UAAU,MAAM,KAAK,aAAa,KAAK,EAAE,WAAW,OAAO,EAAE,CAAC,GAAG;AACvE,UAAM,eACJ,MAAM,KAAK,kBAAkB,KAAK,EAAE,WAAW,OAAO,EAAE,CAAC,GACzD;AAEF,UAAM,mBAAuC,MAAM,QAAQ;AAAA,MACzD,YAAY,IAAI,OAAO,eAAe;AACpC,cAAM,WACJ,MAAM,KAAK,aAAa,KAAK;AAAA,UAC3B;AAAA,UACA,cAAc,WAAW;AAAA,UACzB,OAAO;AAAA,QACT,CAAC,GACD;AAEF,eAAO;AAAA,UACL,GAAG;AAAA,UACH;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,sBAAsB,MAA6B;AAC/D,UAAMG,WAAU,OAAO,OAAO,oCAAoB,MAAM;AAExD,UAAM,QAAQ;AAAA,MACZA,SAAQ,IAAI,OAAO,WAAW;AAC5B,cAAM,iBAAAH,QAAG,OAAO,aAAAE,QAAK,KAAK,MAAM,MAAM,CAAC;AACvC,cAAM,iBAAAF,QAAG,UAAU,aAAAE,QAAK,KAAK,MAAM,QAAQ,UAAU,GAAG,EAAE;AAAA,MAC5D,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,gBAAgB,MAA6B;AACzD,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,IAIF;AACA,UAAM,iBAAAF,QAAG,UAAU,aAAAE,QAAK,KAAK,MAAM,YAAY,GAAG,MAAM,KAAK,WAAAE,QAAG,GAAG,CAAC;AAAA,EACtE;AACF;;;AdtYA,IAAqB,aAArB,MAAgC;AAAA,EAY9B,YAAY,OAAoC;AAC9C,UAAM,cAAc,4CAA4B,MAAM,KAAK;AAE3D,UAAM,WAA8B;AAAA,MAClC,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,MAAM;AAAA,UACJ,aAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF;AACA,SAAK,UAAU,OAAO,OAAO,CAAC,GAAG,UAAU,WAAW;AAEtD,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,OAAO;AACvD,SAAK,cAAc,IAAI,YAAY,KAAK,eAAe;AACvD,SAAK,aAAa,IAAIC,YAAW,KAAK,SAAS,KAAK,WAAW;AAE/D,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,oBAAoB,IAAI;AAAA,MAC3B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,qBAAqB,IAAI;AAAA,MAC5B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,eAAe,IAAI;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,gBAAgB,IAAI;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,QAAI,KAAK,QAAQ,gBAAgB,cAAc;AAC7C,cAAQ;AAAA,QACN,2BAA2B,KAAK,QAAQ,WAAW;AAAA,QACnD;AAAA,UACE,GAAG,KAAK;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAEA,qBAAAC,QAAG,WAAoB,OAAO,QAAQ;AACtC,qBAAAA,QAAG,WAAoB,OAAO,GAAG;AACjC,qBAAAA,QAAG,aAAsB,OAAO,GAAG;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAO;AAChB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,OAAoB;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,WAA2B;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,SAAuB;AAChC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,cAAiC;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,UAAwB;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAW,eAAmC;AAC5C,WAAO,KAAK;AAAA,EACd;AACF;","names":["import_shared","import_fs_extra","import_shared","import_fs_extra","Path","Os","Fs","dirent","import_shared","import_lodash_es","filter","import_shared","import_shared","import_shared","import_shared","import_fs_extra","Fs","GitService","PQueue","files","Fs","IsSvg","import_shared","import_fs_extra","Fs","import_shared","import_fs_extra","import_shared","import_fs_extra","Fs","Fs","import_shared","import_fs_extra","import_os","import_path","import_shared","Fs","Semver","Path","folders","Os","GitService","Fs"]}