@elek-io/core 0.16.0 → 0.16.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.astro.mjs","names":["z","tags","router","tags","router","tags","router","router","router","projectRoutes","collectionRoutes","entryRoutes","assetRoutes","router","v1Routes","contentRoutes","routes","generateUuid","gitExec","Util"],"sources":["../../package.json","../../src/api/middleware/requestResponseLogger.ts","../../src/api/lib/util.ts","../../src/schema/baseSchema.ts","../../src/schema/fileSchema.ts","../../src/schema/gitSchema.ts","../../src/schema/assetSchema.ts","../../src/schema/valueSchema.ts","../../src/schema/entrySchema.ts","../../src/schema/fieldSchema.ts","../../src/schema/collectionSchema.ts","../../src/schema/coreSchema.ts","../../src/schema/projectSchema.ts","../../src/schema/schemaFromFieldDefinition.ts","../../src/schema/serviceSchema.ts","../../src/schema/userSchema.ts","../../src/schema/cliSchema.ts","../../src/schema/logSchema.ts","../../src/api/routes/content/v1/projects.ts","../../src/api/routes/content/v1/collections.ts","../../src/api/routes/content/v1/entries.ts","../../src/api/routes/content/v1/assets.ts","../../src/api/routes/content/v1/index.ts","../../src/api/routes/content/index.ts","../../src/api/routes/index.ts","../../src/api/index.ts","../../src/error/GitError.ts","../../src/error/NoCurrentUserError.ts","../../src/error/ProjectUpgradeError.ts","../../src/error/RequiredParameterMissingError.ts","../../src/util/node.ts","../../src/service/AbstractCrudService.ts","../../src/util/shared.ts","../../src/service/AssetService.ts","../../src/service/CollectionService.ts","../../src/service/EntryService.ts","../../src/service/GitTagService.ts","../../src/service/GitService.ts","../../src/service/JsonFileService.ts","../../src/service/LogService.ts","../../src/error/RemoteOriginMissingError.ts","../../src/error/SynchronizeLocalChangesError.ts","../../src/service/ProjectService.ts","../../src/service/UserService.ts","../../src/index.node.ts","../../src/astro/schema.ts","../../src/astro/transform.ts","../../src/index.astro.ts"],"sourcesContent":["","import { createMiddleware } from 'hono/factory';\nimport type { ApiEnv } from '../lib/types.js';\n\n/**\n * Middleware that logs the details of each request and response\n */\nexport const requestResponseLogger = createMiddleware<ApiEnv>(\n async (c, next) => {\n const { method, url } = c.req;\n const requestId = c.get('requestId');\n\n c.var.logService.info({\n source: 'core',\n message: `Recieved API request \"${method} ${url}\" with requestId ${requestId}`,\n });\n const start = Date.now();\n\n await next();\n\n const durationMs = Date.now() - start;\n const statusCode = c.res.status.toString();\n const resultLog = {\n source: 'core',\n message: `Response for API request \"${method} ${url}\" with requestId ${requestId} and status code ${statusCode} in ${durationMs}ms`,\n } as const;\n\n if (statusCode.startsWith('2')) {\n c.var.logService.info(resultLog);\n } else if (statusCode.startsWith('3')) {\n c.var.logService.warn(resultLog);\n } else if (statusCode.startsWith('4') || statusCode.startsWith('5')) {\n c.var.logService.error(resultLog);\n }\n }\n);\n","import type { Schema } from 'hono';\nimport { OpenAPIHono } from '@hono/zod-openapi';\nimport { requestId } from 'hono/request-id';\nimport { requestResponseLogger } from '../middleware/requestResponseLogger.js';\nimport type { Api, ApiEnv } from './types.js';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { cors } from 'hono/cors';\nimport type {\n AssetService,\n CollectionService,\n EntryService,\n LogService,\n ProjectService,\n} from '../../service/index.js';\nimport { createMiddleware } from 'hono/factory';\nimport { trimTrailingSlash } from 'hono/trailing-slash';\n\n/**\n * Creates a new OpenAPIHono router with default settings\n */\nexport function createRouter() {\n return new OpenAPIHono<ApiEnv>({\n /**\n * @see https://github.com/honojs/middleware/tree/main/packages/zod-openapi#a-dry-approach-to-handling-validation-errors\n */\n defaultHook: (result, c) => {\n if (!result.success) {\n return c.json(\n {\n success: result.success,\n error: {\n name: result.error.name,\n issues: result.error.issues,\n },\n },\n 422\n );\n }\n\n return result;\n },\n });\n}\n\n/**\n * Creates a new OpenAPIHono instance, injects services into context and adds error handling\n */\nexport default function createApi(\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n) {\n const api = createRouter();\n\n api\n .use(requestId())\n .use(trimTrailingSlash())\n .use(\n cors({\n origin: ['http://localhost'],\n })\n )\n .use(\n // Register services in context\n createMiddleware<ApiEnv>((c, next) => {\n c.set('logService', logService);\n c.set('projectService', projectService);\n c.set('collectionService', collectionService);\n c.set('entryService', entryService);\n c.set('assetService', assetService);\n return next();\n })\n )\n .use(requestResponseLogger);\n\n api.notFound((c) => {\n return c.json(\n {\n message: `Not Found - ${c.req.path}`,\n },\n 404\n );\n });\n\n api.onError((err, c) => {\n const currentStatus =\n 'status' in err ? err.status : c.newResponse(null).status;\n const statusCode =\n currentStatus !== 200 ? (currentStatus as ContentfulStatusCode) : 500;\n\n return c.json(\n {\n message: err.message,\n stack: err.stack,\n },\n statusCode\n );\n });\n\n return api;\n}\n\nexport function createTestApi<S extends Schema>(\n router: Api<S>,\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n) {\n return createApi(\n logService,\n projectService,\n collectionService,\n entryService,\n assetService\n ).route('/', router);\n}\n","import { z } from '@hono/zod-openapi';\n\n/**\n * All currently supported, BCP 47 compliant language tags\n *\n * The support depends on the tools and libraries we use.\n * We can't support a given language, if there is no support\n * for it from used third parties. Currently, to check if a langauge\n * tag can be added to this list, it needs to be supported by:\n * - DeepL translation API\n *\n * @see https://www.deepl.com/docs-api/other-functions/listing-supported-languages/\n */\nexport const supportedLanguageSchema = z.enum([\n /**\n * Bulgarian\n */\n 'bg', //\n 'cs', // Czech\n 'da', // Danish\n 'de', // German\n 'el', // Greek\n 'en', // (US) English\n 'es', // Spanish\n 'et', // Estonian\n 'fi', // Finnish\n 'fr', // French\n 'hu', // Hungarian\n 'it', // Italian\n 'ja', // Japanese\n 'lt', // Lithuanian\n 'lv', // Latvian\n 'nl', // Dutch\n 'pl', // Polish\n 'pt', // Portuguese\n 'ro', // Romanian\n 'ru', // Russian\n 'sk', // Slovak\n 'sl', // Slovenian\n 'sv', // Swedish\n 'zh', // (Simplified) Chinese\n]);\nexport type SupportedLanguage = z.infer<typeof supportedLanguageSchema>;\n\nexport const supportedIconSchema = z.enum(['home', 'plus', 'foobar']);\nexport type SupportedIcon = z.infer<typeof supportedIconSchema>;\n\nexport const objectTypeSchema = z.enum([\n 'project',\n 'asset',\n 'collection',\n 'entry',\n 'value',\n 'sharedValue',\n]);\nexport type ObjectType = z.infer<typeof objectTypeSchema>;\n\nexport const logLevelSchema = z.enum(['error', 'warn', 'info', 'debug']);\n\nexport const versionSchema = z.string();\n// .refine((version) => {\n// if (Semver.valid(version) !== null) {\n// return true;\n// }\n// return false;\n// }, 'String must follow the Semantic Versioning format (https://semver.org/)');\nexport type Version = z.infer<typeof versionSchema>;\n\nexport const uuidSchema = z.uuid();\nexport type Uuid = z.infer<typeof uuidSchema>;\n\n/**\n * A record that can be used to translate a string value into all supported languages\n */\nexport const translatableStringSchema = z.partialRecord(\n supportedLanguageSchema,\n z.string().trim().min(1)\n);\nexport type TranslatableString = z.infer<typeof translatableStringSchema>;\n\n/**\n * A record that can be used to translate a number value into all supported languages\n */\nexport const translatableNumberSchema = z.partialRecord(\n supportedLanguageSchema,\n z.number()\n);\nexport type TranslatableNumber = z.infer<typeof translatableNumberSchema>;\n\n/**\n * A record that can be used to translate a boolean value into all supported languages\n */\nexport const translatableBooleanSchema = z.partialRecord(\n supportedLanguageSchema,\n z.boolean()\n);\nexport type TranslatableBoolean = z.infer<typeof translatableBooleanSchema>;\n\nexport function translatableArrayOf<T extends z.ZodTypeAny>(schema: T) {\n return z.partialRecord(supportedLanguageSchema, z.array(schema));\n}\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\n\n/**\n * A basic file structure every elek.io file on disk has to follow\n */\nexport const baseFileSchema = z.object({\n /**\n * The object type of the file\n */\n objectType: objectTypeSchema.readonly(),\n /**\n * The ID of the file\n *\n * The ID is part of the files name.\n */\n id: uuidSchema.readonly(),\n /**\n * The datetime of the file being created is set by the service of \"objectType\" while creating it\n */\n created: z.string().datetime().readonly(),\n /**\n * The datetime of the file being updated is set by the service of \"objectType\" while updating it\n */\n updated: z.string().datetime().nullable(),\n});\nexport type BaseFile = z.infer<typeof baseFileSchema>;\n\nexport const fileReferenceSchema = z.object({\n id: uuidSchema,\n extension: z.string().optional(),\n});\nexport type FileReference = z.infer<typeof fileReferenceSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\n\n/**\n * Signature git uses to identify users\n */\nexport const gitSignatureSchema = z.object({\n name: z.string(),\n email: z.string().email(),\n});\nexport type GitSignature = z.infer<typeof gitSignatureSchema>;\n\nexport const gitMessageSchema = z.object({\n method: z.enum(['create', 'update', 'delete', 'upgrade']),\n reference: z.object({\n objectType: objectTypeSchema,\n /**\n * ID of the objectType\n */\n id: uuidSchema,\n /**\n * Only present if the objectType is of \"entry\"\n */\n collectionId: uuidSchema.optional(),\n }),\n});\nexport type GitMessage = z.infer<typeof gitMessageSchema>;\n\nexport const gitTagSchema = z.object({\n id: uuidSchema,\n message: z.string(),\n author: gitSignatureSchema,\n datetime: z.string().datetime(),\n});\nexport type GitTag = z.infer<typeof gitTagSchema>;\n\nexport const gitCommitSchema = z.object({\n /**\n * SHA-1 hash of the commit\n */\n hash: z.string(),\n message: gitMessageSchema,\n author: gitSignatureSchema,\n datetime: z.string().datetime(),\n tag: gitTagSchema.nullable(),\n});\nexport type GitCommit = z.infer<typeof gitCommitSchema>;\n\nexport const gitInitOptionsSchema = z.object({\n /**\n * Use the specified name for the initial branch in the newly created repository. If not specified, fall back to the default name (currently master, but this is subject to change in the future; the name can be customized via the init.defaultBranch configuration variable).\n */\n initialBranch: z.string(),\n});\nexport type GitInitOptions = z.infer<typeof gitInitOptionsSchema>;\n\nexport const gitCloneOptionsSchema = z.object({\n /**\n * Create a shallow clone with a history truncated to the specified number of commits. Implies --single-branch unless --no-single-branch is given to fetch the histories near the tips of all branches. If you want to clone submodules shallowly, also pass --shallow-submodules.\n */\n depth: z.number(),\n /**\n * Clone only the history leading to the tip of a single branch, either specified by the --branch option or the primary branch remote’s HEAD points at. Further fetches into the resulting repository will only update the remote-tracking branch for the branch this option was used for the initial cloning. If the HEAD at the remote did not point at any branch when --single-branch clone was made, no remote-tracking branch is created.\n */\n singleBranch: z.boolean(),\n /**\n * Instead of pointing the newly created HEAD to the branch pointed to by the cloned repository’s HEAD, point to <name> branch instead. In a non-bare repository, this is the branch that will be checked out. --branch can also take tags and detaches the HEAD at that commit in the resulting repository.\n */\n branch: z.string(),\n /**\n * Make a bare Git repository. That is, instead of creating <directory> and placing the administrative files in <directory>`/.git`, make the <directory> itself the $GIT_DIR.\n * Used primarily to copy an existing local repository to a server, where you want to set up the repository as a central point to work with others.\n *\n * The destination path for the cloned repository should end with a .git by convention.\n *\n * @see https://git-scm.com/book/en/v2/Git-on-the-Server-Getting-Git-on-a-Server\n */\n bare: z.boolean(),\n});\nexport type GitCloneOptions = z.infer<typeof gitCloneOptionsSchema>;\n\nexport const gitMergeOptionsSchema = z.object({\n squash: z.boolean(),\n});\nexport type GitMergeOptions = z.infer<typeof gitMergeOptionsSchema>;\n\nexport const gitSwitchOptionsSchema = z.object({\n /**\n * If true, creates a new local branch and then switches to it\n *\n * @see https://git-scm.com/docs/git-switch#Documentation/git-switch.txt---createltnew-branchgt\n */\n isNew: z.boolean().optional(),\n});\nexport type GitSwitchOptions = z.infer<typeof gitSwitchOptionsSchema>;\n\nexport const gitLogOptionsSchema = z.object({\n /**\n * Limit the result to given number of commits\n */\n limit: z.number().optional(),\n /**\n * Only list commits that are between given SHAs or tag names\n *\n * Note that the commits of from and to are not included in the result\n */\n between: z.object({\n /**\n * From the oldest commit\n */\n from: z.string(),\n /**\n * To the newest commit\n *\n * Defaults to the current HEAD\n */\n to: z.string().optional(),\n }),\n /**\n * Only shows commits of given file\n */\n filePath: z.string().optional(),\n});\nexport type GitLogOptions = z.infer<typeof gitLogOptionsSchema>;\n\nexport const createGitTagSchema = gitTagSchema\n .pick({\n message: true,\n })\n .extend({\n path: z.string(),\n hash: z.string().optional(),\n });\nexport type CreateGitTagProps = z.infer<typeof createGitTagSchema>;\n\nexport const readGitTagSchema = z.object({\n path: z.string(),\n id: uuidSchema.readonly(),\n});\nexport type ReadGitTagProps = z.infer<typeof readGitTagSchema>;\n\nexport const deleteGitTagSchema = readGitTagSchema.extend({});\nexport type DeleteGitTagProps = z.infer<typeof deleteGitTagSchema>;\n\nexport const countGitTagsSchema = z.object({\n path: z.string(),\n});\nexport type CountGitTagsProps = z.infer<typeof countGitTagsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\n\nexport const assetFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.asset).readonly(),\n name: z.string(),\n description: z.string(),\n extension: z.string().readonly(),\n mimeType: z.string().readonly(),\n /**\n * Total size in bytes\n */\n size: z.number().readonly(),\n});\nexport type AssetFile = z.infer<typeof assetFileSchema>;\n\nexport const assetSchema = assetFileSchema\n .extend({\n /**\n * Absolute path on this filesystem\n */\n absolutePath: z.string().readonly(),\n /**\n * Commit history of this Asset\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Asset');\nexport type Asset = z.infer<typeof assetSchema>;\n\nexport const assetExportSchema = assetSchema.extend({});\nexport type AssetExport = z.infer<typeof assetExportSchema>;\n\nexport const createAssetSchema = assetFileSchema\n .pick({\n name: true,\n description: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n /**\n * Path of the file to add as a new Asset\n */\n filePath: z.string().readonly(),\n });\nexport type CreateAssetProps = z.infer<typeof createAssetSchema>;\n\nexport const readAssetSchema = assetFileSchema\n .pick({\n id: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n });\nexport type ReadAssetProps = z.infer<typeof readAssetSchema>;\n\nexport const saveAssetSchema = assetFileSchema\n .pick({\n id: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n filePath: z.string().readonly(),\n commitHash: z.string().optional().readonly(),\n });\nexport type SaveAssetProps = z.infer<typeof saveAssetSchema>;\n\nexport const updateAssetSchema = assetFileSchema\n .pick({\n id: true,\n name: true,\n description: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n /**\n * Path of the new file to update the Asset with\n */\n newFilePath: z.string().readonly().optional(),\n });\nexport type UpdateAssetProps = z.infer<typeof updateAssetSchema>;\n\nexport const deleteAssetSchema = assetFileSchema\n .pick({\n id: true,\n extension: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type DeleteAssetProps = z.infer<typeof deleteAssetSchema>;\n\nexport const countAssetsSchema = z.object({ projectId: uuidSchema.readonly() });\nexport type CountAssetsProps = z.infer<typeof countAssetsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport {\n objectTypeSchema,\n translatableArrayOf,\n translatableBooleanSchema,\n translatableNumberSchema,\n translatableStringSchema,\n uuidSchema,\n} from './baseSchema.js';\n\nexport const ValueTypeSchema = z.enum([\n 'string',\n 'number',\n 'boolean',\n 'reference',\n]);\nexport type ValueType = z.infer<typeof ValueTypeSchema>;\n\nexport const valueContentReferenceBase = z.object({\n id: uuidSchema,\n});\n\nexport const valueContentReferenceToAssetSchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.asset),\n });\nexport type ValueContentReferenceToAsset = z.infer<\n typeof valueContentReferenceToAssetSchema\n>;\n\nexport const valueContentReferenceToCollectionSchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.collection),\n });\nexport type ValueContentReferenceToCollection = z.infer<\n typeof valueContentReferenceToCollectionSchema\n>;\n\nexport const valueContentReferenceToEntrySchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.entry),\n });\nexport type ValueContentReferenceToEntry = z.infer<\n typeof valueContentReferenceToEntrySchema\n>;\n\n// export const valueContentReferenceToSharedValueSchema = z.object({\n// referenceObjectType: z.literal(objectTypeSchema.enum.sharedValue),\n// references: z.object({\n// id: uuidSchema,\n// language: supportedLanguageSchema,\n// }),\n// });\n// export type ValueContentReferenceToSharedValue = z.infer<\n// typeof valueContentReferenceToSharedValueSchema\n// >;\n\n// export const sharedValueFileSchema = baseFileWithLanguageSchema.extend({\n// objectType: z.literal(objectTypeSchema.enum.sharedValue).readonly(),\n// valueType: ValueTypeSchema.exclude(['reference']).readonly(),\n// // valueType: ValueTypeSchema.readonly(), @todo do we allow shared Values to reference assets or others?\n// content: z.union([\n// z.string(),\n// z.number(),\n// z.boolean(),\n// z.string().optional(),\n// z.number().optional(),\n// z.boolean().optional(),\n// // valueContentReferenceToAssetSchema, @todo do we allow shared Values to reference assets or others?\n// // valueContentReferenceToSharedValueSchema,\n// ]),\n// });\n// export type SharedValueFile = z.infer<typeof sharedValueFileSchema>;\n\n// export const sharedValueSchema = sharedValueFileSchema.extend({});\n// export type SharedValue = z.infer<typeof sharedValueSchema>;\n\n// export const sharedValueExportSchema = sharedValueSchema.extend({});\n// export type SharedValueExport = z.infer<typeof sharedValueExportSchema>;\n\n// export const resolvedValueContentReferenceToSharedValueSchema =\n// valueContentReferenceToSharedValueSchema.extend({\n// references: z.object({\n// id: uuidSchema,\n// language: supportedLanguageSchema,\n// resolved: sharedValueSchema,\n// }),\n// });\n// export type ResolvedValueContentReferenceToSharedValue = z.infer<\n// typeof resolvedValueContentReferenceToSharedValueSchema\n// >;\n\nexport const valueContentReferenceSchema = z.union([\n valueContentReferenceToAssetSchema,\n valueContentReferenceToCollectionSchema,\n valueContentReferenceToEntrySchema,\n // valueContentReferenceToSharedValueSchema,\n]);\nexport type ValueContentReference = z.infer<typeof valueContentReferenceSchema>;\n\nexport const directValueBaseSchema = z.object({\n objectType: z.literal(objectTypeSchema.enum.value).readonly(),\n fieldDefinitionId: uuidSchema.readonly(),\n});\n\nexport const directStringValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.string).readonly(),\n content: translatableStringSchema,\n});\nexport type DirectStringValue = z.infer<typeof directStringValueSchema>;\n\nexport const directNumberValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.number).readonly(),\n content: translatableNumberSchema,\n});\nexport type DirectNumberValue = z.infer<typeof directNumberValueSchema>;\n\nexport const directBooleanValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.boolean).readonly(),\n content: translatableBooleanSchema,\n});\nexport type DirectBooleanValue = z.infer<typeof directBooleanValueSchema>;\n\nexport const directValueSchema = z.union([\n directStringValueSchema,\n directNumberValueSchema,\n directBooleanValueSchema,\n]);\nexport type DirectValue = z.infer<typeof directValueSchema>;\n\nexport const referencedValueSchema = z.object({\n objectType: z.literal(objectTypeSchema.enum.value).readonly(),\n fieldDefinitionId: uuidSchema.readonly(),\n valueType: z.literal(ValueTypeSchema.enum.reference).readonly(),\n content: translatableArrayOf(valueContentReferenceSchema),\n});\nexport type ReferencedValue = z.infer<typeof referencedValueSchema>;\n\nexport const valueSchema = z.union([directValueSchema, referencedValueSchema]);\nexport type Value = z.infer<typeof valueSchema>;\n\n/**\n * ---\n */\n\n// export const createSharedValueSchema = sharedValueFileSchema\n// .pick({\n// valueType: true,\n// content: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type CreateSharedValueProps = z.infer<typeof createSharedValueSchema>;\n\n// export const readSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type ReadSharedValueProps = z.infer<typeof readSharedValueSchema>;\n\n// export const updateSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// content: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type UpdateSharedValueProps = z.infer<typeof updateSharedValueSchema>;\n\n// export const deleteSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type DeleteSharedValueProps = z.infer<typeof deleteSharedValueSchema>;\n\n/**\n * @todo maybe we need to validate Values and shared Values\n */\n// export const validateValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// definition: FieldDefinitionSchema.readonly(),\n// });\n// export type ValidateValueProps = z.infer<typeof validateValueSchema>;\n\n// export const countValuesSchema = z.object({ projectId: uuidSchema.readonly() });\n// export type CountValuesProps = z.infer<typeof countValuesSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\nimport { valueSchema } from './valueSchema.js';\n\nexport const entryFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.entry).readonly(),\n values: z.array(valueSchema),\n});\nexport type EntryFile = z.infer<typeof entryFileSchema>;\n\nexport const entrySchema = entryFileSchema\n .extend({\n /**\n * Commit history of this Entry\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Entry');\nexport type Entry = z.infer<typeof entrySchema>;\n\nexport const entryExportSchema = entrySchema.extend({});\nexport type EntryExport = z.infer<typeof entryExportSchema>;\n\nexport const createEntrySchema = entryFileSchema\n .omit({\n id: true,\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n values: z.array(valueSchema),\n });\nexport type CreateEntryProps = z.infer<typeof createEntrySchema>;\n\nexport const readEntrySchema = z.object({\n id: uuidSchema.readonly(),\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadEntryProps = z.infer<typeof readEntrySchema>;\n\nexport const updateEntrySchema = entryFileSchema\n .omit({\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n });\nexport type UpdateEntryProps = z.infer<typeof updateEntrySchema>;\n\nexport const deleteEntrySchema = readEntrySchema.extend({});\nexport type DeleteEntryProps = z.infer<typeof deleteEntrySchema>;\n\nexport const countEntriesSchema = z.object({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n});\nexport type CountEntriesProps = z.infer<typeof countEntriesSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { translatableStringSchema, uuidSchema } from './baseSchema.js';\nimport { ValueTypeSchema } from './valueSchema.js';\n\nexport const FieldTypeSchema = z.enum([\n // String Values\n 'text',\n 'textarea',\n 'email',\n // 'password', @todo maybe if there is a usecase\n 'url',\n 'ipv4',\n 'date',\n 'time',\n 'datetime',\n 'telephone',\n // Number Values\n 'number',\n 'range',\n // Boolean Values\n 'toggle',\n // Reference Values\n 'asset',\n 'entry',\n // 'sharedValue', // @todo\n]);\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\nexport const FieldWidthSchema = z.enum(['12', '6', '4', '3']);\n\nexport const FieldDefinitionBaseSchema = z.object({\n id: uuidSchema.readonly(),\n label: translatableStringSchema,\n description: translatableStringSchema.nullable(),\n isRequired: z.boolean(),\n isDisabled: z.boolean(),\n isUnique: z.boolean(),\n inputWidth: FieldWidthSchema,\n});\nexport type FieldDefinitionBase = z.infer<typeof FieldDefinitionBaseSchema>;\n\n/**\n * String based Field definitions\n */\n\nexport const StringFieldDefinitionBaseSchema = FieldDefinitionBaseSchema.extend(\n {\n valueType: z.literal(ValueTypeSchema.enum.string),\n defaultValue: z.string().nullable(),\n }\n);\n\nexport const textFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.text),\n min: z.number().nullable(),\n max: z.number().nullable(),\n }\n);\nexport type TextFieldDefinition = z.infer<typeof textFieldDefinitionSchema>;\n\nexport const textareaFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.textarea),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type TextareaFieldDefinition = z.infer<\n typeof textareaFieldDefinitionSchema\n>;\n\nexport const emailFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.email),\n defaultValue: z.email().nullable(),\n });\nexport type EmailFieldDefinition = z.infer<typeof emailFieldDefinitionSchema>;\n\n// @todo why should we support password Values? Client saves it in clear text anyways\n// export const passwordFieldDefinitionSchema =\n// StringFieldDefinitionBaseSchema.extend({\n// fieldType: z.literal(FieldfieldTypeSchema.enum.password),\n// });\n\nexport const urlFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.url),\n defaultValue: z.url().nullable(),\n});\nexport type UrlFieldDefinition = z.infer<typeof urlFieldDefinitionSchema>;\n\nexport const ipv4FieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.ipv4),\n defaultValue: z.ipv4().nullable(),\n }\n);\nexport type Ipv4FieldDefinition = z.infer<typeof ipv4FieldDefinitionSchema>;\n\nexport const dateFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.date),\n defaultValue: z.iso.date().nullable(),\n }\n);\nexport type DateFieldDefinition = z.infer<typeof dateFieldDefinitionSchema>;\n\nexport const timeFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.time),\n defaultValue: z.iso.time().nullable(),\n }\n);\nexport type TimeFieldDefinition = z.infer<typeof timeFieldDefinitionSchema>;\n\nexport const datetimeFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.datetime),\n defaultValue: z.iso.datetime().nullable(),\n });\nexport type DatetimeFieldDefinition = z.infer<\n typeof datetimeFieldDefinitionSchema\n>;\n\nexport const telephoneFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.telephone),\n defaultValue: z.e164().nullable(),\n });\nexport type TelephoneFieldDefinition = z.infer<\n typeof telephoneFieldDefinitionSchema\n>;\n\nexport const stringFieldDefinitionSchema = z.union([\n textFieldDefinitionSchema,\n textareaFieldDefinitionSchema,\n emailFieldDefinitionSchema,\n urlFieldDefinitionSchema,\n ipv4FieldDefinitionSchema,\n dateFieldDefinitionSchema,\n timeFieldDefinitionSchema,\n datetimeFieldDefinitionSchema,\n telephoneFieldDefinitionSchema,\n]);\nexport type StringFieldDefinition = z.infer<typeof stringFieldDefinitionSchema>;\n\n/**\n * Number based Field definitions\n */\n\nexport const NumberFieldDefinitionBaseSchema = FieldDefinitionBaseSchema.extend(\n {\n valueType: z.literal(ValueTypeSchema.enum.number),\n min: z.number().nullable(),\n max: z.number().nullable(),\n isUnique: z.literal(false),\n defaultValue: z.number().nullable(),\n }\n);\n\nexport const numberFieldDefinitionSchema =\n NumberFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.number),\n });\nexport type NumberFieldDefinition = z.infer<typeof numberFieldDefinitionSchema>;\n\nexport const rangeFieldDefinitionSchema =\n NumberFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.range),\n // Overwrite from nullable to required because a range needs min, max and default to work and is required, since it always returns a number\n isRequired: z.literal(true),\n min: z.number(),\n max: z.number(),\n defaultValue: z.number(),\n });\nexport type RangeFieldDefinition = z.infer<typeof rangeFieldDefinitionSchema>;\n\n/**\n * Boolean based Field definitions\n */\n\nexport const BooleanFieldDefinitionBaseSchema =\n FieldDefinitionBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.boolean),\n // Overwrite from nullable to required because a boolean needs a default to work and is required, since it always is either true or false\n isRequired: z.literal(true),\n defaultValue: z.boolean(),\n isUnique: z.literal(false),\n });\n\nexport const toggleFieldDefinitionSchema =\n BooleanFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.toggle),\n });\nexport type ToggleFieldDefinition = z.infer<typeof toggleFieldDefinitionSchema>;\n\n/**\n * Reference based Field definitions\n */\n\nexport const ReferenceFieldDefinitionBaseSchema =\n FieldDefinitionBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.reference),\n });\n\nexport const assetFieldDefinitionSchema =\n ReferenceFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.asset),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type AssetFieldDefinition = z.infer<typeof assetFieldDefinitionSchema>;\n\nexport const entryFieldDefinitionSchema =\n ReferenceFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.entry),\n ofCollections: z.array(uuidSchema),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type EntryFieldDefinition = z.infer<typeof entryFieldDefinitionSchema>;\n\n// export const sharedValueDefinitionSchema =\n// ReferenceValueDefinitionBaseSchema.extend({\n// fieldType: z.literal(ValueInputTypeSchema.enum.sharedValue),\n// // The shared Value can have any of the direct types\n// // but not any reference itself (a shared Value cannot have a reference to another shared Value / Asset or any other future reference)\n// sharedValueType: z.union([\n// z.literal(ValueTypeSchema.enum.boolean),\n// z.literal(ValueTypeSchema.enum.number),\n// z.literal(ValueTypeSchema.enum.string),\n// ]),\n// });\n// export type SharedValueValueDefinition = z.infer<\n// typeof sharedValueDefinitionSchema\n// >;\n\nexport const fieldDefinitionSchema = z.union([\n stringFieldDefinitionSchema,\n numberFieldDefinitionSchema,\n rangeFieldDefinitionSchema,\n toggleFieldDefinitionSchema,\n assetFieldDefinitionSchema,\n entryFieldDefinitionSchema,\n // sharedValueDefinitionSchema,\n]);\nexport type FieldDefinition = z.infer<typeof fieldDefinitionSchema>;\n","import { z } from '@hono/zod-openapi';\nimport {\n objectTypeSchema,\n supportedIconSchema,\n translatableStringSchema,\n uuidSchema,\n} from './baseSchema.js';\nimport { entryExportSchema } from './entrySchema.js';\nimport { fieldDefinitionSchema } from './fieldSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\n\nexport const collectionFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.collection).readonly(),\n name: z.object({\n singular: translatableStringSchema,\n plural: translatableStringSchema,\n }),\n slug: z.object({\n singular: z.string(),\n plural: z.string(),\n }),\n description: translatableStringSchema,\n icon: supportedIconSchema,\n fieldDefinitions: z.array(fieldDefinitionSchema),\n});\nexport type CollectionFile = z.infer<typeof collectionFileSchema>;\n\nexport const collectionSchema = collectionFileSchema\n .extend({\n /**\n * Commit history of this Collection\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Collection');\nexport type Collection = z.infer<typeof collectionSchema>;\n\nexport const collectionExportSchema = collectionSchema.extend({\n entries: z.array(entryExportSchema),\n});\nexport type CollectionExport = z.infer<typeof collectionExportSchema>;\n\nexport const createCollectionSchema = collectionFileSchema\n .omit({\n id: true,\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type CreateCollectionProps = z.infer<typeof createCollectionSchema>;\n\nexport const readCollectionSchema = z.object({\n id: uuidSchema.readonly(),\n projectId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadCollectionProps = z.infer<typeof readCollectionSchema>;\n\nexport const updateCollectionSchema = collectionFileSchema\n .pick({\n id: true,\n name: true,\n slug: true,\n description: true,\n icon: true,\n fieldDefinitions: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type UpdateCollectionProps = z.infer<typeof updateCollectionSchema>;\n\nexport const deleteCollectionSchema = readCollectionSchema.extend({});\nexport type DeleteCollectionProps = z.infer<typeof deleteCollectionSchema>;\n\nexport const countCollectionsSchema = z.object({\n projectId: uuidSchema.readonly(),\n});\nexport type CountCollectionsProps = z.infer<typeof countCollectionsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { logLevelSchema } from './baseSchema.js';\n\n/**\n * Options that can be passed to elek.io core\n */\nexport const elekIoCoreOptionsSchema = z.object({\n log: z.object({\n /**\n * The lowest level that should be logged\n *\n * @default 'info'\n */\n level: logLevelSchema,\n }),\n file: z.object({\n /**\n * If set to true, caches files in memory to speed up access\n *\n * @default true\n */\n cache: z.boolean(),\n }),\n});\nexport type ElekIoCoreOptions = z.infer<typeof elekIoCoreOptionsSchema>;\n\nexport const constructorElekIoCoreSchema = elekIoCoreOptionsSchema\n .partial({\n log: true,\n file: true,\n })\n .optional();\nexport type ConstructorElekIoCoreProps = z.infer<\n typeof constructorElekIoCoreSchema\n>;\n","import { z } from '@hono/zod-openapi';\nimport { assetExportSchema } from './assetSchema.js';\nimport {\n objectTypeSchema,\n supportedLanguageSchema,\n uuidSchema,\n versionSchema,\n} from './baseSchema.js';\nimport { collectionExportSchema } from './collectionSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema, gitSwitchOptionsSchema } from './gitSchema.js';\n\nexport const projectStatusSchema = z.enum(['foo', 'bar', 'todo']);\nexport type ProjectStatus = z.infer<typeof projectStatusSchema>;\n\nexport const projectSettingsSchema = z.object({\n language: z.object({\n default: supportedLanguageSchema,\n supported: z.array(supportedLanguageSchema),\n }),\n});\nexport type ProjectSettings = z.infer<typeof projectSettingsSchema>;\n\nexport const projectFolderSchema = z.enum([\n 'assets',\n 'collections',\n 'shared-values',\n 'lfs',\n // 'logs',\n // 'public',\n // 'theme',\n]);\nexport type ProjectFolder = z.infer<typeof projectFolderSchema>;\n\nexport const projectBranchSchema = z.enum(['production', 'work']);\nexport type ProjectBranch = z.infer<typeof projectBranchSchema>;\n\nexport const projectFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.project).readonly(),\n coreVersion: versionSchema,\n name: z.string().trim().min(1),\n description: z.string().trim().min(1),\n version: versionSchema,\n status: projectStatusSchema,\n settings: projectSettingsSchema,\n});\nexport type ProjectFile = z.infer<typeof projectFileSchema>;\n\nexport const projectSchema = projectFileSchema\n .extend({\n remoteOriginUrl: z.string().nullable().openapi({\n description: 'URL of the remote Git repository',\n }),\n history: z.array(gitCommitSchema).openapi({\n description: 'Commit history of this Project',\n }),\n fullHistory: z.array(gitCommitSchema).openapi({\n description:\n 'Full commit history of this Project including all Assets, Collections, Entries and other files',\n }),\n })\n .openapi('Project');\nexport type Project = z.infer<typeof projectSchema>;\n\nexport const migrateProjectSchema = projectFileSchema\n .pick({\n id: true,\n coreVersion: true,\n })\n .loose();\nexport type MigrateProjectProps = z.infer<typeof migrateProjectSchema>;\n\nexport const projectExportSchema = projectSchema.extend({\n assets: z.array(assetExportSchema),\n collections: z.array(collectionExportSchema),\n});\nexport type ProjectExport = z.infer<typeof projectExportSchema>;\n\nexport const createProjectSchema = projectSchema.pick({\n name: true,\n description: true,\n settings: true,\n});\nexport type CreateProjectProps = z.infer<typeof createProjectSchema>;\n\nexport const readProjectSchema = z.object({\n id: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadProjectProps = z.infer<typeof readProjectSchema>;\n\nexport const updateProjectSchema = projectSchema.pick({\n id: true,\n name: true,\n description: true,\n settings: true,\n});\nexport type UpdateProjectProps = z.infer<typeof updateProjectSchema>;\n\nexport const upgradeProjectSchema = z.object({\n id: uuidSchema.readonly(),\n /**\n * Force the upgrade even if the Project is up-to-date\n */\n force: z.boolean().optional(),\n});\nexport type UpgradeProjectProps = z.infer<typeof upgradeProjectSchema>;\n\nexport const deleteProjectSchema = readProjectSchema.extend({\n force: z.boolean().optional(),\n});\nexport type DeleteProjectProps = z.infer<typeof deleteProjectSchema>;\n\nexport const projectUpgradeSchema = z.object({\n /**\n * The Core version the Project will be upgraded to\n */\n to: versionSchema.readonly(),\n /**\n * Function that will be executed in the process of upgrading a Project\n */\n run: z.function({\n input: [projectFileSchema],\n output: z.promise(z.void()),\n }),\n});\nexport type ProjectUpgrade = z.infer<typeof projectUpgradeSchema>;\n\nexport const cloneProjectSchema = z.object({\n url: z.string(),\n});\nexport type CloneProjectProps = z.infer<typeof cloneProjectSchema>;\n\nexport const listBranchesProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type ListBranchesProjectProps = z.infer<\n typeof listBranchesProjectSchema\n>;\n\nexport const currentBranchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type CurrentBranchProjectProps = z.infer<\n typeof currentBranchProjectSchema\n>;\n\nexport const switchBranchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n branch: z.string(),\n options: gitSwitchOptionsSchema.optional(),\n});\nexport type SwitchBranchProjectProps = z.infer<\n typeof switchBranchProjectSchema\n>;\n\nexport const getRemoteOriginUrlProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type GetRemoteOriginUrlProjectProps = z.infer<\n typeof getRemoteOriginUrlProjectSchema\n>;\n\nexport const setRemoteOriginUrlProjectSchema = z.object({\n id: uuidSchema.readonly(),\n url: z.string(),\n});\nexport type SetRemoteOriginUrlProjectProps = z.infer<\n typeof setRemoteOriginUrlProjectSchema\n>;\n\nexport const getChangesProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type GetChangesProjectProps = z.infer<typeof getChangesProjectSchema>;\n\nexport const synchronizeProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type SynchronizeProjectProps = z.infer<typeof synchronizeProjectSchema>;\n\nexport const searchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n query: z.string(),\n language: supportedLanguageSchema,\n type: z.array(objectTypeSchema).optional(),\n});\nexport type SearchProjectProps = z.infer<typeof searchProjectSchema>;\n","/**\n * Dynamic zod schema generation\n *\n * Altough everything is already strictly typed, a type of string might not be an email or text of a certain length.\n * To validate this, we need to generate zod schemas based on Field definitions the user created.\n */\n\nimport { z } from '@hono/zod-openapi';\nimport { supportedLanguageSchema } from './baseSchema.js';\nimport {\n createEntrySchema,\n entrySchema,\n updateEntrySchema,\n} from './entrySchema.js';\nimport type {\n AssetFieldDefinition,\n EntryFieldDefinition,\n FieldDefinition,\n NumberFieldDefinition,\n RangeFieldDefinition,\n StringFieldDefinition,\n} from './fieldSchema.js';\nimport { FieldTypeSchema } from './fieldSchema.js';\nimport {\n directBooleanValueSchema,\n directNumberValueSchema,\n directStringValueSchema,\n referencedValueSchema,\n valueContentReferenceToAssetSchema,\n valueContentReferenceToEntrySchema,\n ValueTypeSchema,\n} from './valueSchema.js';\n\n/**\n * Boolean Values are always either true or false, so we don't need the Field definition here\n */\nfunction getBooleanValueContentSchemaFromFieldDefinition() {\n return z.boolean();\n}\n\n/**\n * Number Values can have min and max values and can be required or not\n */\nfunction getNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition: NumberFieldDefinition | RangeFieldDefinition\n) {\n let schema = z.number();\n\n if (fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n if (fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n if (fieldDefinition.isRequired === false) {\n return schema.nullable();\n }\n\n return schema;\n}\n\n/**\n * String Values can have different formats (email, url, ipv4, date, time, ...)\n * and can have min and max length and can be required or not\n */\nfunction getStringValueContentSchemaFromFieldDefinition(\n fieldDefinition: StringFieldDefinition\n) {\n let schema = null;\n\n switch (fieldDefinition.fieldType) {\n case FieldTypeSchema.enum.email:\n schema = z.email();\n break;\n case FieldTypeSchema.enum.url:\n schema = z.url();\n break;\n case FieldTypeSchema.enum.ipv4:\n schema = z.ipv4();\n break;\n case FieldTypeSchema.enum.date:\n schema = z.iso.date();\n break;\n case FieldTypeSchema.enum.time:\n schema = z.iso.time();\n break;\n case FieldTypeSchema.enum.datetime:\n schema = z.iso.datetime();\n break;\n case FieldTypeSchema.enum.telephone:\n schema = z.e164();\n break;\n case FieldTypeSchema.enum.text:\n case FieldTypeSchema.enum.textarea:\n schema = z.string().trim();\n break;\n }\n\n if ('min' in fieldDefinition && fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n if ('max' in fieldDefinition && fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n if (fieldDefinition.isRequired === false) {\n return schema.nullable();\n }\n\n return schema.min(1); // @see https://github.com/colinhacks/zod/issues/2466\n}\n\n/**\n * Reference Values can reference either Assets or Entries (or Shared Values in the future)\n * and can have min and max number of references and can be required or not\n */\nfunction getReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition: AssetFieldDefinition | EntryFieldDefinition // | SharedValueFieldDefinition\n) {\n let schema;\n\n switch (fieldDefinition.fieldType) {\n case FieldTypeSchema.enum.asset:\n {\n schema = z.array(valueContentReferenceToAssetSchema);\n }\n break;\n case FieldTypeSchema.enum.entry:\n {\n schema = z.array(valueContentReferenceToEntrySchema);\n }\n break;\n // case ValueInputTypeSchema.enum.sharedValue: {\n // let schema = valueContentReferenceToSharedValueSchema.extend({}); // Deep copy to not overwrite the base schema\n // if (definition.isRequired) {\n // const requiredReferences = schema.shape.references.min(\n // 1,\n // 'shared.assetValueRequired'\n // );\n // schema = schema.extend({\n // references: requiredReferences,\n // });\n // }\n // return valueContentReferenceToSharedValueSchema;\n // }\n }\n\n if (fieldDefinition.isRequired) {\n schema = schema.min(1);\n }\n\n if (fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n\n if (fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n return schema;\n}\n\nexport function getTranslatableStringValueContentSchemaFromFieldDefinition(\n fieldDefinition: StringFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getStringValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\nexport function getTranslatableNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition: NumberFieldDefinition | RangeFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getNumberValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\nexport function getTranslatableBooleanValueContentSchemaFromFieldDefinition() {\n return z.partialRecord(\n supportedLanguageSchema,\n getBooleanValueContentSchemaFromFieldDefinition()\n );\n}\n\nexport function getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition: AssetFieldDefinition | EntryFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getReferenceValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\n/**\n * Generates a zod schema to check a Value based on given Field definition\n */\nexport function getValueSchemaFromFieldDefinition(\n fieldDefinition: FieldDefinition\n) {\n switch (fieldDefinition.valueType) {\n case ValueTypeSchema.enum.boolean:\n return directBooleanValueSchema.extend({\n content: getTranslatableBooleanValueContentSchemaFromFieldDefinition(),\n });\n case ValueTypeSchema.enum.number:\n return directNumberValueSchema.extend({\n content:\n getTranslatableNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n case ValueTypeSchema.enum.string:\n return directStringValueSchema.extend({\n content:\n getTranslatableStringValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n case ValueTypeSchema.enum.reference:\n return referencedValueSchema.extend({\n content:\n getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n default:\n throw new Error(\n // @ts-expect-error Code cannot be reached, but if we add a new ValueType and forget to update this function, we want to be notified about it\n `Error generating schema for unsupported ValueType \"${fieldDefinition.valueType}\"`\n );\n }\n}\n\n/**\n * Generates a schema for an Entry based on the given Field definitions and Values\n */\nexport function getEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...entrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n\n/**\n * Generates a schema for creating a new Entry based on the given Field definitions and Values\n */\nexport function getCreateEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...createEntrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n\n/**\n * Generates a schema for updating an existing Entry based on the given Field definitions and Values\n */\nexport function getUpdateEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...updateEntrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n","import { z } from '@hono/zod-openapi';\nimport { uuidSchema } from './baseSchema.js';\n\nexport const serviceTypeSchema = z.enum([\n 'Git',\n 'GitTag',\n 'User',\n 'Project',\n 'Asset',\n 'JsonFile',\n 'Search',\n 'Collection',\n 'Entry',\n 'Value',\n]);\nexport type ServiceType = z.infer<typeof serviceTypeSchema>;\n\nexport interface PaginatedList<T> {\n total: number;\n limit: number;\n offset: number;\n list: T[];\n}\n\nexport function paginatedListOf<T extends z.ZodTypeAny>(schema: T) {\n return z.object({\n total: z.number(),\n limit: z.number(),\n offset: z.number(),\n list: z.array(schema),\n });\n}\n\nexport interface PaginationOptions {\n limit: number;\n offset: number;\n}\n\n/**\n * Implements create, read, update and delete methods\n */\nexport interface CrudService<T> {\n create: (props: never) => Promise<T>;\n read: (props: never) => Promise<T>;\n update: (props: never) => Promise<T>;\n delete: (props: never) => Promise<void>;\n}\n\n/**\n * Implements list and count methods additionally\n * to create, read, update and delete\n */\nexport interface CrudServiceWithListCount<T> extends CrudService<T> {\n /**\n * Returns a list of this services objects\n *\n * Does not return objects where the schema validation fails.\n * If that is the case, upgrade the Client and then Project to the latest version.\n */\n list: (...props: never[]) => Promise<PaginatedList<T>>;\n /**\n * Returns the total number of this services objects\n */\n count: (...props: never[]) => Promise<number>;\n}\n\nconst listSchema = z.object({\n projectId: uuidSchema,\n limit: z.number().optional(),\n offset: z.number().optional(),\n});\n\nexport const listCollectionsSchema = listSchema;\nexport type ListCollectionsProps = z.infer<typeof listCollectionsSchema>;\n\nexport const listEntriesSchema = listSchema.extend({\n collectionId: uuidSchema,\n});\nexport type ListEntriesProps = z.infer<typeof listEntriesSchema>;\n\nexport const listAssetsSchema = listSchema;\nexport type ListAssetsProps = z.infer<typeof listAssetsSchema>;\n\n// export const listSharedValuesSchema = listSchema(sharedValueSchema);\n// export type ListSharedValuesProps = z.infer<typeof listSharedValuesSchema>;\n\nexport const listProjectsSchema = listSchema.omit({\n projectId: true,\n});\nexport type ListProjectsProps = z.infer<typeof listProjectsSchema>;\n\nexport const listGitTagsSchema = z.object({\n path: z.string(),\n});\nexport type ListGitTagsProps = z.infer<typeof listGitTagsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { supportedLanguageSchema, uuidSchema } from './baseSchema.js';\nimport { gitSignatureSchema } from './gitSchema.js';\n\nexport const UserTypeSchema = z.enum(['local', 'cloud']);\n\nexport const baseUserSchema = gitSignatureSchema.extend({\n userType: UserTypeSchema,\n language: supportedLanguageSchema,\n localApi: z.object({\n /**\n * If set to true the local API is started whenever Core is initialized\n */\n isEnabled: z.boolean(),\n /**\n * The port the local API uses\n */\n port: z.number(),\n }),\n});\nexport type BaseUser = z.infer<typeof baseUserSchema>;\n\nexport const localUserSchema = baseUserSchema.extend({\n userType: z.literal(UserTypeSchema.enum.local),\n});\nexport type LocalUser = z.infer<typeof localUserSchema>;\n\nexport const cloudUserSchema = baseUserSchema.extend({\n userType: z.literal(UserTypeSchema.enum.cloud),\n id: uuidSchema,\n});\nexport type CloudUser = z.infer<typeof cloudUserSchema>;\n\nexport const userFileSchema = z.union([localUserSchema, cloudUserSchema]);\nexport type UserFile = z.infer<typeof userFileSchema>;\n\nexport const userSchema = userFileSchema;\nexport type User = z.infer<typeof userSchema>;\n\nexport const setUserSchema = userSchema;\nexport type SetUserProps = z.infer<typeof setUserSchema>;\n","import { z } from 'zod';\nimport { uuidSchema } from './baseSchema.js';\n\nconst outDirSchema = z.string().default('./.elek.io');\nconst languageSchema = z.enum(['ts', 'js']).default('ts');\nconst formatSchema = z.enum(['esm', 'cjs']).default('esm');\nconst targetSchema = z\n .enum([\n 'es3',\n 'es5',\n 'es6',\n 'es2015',\n 'es2016',\n 'es2017',\n 'es2018',\n 'es2019',\n 'es2020',\n 'es2021',\n 'es2022',\n 'es2023',\n 'es2024',\n 'esnext',\n ])\n .default('es2020');\nconst projectsSchema = z\n .string()\n .default('all')\n .transform((value) => {\n if (value === 'all') {\n return 'all';\n }\n\n return value.split(',').map((v) => uuidSchema.parse(v.trim()));\n });\nconst generateApiClientOptionsSchema = z.object({\n watch: z.boolean().default(false),\n});\nconst exportProjectsOptionsSchema = generateApiClientOptionsSchema.extend({\n watch: z.boolean().default(false),\n});\n\nexport const generateApiClientSchema = z.object({\n outDir: outDirSchema,\n language: languageSchema,\n format: formatSchema,\n target: targetSchema,\n options: generateApiClientOptionsSchema,\n});\nexport type GenerateApiClientProps = z.infer<typeof generateApiClientSchema>;\n\nconst portSchema = z\n .string()\n .default('31310')\n .transform((value, context) => {\n try {\n const parsed = parseInt(value);\n\n return parsed;\n } catch (_error) {\n context.addIssue({\n code: 'custom',\n message: 'Invalid port number',\n input: value,\n });\n\n // this is a special constant with type `never`\n // returning it lets you exit the transform without impacting the inferred return type\n return z.NEVER;\n }\n });\n\nexport const apiStartSchema = z.object({\n port: portSchema,\n});\nexport type ApiStartProps = z.infer<typeof apiStartSchema>;\n\nexport const exportSchema = z.object({\n outDir: outDirSchema,\n projects: projectsSchema,\n template: z.enum(['nested', 'separate']).default('nested'),\n options: exportProjectsOptionsSchema,\n});\nexport type ExportProps = z.infer<typeof exportSchema>;\n","import { z } from '@hono/zod-openapi';\n\nexport const logSourceSchema = z.enum(['core', 'desktop']);\nexport type LogSource = z.infer<typeof logSourceSchema>;\n\nexport const logSchema = z.object({\n source: logSourceSchema,\n message: z.string(),\n /**\n * Additional metadata for the log entry\n *\n * @example { userId: '12345', action: 'login' }\n */\n meta: z.record(z.string(), z.unknown()).optional(),\n});\nexport type LogProps = z.infer<typeof logSchema>;\n\nexport const logConsoleTransportSchema = logSchema.extend({\n timestamp: z.string(),\n level: z.string(),\n});\nexport type LogConsoleTransportProps = z.infer<\n typeof logConsoleTransportSchema\n>;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n paginatedListOf,\n projectSchema,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Projects',\n description: 'Lists all Projects you currently have access to',\n method: 'get',\n path: '/',\n tags,\n request: {\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: 15,\n description: 'The maximum number of Projects to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: 0,\n description:\n 'The number of Projects to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(projectSchema),\n },\n },\n description: 'A list of Projects you have access to',\n },\n },\n }),\n async (c) => {\n const { limit, offset } = c.req.valid('query');\n const projects = await c.var.projectService.list({ limit, offset });\n\n return c.json(projects, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Projects',\n description: 'Counts all Projects you currently have access to',\n method: 'get',\n path: '/count',\n tags,\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Projects you have access to',\n },\n },\n }),\n async (c) => {\n const count = await c.var.projectService.count();\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Project',\n description: 'Retrieve a Project by ID',\n method: 'get',\n path: '/{projectId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: projectSchema,\n },\n },\n description: 'The requested Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const project = await c.var.projectService.read({ id: projectId });\n\n return c.json(project, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n collectionSchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Collections',\n description: 'Lists all Collections of the given Project',\n method: 'get',\n path: '/{projectId}/collections',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Collections to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Collections to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(collectionSchema),\n },\n },\n description: 'A list of Collections for the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const collections = await c.var.collectionService.list({\n projectId,\n limit,\n offset,\n });\n\n return c.json(collections, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Collections',\n description: 'Counts all Collections of the given Project',\n method: 'get',\n path: '/{projectId}/collections/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Collections of the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const count = await c.var.collectionService.count({ projectId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Collection',\n description: 'Retrieve a Collection by ID',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: collectionSchema,\n },\n },\n description: 'The requested Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const collection = await c.var.collectionService.read({\n projectId,\n id: collectionId,\n });\n\n return c.json(collection, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n entrySchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Entries',\n description: 'Lists all Entries of the given Projects Collection',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Entries to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Entries to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(entrySchema),\n },\n },\n description: 'A list of Entries for the given Projects Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const entries = await c.var.entryService.list({\n projectId,\n collectionId,\n limit,\n offset,\n });\n\n return c.json(entries, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Entries',\n description: 'Counts all Entries of the given Projects Collection',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Entries of the given Projects Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const count = await c.var.entryService.count({ projectId, collectionId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Entry',\n description: 'Retrieve an Entry by ID',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries/{entryId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n entryId: uuidSchema.openapi({\n param: {\n name: 'entryId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: entrySchema,\n },\n },\n description: 'The requested Entry',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId, entryId } = c.req.valid('param');\n const entry = await c.var.entryService.read({\n projectId,\n collectionId,\n id: entryId,\n });\n\n return c.json(entry, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n assetSchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Assets',\n description: 'Lists all Assets of the given Project',\n method: 'get',\n path: '/{projectId}/assets',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Assets to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Assets to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(assetSchema),\n },\n },\n description: 'A list of Assets for the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const assets = await c.var.assetService.list({\n projectId,\n limit,\n offset,\n });\n\n return c.json(assets, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Assets',\n description: 'Counts all Assets of the given Project',\n method: 'get',\n path: '/{projectId}/assets/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Assets of the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const count = await c.var.assetService.count({ projectId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Asset',\n description: 'Retrieve an Asset by ID',\n method: 'get',\n path: '/{projectId}/assets/{assetId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n assetId: uuidSchema.openapi({\n param: {\n name: 'assetId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: assetSchema,\n },\n },\n description: 'The requested Asset',\n },\n },\n }),\n async (c) => {\n const { projectId, assetId } = c.req.valid('param');\n const asset = await c.var.assetService.read({\n projectId,\n id: assetId,\n });\n\n return c.json(asset, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport projectRoutes from './projects.js';\nimport collectionRoutes from './collections.js';\nimport entryRoutes from './entries.js';\nimport assetRoutes from './assets.js';\n\nconst router = createRouter()\n .route('/projects', projectRoutes)\n .route('/projects', collectionRoutes)\n .route('/projects', entryRoutes)\n .route('/projects', assetRoutes);\n\nexport default router;\n","import { createRouter } from '../../lib/util.js';\nimport v1Routes from './v1/index.js';\n\nconst router = createRouter().route('/v1', v1Routes);\n\nexport default router;\n","import { createRouter } from '../lib/util.js';\nimport contentRoutes from './content/index.js';\n\nconst router = createRouter().route('/content', contentRoutes);\n\nexport default router;\n","import { serve } from '@hono/node-server';\nimport type { OpenAPIHono } from '@hono/zod-openapi';\nimport type { Server } from 'node:http';\nimport type { Http2SecureServer, Http2Server } from 'node:http2';\nimport type {\n AssetService,\n CollectionService,\n EntryService,\n LogService,\n ProjectService,\n} from '../service/index.js';\nimport createApi from './lib/util.js';\nimport routes from './routes/index.js';\nimport type { ApiEnv } from './lib/types.js';\nimport { Scalar } from '@scalar/hono-api-reference';\n\nexport class LocalApi {\n private logService: LogService;\n private projectService: ProjectService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n private assetService: AssetService;\n private api: OpenAPIHono<ApiEnv>;\n private server: Server | Http2Server | Http2SecureServer | null = null;\n\n constructor(\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n ) {\n this.logService = logService;\n this.projectService = projectService;\n this.collectionService = collectionService;\n this.entryService = entryService;\n this.assetService = assetService;\n this.api = createApi(\n this.logService,\n this.projectService,\n this.collectionService,\n this.entryService,\n this.assetService\n )\n .route('/', routes)\n .doc('/openapi.json', {\n openapi: '3.0.0',\n externalDocs: { url: 'https://elek.io/docs' },\n info: {\n version: '0.1.0',\n title: 'elek.io local API',\n description:\n 'This API allows reading content from local elek.io Projects. You can use this API for development and building static websites and applications locally.',\n },\n servers: [\n {\n url: 'http://localhost:{port}',\n description: 'elek.io local API',\n variables: {\n port: {\n default: 31310,\n description:\n 'The port specified in elek.io Clients user configuration',\n },\n },\n },\n ],\n tags: [\n {\n name: 'Content API v1',\n description:\n 'Version 1 of the elek.io content API lets you read Projects, Collections, Entries and Assets. \\n### Resources\\n - [Projects](https://elek.io/docs/projects)\\n - [Collections](https://elek.io/docs/collections)\\n - [Entries](https://elek.io/docs/entries)\\n - [Assets](https://elek.io/docs/assets)',\n },\n // {\n // name: 'Projects',\n // description: 'Retrieve information about Projects',\n // externalDocs: { url: 'https://elek.io/docs/projects' },\n // },\n // {\n // name: 'Collections',\n // description: 'Retrieve information about Collections',\n // externalDocs: { url: 'https://elek.io/docs/collections' },\n // },\n // {\n // name: 'Entries',\n // description: 'Retrieve information about Entries',\n // externalDocs: { url: 'https://elek.io/docs/entries' },\n // },\n // {\n // name: 'Assets',\n // description: 'Retrieve information about Assets',\n // externalDocs: { url: 'https://elek.io/docs/assets' },\n // },\n ],\n });\n\n this.api.get(\n '/',\n Scalar({\n pageTitle: 'elek.io local API',\n url: '/openapi.json',\n theme: 'kepler',\n layout: 'modern',\n defaultHttpClient: {\n targetKey: 'js',\n clientKey: 'fetch',\n },\n })\n );\n }\n\n /**\n * Starts the local API on given port\n */\n public start(port: number) {\n this.server = serve(\n {\n fetch: this.api.fetch,\n port,\n },\n (info) => {\n this.logService.info({\n source: 'core',\n message: `Started local API on http://localhost:${info.port}`,\n });\n }\n );\n }\n\n /**\n * Stops the local API\n */\n public stop() {\n this.server?.close(() => {\n this.logService.info({ source: 'core', message: 'Stopped local API' });\n });\n }\n\n /**\n * Returns true if the local API is running\n */\n public isRunning() {\n if (this.server?.listening) {\n return true;\n }\n return false;\n }\n}\n","export class GitError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'GitError';\n }\n}\n","export 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","export class ProjectUpgradeError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'ProjectUpgradeError';\n }\n}\n","export class RequiredParameterMissingError extends Error {\n constructor(parameter: string) {\n super(`Missing required parameter \"${parameter}\"`);\n\n this.name = 'RequiredParameterMissingError';\n }\n}\n","import Fs from 'fs-extra';\nimport Os from 'node:os';\nimport Path from 'node:path';\nimport { execFile, type ExecFileOptions } from 'node:child_process';\nimport { projectFolderSchema } from '../schema/projectSchema.js';\nimport type { LogService } from '../service/LogService.js';\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: (projectId: string, collectionId: string, id: string) => {\n return Path.join(pathTo.entries(projectId, collectionId), `${id}.json`);\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): string => {\n return Path.join(pathTo.assets(projectId), `${id}.json`);\n },\n asset: (projectId: string, id: string, extension: string): string => {\n return Path.join(pathTo.lfs(projectId), `${id}.${extension}`);\n },\n tmpAsset: (id: string, commitHash: string, extension: string) => {\n return Path.join(pathTo.tmp, `${id}.${commitHash}.${extension}`);\n },\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 isNotEmpty<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\n/**\n * Used as parameter for filter() methods to assure,\n * only items that are not of type Error are returned\n *\n * @param item Item to check\n */\nexport function isNotAnError<T>(item: T | Error): item is T {\n return item instanceof Error !== true;\n}\n\n/**\n * Returns all folders of given path to a directory\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 to a directory,\n * 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 * Executes a shell command async and returns the output.\n *\n * When on Windows, it will automatically append `.cmd` to the command if it is in the `commandsToSuffix` list.\n */\nexport function execCommand({\n command,\n args,\n options,\n logger,\n}: {\n command: string;\n args: string[];\n options?: ExecFileOptions;\n logger: LogService;\n}) {\n return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {\n const commandsToSuffix = ['pnpm'];\n const isWindows = Os.platform() === 'win32';\n const suffixedCommand = isWindows\n ? command\n .split(' ')\n .map((cmd) => (commandsToSuffix.includes(cmd) ? `${cmd}.cmd` : cmd))\n .join(' ')\n : command;\n const fullCommand = `${suffixedCommand} ${args.join(' ')}`;\n const execOptions: ExecFileOptions = {\n ...options,\n shell: true,\n };\n const start = Date.now();\n\n execFile(suffixedCommand, args, execOptions, (error, stdout, stderr) => {\n const durationMs = Date.now() - start;\n if (error) {\n logger.error({\n source: 'core',\n message: `Error executing command \"${fullCommand}\" after ${durationMs}ms: ${error.message}`,\n meta: { error, stdout: stdout.toString(), stderr: stderr.toString() },\n });\n reject(error instanceof Error ? error : new Error(error.message));\n } else {\n logger.info({\n source: 'core',\n message: `Command \"${fullCommand}\" executed successfully in ${durationMs}ms.`,\n meta: { stdout: stdout.toString(), stderr: stderr.toString() },\n });\n resolve({ stdout: stdout.toString(), stderr: stderr.toString() });\n }\n });\n });\n}\n","import { RequiredParameterMissingError } from '../error/index.js';\nimport {\n fileReferenceSchema,\n objectTypeSchema,\n type ElekIoCoreOptions,\n type FileReference,\n type ObjectType,\n type ServiceType,\n} from '../schema/index.js';\nimport {\n files,\n folders,\n isNotAnError,\n isNotEmpty,\n pathTo,\n} from '../util/node.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * A base service that provides properties for most other services\n */\nexport abstract class AbstractCrudService {\n public readonly type: ServiceType;\n public readonly options: ElekIoCoreOptions;\n protected readonly logService: LogService;\n\n /**\n * Do not instantiate directly as this is an abstract class\n */\n protected constructor(\n type: ServiceType,\n options: ElekIoCoreOptions,\n logService: LogService\n ) {\n this.type = type;\n this.options = options;\n this.logService = logService;\n }\n\n /**\n * Basically a Promise.all() without rejecting if one promise fails to resolve\n */\n protected async returnResolved<T>(promises: Promise<T>[]) {\n const toCheck: Promise<T | Error>[] = [];\n\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\n // Here comes the trick:\n // By using \"then\" and \"catch\" we are able to create an array of T 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 const actualError =\n error instanceof Error ? error : new Error(String(error));\n\n this.logService.warn({\n source: 'core',\n message: `Function \"returnResolved\" catched an error while resolving a promise: ${actualError.message}`,\n meta: { error: actualError, promise },\n });\n\n return actualError;\n })\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\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(isNotAnError);\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(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(pathTo.projects);\n\n case objectTypeSchema.enum.collection:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFolderReferences(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 pathTo.collection(projectId, collectionId)\n );\n\n case objectTypeSchema.enum.sharedValue:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(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 folders(path);\n\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 {\n this.logService.warn({\n source: 'core',\n message: `Function \"getFolderReferences\" is ignoring folder \"${possibleFolder.name}\" in \"${path}\" as it does not match the expected format`,\n });\n\n return null;\n }\n });\n\n return results.filter(isNotEmpty);\n }\n\n /**\n * Searches for all files inside given folder,\n * parses their names and returns them as FileReference\n *\n * Ignores files if the extension is not supported.\n */\n private async getFileReferences(path: string): Promise<FileReference[]> {\n const possibleFiles = await files(path);\n\n const results = possibleFiles.map((possibleFile) => {\n const fileNameArray = possibleFile.name.split('.');\n\n const fileReference = {\n id: fileNameArray[0],\n extension: fileNameArray[1],\n };\n\n try {\n return fileReferenceSchema.parse(fileReference);\n } catch {\n this.logService.warn({\n source: 'core',\n message: `Function \"getFileReferences\" is ignoring file \"${possibleFile.name}\" in \"${path}\" as it does not match the expected format`,\n });\n\n return null;\n }\n });\n\n return results.filter(isNotEmpty);\n }\n}\n","import slugify from '@sindresorhus/slugify';\nimport { v4 as generateUuid } from 'uuid';\nimport { type Uuid } from '../schema/baseSchema.js';\n\n/**\n * Returns a new UUID\n */\nexport function uuid(): Uuid {\n return generateUuid();\n}\n\n/**\n * Returns a string representing date and time\n * in a simplified format based on ISO 8601.\n * The timezone is always UTC.\n *\n * - If value is not given, the current date and time is used\n * - If value is given, it's converted to above representation and UTC timezone\n *\n * @example 'YYYY-MM-DDTHH:mm:ss.sssZ'\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString\n * @see https://en.wikipedia.org/wiki/ISO_8601\n */\nexport function datetime(value?: number | string | Date) {\n if (!value) {\n return new Date().toISOString();\n }\n return new Date(value).toISOString();\n}\n\n/**\n * Returns the slug of given string\n */\nexport function slug(string: string): string {\n return slugify(string, {\n separator: '-',\n lowercase: true,\n decamelize: true,\n });\n}\n","import Fs from 'fs-extra';\nimport mime from 'mime';\nimport type { SaveAssetProps } from '../schema/index.js';\nimport {\n assetFileSchema,\n assetSchema,\n countAssetsSchema,\n createAssetSchema,\n deleteAssetSchema,\n listAssetsSchema,\n objectTypeSchema,\n readAssetSchema,\n saveAssetSchema,\n serviceTypeSchema,\n updateAssetSchema,\n type Asset,\n type AssetFile,\n type CountAssetsProps,\n type CreateAssetProps,\n type CrudServiceWithListCount,\n type DeleteAssetProps,\n type ElekIoCoreOptions,\n type ListAssetsProps,\n type PaginatedList,\n type ReadAssetProps,\n type UpdateAssetProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, slug, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport class AssetService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Asset>\n{\n private readonly jsonFileService: JsonFileService;\n private readonly gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.enum.Asset, options, logService);\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 = pathTo.project(props.projectId);\n const fileType = this.getFileType(props.filePath);\n const size = await this.getFileSize(props.filePath);\n const assetPath = pathTo.asset(props.projectId, id, fileType.extension);\n const assetFilePath = pathTo.assetFile(props.projectId, id);\n\n const assetFile: AssetFile = {\n ...props,\n name: slug(props.name),\n objectType: 'asset',\n id,\n created: datetime(),\n updated: null,\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, {\n method: 'create',\n reference: { objectType: 'asset', id },\n });\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Returns an Asset by ID\n *\n * If a commit hash is provided, the Asset is read from history\n */\n public async read(props: ReadAssetProps): Promise<Asset> {\n readAssetSchema.parse(props);\n\n if (!props.commitHash) {\n const assetFile = await this.jsonFileService.read(\n pathTo.assetFile(props.projectId, props.id),\n assetFileSchema\n );\n\n return this.toAsset(props.projectId, assetFile);\n } else {\n const assetFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.assetFile(props.projectId, props.id),\n props.commitHash\n )\n )\n );\n\n const assetBlob = await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.asset(props.projectId, props.id, assetFile.extension),\n props.commitHash,\n 'binary'\n );\n await Fs.writeFile(\n pathTo.tmpAsset(assetFile.id, props.commitHash, assetFile.extension),\n assetBlob,\n 'binary'\n );\n\n return this.toAsset(props.projectId, assetFile, props.commitHash);\n }\n }\n\n /**\n * Copies an Asset to given file path on disk\n */\n public async save(props: SaveAssetProps) {\n saveAssetSchema.parse(props);\n\n const asset = await this.read(props);\n await Fs.copyFile(asset.absolutePath, props.filePath);\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 = pathTo.project(props.projectId);\n const assetFilePath = pathTo.assetFile(props.projectId, props.id);\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 name: slug(props.name),\n updated: datetime(),\n };\n\n if (props.newFilePath) {\n // Overwrite the file itself (in LFS folder)...\n\n const fileType = this.getFileType(props.newFilePath);\n const size = await this.getFileSize(props.newFilePath);\n const prevAssetPath = pathTo.asset(\n props.projectId,\n props.id,\n prevAssetFile.extension\n );\n const assetPath = pathTo.asset(\n props.projectId,\n props.id,\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 await this.gitService.add(projectPath, [prevAssetPath, 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, {\n method: 'update',\n reference: { objectType: 'asset', id: assetFile.id },\n });\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 = pathTo.project(props.projectId);\n const assetFilePath = pathTo.assetFile(props.projectId, props.id);\n const assetPath = pathTo.asset(props.projectId, props.id, props.extension);\n await Fs.remove(assetPath);\n await Fs.remove(assetFilePath);\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: { objectType: 'asset', id: props.id },\n });\n }\n\n public async list(props: ListAssetsProps): Promise<PaginatedList<Asset>> {\n listAssetsSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const assetReferences = await this.listReferences(\n objectTypeSchema.enum.asset,\n props.projectId\n );\n\n const partialAssetReferences =\n limit === 0\n ? assetReferences.slice(offset)\n : assetReferences.slice(offset, offset + limit);\n\n const assets = await this.returnResolved(\n partialAssetReferences.map((assetReference) => {\n return this.read({\n projectId: props.projectId,\n id: assetReference.id,\n });\n })\n );\n\n return {\n total: assetReferences.length,\n limit,\n offset,\n list: assets,\n };\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: unknown): obj is Asset {\n return assetSchema.safeParse(obj).success;\n }\n\n /**\n * Returns the size of an file in bytes\n *\n * @param path Path of the file to get the size from\n */\n private async getFileSize(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 commitHash?: string\n ): Promise<Asset> {\n const assetPath = commitHash\n ? pathTo.tmpAsset(assetFile.id, commitHash, assetFile.extension)\n : pathTo.asset(projectId, assetFile.id, assetFile.extension);\n\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.assetFile(projectId, assetFile.id),\n });\n\n const asset: Asset = {\n ...assetFile,\n absolutePath: assetPath,\n history,\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 getFileType(filePath: string) {\n const mimeType = mime.getType(filePath);\n\n if (mimeType === null) {\n throw new Error(`Unsupported MIME type of file \"${filePath}\"`);\n }\n\n const extension = mime.getExtension(mimeType);\n\n if (extension === null) {\n throw new Error(\n `Unsupported extension for MIME type \"${mimeType}\" of file \"${filePath}\"`\n );\n }\n\n return {\n extension,\n mimeType,\n };\n }\n\n /**\n * Migrates an potentially outdated Asset file to the current schema\n */\n public migrate(potentiallyOutdatedAssetFile: unknown) {\n // @todo\n\n return assetFileSchema.parse(potentiallyOutdatedAssetFile);\n }\n}\n","import Fs from 'fs-extra';\nimport {\n collectionFileSchema,\n countCollectionsSchema,\n createCollectionSchema,\n deleteCollectionSchema,\n listCollectionsSchema,\n objectTypeSchema,\n readCollectionSchema,\n serviceTypeSchema,\n updateCollectionSchema,\n type Collection,\n type CollectionFile,\n type CountCollectionsProps,\n type CreateCollectionProps,\n type CrudServiceWithListCount,\n type DeleteCollectionProps,\n type ElekIoCoreOptions,\n type ListCollectionsProps,\n type PaginatedList,\n type ReadCollectionProps,\n type UpdateCollectionProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, slug, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Collection files on disk\n */\nexport class CollectionService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Collection>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.enum.Collection, options, logService);\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 = pathTo.project(props.projectId);\n const collectionPath = pathTo.collection(props.projectId, id);\n const collectionFilePath = pathTo.collectionFile(props.projectId, id);\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: datetime(),\n updated: null,\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, {\n method: 'create',\n reference: { objectType: 'collection', id },\n });\n\n return this.toCollection(props.projectId, collectionFile);\n }\n\n /**\n * Returns a Collection by ID\n *\n * If a commit hash is provided, the Collection is read from history\n */\n public async read(props: ReadCollectionProps): Promise<Collection> {\n readCollectionSchema.parse(props);\n\n if (!props.commitHash) {\n const collectionFile = await this.jsonFileService.read(\n pathTo.collectionFile(props.projectId, props.id),\n collectionFileSchema\n );\n\n return this.toCollection(props.projectId, collectionFile);\n } else {\n const collectionFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.collectionFile(props.projectId, props.id),\n props.commitHash\n )\n )\n );\n\n return this.toCollection(props.projectId, collectionFile);\n }\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 = pathTo.project(props.projectId);\n const collectionFilePath = pathTo.collectionFile(props.projectId, props.id);\n const prevCollectionFile = await this.read(props);\n\n const collectionFile: CollectionFile = {\n ...prevCollectionFile,\n ...props,\n updated: datetime(),\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 = 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, {\n method: 'update',\n reference: { objectType: 'collection', id: collectionFile.id },\n });\n\n return this.toCollection(props.projectId, 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 = pathTo.project(props.projectId);\n const collectionPath = pathTo.collection(props.projectId, props.id);\n\n await Fs.remove(collectionPath);\n await this.gitService.add(projectPath, [collectionPath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: { objectType: 'collection', id: props.id },\n });\n }\n\n public async list(\n props: ListCollectionsProps\n ): Promise<PaginatedList<Collection>> {\n listCollectionsSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const collectionReferences = await this.listReferences(\n objectTypeSchema.enum.collection,\n props.projectId\n );\n\n const partialCollectionReferences =\n limit === 0\n ? collectionReferences.slice(offset)\n : collectionReferences.slice(offset, offset + limit);\n\n const collections = await this.returnResolved(\n partialCollectionReferences.map((reference) => {\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n });\n })\n );\n\n return {\n total: collectionReferences.length,\n limit,\n offset,\n list: collections,\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: unknown): obj is Collection {\n return collectionFileSchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Collection file to the current schema\n */\n public migrate(potentiallyOutdatedCollectionFile: unknown) {\n // @todo\n\n return collectionFileSchema.parse(potentiallyOutdatedCollectionFile);\n }\n\n /**\n * Creates an Collection from given CollectionFile\n *\n * @param projectId The project's ID\n * @param collectionFile The CollectionFile to convert\n */\n private async toCollection(\n projectId: string,\n collectionFile: CollectionFile\n ): Promise<Collection> {\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.collectionFile(projectId, collectionFile.id),\n });\n\n const collection: Collection = {\n ...collectionFile,\n history,\n };\n\n return collection;\n }\n}\n","import Fs from 'fs-extra';\nimport {\n countEntriesSchema,\n createEntrySchema,\n deleteEntrySchema,\n entryFileSchema,\n entrySchema,\n getCreateEntrySchemaFromFieldDefinitions,\n getUpdateEntrySchemaFromFieldDefinitions,\n listEntriesSchema,\n objectTypeSchema,\n readEntrySchema,\n serviceTypeSchema,\n updateEntrySchema,\n type CountEntriesProps,\n type CreateEntryProps,\n type CrudServiceWithListCount,\n type DeleteEntryProps,\n type ElekIoCoreOptions,\n type Entry,\n type EntryFile,\n type ListEntriesProps,\n type ReadEntryProps,\n type UpdateEntryProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { CollectionService } from './CollectionService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Entry files on disk\n */\nexport class EntryService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Entry>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private collectionService: CollectionService;\n // private sharedValueService: SharedValueService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService,\n collectionService: CollectionService\n // sharedValueService: SharedValueService\n ) {\n super(serviceTypeSchema.enum.Entry, options, logService);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n this.collectionService = collectionService;\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n id\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 values: props.values,\n created: datetime(),\n updated: null,\n };\n\n const entry = await this.toEntry(\n props.projectId,\n props.collectionId,\n entryFile\n );\n\n // Validate all Values against their Field Definitions\n const createEntrySchemaFromFieldDefinitions =\n getCreateEntrySchemaFromFieldDefinitions(collection.fieldDefinitions);\n createEntrySchemaFromFieldDefinitions.parse(props);\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, {\n method: 'create',\n reference: {\n objectType: 'entry',\n id: entryFile.id,\n collectionId: props.collectionId,\n },\n });\n\n return entry;\n }\n\n /**\n * Returns an Entry from given Collection by ID\n *\n * If a commit hash is provided, the Entry is read from history\n */\n public async read(props: ReadEntryProps): Promise<Entry> {\n readEntrySchema.parse(props);\n\n if (!props.commitHash) {\n const entryFile: EntryFile = await this.jsonFileService.read(\n pathTo.entryFile(props.projectId, props.collectionId, props.id),\n entryFileSchema\n );\n\n return this.toEntry(props.projectId, props.collectionId, entryFile);\n } else {\n const entryFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.entryFile(props.projectId, props.collectionId, props.id),\n props.commitHash\n )\n )\n );\n\n return this.toEntry(props.projectId, props.collectionId, entryFile);\n }\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id\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 });\n\n const entryFile: EntryFile = {\n ...prevEntryFile,\n values: props.values,\n updated: datetime(),\n };\n\n const entry = await this.toEntry(\n props.projectId,\n props.collectionId,\n entryFile\n );\n\n // Validate all Values against their Field Definitions\n const updateEntrySchemaFromFieldDefinitions =\n getUpdateEntrySchemaFromFieldDefinitions(collection.fieldDefinitions);\n updateEntrySchemaFromFieldDefinitions.parse(props);\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, {\n method: 'update',\n reference: {\n objectType: 'entry',\n id: entryFile.id,\n collectionId: props.collectionId,\n },\n });\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id\n );\n\n await Fs.remove(entryFilePath);\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: {\n objectType: 'entry',\n id: props.id,\n collectionId: props.collectionId,\n },\n });\n }\n\n public async list(props: ListEntriesProps) {\n listEntriesSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const entryReferences = await this.listReferences(\n objectTypeSchema.enum.entry,\n props.projectId,\n props.collectionId\n );\n\n const partialEntryReferences =\n limit === 0\n ? entryReferences.slice(offset)\n : entryReferences.slice(offset, offset + limit);\n\n const entries = await this.returnResolved(\n partialEntryReferences.map((reference) => {\n return this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: reference.id,\n });\n })\n );\n\n return {\n total: entryReferences.length,\n limit,\n offset,\n list: entries,\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: unknown): obj is Entry {\n return entrySchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Entry file to the current schema\n */\n public migrate(potentiallyOutdatedEntryFile: unknown) {\n // @todo\n\n return entryFileSchema.parse(potentiallyOutdatedEntryFile);\n }\n\n /**\n * Creates an Entry from given EntryFile by resolving it's Values\n */\n private async toEntry(\n projectId: string,\n collectionId: string,\n entryFile: EntryFile\n ): Promise<Entry> {\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.entryFile(projectId, collectionId, entryFile.id),\n });\n\n return {\n ...entryFile,\n history,\n };\n }\n}\n","import { GitError } from '../error/index.js';\nimport {\n countGitTagsSchema,\n createGitTagSchema,\n deleteGitTagSchema,\n gitTagSchema,\n listGitTagsSchema,\n readGitTagSchema,\n serviceTypeSchema,\n type CountGitTagsProps,\n type CreateGitTagProps,\n type CrudServiceWithListCount,\n type DeleteGitTagProps,\n type ElekIoCoreOptions,\n type GitTag,\n type ListGitTagsProps,\n type PaginatedList,\n type ReadGitTagProps,\n} from '../schema/index.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for GitTags\n */\nexport class GitTagService\n extends AbstractCrudService\n implements CrudServiceWithListCount<GitTag>\n{\n private git: GitService['git'];\n\n public constructor(\n options: ElekIoCoreOptions,\n git: GitService['git'],\n logService: LogService\n ) {\n super(serviceTypeSchema.enum.GitTag, options, logService);\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() but only returns the tag with matching ID.\n */\n public async read(props: ReadGitTagProps): Promise<GitTag> {\n readGitTagSchema.parse(props);\n\n const tags = await this.list({ path: props.path });\n const tag = tags.list.find((tag) => {\n return tag.id === props.id;\n });\n\n if (!tag) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" did not match any known tags`\n );\n }\n\n return tag;\n }\n\n /**\n * Updating a git tag is not supported.\n * Please delete the old and create a new one\n *\n * @deprecated\n * @see https://git-scm.com/docs/git-tag#_on_re_tagging\n */\n public update(): 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 when 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:iso-strict)',\n ];\n const result = await this.git(props.path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n\n // Remove the '<' and '>' enclosing the email\n // @todo is there another format like authoremail that returns the original email?\n if (lineArray[3]?.startsWith('<') && lineArray[3]?.endsWith('>')) {\n lineArray[3] = lineArray[3].slice(1, -1);\n lineArray[3] = lineArray[3].slice(0, -1);\n }\n\n return {\n id: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n datetime: datetime(lineArray[4]),\n };\n });\n\n const gitTags = lineObjArr.filter(this.isGitTag.bind(this));\n\n return {\n total: gitTags.length,\n limit: 0,\n offset: 0,\n list: gitTags,\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 type { ChildProcess } from 'node:child_process';\nimport type { IGitExecutionOptions, IGitStringResult } from 'dugite';\nimport { exec as gitExec } from 'dugite';\nimport PQueue from 'p-queue';\nimport Path from 'node:path';\nimport { GitError, NoCurrentUserError } from '../error/index.js';\nimport type { GitMergeOptions, GitMessage } from '../schema/index.js';\nimport {\n gitCommitSchema,\n gitMessageSchema,\n uuidSchema,\n type ElekIoCoreOptions,\n type GitCloneOptions,\n type GitCommit,\n type GitInitOptions,\n type GitLogOptions,\n type GitSwitchOptions,\n} from '../schema/index.js';\nimport { datetime } from '../util/shared.js';\nimport { GitTagService } from './GitTagService.js';\nimport type { LogService } from './LogService.js';\nimport type { UserService } from './UserService.js';\nimport type { LogProps } from '../schema/index.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 *\n * @todo All public methods should recieve only a single object as parameter and the type should be defined through the shared library to be accessible in Core and Client\n */\nexport class GitService {\n private version: string | null;\n private gitPath: string | null;\n private queue: PQueue;\n private logService: LogService;\n private gitTagService: GitTagService;\n private userService: UserService;\n\n public constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n userService: UserService\n ) {\n this.version = null;\n this.gitPath = null;\n this.queue = new PQueue({\n concurrency: 1, // No concurrency because git operations are sequencial\n });\n this.gitTagService = new GitTagService(\n options,\n this.git.bind(this),\n logService\n );\n this.logService = logService;\n this.userService = userService;\n\n void this.updateVersion();\n void this.updateGitPath();\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 * 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 }\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?.bare) {\n args = [...args, '--bare'];\n }\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('', [...args, url, path]);\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 relativePathsFromRepositoryRoot = files.map((filePath) => {\n return filePath.replace(`${path}${Path.sep}`, '');\n });\n\n const args = ['add', '--', ...relativePathsFromRepositoryRoot];\n\n await this.git(path, args);\n }\n\n public async status(path: string) {\n const args = ['status', '--porcelain=2'];\n const result = await this.git(path, args);\n\n const normalizedLinesArr = result.stdout\n .split('\\n')\n .filter((line) => {\n return line.trim() !== '';\n })\n .map((line) => {\n const lineArr = line.trim().split(' ');\n\n return {\n filePath: lineArr[8],\n };\n });\n\n return normalizedLinesArr;\n }\n\n public branches = {\n /**\n * List branches\n *\n * @see https://www.git-scm.com/docs/git-branch\n *\n * @param path Path to the repository\n */\n list: async (path: string) => {\n const args = ['branch', '--list', '--all'];\n const result = await this.git(path, args);\n\n const normalizedLinesArr = result.stdout\n .split('\\n')\n .filter((line) => {\n return line.trim() !== '';\n })\n .map((line) => {\n return line.trim().replace('* ', '');\n });\n\n const local: string[] = [];\n const remote: string[] = [];\n normalizedLinesArr.forEach((line) => {\n if (line.startsWith('remotes/')) {\n remote.push(line.replace('remotes/', ''));\n } else {\n local.push(line);\n }\n });\n return {\n local,\n remote,\n };\n },\n /**\n * Returns the name of the current branch. In detached HEAD state, an empty string is returned.\n *\n * @see https://www.git-scm.com/docs/git-branch#Documentation/git-branch.txt---show-current\n *\n * @param path Path to the repository\n */\n current: async (path: string) => {\n const args = ['branch', '--show-current'];\n const result = await this.git(path, args);\n\n return result.stdout.trim();\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 branch Name of the branch to switch to\n * @param options Options specific to the switch operation\n */\n switch: async (\n path: string,\n branch: string,\n options?: GitSwitchOptions\n ) => {\n await this.checkBranchOrTagName(path, branch);\n\n let args = ['switch'];\n\n if (options?.isNew === true) {\n args = [...args, '--create', branch];\n } else {\n args = [...args, branch];\n }\n\n await this.git(path, args);\n },\n /**\n * Delete a branch\n *\n * @see https://git-scm.com/docs/git-branch#Documentation/git-branch.txt---delete\n *\n * @param path Path to the repository\n * @param branch Name of the branch to delete\n */\n delete: async (path: string, branch: string, force?: boolean) => {\n let args = ['branch', '--delete'];\n\n if (force === true) {\n args = [...args, '--force'];\n }\n\n await this.git(path, [...args, branch]);\n },\n };\n\n public remotes = {\n /**\n * Returns a list of currently tracked remotes\n *\n * @see https://git-scm.com/docs/git-remote\n *\n * @param path Path to the repository\n */\n list: async (path: string) => {\n const args = ['remote'];\n const result = await this.git(path, args);\n const normalizedLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n return normalizedLinesArr;\n },\n /**\n * Returns true if the `origin` remote exists, otherwise false\n *\n * @param path Path to the repository\n */\n hasOrigin: async (path: string) => {\n const remotes = await this.remotes.list(path);\n\n if (remotes.includes('origin')) {\n return true;\n }\n return false;\n },\n /**\n * Adds the `origin` remote with given URL\n *\n * Throws if `origin` remote is added already.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emaddem\n *\n * @param path Path to the repository\n */\n addOrigin: async (path: string, url: string) => {\n const args = ['remote', 'add', 'origin', url.trim()];\n await this.git(path, args);\n },\n /**\n * Returns the current `origin` remote URL\n *\n * Throws if no `origin` remote is added yet.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem\n *\n * @param path Path to the repository\n */\n getOriginUrl: async (path: string) => {\n const args = ['remote', 'get-url', 'origin'];\n const result = (await this.git(path, args)).stdout.trim();\n\n return result.length === 0 ? null : result;\n },\n /**\n * Sets the current `origin` remote URL\n *\n * Throws if no `origin` remote is added yet.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem\n *\n * @param path Path to the repository\n */\n setOriginUrl: async (path: string, url: string) => {\n const args = ['remote', 'set-url', 'origin', url.trim()];\n await this.git(path, args);\n },\n };\n\n /**\n * Join two development histories together\n *\n * @see https://git-scm.com/docs/git-merge\n */\n public async merge(\n path: string,\n branch: string,\n options?: Partial<GitMergeOptions>\n ) {\n let args = ['merge'];\n\n if (options?.squash === true) {\n args = [...args, '--squash'];\n }\n\n args = [...args, branch];\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 * Download objects and refs from remote `origin`\n *\n * @see https://www.git-scm.com/docs/git-fetch\n *\n * @param path Path to the repository\n */\n public async fetch(path: string): Promise<void> {\n const args = ['fetch'];\n await this.git(path, args);\n }\n\n /**\n * Fetch from and integrate (rebase or merge) with 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\n await this.git(path, args);\n }\n\n /**\n * Update remote refs along with associated objects to remote `origin`\n *\n * @see https://git-scm.com/docs/git-push\n *\n * @param path Path to the repository\n */\n public async push(\n path: string,\n // branch: string,\n options?: Partial<{ all: boolean; force: boolean }>\n ): Promise<void> {\n let args = ['push', 'origin'];\n\n // if (options?.trackRemoteBranch === true) {\n // args = [...args, '--set-upstream'];\n // }\n\n // args = [...args, 'origin'];\n\n if (options?.all === true) {\n args = [...args, '--all'];\n }\n\n if (options?.force === true) {\n args = [...args, '--force'];\n }\n\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 An object describing the changes\n */\n public async commit(path: string, message: GitMessage): Promise<void> {\n gitMessageSchema.parse(message);\n\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const args = [\n 'commit',\n `--message=${JSON.stringify(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 args = [...args, '--format=%H|%s|%an|%ae|%aI|%D'];\n\n if (options?.filePath) {\n args = [...args, '--', options.filePath];\n }\n\n const result = await this.git(path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n const lineObjArr = await Promise.all(\n noEmptyLinesArr.map(async (line) => {\n const lineArray = line.split('|');\n const tagId = this.refNameToTagName(lineArray[5] || '');\n const tag = tagId ? await this.tags.read({ path, id: tagId }) : null;\n\n return {\n hash: lineArray[0],\n // We don't want to parse the message because it could throw.\n // Filtering it through isGitCommit ensures it's valid as a whole.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: JSON.parse(lineArray[1] || ''),\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n datetime: datetime(lineArray[4]),\n tag,\n };\n })\n );\n\n return lineObjArr.filter(this.isGitCommit.bind(this));\n }\n\n /**\n * Retrieves the content of a file at a specific commit\n *\n * @see https://git-scm.com/docs/git-show\n */\n public async getFileContentAtCommit(\n path: string,\n filePath: string,\n commitHash: string,\n encoding: 'utf8' | 'binary' = 'utf8'\n ) {\n const relativePathFromRepositoryRoot = filePath.replace(\n `${path}${Path.sep}`,\n ''\n );\n const normalizedPath = relativePathFromRepositoryRoot.split('\\\\').join('/');\n const args = ['show', `${commitHash}:${normalizedPath}`];\n const setEncoding: (process: ChildProcess) => void = (cb) => {\n if (cb.stdout) {\n cb.stdout.setEncoding(encoding);\n }\n };\n\n return (\n await this.git(path, args, {\n processCallback: setEncoding,\n })\n ).stdout;\n }\n\n public refNameToTagName(refName: string) {\n const tagName = refName.replace('tag: ', '').trim();\n\n // Return null for anything else than UUIDs (tag names are UUIDs)\n if (tagName === '' || uuidSchema.safeParse(tagName).success === false) {\n return null;\n }\n\n return tagName;\n }\n\n /**\n * Reads the currently used version of Git\n *\n * This can help debugging\n */\n private async updateVersion(): Promise<void> {\n const result = await this.git('', ['--version']);\n this.version = result.stdout.replace('git version', '').trim();\n }\n\n /**\n * Reads the path to the executable of Git that is used\n *\n * This can help debugging, since dugite is shipping their own executable\n * but in some cases resolves another executable\n * @see https://github.com/desktop/dugite/blob/main/lib/git-environment.ts\n */\n private async updateGitPath(): Promise<void> {\n const result = await this.git('', ['--exec-path']);\n this.gitPath = result.stdout.trim();\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 * 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 // Setup the local User\n const userNameArgs = ['config', '--local', 'user.name', user.name];\n const userEmailArgs = ['config', '--local', 'user.email', user.email];\n // By default new branches that are pushed are automatically tracking\n // their remote without the need of using the `--set-upstream` argument of `git push`\n const autoSetupRemoteArgs = [\n 'config',\n '--local',\n 'push.autoSetupRemote',\n 'true',\n ];\n // By default `git pull` will try to rebase first\n // to reduce the amount of merge commits\n const pullRebaseArgs = ['config', '--local', 'pull.rebase', 'true'];\n\n await this.git(path, userNameArgs);\n await this.git(path, userEmailArgs);\n await this.git(path, autoSetupRemoteArgs);\n await this.git(path, pullRebaseArgs);\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(\n path: string,\n args: string[],\n options?: IGitExecutionOptions\n ): Promise<IGitStringResult> {\n const result = await this.queue.add(async () => {\n const start = Date.now();\n const gitResult = await gitExec(args, path, options);\n const durationMs = Date.now() - start;\n return {\n gitResult,\n durationMs,\n };\n });\n\n if (!result) {\n throw new GitError(\n `Git ${this.version} (${this.gitPath}) command \"git ${args.join(\n ' '\n )}\" executed for \"${path}\" failed to return a result`\n );\n }\n\n const gitLog: LogProps = {\n source: 'core',\n message: `Executed \"git ${args.join(' ')}\" in ${result.durationMs}ms`,\n meta: { command: `git ${args.join(' ')}` },\n };\n if (result.durationMs >= 100) {\n this.logService.warn(gitLog);\n } else {\n this.logService.debug(gitLog);\n }\n\n if (result.gitResult.exitCode !== 0) {\n throw new GitError(\n `Git ${this.version} (${this.gitPath}) command \"git ${args.join(\n ' '\n )}\" executed for \"${path}\" failed with exit code \"${\n result.gitResult.exitCode\n }\" and message \"${\n result.gitResult.stderr.toString().trim() ||\n result.gitResult.stdout.toString().trim()\n }\"`\n );\n }\n\n return {\n ...result.gitResult,\n stdout: result.gitResult.stdout.toString(),\n stderr: result.gitResult.stderr.toString(),\n };\n }\n}\n","import Fs from 'fs-extra';\nimport type { z } from '@hono/zod-openapi';\nimport type { ElekIoCoreOptions } from '../schema/coreSchema.js';\nimport type { BaseFile } from '../schema/fileSchema.js';\nimport { serviceTypeSchema } from '../schema/serviceSchema.js';\nimport type { UserFile } from '../schema/userSchema.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for JSON files on disk\n */\nexport class JsonFileService extends AbstractCrudService {\n private cache: Map<string, unknown> = new Map();\n\n constructor(options: ElekIoCoreOptions, logService: LogService) {\n super(serviceTypeSchema.enum.JsonFile, options, logService);\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n this.logService.debug({\n source: 'core',\n message: `Created file \"${path}\"`,\n });\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.options.file.cache === true && this.cache.has(path)) {\n this.logService.debug({\n source: 'core',\n message: `Cache hit reading file \"${path}\"`,\n });\n const json = this.cache.get(path);\n const parsedData = schema.parse(json);\n return parsedData;\n }\n\n this.logService.debug({\n source: 'core',\n message: `Cache miss reading file \"${path}\"`,\n });\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n\n return parsedData;\n }\n\n /**\n * Reads the content of a file on disk. Fails if path does not exist.\n * Does not validate the content of the file against a schema and\n * therefore is only to be used when retrieving data we do not have\n * a current schema for. E.g. reading from history or while upgrading\n * the old schema of a file to a new, current schema.\n *\n * Does not read from or write to cache.\n *\n * @param path Path to read the file from\n * @returns Unvalidated content of the file from disk\n */\n public async unsafeRead(path: string): Promise<unknown> {\n this.logService.warn({\n source: 'core',\n message: `Unsafe reading of file \"${path}\"`,\n });\n const data = await Fs.readFile(path, {\n flag: 'r',\n encoding: 'utf8',\n });\n const json = this.deserialize(data);\n\n return json;\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n this.logService.debug({\n source: 'core',\n message: `Updated file \"${path}\"`,\n });\n\n return parsedData;\n }\n\n private serialize(data: unknown): string {\n return JSON.stringify(data, null, 2);\n }\n\n private deserialize(data: string): unknown {\n return JSON.parse(data);\n }\n}\n","import type { Logger } from 'winston';\nimport { createLogger, format, transports } from 'winston';\nimport DailyRotateFile from 'winston-daily-rotate-file';\nimport { type ElekIoCoreOptions } from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport type { LogProps } from '../schema/logSchema.js';\nimport { logConsoleTransportSchema, logSchema } from '../schema/logSchema.js';\n\n/**\n * Service that handles logging to file and console\n */\nexport class LogService {\n private readonly logger: Logger;\n\n constructor(options: ElekIoCoreOptions) {\n const rotatingFileTransport = new DailyRotateFile({\n dirname: pathTo.logs,\n filename: '%DATE%.log',\n datePattern: 'YYYY-MM-DD',\n zippedArchive: true,\n maxFiles: '30d',\n handleExceptions: true,\n handleRejections: true,\n format: format.combine(format.timestamp(), format.json()),\n });\n\n rotatingFileTransport.on('rotate', (oldFilename, newFilename) => {\n this.info({\n message: `Rotated log file from ${oldFilename} to ${newFilename}`,\n source: 'core',\n });\n });\n\n rotatingFileTransport.on('error', (error) => {\n this.error({\n message: `Error rotating log file: ${error.message}`,\n source: 'core',\n meta: { error },\n });\n });\n\n const consoleTransport = new transports.Console({\n handleExceptions: true,\n handleRejections: true,\n format: format.combine(\n format.colorize(),\n format.timestamp({ format: 'HH:mm:ss' }),\n format.printf((props) => {\n const splatArgs = props[Symbol.for('splat') as unknown as string] as\n | Record<string, unknown>[]\n | undefined;\n const result = logConsoleTransportSchema.safeParse({\n ...(splatArgs?.[0] ?? {}),\n timestamp: props['timestamp'],\n level: props.level,\n message: props.message,\n });\n\n if (result.success) {\n const { timestamp, level, source, message } = result.data;\n return `${timestamp} [${source}] ${level}: ${message}`;\n }\n\n // Fallback for logs not originating from LogService (e.g. unhandled exceptions caught by winston)\n return `${String(props['timestamp'])} ${props.level}: ${String(props.message)}`;\n })\n ),\n });\n\n this.logger = createLogger({\n level: options.log.level,\n transports: [rotatingFileTransport, consoleTransport],\n });\n }\n\n public debug(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.debug(message, { source, meta });\n }\n\n public info(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.info(message, { source, meta });\n }\n\n public warn(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.warn(message, { source, meta });\n }\n\n public error(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.error(message, { source, meta });\n }\n}\n","export class RemoteOriginMissingError extends Error {\n constructor(projectId: string) {\n super(\n `Tried to delete Project \"${projectId}\" but it does not have a remote origin. Deleting a Project without a remote origin could lead to data loss. Use the \"force\" option to delete it anyway.`\n );\n\n this.name = 'RemoteOriginMissingError';\n }\n}\n","export class SynchronizeLocalChangesError extends Error {\n constructor(projectId: string) {\n super(\n `Tried to delete Project \"${projectId}\" but it has local changes that are not yet pushed to the remote origin. Deleting a Project with local changes could lead to data loss. Use the \"force\" option to delete it anyway.`\n );\n\n this.name = 'SynchronizeLocalChangesError';\n }\n}\n","import Fs from 'fs-extra';\nimport Os from 'node:os';\nimport Path from 'node:path';\nimport Semver from 'semver';\nimport {\n ProjectUpgradeError,\n RequiredParameterMissingError,\n} from '../error/index.js';\nimport { RemoteOriginMissingError } from '../error/RemoteOriginMissingError.js';\nimport { SynchronizeLocalChangesError } from '../error/SynchronizeLocalChangesError.js';\nimport type {\n FileReference,\n ObjectType,\n MigrateProjectProps,\n Version,\n} from '../schema/index.js';\nimport {\n cloneProjectSchema,\n createProjectSchema,\n currentBranchProjectSchema,\n deleteProjectSchema,\n getChangesProjectSchema,\n listBranchesProjectSchema,\n listProjectsSchema,\n objectTypeSchema,\n migrateProjectSchema,\n projectBranchSchema,\n projectFileSchema,\n projectFolderSchema,\n readProjectSchema,\n serviceTypeSchema,\n setRemoteOriginUrlProjectSchema,\n switchBranchProjectSchema,\n synchronizeProjectSchema,\n updateProjectSchema,\n upgradeProjectSchema,\n type CloneProjectProps,\n type CreateProjectProps,\n type CrudServiceWithListCount,\n type CurrentBranchProjectProps,\n type DeleteProjectProps,\n type ElekIoCoreOptions,\n type GetChangesProjectProps,\n type ListBranchesProjectProps,\n type ListProjectsProps,\n type PaginatedList,\n type Project,\n type ProjectFile,\n type ReadProjectProps,\n type SetRemoteOriginUrlProjectProps,\n type SwitchBranchProjectProps,\n type SynchronizeProjectProps,\n type UpdateProjectProps,\n type UpgradeProjectProps,\n} from '../schema/index.js';\nimport { isNotEmpty, pathTo } from '../util/node.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { AssetService } from './AssetService.js';\nimport type { CollectionService } from './CollectionService.js';\nimport type { EntryService } from './EntryService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Project files on disk\n */\nexport class ProjectService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Project>\n{\n private coreVersion: Version;\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private assetService: AssetService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n\n constructor(\n coreVersion: Version,\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService,\n assetService: AssetService,\n collectionService: CollectionService,\n entryService: EntryService\n ) {\n super(serviceTypeSchema.enum.Project, options, logService);\n\n this.coreVersion = coreVersion;\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\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 id = uuid();\n\n const projectFile: ProjectFile = {\n ...props,\n objectType: 'project',\n id,\n created: datetime(),\n updated: null,\n coreVersion: this.coreVersion,\n status: 'todo',\n version: '0.0.1',\n };\n\n const projectPath = 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, {\n initialBranch: projectBranchSchema.enum.production,\n });\n await this.jsonFileService.create(\n projectFile,\n pathTo.projectFile(id),\n projectFileSchema\n );\n await this.gitService.add(projectPath, ['.']);\n await this.gitService.commit(projectPath, {\n method: 'create',\n reference: { objectType: 'project', id },\n });\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work,\n {\n isNew: true,\n }\n );\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 force: true,\n });\n throw error;\n }\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Clones a Project by URL\n */\n public async clone(props: CloneProjectProps): Promise<Project> {\n cloneProjectSchema.parse(props);\n\n const tmpId = uuid();\n const tmpProjectPath = Path.join(pathTo.tmp, tmpId);\n // await Fs.ensureDir(tmpProjectPath);\n await this.gitService.clone(props.url, tmpProjectPath);\n\n // Check if it is actually a Project by trying to read it\n const projectFile = await this.jsonFileService.read(\n Path.join(tmpProjectPath, 'project.json'),\n projectFileSchema\n );\n\n // If so, copy it into the correct directory\n const projectPath = pathTo.project(projectFile.id);\n const alreadyExists = await Fs.pathExists(projectPath);\n if (alreadyExists) {\n throw new Error(\n `Tried to clone Project \"${projectFile.id}\" from \"${props.url}\" - but the Project already exists locally`\n );\n }\n await Fs.copy(tmpProjectPath, projectPath);\n await Fs.remove(tmpProjectPath);\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Returns a Project by ID\n *\n * If a commit hash is provided, the Project is read from history\n */\n public async read(props: ReadProjectProps): Promise<Project> {\n readProjectSchema.parse(props);\n\n if (!props.commitHash) {\n const projectFile = await this.jsonFileService.read(\n pathTo.projectFile(props.id),\n projectFileSchema\n );\n\n return await this.toProject(projectFile);\n } else {\n const projectFile = this.migrate(\n migrateProjectSchema.parse(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.id),\n pathTo.projectFile(props.id),\n props.commitHash\n )\n )\n )\n );\n\n return await this.toProject(projectFile);\n }\n }\n\n /**\n * Updates given Project\n */\n public async update(props: UpdateProjectProps): Promise<Project> {\n updateProjectSchema.parse(props);\n\n const projectPath = pathTo.project(props.id);\n const filePath = pathTo.projectFile(props.id);\n const prevProjectFile = await this.read(props);\n\n const projectFile: ProjectFile = {\n ...prevProjectFile,\n ...props,\n updated: datetime(),\n };\n\n await this.jsonFileService.update(projectFile, filePath, projectFileSchema);\n await this.gitService.add(projectPath, [filePath]);\n await this.gitService.commit(projectPath, {\n method: 'update',\n reference: { objectType: 'project', id: projectFile.id },\n });\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Upgrades given Project to the current version of Core\n *\n * Needed when a new Core version is requiring changes to existing files or structure.\n */\n public async upgrade(props: UpgradeProjectProps): Promise<void> {\n upgradeProjectSchema.parse(props);\n\n const projectPath = pathTo.project(props.id);\n const projectFilePath = pathTo.projectFile(props.id);\n const currentBranch = await this.gitService.branches.current(projectPath);\n\n if (currentBranch !== projectBranchSchema.enum.work) {\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n }\n\n // Get the current Project file\n const currentProjectFile = migrateProjectSchema.parse(\n await this.jsonFileService.unsafeRead(projectFilePath)\n );\n\n if (Semver.gt(currentProjectFile.coreVersion, this.coreVersion)) {\n // Upgrade of the client needed before the project can be upgraded\n throw new ProjectUpgradeError(\n `The Projects Core version \"${currentProjectFile.coreVersion}\" is higher than the current Core version \"${this.coreVersion}\".`\n );\n }\n\n if (\n Semver.eq(currentProjectFile.coreVersion, this.coreVersion) &&\n props.force !== true\n ) {\n // Nothing, since both are equal\n throw new ProjectUpgradeError(\n `The Projects Core version \"${currentProjectFile.coreVersion}\" is already up to date.`\n );\n }\n\n const assetReferences = await this.listReferences('asset', props.id);\n const collectionReferences = await this.listReferences(\n 'collection',\n props.id\n );\n\n this.logService.info({\n source: 'core',\n message: `Attempting to upgrade Project \"${props.id}\" from Core version ${currentProjectFile.coreVersion} to ${this.coreVersion}`,\n });\n\n // Create a new branch to work on this migration\n const upgradeBranchName = `upgrade/core-${currentProjectFile.coreVersion}-to-${this.coreVersion}`;\n await this.gitService.branches.switch(projectPath, upgradeBranchName, {\n isNew: true,\n });\n\n try {\n await Promise.all(\n assetReferences.map(async (reference) => {\n await this.upgradeObjectFile(props.id, 'asset', reference);\n })\n );\n\n await Promise.all(\n collectionReferences.map(async (reference) => {\n await this.upgradeObjectFile(props.id, 'collection', reference);\n })\n );\n\n await Promise.all(\n collectionReferences.map(async (collectionReference) => {\n const entryReferences = await this.listReferences(\n 'entry',\n props.id,\n collectionReference.id\n );\n\n await Promise.all(\n entryReferences.map(async (reference) => {\n await this.upgradeObjectFile(\n props.id,\n 'entry',\n reference,\n collectionReference.id\n );\n })\n );\n })\n );\n\n // Upgrade the Project file itself\n const migratedProjectFile = this.migrate(currentProjectFile);\n await this.update(migratedProjectFile);\n\n // Merge the upgrade branch back into the work branch\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n await this.gitService.merge(projectPath, upgradeBranchName, {\n squash: true,\n });\n await this.gitService.commit(projectPath, {\n method: 'upgrade',\n reference: { objectType: 'project', id: migratedProjectFile.id },\n });\n await this.gitService.tags.create({\n path: projectPath,\n message: `Upgraded Project to Core version ${migratedProjectFile.coreVersion}`,\n });\n await this.gitService.branches.delete(\n projectPath,\n upgradeBranchName,\n true\n );\n\n this.logService.info({\n source: 'core',\n message: `Successfully upgraded Project \"${props.id}\" to Core version \"${this.coreVersion}\"`,\n meta: {\n previous: currentProjectFile,\n migrated: migratedProjectFile,\n },\n });\n } catch (error) {\n // Revert back to the work branch and delete the upgrade branch\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n await this.gitService.branches.delete(\n projectPath,\n upgradeBranchName,\n true\n );\n\n throw error;\n }\n }\n\n public branches = {\n list: async (props: ListBranchesProjectProps) => {\n listBranchesProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (hasOrigin) {\n await this.gitService.fetch(projectPath);\n }\n return await this.gitService.branches.list(projectPath);\n },\n current: async (props: CurrentBranchProjectProps) => {\n currentBranchProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n return await this.gitService.branches.current(projectPath);\n },\n switch: async (props: SwitchBranchProjectProps) => {\n switchBranchProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n return await this.gitService.branches.switch(\n projectPath,\n props.branch,\n props.options\n );\n },\n };\n\n /**\n * Updates the remote origin URL of given Project\n *\n * @todo maybe add this logic to the update method\n */\n public async setRemoteOriginUrl(props: SetRemoteOriginUrlProjectProps) {\n setRemoteOriginUrlProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (!hasOrigin) {\n await this.gitService.remotes.addOrigin(projectPath, props.url);\n } else {\n await this.gitService.remotes.setOriginUrl(projectPath, props.url);\n }\n }\n\n /**\n * Returns the differences of the given Projects current branch\n * between the local and remote `origin` (commits ahead & behind)\n *\n * Throws an error if the Project does not have a remote origin.\n *\n * - `behind` contains a list of commits on the current branch that are available on the remote `origin` but not yet locally\n * - `ahead` contains a list of commits on the current branch that are available locally but not yet on the remote `origin`\n */\n public async getChanges(props: GetChangesProjectProps) {\n getChangesProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasRemoteOrigin =\n await this.gitService.remotes.hasOrigin(projectPath);\n if (hasRemoteOrigin === false) {\n throw new Error(`Project \"${props.id}\" does not have a remote origin`);\n }\n const currentBranch = await this.gitService.branches.current(projectPath);\n\n await this.gitService.fetch(projectPath);\n const behind = await this.gitService.log(projectPath, {\n between: { from: currentBranch, to: `origin/${currentBranch}` },\n });\n const ahead = await this.gitService.log(projectPath, {\n between: { from: `origin/${currentBranch}`, to: currentBranch },\n });\n\n return {\n behind,\n ahead,\n };\n }\n\n /**\n * Pulls remote changes of `origin` down to the local repository\n * and then pushes local commits to the upstream branch\n */\n public async synchronize(props: SynchronizeProjectProps) {\n synchronizeProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n\n await this.gitService.pull(projectPath);\n await this.gitService.push(projectPath);\n }\n\n /**\n * Deletes given Project\n *\n * Deletes the whole Project folder including the history, not only the config file.\n * Throws in case a Project is only available locally and could be lost forever,\n * or changes are not pushed to a remote yet.\n */\n public async delete(props: DeleteProjectProps): Promise<void> {\n deleteProjectSchema.parse(props);\n\n const hasRemoteOrigin = await this.gitService.remotes.hasOrigin(\n pathTo.project(props.id)\n );\n\n if (hasRemoteOrigin === false && props.force !== true) {\n throw new RemoteOriginMissingError(props.id);\n }\n\n if (hasRemoteOrigin === true && props.force !== true) {\n const changes = await this.getChanges({ id: props.id });\n if (changes.ahead.length > 0) {\n throw new SynchronizeLocalChangesError(props.id);\n }\n }\n\n await Fs.remove(pathTo.project(props.id));\n }\n\n /**\n * Lists outdated Projects that need to be upgraded\n */\n public async listOutdated(): Promise<MigrateProjectProps[]> {\n const projectReferences = await this.listReferences(\n objectTypeSchema.enum.project\n );\n\n const result = await Promise.all(\n projectReferences.map(async (reference) => {\n const json = await this.jsonFileService.unsafeRead(\n pathTo.projectFile(reference.id)\n );\n const projectFile = migrateProjectSchema.parse(json);\n\n if (projectFile.coreVersion !== this.coreVersion) {\n return projectFile;\n }\n\n return null;\n })\n );\n\n return result.filter(isNotEmpty);\n }\n\n public async list(\n props?: ListProjectsProps\n ): Promise<PaginatedList<Project>> {\n if (props) {\n listProjectsSchema.parse(props);\n }\n\n const offset = props?.offset || 0;\n const limit = props?.limit ?? 15;\n\n const projectReferences = await this.listReferences(\n objectTypeSchema.enum.project\n );\n\n const partialProjectReferences =\n limit === 0\n ? projectReferences.slice(offset)\n : projectReferences.slice(offset, offset + limit);\n\n const projects = await this.returnResolved(\n partialProjectReferences.map((reference) => {\n return this.read({ id: reference.id });\n })\n );\n\n return {\n total: projectReferences.length,\n limit,\n offset,\n list: projects,\n };\n }\n\n public async count(): Promise<number> {\n return (await this.listReferences(objectTypeSchema.enum.project)).length;\n }\n\n /**\n * Checks if given object is of type Project\n */\n public isProject(obj: unknown): obj is Project {\n return projectFileSchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Project file to the current schema\n */\n public migrate(props: MigrateProjectProps) {\n // @todo\n\n props.coreVersion = this.coreVersion;\n\n return projectFileSchema.parse(props);\n }\n\n /**\n * Creates a Project from given ProjectFile\n */\n private async toProject(projectFile: ProjectFile): Promise<Project> {\n const projectPath = pathTo.project(projectFile.id);\n\n let remoteOriginUrl = null;\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (hasOrigin) {\n remoteOriginUrl = await this.gitService.remotes.getOriginUrl(projectPath);\n }\n\n const fullHistory = await this.gitService.log(\n pathTo.project(projectFile.id)\n );\n const history = await this.gitService.log(pathTo.project(projectFile.id), {\n filePath: pathTo.projectFile(projectFile.id),\n });\n\n return {\n ...projectFile,\n remoteOriginUrl,\n history,\n fullHistory,\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.enum);\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 private async upgradeObjectFile(\n projectId: string,\n objectType: ObjectType,\n reference: FileReference,\n collectionId?: string\n ) {\n switch (objectType) {\n case 'asset': {\n const assetFilePath = pathTo.assetFile(projectId, reference.id);\n const prevAssetFile =\n await this.jsonFileService.unsafeRead(assetFilePath);\n const migratedAssetFile = this.assetService.migrate(prevAssetFile);\n await this.assetService.update({ projectId, ...migratedAssetFile });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${assetFilePath}\"`,\n meta: {\n previous: prevAssetFile,\n migrated: migratedAssetFile,\n },\n });\n return;\n }\n case 'collection': {\n const collectionFilePath = pathTo.collectionFile(\n projectId,\n reference.id\n );\n const prevCollectionFile =\n await this.jsonFileService.unsafeRead(collectionFilePath);\n const migratedCollectionFile =\n this.collectionService.migrate(prevCollectionFile);\n await this.collectionService.update({\n projectId,\n ...migratedCollectionFile,\n });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${collectionFilePath}\"`,\n meta: {\n previous: prevCollectionFile,\n migrated: migratedCollectionFile,\n },\n });\n return;\n }\n case 'entry': {\n if (!collectionId) {\n throw new RequiredParameterMissingError('collectionId');\n }\n const entryFilePath = pathTo.entryFile(\n projectId,\n collectionId,\n reference.id\n );\n const prevEntryFile =\n await this.jsonFileService.unsafeRead(entryFilePath);\n const migratedEntryFile = this.entryService.migrate(prevEntryFile);\n await this.entryService.update({\n projectId,\n collectionId,\n ...migratedEntryFile,\n });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${entryFilePath}\"`,\n meta: {\n previous: prevEntryFile,\n migrated: migratedEntryFile,\n },\n });\n return;\n }\n default:\n throw new Error(\n `Trying to upgrade unsupported object file of type \"${objectType}\"`\n );\n }\n }\n}\n","import {\n UserTypeSchema,\n setUserSchema,\n userFileSchema,\n type SetUserProps,\n type User,\n type UserFile,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service to handle the User that is currently working with Core\n */\nexport class UserService {\n private readonly logService: LogService;\n private readonly jsonFileService: JsonFileService;\n\n constructor(logService: LogService, jsonFileService: JsonFileService) {\n this.logService = logService;\n this.jsonFileService = jsonFileService;\n }\n\n /**\n * Returns the User currently working with Core\n */\n public async get(): Promise<User | null> {\n try {\n return await this.jsonFileService.read(pathTo.userFile, userFileSchema);\n } catch {\n this.logService.info({ source: 'core', message: 'No User found' });\n\n return null;\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 = 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 this.logService.debug({\n source: 'core',\n message: 'Updated User',\n });\n\n return userFile;\n }\n}\n","import Fs from 'fs-extra';\nimport * as packageJson from '../package.json' with { type: 'json' };\nimport { LocalApi } from './api/index.js';\nimport type { Version } from './schema/index.js';\nimport {\n constructorElekIoCoreSchema,\n type ConstructorElekIoCoreProps,\n type ElekIoCoreOptions,\n} from './schema/index.js';\nimport {\n AssetService,\n CollectionService,\n EntryService,\n GitService,\n JsonFileService,\n ProjectService,\n UserService,\n} from './service/index.js';\nimport { LogService } from './service/LogService.js';\nimport * as Util from './util/node.js';\n\n// Export all schemas and shared code that works inside node environments,\n// including code that requires filesystem access / git integration etc.\nexport * from './schema/index.js';\nexport * from './util/shared.js';\n\n/**\n * elek.io Core\n *\n * Provides access to all services Core is offering\n */\nexport default class ElekIoCore {\n public readonly coreVersion: Version;\n public readonly options: ElekIoCoreOptions;\n private readonly logService: LogService;\n private readonly userService: UserService;\n private readonly gitService: GitService;\n private readonly jsonFileService: JsonFileService;\n private readonly assetService: AssetService;\n private readonly projectService: ProjectService;\n private readonly collectionService: CollectionService;\n private readonly entryService: EntryService;\n private readonly localApi: LocalApi;\n\n constructor(props?: ConstructorElekIoCoreProps) {\n this.coreVersion = packageJson.default.version;\n const parsedProps = constructorElekIoCoreSchema.parse(props);\n\n const defaults: ElekIoCoreOptions = {\n log: {\n level: 'info',\n },\n file: {\n cache: true,\n },\n };\n this.options = Object.assign({}, defaults, parsedProps);\n\n this.logService = new LogService(this.options);\n this.jsonFileService = new JsonFileService(this.options, this.logService);\n this.userService = new UserService(this.logService, this.jsonFileService);\n this.gitService = new GitService(\n this.options,\n this.logService,\n this.userService\n );\n this.assetService = new AssetService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService\n );\n this.collectionService = new CollectionService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService\n );\n this.entryService = new EntryService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService,\n this.collectionService\n );\n this.projectService = new ProjectService(\n this.coreVersion,\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService,\n this.assetService,\n this.collectionService,\n this.entryService\n );\n this.localApi = new LocalApi(\n this.logService,\n this.projectService,\n this.collectionService,\n this.entryService,\n this.assetService\n );\n\n this.logService.info({\n source: 'core',\n message: `Initializing elek.io Core ${this.coreVersion}`,\n meta: { options: this.options },\n });\n\n Fs.mkdirpSync(Util.pathTo.projects);\n Fs.mkdirpSync(Util.pathTo.tmp);\n Fs.emptyDirSync(Util.pathTo.tmp);\n }\n\n /**\n * Exposes the logger\n */\n public get logger() {\n return this.logService;\n }\n\n /**\n * Utility / helper functions\n */\n public get util() {\n return Util;\n }\n\n /**\n * Exposes git functions\n */\n public get git(): GitService {\n return this.gitService;\n }\n\n /**\n * Getter and setter methods for the User currently working with Core\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 * Allows starting and stopping a REST API\n * to allow developers to read local Project data\n */\n public get api(): LocalApi {\n return this.localApi;\n }\n}\n","import { z } from '@hono/zod-openapi';\nimport type { FieldDefinition } from '../schema/fieldSchema.js';\nimport {\n getTranslatableBooleanValueContentSchemaFromFieldDefinition,\n getTranslatableNumberValueContentSchemaFromFieldDefinition,\n getTranslatableReferenceValueContentSchemaFromFieldDefinition,\n getTranslatableStringValueContentSchemaFromFieldDefinition,\n} from '../schema/schemaFromFieldDefinition.js';\nimport { ValueTypeSchema } from '../schema/valueSchema.js';\n\n/**\n * Generates a flat Zod object schema from collection field definitions\n * for use with Astro's `parseData` validation.\n *\n * Each key is the field definition ID (UUID) and each value schema\n * is the translatable content schema for that field type.\n */\nexport function buildEntryValuesSchema(fieldDefinitions: FieldDefinition[]) {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const fieldDef of fieldDefinitions) {\n switch (fieldDef.valueType) {\n case ValueTypeSchema.enum.string:\n shape[fieldDef.id] =\n getTranslatableStringValueContentSchemaFromFieldDefinition(fieldDef);\n break;\n case ValueTypeSchema.enum.number:\n shape[fieldDef.id] =\n getTranslatableNumberValueContentSchemaFromFieldDefinition(fieldDef);\n break;\n case ValueTypeSchema.enum.boolean:\n shape[fieldDef.id] =\n getTranslatableBooleanValueContentSchemaFromFieldDefinition();\n break;\n case ValueTypeSchema.enum.reference:\n shape[fieldDef.id] =\n getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDef\n );\n break;\n }\n }\n\n return z.object(shape);\n}\n","import type { Value } from '../schema/valueSchema.js';\n\n/**\n * Transforms an elek.io Entry's values array into a flat object\n * keyed by field definition ID. Each value's translatable content\n * is preserved as-is.\n */\nexport function transformEntryValues(\n values: Value[]\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const value of values) {\n result[value.fieldDefinitionId] = value.content;\n }\n return result;\n}\n","import type { Loader } from 'astro/loaders';\nimport type { ZodSchema as AstroZodSchema } from 'astro/zod';\nimport Path from 'node:path';\nimport Fs from 'fs-extra';\nimport ElekIoCore, { assetSchema } from './index.node.js';\nimport { buildEntryValuesSchema } from './astro/schema.js';\nimport { transformEntryValues } from './astro/transform.js';\n\ninterface ElekAssetsProps {\n projectId: string;\n outDir: string;\n}\n\ninterface ElekEntriesOptions {\n projectId: string;\n collectionId: string;\n}\n\nconst core = new ElekIoCore({\n log: { level: 'info' },\n});\n\n/**\n * Astro content loader for elek.io Assets.\n *\n * Reads and saves Assets from a Project and exposes them through\n * Astro's content collection system.\n *\n * @example\n * ```ts\n * // src/content.config.ts\n * import { defineCollection } from 'astro:content';\n * import { elekAssets } from '@elek-io/core/astro';\n *\n * export const collections = {\n * assets: defineCollection({\n * loader: elekAssets({\n * projectId: 'abc-123-...',\n * outDir: './content/assets',\n * }),\n * });\n * };\n * ```\n */\nexport function elekAssets(props: ElekAssetsProps): Loader {\n return {\n name: 'elek-assets',\n schema: () => assetSchema as unknown as AstroZodSchema,\n load: async (context) => {\n context.logger.info(\n `Loading elek.io Assets for Project \"${props.projectId}\", saving to \"${props.outDir}\"`\n );\n context.store.clear();\n\n const { list: assets, total } = await core.assets.list({\n projectId: props.projectId,\n limit: 0,\n });\n if (total === 0) {\n context.logger.warn('No Assets found');\n } else {\n context.logger.info(`Found ${total} Assets`);\n }\n\n for (const asset of assets) {\n const absoluteAssetFilePath = Path.resolve(\n Path.join(props.outDir, `${asset.id}.${asset.extension}`)\n );\n await Fs.ensureDir(Path.dirname(absoluteAssetFilePath));\n await core.assets.save({\n projectId: props.projectId,\n id: asset.id,\n filePath: absoluteAssetFilePath,\n });\n\n const parsed = await context.parseData({\n id: asset.id,\n data: {\n ...asset,\n absolutePath: absoluteAssetFilePath,\n },\n });\n context.store.set({ id: asset.id, data: parsed });\n }\n\n context.logger.info('Finished loading Assets');\n },\n };\n}\n\n/**\n * Astro content loader for elek.io Collection Entries.\n *\n * Reads all Entries from a Collection and exposes them through\n * Astro's content collection system.\n *\n * @example\n * ```ts\n * // src/content.config.ts\n * import { defineCollection } from 'astro:content';\n * import { elekEntries } from '@elek-io/core/astro';\n *\n * export const collections = {\n * entries: defineCollection({\n * loader: elekEntries({\n * projectId: 'abc-123-...',\n * collectionId: 'def-456-...',\n * }),\n * });\n * };\n * ```\n */\nexport function elekEntries(props: ElekEntriesOptions): Loader {\n return {\n name: 'elek-entries',\n schema: async () => {\n const collection = await core.collections.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n return buildEntryValuesSchema(\n collection.fieldDefinitions\n ) as unknown as AstroZodSchema;\n },\n load: async (context) => {\n context.logger.info(\n `Loading elek.io Entries of Collection \"${props.collectionId}\" and Project \"${props.projectId}\"`\n );\n context.store.clear();\n\n const { list: entries, total } = await core.entries.list({\n projectId: props.projectId,\n collectionId: props.collectionId,\n limit: 0,\n });\n if (total === 0) {\n context.logger.warn('No Entries found');\n } else {\n context.logger.info(`Found ${total} Entries`);\n }\n\n for (const entry of entries) {\n const values = transformEntryValues(entry.values);\n\n const parsed = await context.parseData({ id: entry.id, data: values });\n context.store.set({ id: entry.id, data: parsed });\n }\n\n context.logger.info('Finished loading Entries');\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.astro.mjs","names":["z","tags","router","tags","router","tags","router","router","router","projectRoutes","collectionRoutes","entryRoutes","assetRoutes","router","v1Routes","contentRoutes","routes","generateUuid","gitExec","Util"],"sources":["../../package.json","../../src/api/middleware/requestResponseLogger.ts","../../src/api/lib/util.ts","../../src/schema/baseSchema.ts","../../src/schema/fileSchema.ts","../../src/schema/gitSchema.ts","../../src/schema/assetSchema.ts","../../src/schema/valueSchema.ts","../../src/schema/entrySchema.ts","../../src/schema/fieldSchema.ts","../../src/schema/collectionSchema.ts","../../src/schema/coreSchema.ts","../../src/schema/projectSchema.ts","../../src/schema/schemaFromFieldDefinition.ts","../../src/schema/serviceSchema.ts","../../src/schema/userSchema.ts","../../src/schema/cliSchema.ts","../../src/schema/logSchema.ts","../../src/api/routes/content/v1/projects.ts","../../src/api/routes/content/v1/collections.ts","../../src/api/routes/content/v1/entries.ts","../../src/api/routes/content/v1/assets.ts","../../src/api/routes/content/v1/index.ts","../../src/api/routes/content/index.ts","../../src/api/routes/index.ts","../../src/api/index.ts","../../src/error/GitError.ts","../../src/error/NoCurrentUserError.ts","../../src/error/ProjectUpgradeError.ts","../../src/error/RequiredParameterMissingError.ts","../../src/util/node.ts","../../src/service/AbstractCrudService.ts","../../src/util/shared.ts","../../src/service/AssetService.ts","../../src/service/CollectionService.ts","../../src/service/EntryService.ts","../../src/service/GitTagService.ts","../../src/service/GitService.ts","../../src/service/JsonFileService.ts","../../src/service/LogService.ts","../../src/error/RemoteOriginMissingError.ts","../../src/error/SynchronizeLocalChangesError.ts","../../src/service/ProjectService.ts","../../src/service/UserService.ts","../../src/index.node.ts","../../src/astro/schema.ts","../../src/astro/transform.ts","../../src/index.astro.ts"],"sourcesContent":["","import { createMiddleware } from 'hono/factory';\nimport type { ApiEnv } from '../lib/types.js';\n\n/**\n * Middleware that logs the details of each request and response\n */\nexport const requestResponseLogger = createMiddleware<ApiEnv>(\n async (c, next) => {\n const { method, url } = c.req;\n const requestId = c.get('requestId');\n\n c.var.logService.info({\n source: 'core',\n message: `Recieved API request \"${method} ${url}\" with requestId ${requestId}`,\n });\n const start = Date.now();\n\n await next();\n\n const durationMs = Date.now() - start;\n const statusCode = c.res.status.toString();\n const resultLog = {\n source: 'core',\n message: `Response for API request \"${method} ${url}\" with requestId ${requestId} and status code ${statusCode} in ${durationMs}ms`,\n } as const;\n\n if (statusCode.startsWith('2')) {\n c.var.logService.info(resultLog);\n } else if (statusCode.startsWith('3')) {\n c.var.logService.warn(resultLog);\n } else if (statusCode.startsWith('4') || statusCode.startsWith('5')) {\n c.var.logService.error(resultLog);\n }\n }\n);\n","import type { Schema } from 'hono';\nimport { OpenAPIHono } from '@hono/zod-openapi';\nimport { requestId } from 'hono/request-id';\nimport { requestResponseLogger } from '../middleware/requestResponseLogger.js';\nimport type { Api, ApiEnv } from './types.js';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { cors } from 'hono/cors';\nimport type {\n AssetService,\n CollectionService,\n EntryService,\n LogService,\n ProjectService,\n} from '../../service/index.js';\nimport { createMiddleware } from 'hono/factory';\nimport { trimTrailingSlash } from 'hono/trailing-slash';\n\n/**\n * Creates a new OpenAPIHono router with default settings\n */\nexport function createRouter() {\n return new OpenAPIHono<ApiEnv>({\n /**\n * @see https://github.com/honojs/middleware/tree/main/packages/zod-openapi#a-dry-approach-to-handling-validation-errors\n */\n defaultHook: (result, c) => {\n if (!result.success) {\n return c.json(\n {\n success: result.success,\n error: {\n name: result.error.name,\n issues: result.error.issues,\n },\n },\n 422\n );\n }\n\n return result;\n },\n });\n}\n\n/**\n * Creates a new OpenAPIHono instance, injects services into context and adds error handling\n */\nexport default function createApi(\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n) {\n const api = createRouter();\n\n api\n .use(requestId())\n .use(trimTrailingSlash())\n .use(\n cors({\n origin: ['http://localhost'],\n })\n )\n .use(\n // Register services in context\n createMiddleware<ApiEnv>((c, next) => {\n c.set('logService', logService);\n c.set('projectService', projectService);\n c.set('collectionService', collectionService);\n c.set('entryService', entryService);\n c.set('assetService', assetService);\n return next();\n })\n )\n .use(requestResponseLogger);\n\n api.notFound((c) => {\n return c.json(\n {\n message: `Not Found - ${c.req.path}`,\n },\n 404\n );\n });\n\n api.onError((err, c) => {\n const currentStatus =\n 'status' in err ? err.status : c.newResponse(null).status;\n const statusCode =\n currentStatus !== 200 ? (currentStatus as ContentfulStatusCode) : 500;\n\n return c.json(\n {\n message: err.message,\n stack: err.stack,\n },\n statusCode\n );\n });\n\n return api;\n}\n\nexport function createTestApi<S extends Schema>(\n router: Api<S>,\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n) {\n return createApi(\n logService,\n projectService,\n collectionService,\n entryService,\n assetService\n ).route('/', router);\n}\n","import { z } from '@hono/zod-openapi';\n\n/**\n * All currently supported, BCP 47 compliant language tags\n *\n * The support depends on the tools and libraries we use.\n * We can't support a given language, if there is no support\n * for it from used third parties. Currently, to check if a langauge\n * tag can be added to this list, it needs to be supported by:\n * - DeepL translation API\n *\n * @see https://www.deepl.com/docs-api/other-functions/listing-supported-languages/\n */\nexport const supportedLanguageSchema = z.enum([\n /**\n * Bulgarian\n */\n 'bg', //\n 'cs', // Czech\n 'da', // Danish\n 'de', // German\n 'el', // Greek\n 'en', // (US) English\n 'es', // Spanish\n 'et', // Estonian\n 'fi', // Finnish\n 'fr', // French\n 'hu', // Hungarian\n 'it', // Italian\n 'ja', // Japanese\n 'lt', // Lithuanian\n 'lv', // Latvian\n 'nl', // Dutch\n 'pl', // Polish\n 'pt', // Portuguese\n 'ro', // Romanian\n 'ru', // Russian\n 'sk', // Slovak\n 'sl', // Slovenian\n 'sv', // Swedish\n 'zh', // (Simplified) Chinese\n]);\nexport type SupportedLanguage = z.infer<typeof supportedLanguageSchema>;\n\nexport const supportedIconSchema = z.enum(['home', 'plus', 'foobar']);\nexport type SupportedIcon = z.infer<typeof supportedIconSchema>;\n\nexport const objectTypeSchema = z.enum([\n 'project',\n 'asset',\n 'collection',\n 'entry',\n 'value',\n 'sharedValue',\n]);\nexport type ObjectType = z.infer<typeof objectTypeSchema>;\n\nexport const logLevelSchema = z.enum(['error', 'warn', 'info', 'debug']);\n\nexport const versionSchema = z.string();\n// .refine((version) => {\n// if (Semver.valid(version) !== null) {\n// return true;\n// }\n// return false;\n// }, 'String must follow the Semantic Versioning format (https://semver.org/)');\nexport type Version = z.infer<typeof versionSchema>;\n\nexport const uuidSchema = z.uuid();\nexport type Uuid = z.infer<typeof uuidSchema>;\n\n/**\n * A record that can be used to translate a string value into all supported languages\n */\nexport const translatableStringSchema = z.partialRecord(\n supportedLanguageSchema,\n z.string().trim().min(1)\n);\nexport type TranslatableString = z.infer<typeof translatableStringSchema>;\n\n/**\n * A record that can be used to translate a number value into all supported languages\n */\nexport const translatableNumberSchema = z.partialRecord(\n supportedLanguageSchema,\n z.number()\n);\nexport type TranslatableNumber = z.infer<typeof translatableNumberSchema>;\n\n/**\n * A record that can be used to translate a boolean value into all supported languages\n */\nexport const translatableBooleanSchema = z.partialRecord(\n supportedLanguageSchema,\n z.boolean()\n);\nexport type TranslatableBoolean = z.infer<typeof translatableBooleanSchema>;\n\nexport function translatableArrayOf<T extends z.ZodTypeAny>(schema: T) {\n return z.partialRecord(supportedLanguageSchema, z.array(schema));\n}\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\n\n/**\n * A basic file structure every elek.io file on disk has to follow\n */\nexport const baseFileSchema = z.object({\n /**\n * The object type of the file\n */\n objectType: objectTypeSchema.readonly(),\n /**\n * The ID of the file\n *\n * The ID is part of the files name.\n */\n id: uuidSchema.readonly(),\n /**\n * The datetime of the file being created is set by the service of \"objectType\" while creating it\n */\n created: z.string().datetime().readonly(),\n /**\n * The datetime of the file being updated is set by the service of \"objectType\" while updating it\n */\n updated: z.string().datetime().nullable(),\n});\nexport type BaseFile = z.infer<typeof baseFileSchema>;\n\nexport const fileReferenceSchema = z.object({\n id: uuidSchema,\n extension: z.string().optional(),\n});\nexport type FileReference = z.infer<typeof fileReferenceSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\n\n/**\n * Signature git uses to identify users\n */\nexport const gitSignatureSchema = z.object({\n name: z.string(),\n email: z.string().email(),\n});\nexport type GitSignature = z.infer<typeof gitSignatureSchema>;\n\nexport const gitMessageSchema = z.object({\n method: z.enum(['create', 'update', 'delete', 'upgrade']),\n reference: z.object({\n objectType: objectTypeSchema,\n /**\n * ID of the objectType\n */\n id: uuidSchema,\n /**\n * Only present if the objectType is of \"entry\"\n */\n collectionId: uuidSchema.optional(),\n }),\n});\nexport type GitMessage = z.infer<typeof gitMessageSchema>;\n\nexport const gitTagSchema = z.object({\n id: uuidSchema,\n message: z.string(),\n author: gitSignatureSchema,\n datetime: z.string().datetime(),\n});\nexport type GitTag = z.infer<typeof gitTagSchema>;\n\nexport const gitCommitSchema = z.object({\n /**\n * SHA-1 hash of the commit\n */\n hash: z.string(),\n message: gitMessageSchema,\n author: gitSignatureSchema,\n datetime: z.string().datetime(),\n tag: gitTagSchema.nullable(),\n});\nexport type GitCommit = z.infer<typeof gitCommitSchema>;\n\nexport const gitInitOptionsSchema = z.object({\n /**\n * Use the specified name for the initial branch in the newly created repository. If not specified, fall back to the default name (currently master, but this is subject to change in the future; the name can be customized via the init.defaultBranch configuration variable).\n */\n initialBranch: z.string(),\n});\nexport type GitInitOptions = z.infer<typeof gitInitOptionsSchema>;\n\nexport const gitCloneOptionsSchema = z.object({\n /**\n * Create a shallow clone with a history truncated to the specified number of commits. Implies --single-branch unless --no-single-branch is given to fetch the histories near the tips of all branches. If you want to clone submodules shallowly, also pass --shallow-submodules.\n */\n depth: z.number(),\n /**\n * Clone only the history leading to the tip of a single branch, either specified by the --branch option or the primary branch remote’s HEAD points at. Further fetches into the resulting repository will only update the remote-tracking branch for the branch this option was used for the initial cloning. If the HEAD at the remote did not point at any branch when --single-branch clone was made, no remote-tracking branch is created.\n */\n singleBranch: z.boolean(),\n /**\n * Instead of pointing the newly created HEAD to the branch pointed to by the cloned repository’s HEAD, point to <name> branch instead. In a non-bare repository, this is the branch that will be checked out. --branch can also take tags and detaches the HEAD at that commit in the resulting repository.\n */\n branch: z.string(),\n /**\n * Make a bare Git repository. That is, instead of creating <directory> and placing the administrative files in <directory>`/.git`, make the <directory> itself the $GIT_DIR.\n * Used primarily to copy an existing local repository to a server, where you want to set up the repository as a central point to work with others.\n *\n * The destination path for the cloned repository should end with a .git by convention.\n *\n * @see https://git-scm.com/book/en/v2/Git-on-the-Server-Getting-Git-on-a-Server\n */\n bare: z.boolean(),\n});\nexport type GitCloneOptions = z.infer<typeof gitCloneOptionsSchema>;\n\nexport const gitMergeOptionsSchema = z.object({\n squash: z.boolean(),\n});\nexport type GitMergeOptions = z.infer<typeof gitMergeOptionsSchema>;\n\nexport const gitSwitchOptionsSchema = z.object({\n /**\n * If true, creates a new local branch and then switches to it\n *\n * @see https://git-scm.com/docs/git-switch#Documentation/git-switch.txt---createltnew-branchgt\n */\n isNew: z.boolean().optional(),\n});\nexport type GitSwitchOptions = z.infer<typeof gitSwitchOptionsSchema>;\n\nexport const gitLogOptionsSchema = z.object({\n /**\n * Limit the result to given number of commits\n */\n limit: z.number().optional(),\n /**\n * Only list commits that are between given SHAs or tag names\n *\n * Note that the commits of from and to are not included in the result\n */\n between: z.object({\n /**\n * From the oldest commit\n */\n from: z.string(),\n /**\n * To the newest commit\n *\n * Defaults to the current HEAD\n */\n to: z.string().optional(),\n }),\n /**\n * Only shows commits of given file\n */\n filePath: z.string().optional(),\n});\nexport type GitLogOptions = z.infer<typeof gitLogOptionsSchema>;\n\nexport const createGitTagSchema = gitTagSchema\n .pick({\n message: true,\n })\n .extend({\n path: z.string(),\n hash: z.string().optional(),\n });\nexport type CreateGitTagProps = z.infer<typeof createGitTagSchema>;\n\nexport const readGitTagSchema = z.object({\n path: z.string(),\n id: uuidSchema.readonly(),\n});\nexport type ReadGitTagProps = z.infer<typeof readGitTagSchema>;\n\nexport const deleteGitTagSchema = readGitTagSchema.extend({});\nexport type DeleteGitTagProps = z.infer<typeof deleteGitTagSchema>;\n\nexport const countGitTagsSchema = z.object({\n path: z.string(),\n});\nexport type CountGitTagsProps = z.infer<typeof countGitTagsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\n\nexport const assetFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.asset).readonly(),\n name: z.string(),\n description: z.string(),\n extension: z.string().readonly(),\n mimeType: z.string().readonly(),\n /**\n * Total size in bytes\n */\n size: z.number().readonly(),\n});\nexport type AssetFile = z.infer<typeof assetFileSchema>;\n\nexport const assetSchema = assetFileSchema\n .extend({\n /**\n * Absolute path on this filesystem\n */\n absolutePath: z.string().readonly(),\n /**\n * Commit history of this Asset\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Asset');\nexport type Asset = z.infer<typeof assetSchema>;\n\nexport const assetExportSchema = assetSchema.extend({});\nexport type AssetExport = z.infer<typeof assetExportSchema>;\n\nexport const createAssetSchema = assetFileSchema\n .pick({\n name: true,\n description: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n /**\n * Path of the file to add as a new Asset\n */\n filePath: z.string().readonly(),\n });\nexport type CreateAssetProps = z.infer<typeof createAssetSchema>;\n\nexport const readAssetSchema = assetFileSchema\n .pick({\n id: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n });\nexport type ReadAssetProps = z.infer<typeof readAssetSchema>;\n\nexport const saveAssetSchema = assetFileSchema\n .pick({\n id: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n filePath: z.string().readonly(),\n commitHash: z.string().optional().readonly(),\n });\nexport type SaveAssetProps = z.infer<typeof saveAssetSchema>;\n\nexport const updateAssetSchema = assetFileSchema\n .pick({\n id: true,\n name: true,\n description: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n /**\n * Path of the new file to update the Asset with\n */\n newFilePath: z.string().readonly().optional(),\n });\nexport type UpdateAssetProps = z.infer<typeof updateAssetSchema>;\n\nexport const deleteAssetSchema = assetFileSchema\n .pick({\n id: true,\n extension: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type DeleteAssetProps = z.infer<typeof deleteAssetSchema>;\n\nexport const countAssetsSchema = z.object({ projectId: uuidSchema.readonly() });\nexport type CountAssetsProps = z.infer<typeof countAssetsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport {\n objectTypeSchema,\n translatableArrayOf,\n translatableBooleanSchema,\n translatableNumberSchema,\n translatableStringSchema,\n uuidSchema,\n} from './baseSchema.js';\n\nexport const ValueTypeSchema = z.enum([\n 'string',\n 'number',\n 'boolean',\n 'reference',\n]);\nexport type ValueType = z.infer<typeof ValueTypeSchema>;\n\nexport const valueContentReferenceBase = z.object({\n id: uuidSchema,\n});\n\nexport const valueContentReferenceToAssetSchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.asset),\n });\nexport type ValueContentReferenceToAsset = z.infer<\n typeof valueContentReferenceToAssetSchema\n>;\n\nexport const valueContentReferenceToCollectionSchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.collection),\n });\nexport type ValueContentReferenceToCollection = z.infer<\n typeof valueContentReferenceToCollectionSchema\n>;\n\nexport const valueContentReferenceToEntrySchema =\n valueContentReferenceBase.extend({\n objectType: z.literal(objectTypeSchema.enum.entry),\n });\nexport type ValueContentReferenceToEntry = z.infer<\n typeof valueContentReferenceToEntrySchema\n>;\n\n// export const valueContentReferenceToSharedValueSchema = z.object({\n// referenceObjectType: z.literal(objectTypeSchema.enum.sharedValue),\n// references: z.object({\n// id: uuidSchema,\n// language: supportedLanguageSchema,\n// }),\n// });\n// export type ValueContentReferenceToSharedValue = z.infer<\n// typeof valueContentReferenceToSharedValueSchema\n// >;\n\n// export const sharedValueFileSchema = baseFileWithLanguageSchema.extend({\n// objectType: z.literal(objectTypeSchema.enum.sharedValue).readonly(),\n// valueType: ValueTypeSchema.exclude(['reference']).readonly(),\n// // valueType: ValueTypeSchema.readonly(), @todo do we allow shared Values to reference assets or others?\n// content: z.union([\n// z.string(),\n// z.number(),\n// z.boolean(),\n// z.string().optional(),\n// z.number().optional(),\n// z.boolean().optional(),\n// // valueContentReferenceToAssetSchema, @todo do we allow shared Values to reference assets or others?\n// // valueContentReferenceToSharedValueSchema,\n// ]),\n// });\n// export type SharedValueFile = z.infer<typeof sharedValueFileSchema>;\n\n// export const sharedValueSchema = sharedValueFileSchema.extend({});\n// export type SharedValue = z.infer<typeof sharedValueSchema>;\n\n// export const sharedValueExportSchema = sharedValueSchema.extend({});\n// export type SharedValueExport = z.infer<typeof sharedValueExportSchema>;\n\n// export const resolvedValueContentReferenceToSharedValueSchema =\n// valueContentReferenceToSharedValueSchema.extend({\n// references: z.object({\n// id: uuidSchema,\n// language: supportedLanguageSchema,\n// resolved: sharedValueSchema,\n// }),\n// });\n// export type ResolvedValueContentReferenceToSharedValue = z.infer<\n// typeof resolvedValueContentReferenceToSharedValueSchema\n// >;\n\nexport const valueContentReferenceSchema = z.union([\n valueContentReferenceToAssetSchema,\n valueContentReferenceToCollectionSchema,\n valueContentReferenceToEntrySchema,\n // valueContentReferenceToSharedValueSchema,\n]);\nexport type ValueContentReference = z.infer<typeof valueContentReferenceSchema>;\n\nexport const directValueBaseSchema = z.object({\n objectType: z.literal(objectTypeSchema.enum.value).readonly(),\n fieldDefinitionId: uuidSchema.readonly(),\n});\n\nexport const directStringValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.string).readonly(),\n content: translatableStringSchema,\n});\nexport type DirectStringValue = z.infer<typeof directStringValueSchema>;\n\nexport const directNumberValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.number).readonly(),\n content: translatableNumberSchema,\n});\nexport type DirectNumberValue = z.infer<typeof directNumberValueSchema>;\n\nexport const directBooleanValueSchema = directValueBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.boolean).readonly(),\n content: translatableBooleanSchema,\n});\nexport type DirectBooleanValue = z.infer<typeof directBooleanValueSchema>;\n\nexport const directValueSchema = z.union([\n directStringValueSchema,\n directNumberValueSchema,\n directBooleanValueSchema,\n]);\nexport type DirectValue = z.infer<typeof directValueSchema>;\n\nexport const referencedValueSchema = z.object({\n objectType: z.literal(objectTypeSchema.enum.value).readonly(),\n fieldDefinitionId: uuidSchema.readonly(),\n valueType: z.literal(ValueTypeSchema.enum.reference).readonly(),\n content: translatableArrayOf(valueContentReferenceSchema),\n});\nexport type ReferencedValue = z.infer<typeof referencedValueSchema>;\n\nexport const valueSchema = z.union([directValueSchema, referencedValueSchema]);\nexport type Value = z.infer<typeof valueSchema>;\n\n/**\n * ---\n */\n\n// export const createSharedValueSchema = sharedValueFileSchema\n// .pick({\n// valueType: true,\n// content: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type CreateSharedValueProps = z.infer<typeof createSharedValueSchema>;\n\n// export const readSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type ReadSharedValueProps = z.infer<typeof readSharedValueSchema>;\n\n// export const updateSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// content: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type UpdateSharedValueProps = z.infer<typeof updateSharedValueSchema>;\n\n// export const deleteSharedValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// });\n// export type DeleteSharedValueProps = z.infer<typeof deleteSharedValueSchema>;\n\n/**\n * @todo maybe we need to validate Values and shared Values\n */\n// export const validateValueSchema = sharedValueFileSchema\n// .pick({\n// id: true,\n// language: true,\n// })\n// .extend({\n// projectId: uuidSchema.readonly(),\n// definition: FieldDefinitionSchema.readonly(),\n// });\n// export type ValidateValueProps = z.infer<typeof validateValueSchema>;\n\n// export const countValuesSchema = z.object({ projectId: uuidSchema.readonly() });\n// export type CountValuesProps = z.infer<typeof countValuesSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { objectTypeSchema, uuidSchema } from './baseSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\nimport { valueSchema } from './valueSchema.js';\n\nexport const entryFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.entry).readonly(),\n values: z.array(valueSchema),\n});\nexport type EntryFile = z.infer<typeof entryFileSchema>;\n\nexport const entrySchema = entryFileSchema\n .extend({\n /**\n * Commit history of this Entry\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Entry');\nexport type Entry = z.infer<typeof entrySchema>;\n\nexport const entryExportSchema = entrySchema.extend({});\nexport type EntryExport = z.infer<typeof entryExportSchema>;\n\nexport const createEntrySchema = entryFileSchema\n .omit({\n id: true,\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n values: z.array(valueSchema),\n });\nexport type CreateEntryProps = z.infer<typeof createEntrySchema>;\n\nexport const readEntrySchema = z.object({\n id: uuidSchema.readonly(),\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadEntryProps = z.infer<typeof readEntrySchema>;\n\nexport const updateEntrySchema = entryFileSchema\n .omit({\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n });\nexport type UpdateEntryProps = z.infer<typeof updateEntrySchema>;\n\nexport const deleteEntrySchema = readEntrySchema.extend({});\nexport type DeleteEntryProps = z.infer<typeof deleteEntrySchema>;\n\nexport const countEntriesSchema = z.object({\n projectId: uuidSchema.readonly(),\n collectionId: uuidSchema.readonly(),\n});\nexport type CountEntriesProps = z.infer<typeof countEntriesSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { translatableStringSchema, uuidSchema } from './baseSchema.js';\nimport { ValueTypeSchema } from './valueSchema.js';\n\nexport const FieldTypeSchema = z.enum([\n // String Values\n 'text',\n 'textarea',\n 'email',\n // 'password', @todo maybe if there is a usecase\n 'url',\n 'ipv4',\n 'date',\n 'time',\n 'datetime',\n 'telephone',\n // Number Values\n 'number',\n 'range',\n // Boolean Values\n 'toggle',\n // Reference Values\n 'asset',\n 'entry',\n // 'sharedValue', // @todo\n]);\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\nexport const FieldWidthSchema = z.enum(['12', '6', '4', '3']);\n\nexport const FieldDefinitionBaseSchema = z.object({\n id: uuidSchema.readonly(),\n label: translatableStringSchema,\n description: translatableStringSchema.nullable(),\n isRequired: z.boolean(),\n isDisabled: z.boolean(),\n isUnique: z.boolean(),\n inputWidth: FieldWidthSchema,\n});\nexport type FieldDefinitionBase = z.infer<typeof FieldDefinitionBaseSchema>;\n\n/**\n * String based Field definitions\n */\n\nexport const StringFieldDefinitionBaseSchema = FieldDefinitionBaseSchema.extend(\n {\n valueType: z.literal(ValueTypeSchema.enum.string),\n defaultValue: z.string().nullable(),\n }\n);\n\nexport const textFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.text),\n min: z.number().nullable(),\n max: z.number().nullable(),\n }\n);\nexport type TextFieldDefinition = z.infer<typeof textFieldDefinitionSchema>;\n\nexport const textareaFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.textarea),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type TextareaFieldDefinition = z.infer<\n typeof textareaFieldDefinitionSchema\n>;\n\nexport const emailFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.email),\n defaultValue: z.email().nullable(),\n });\nexport type EmailFieldDefinition = z.infer<typeof emailFieldDefinitionSchema>;\n\n// @todo why should we support password Values? Client saves it in clear text anyways\n// export const passwordFieldDefinitionSchema =\n// StringFieldDefinitionBaseSchema.extend({\n// fieldType: z.literal(FieldfieldTypeSchema.enum.password),\n// });\n\nexport const urlFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.url),\n defaultValue: z.url().nullable(),\n});\nexport type UrlFieldDefinition = z.infer<typeof urlFieldDefinitionSchema>;\n\nexport const ipv4FieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.ipv4),\n defaultValue: z.ipv4().nullable(),\n }\n);\nexport type Ipv4FieldDefinition = z.infer<typeof ipv4FieldDefinitionSchema>;\n\nexport const dateFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.date),\n defaultValue: z.iso.date().nullable(),\n }\n);\nexport type DateFieldDefinition = z.infer<typeof dateFieldDefinitionSchema>;\n\nexport const timeFieldDefinitionSchema = StringFieldDefinitionBaseSchema.extend(\n {\n fieldType: z.literal(FieldTypeSchema.enum.time),\n defaultValue: z.iso.time().nullable(),\n }\n);\nexport type TimeFieldDefinition = z.infer<typeof timeFieldDefinitionSchema>;\n\nexport const datetimeFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.datetime),\n defaultValue: z.iso.datetime().nullable(),\n });\nexport type DatetimeFieldDefinition = z.infer<\n typeof datetimeFieldDefinitionSchema\n>;\n\nexport const telephoneFieldDefinitionSchema =\n StringFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.telephone),\n defaultValue: z.e164().nullable(),\n });\nexport type TelephoneFieldDefinition = z.infer<\n typeof telephoneFieldDefinitionSchema\n>;\n\nexport const stringFieldDefinitionSchema = z.union([\n textFieldDefinitionSchema,\n textareaFieldDefinitionSchema,\n emailFieldDefinitionSchema,\n urlFieldDefinitionSchema,\n ipv4FieldDefinitionSchema,\n dateFieldDefinitionSchema,\n timeFieldDefinitionSchema,\n datetimeFieldDefinitionSchema,\n telephoneFieldDefinitionSchema,\n]);\nexport type StringFieldDefinition = z.infer<typeof stringFieldDefinitionSchema>;\n\n/**\n * Number based Field definitions\n */\n\nexport const NumberFieldDefinitionBaseSchema = FieldDefinitionBaseSchema.extend(\n {\n valueType: z.literal(ValueTypeSchema.enum.number),\n min: z.number().nullable(),\n max: z.number().nullable(),\n isUnique: z.literal(false),\n defaultValue: z.number().nullable(),\n }\n);\n\nexport const numberFieldDefinitionSchema =\n NumberFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.number),\n });\nexport type NumberFieldDefinition = z.infer<typeof numberFieldDefinitionSchema>;\n\nexport const rangeFieldDefinitionSchema =\n NumberFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.range),\n // Overwrite from nullable to required because a range needs min, max and default to work and is required, since it always returns a number\n isRequired: z.literal(true),\n min: z.number(),\n max: z.number(),\n defaultValue: z.number(),\n });\nexport type RangeFieldDefinition = z.infer<typeof rangeFieldDefinitionSchema>;\n\n/**\n * Boolean based Field definitions\n */\n\nexport const BooleanFieldDefinitionBaseSchema =\n FieldDefinitionBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.boolean),\n // Overwrite from nullable to required because a boolean needs a default to work and is required, since it always is either true or false\n isRequired: z.literal(true),\n defaultValue: z.boolean(),\n isUnique: z.literal(false),\n });\n\nexport const toggleFieldDefinitionSchema =\n BooleanFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.toggle),\n });\nexport type ToggleFieldDefinition = z.infer<typeof toggleFieldDefinitionSchema>;\n\n/**\n * Reference based Field definitions\n */\n\nexport const ReferenceFieldDefinitionBaseSchema =\n FieldDefinitionBaseSchema.extend({\n valueType: z.literal(ValueTypeSchema.enum.reference),\n });\n\nexport const assetFieldDefinitionSchema =\n ReferenceFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.asset),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type AssetFieldDefinition = z.infer<typeof assetFieldDefinitionSchema>;\n\nexport const entryFieldDefinitionSchema =\n ReferenceFieldDefinitionBaseSchema.extend({\n fieldType: z.literal(FieldTypeSchema.enum.entry),\n ofCollections: z.array(uuidSchema),\n min: z.number().nullable(),\n max: z.number().nullable(),\n });\nexport type EntryFieldDefinition = z.infer<typeof entryFieldDefinitionSchema>;\n\n// export const sharedValueDefinitionSchema =\n// ReferenceValueDefinitionBaseSchema.extend({\n// fieldType: z.literal(ValueInputTypeSchema.enum.sharedValue),\n// // The shared Value can have any of the direct types\n// // but not any reference itself (a shared Value cannot have a reference to another shared Value / Asset or any other future reference)\n// sharedValueType: z.union([\n// z.literal(ValueTypeSchema.enum.boolean),\n// z.literal(ValueTypeSchema.enum.number),\n// z.literal(ValueTypeSchema.enum.string),\n// ]),\n// });\n// export type SharedValueValueDefinition = z.infer<\n// typeof sharedValueDefinitionSchema\n// >;\n\nexport const fieldDefinitionSchema = z.union([\n stringFieldDefinitionSchema,\n numberFieldDefinitionSchema,\n rangeFieldDefinitionSchema,\n toggleFieldDefinitionSchema,\n assetFieldDefinitionSchema,\n entryFieldDefinitionSchema,\n // sharedValueDefinitionSchema,\n]);\nexport type FieldDefinition = z.infer<typeof fieldDefinitionSchema>;\n","import { z } from '@hono/zod-openapi';\nimport {\n objectTypeSchema,\n supportedIconSchema,\n translatableStringSchema,\n uuidSchema,\n} from './baseSchema.js';\nimport { entryExportSchema } from './entrySchema.js';\nimport { fieldDefinitionSchema } from './fieldSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema } from './gitSchema.js';\n\nexport const collectionFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.collection).readonly(),\n name: z.object({\n singular: translatableStringSchema,\n plural: translatableStringSchema,\n }),\n slug: z.object({\n singular: z.string(),\n plural: z.string(),\n }),\n description: translatableStringSchema,\n icon: supportedIconSchema,\n fieldDefinitions: z.array(fieldDefinitionSchema),\n});\nexport type CollectionFile = z.infer<typeof collectionFileSchema>;\n\nexport const collectionSchema = collectionFileSchema\n .extend({\n /**\n * Commit history of this Collection\n */\n history: z.array(gitCommitSchema),\n })\n .openapi('Collection');\nexport type Collection = z.infer<typeof collectionSchema>;\n\nexport const collectionExportSchema = collectionSchema.extend({\n entries: z.array(entryExportSchema),\n});\nexport type CollectionExport = z.infer<typeof collectionExportSchema>;\n\nexport const createCollectionSchema = collectionFileSchema\n .omit({\n id: true,\n objectType: true,\n created: true,\n updated: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type CreateCollectionProps = z.infer<typeof createCollectionSchema>;\n\nexport const readCollectionSchema = z.object({\n id: uuidSchema.readonly(),\n projectId: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadCollectionProps = z.infer<typeof readCollectionSchema>;\n\nexport const updateCollectionSchema = collectionFileSchema\n .pick({\n id: true,\n name: true,\n slug: true,\n description: true,\n icon: true,\n fieldDefinitions: true,\n })\n .extend({\n projectId: uuidSchema.readonly(),\n });\nexport type UpdateCollectionProps = z.infer<typeof updateCollectionSchema>;\n\nexport const deleteCollectionSchema = readCollectionSchema.extend({});\nexport type DeleteCollectionProps = z.infer<typeof deleteCollectionSchema>;\n\nexport const countCollectionsSchema = z.object({\n projectId: uuidSchema.readonly(),\n});\nexport type CountCollectionsProps = z.infer<typeof countCollectionsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { logLevelSchema } from './baseSchema.js';\n\n/**\n * Options that can be passed to elek.io core\n */\nexport const elekIoCoreOptionsSchema = z.object({\n log: z.object({\n /**\n * The lowest level that should be logged\n *\n * @default 'info'\n */\n level: logLevelSchema,\n }),\n file: z.object({\n /**\n * If set to true, caches files in memory to speed up access\n *\n * @default true\n */\n cache: z.boolean(),\n }),\n});\nexport type ElekIoCoreOptions = z.infer<typeof elekIoCoreOptionsSchema>;\n\nexport const constructorElekIoCoreSchema = elekIoCoreOptionsSchema\n .partial({\n log: true,\n file: true,\n })\n .optional();\nexport type ConstructorElekIoCoreProps = z.infer<\n typeof constructorElekIoCoreSchema\n>;\n","import { z } from '@hono/zod-openapi';\nimport { assetExportSchema } from './assetSchema.js';\nimport {\n objectTypeSchema,\n supportedLanguageSchema,\n uuidSchema,\n versionSchema,\n} from './baseSchema.js';\nimport { collectionExportSchema } from './collectionSchema.js';\nimport { baseFileSchema } from './fileSchema.js';\nimport { gitCommitSchema, gitSwitchOptionsSchema } from './gitSchema.js';\n\nexport const projectStatusSchema = z.enum(['foo', 'bar', 'todo']);\nexport type ProjectStatus = z.infer<typeof projectStatusSchema>;\n\nexport const projectSettingsSchema = z.object({\n language: z.object({\n default: supportedLanguageSchema,\n supported: z.array(supportedLanguageSchema),\n }),\n});\nexport type ProjectSettings = z.infer<typeof projectSettingsSchema>;\n\nexport const projectFolderSchema = z.enum([\n 'assets',\n 'collections',\n 'shared-values',\n 'lfs',\n // 'logs',\n // 'public',\n // 'theme',\n]);\nexport type ProjectFolder = z.infer<typeof projectFolderSchema>;\n\nexport const projectBranchSchema = z.enum(['production', 'work']);\nexport type ProjectBranch = z.infer<typeof projectBranchSchema>;\n\nexport const projectFileSchema = baseFileSchema.extend({\n objectType: z.literal(objectTypeSchema.enum.project).readonly(),\n coreVersion: versionSchema,\n name: z.string().trim().min(1),\n description: z.string().trim().min(1),\n version: versionSchema,\n status: projectStatusSchema,\n settings: projectSettingsSchema,\n});\nexport type ProjectFile = z.infer<typeof projectFileSchema>;\n\nexport const projectSchema = projectFileSchema\n .extend({\n remoteOriginUrl: z.string().nullable().openapi({\n description: 'URL of the remote Git repository',\n }),\n history: z.array(gitCommitSchema).openapi({\n description: 'Commit history of this Project',\n }),\n fullHistory: z.array(gitCommitSchema).openapi({\n description:\n 'Full commit history of this Project including all Assets, Collections, Entries and other files',\n }),\n })\n .openapi('Project');\nexport type Project = z.infer<typeof projectSchema>;\n\nexport const migrateProjectSchema = projectFileSchema\n .pick({\n id: true,\n coreVersion: true,\n })\n .loose();\nexport type MigrateProjectProps = z.infer<typeof migrateProjectSchema>;\n\nexport const projectExportSchema = projectSchema.extend({\n assets: z.array(assetExportSchema),\n collections: z.array(collectionExportSchema),\n});\nexport type ProjectExport = z.infer<typeof projectExportSchema>;\n\nexport const createProjectSchema = projectSchema.pick({\n name: true,\n description: true,\n settings: true,\n});\nexport type CreateProjectProps = z.infer<typeof createProjectSchema>;\n\nexport const readProjectSchema = z.object({\n id: uuidSchema.readonly(),\n commitHash: z.string().optional().readonly(),\n});\nexport type ReadProjectProps = z.infer<typeof readProjectSchema>;\n\nexport const updateProjectSchema = projectSchema.pick({\n id: true,\n name: true,\n description: true,\n settings: true,\n});\nexport type UpdateProjectProps = z.infer<typeof updateProjectSchema>;\n\nexport const upgradeProjectSchema = z.object({\n id: uuidSchema.readonly(),\n /**\n * Force the upgrade even if the Project is up-to-date\n */\n force: z.boolean().optional(),\n});\nexport type UpgradeProjectProps = z.infer<typeof upgradeProjectSchema>;\n\nexport const deleteProjectSchema = readProjectSchema.extend({\n force: z.boolean().optional(),\n});\nexport type DeleteProjectProps = z.infer<typeof deleteProjectSchema>;\n\nexport const projectUpgradeSchema = z.object({\n /**\n * The Core version the Project will be upgraded to\n */\n to: versionSchema.readonly(),\n /**\n * Function that will be executed in the process of upgrading a Project\n */\n run: z.function({\n input: [projectFileSchema],\n output: z.promise(z.void()),\n }),\n});\nexport type ProjectUpgrade = z.infer<typeof projectUpgradeSchema>;\n\nexport const cloneProjectSchema = z.object({\n url: z.string(),\n});\nexport type CloneProjectProps = z.infer<typeof cloneProjectSchema>;\n\nexport const listBranchesProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type ListBranchesProjectProps = z.infer<\n typeof listBranchesProjectSchema\n>;\n\nexport const currentBranchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type CurrentBranchProjectProps = z.infer<\n typeof currentBranchProjectSchema\n>;\n\nexport const switchBranchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n branch: z.string(),\n options: gitSwitchOptionsSchema.optional(),\n});\nexport type SwitchBranchProjectProps = z.infer<\n typeof switchBranchProjectSchema\n>;\n\nexport const getRemoteOriginUrlProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type GetRemoteOriginUrlProjectProps = z.infer<\n typeof getRemoteOriginUrlProjectSchema\n>;\n\nexport const setRemoteOriginUrlProjectSchema = z.object({\n id: uuidSchema.readonly(),\n url: z.string(),\n});\nexport type SetRemoteOriginUrlProjectProps = z.infer<\n typeof setRemoteOriginUrlProjectSchema\n>;\n\nexport const getChangesProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type GetChangesProjectProps = z.infer<typeof getChangesProjectSchema>;\n\nexport const synchronizeProjectSchema = z.object({\n id: uuidSchema.readonly(),\n});\nexport type SynchronizeProjectProps = z.infer<typeof synchronizeProjectSchema>;\n\nexport const searchProjectSchema = z.object({\n id: uuidSchema.readonly(),\n query: z.string(),\n language: supportedLanguageSchema,\n type: z.array(objectTypeSchema).optional(),\n});\nexport type SearchProjectProps = z.infer<typeof searchProjectSchema>;\n","/**\n * Dynamic zod schema generation\n *\n * Altough everything is already strictly typed, a type of string might not be an email or text of a certain length.\n * To validate this, we need to generate zod schemas based on Field definitions the user created.\n */\n\nimport { z } from '@hono/zod-openapi';\nimport { supportedLanguageSchema } from './baseSchema.js';\nimport {\n createEntrySchema,\n entrySchema,\n updateEntrySchema,\n} from './entrySchema.js';\nimport type {\n AssetFieldDefinition,\n EntryFieldDefinition,\n FieldDefinition,\n NumberFieldDefinition,\n RangeFieldDefinition,\n StringFieldDefinition,\n} from './fieldSchema.js';\nimport { FieldTypeSchema } from './fieldSchema.js';\nimport {\n directBooleanValueSchema,\n directNumberValueSchema,\n directStringValueSchema,\n referencedValueSchema,\n valueContentReferenceToAssetSchema,\n valueContentReferenceToEntrySchema,\n ValueTypeSchema,\n} from './valueSchema.js';\n\n/**\n * Boolean Values are always either true or false, so we don't need the Field definition here\n */\nfunction getBooleanValueContentSchemaFromFieldDefinition() {\n return z.boolean();\n}\n\n/**\n * Number Values can have min and max values and can be required or not\n */\nfunction getNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition: NumberFieldDefinition | RangeFieldDefinition\n) {\n let schema = z.number();\n\n if (fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n if (fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n if (fieldDefinition.isRequired === false) {\n return schema.nullable();\n }\n\n return schema;\n}\n\n/**\n * String Values can have different formats (email, url, ipv4, date, time, ...)\n * and can have min and max length and can be required or not\n */\nfunction getStringValueContentSchemaFromFieldDefinition(\n fieldDefinition: StringFieldDefinition\n) {\n let schema = null;\n\n switch (fieldDefinition.fieldType) {\n case FieldTypeSchema.enum.email:\n schema = z.email();\n break;\n case FieldTypeSchema.enum.url:\n schema = z.url();\n break;\n case FieldTypeSchema.enum.ipv4:\n schema = z.ipv4();\n break;\n case FieldTypeSchema.enum.date:\n schema = z.iso.date();\n break;\n case FieldTypeSchema.enum.time:\n schema = z.iso.time();\n break;\n case FieldTypeSchema.enum.datetime:\n schema = z.iso.datetime();\n break;\n case FieldTypeSchema.enum.telephone:\n schema = z.e164();\n break;\n case FieldTypeSchema.enum.text:\n case FieldTypeSchema.enum.textarea:\n schema = z.string().trim();\n break;\n }\n\n if ('min' in fieldDefinition && fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n if ('max' in fieldDefinition && fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n if (fieldDefinition.isRequired === false) {\n return schema.nullable();\n }\n\n return schema.min(1); // @see https://github.com/colinhacks/zod/issues/2466\n}\n\n/**\n * Reference Values can reference either Assets or Entries (or Shared Values in the future)\n * and can have min and max number of references and can be required or not\n */\nfunction getReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition: AssetFieldDefinition | EntryFieldDefinition // | SharedValueFieldDefinition\n) {\n let schema;\n\n switch (fieldDefinition.fieldType) {\n case FieldTypeSchema.enum.asset:\n {\n schema = z.array(valueContentReferenceToAssetSchema);\n }\n break;\n case FieldTypeSchema.enum.entry:\n {\n schema = z.array(valueContentReferenceToEntrySchema);\n }\n break;\n // case ValueInputTypeSchema.enum.sharedValue: {\n // let schema = valueContentReferenceToSharedValueSchema.extend({}); // Deep copy to not overwrite the base schema\n // if (definition.isRequired) {\n // const requiredReferences = schema.shape.references.min(\n // 1,\n // 'shared.assetValueRequired'\n // );\n // schema = schema.extend({\n // references: requiredReferences,\n // });\n // }\n // return valueContentReferenceToSharedValueSchema;\n // }\n }\n\n if (fieldDefinition.isRequired) {\n schema = schema.min(1);\n }\n\n if (fieldDefinition.min) {\n schema = schema.min(fieldDefinition.min);\n }\n\n if (fieldDefinition.max) {\n schema = schema.max(fieldDefinition.max);\n }\n\n return schema;\n}\n\nexport function getTranslatableStringValueContentSchemaFromFieldDefinition(\n fieldDefinition: StringFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getStringValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\nexport function getTranslatableNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition: NumberFieldDefinition | RangeFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getNumberValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\nexport function getTranslatableBooleanValueContentSchemaFromFieldDefinition() {\n return z.partialRecord(\n supportedLanguageSchema,\n getBooleanValueContentSchemaFromFieldDefinition()\n );\n}\n\nexport function getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition: AssetFieldDefinition | EntryFieldDefinition\n) {\n return z.partialRecord(\n supportedLanguageSchema,\n getReferenceValueContentSchemaFromFieldDefinition(fieldDefinition)\n );\n}\n\n/**\n * Generates a zod schema to check a Value based on given Field definition\n */\nexport function getValueSchemaFromFieldDefinition(\n fieldDefinition: FieldDefinition\n) {\n switch (fieldDefinition.valueType) {\n case ValueTypeSchema.enum.boolean:\n return directBooleanValueSchema.extend({\n content: getTranslatableBooleanValueContentSchemaFromFieldDefinition(),\n });\n case ValueTypeSchema.enum.number:\n return directNumberValueSchema.extend({\n content:\n getTranslatableNumberValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n case ValueTypeSchema.enum.string:\n return directStringValueSchema.extend({\n content:\n getTranslatableStringValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n case ValueTypeSchema.enum.reference:\n return referencedValueSchema.extend({\n content:\n getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDefinition\n ),\n });\n default:\n throw new Error(\n // @ts-expect-error Code cannot be reached, but if we add a new ValueType and forget to update this function, we want to be notified about it\n `Error generating schema for unsupported ValueType \"${fieldDefinition.valueType}\"`\n );\n }\n}\n\n/**\n * Generates a schema for an Entry based on the given Field definitions and Values\n */\nexport function getEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...entrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n\n/**\n * Generates a schema for creating a new Entry based on the given Field definitions and Values\n */\nexport function getCreateEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...createEntrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n\n/**\n * Generates a schema for updating an existing Entry based on the given Field definitions and Values\n */\nexport function getUpdateEntrySchemaFromFieldDefinitions(\n fieldDefinitions: FieldDefinition[]\n) {\n const valueSchemas = fieldDefinitions.map((fieldDefinition) => {\n return getValueSchemaFromFieldDefinition(fieldDefinition);\n });\n\n return z.object({\n ...updateEntrySchema.shape,\n values: z.tuple(\n valueSchemas as [\n (typeof valueSchemas)[number],\n ...(typeof valueSchemas)[number][],\n ] // At least one element is required in a tuple\n ),\n });\n}\n","import { z } from '@hono/zod-openapi';\nimport { uuidSchema } from './baseSchema.js';\n\nexport const serviceTypeSchema = z.enum([\n 'Git',\n 'GitTag',\n 'User',\n 'Project',\n 'Asset',\n 'JsonFile',\n 'Search',\n 'Collection',\n 'Entry',\n 'Value',\n]);\nexport type ServiceType = z.infer<typeof serviceTypeSchema>;\n\nexport interface PaginatedList<T> {\n total: number;\n limit: number;\n offset: number;\n list: T[];\n}\n\nexport function paginatedListOf<T extends z.ZodTypeAny>(schema: T) {\n return z.object({\n total: z.number(),\n limit: z.number(),\n offset: z.number(),\n list: z.array(schema),\n });\n}\n\nexport interface PaginationOptions {\n limit: number;\n offset: number;\n}\n\n/**\n * Implements create, read, update and delete methods\n */\nexport interface CrudService<T> {\n create: (props: never) => Promise<T>;\n read: (props: never) => Promise<T>;\n update: (props: never) => Promise<T>;\n delete: (props: never) => Promise<void>;\n}\n\n/**\n * Implements list and count methods additionally\n * to create, read, update and delete\n */\nexport interface CrudServiceWithListCount<T> extends CrudService<T> {\n /**\n * Returns a list of this services objects\n *\n * Does not return objects where the schema validation fails.\n * If that is the case, upgrade the Client and then Project to the latest version.\n */\n list: (...props: never[]) => Promise<PaginatedList<T>>;\n /**\n * Returns the total number of this services objects\n */\n count: (...props: never[]) => Promise<number>;\n}\n\nconst listSchema = z.object({\n projectId: uuidSchema,\n limit: z.number().optional(),\n offset: z.number().optional(),\n});\n\nexport const listCollectionsSchema = listSchema;\nexport type ListCollectionsProps = z.infer<typeof listCollectionsSchema>;\n\nexport const listEntriesSchema = listSchema.extend({\n collectionId: uuidSchema,\n});\nexport type ListEntriesProps = z.infer<typeof listEntriesSchema>;\n\nexport const listAssetsSchema = listSchema;\nexport type ListAssetsProps = z.infer<typeof listAssetsSchema>;\n\n// export const listSharedValuesSchema = listSchema(sharedValueSchema);\n// export type ListSharedValuesProps = z.infer<typeof listSharedValuesSchema>;\n\nexport const listProjectsSchema = listSchema.omit({\n projectId: true,\n});\nexport type ListProjectsProps = z.infer<typeof listProjectsSchema>;\n\nexport const listGitTagsSchema = z.object({\n path: z.string(),\n});\nexport type ListGitTagsProps = z.infer<typeof listGitTagsSchema>;\n","import { z } from '@hono/zod-openapi';\nimport { supportedLanguageSchema, uuidSchema } from './baseSchema.js';\nimport { gitSignatureSchema } from './gitSchema.js';\n\nexport const UserTypeSchema = z.enum(['local', 'cloud']);\n\nexport const baseUserSchema = gitSignatureSchema.extend({\n userType: UserTypeSchema,\n language: supportedLanguageSchema,\n localApi: z.object({\n /**\n * If set to true the local API is started whenever Core is initialized\n */\n isEnabled: z.boolean(),\n /**\n * The port the local API uses\n */\n port: z.number(),\n }),\n});\nexport type BaseUser = z.infer<typeof baseUserSchema>;\n\nexport const localUserSchema = baseUserSchema.extend({\n userType: z.literal(UserTypeSchema.enum.local),\n});\nexport type LocalUser = z.infer<typeof localUserSchema>;\n\nexport const cloudUserSchema = baseUserSchema.extend({\n userType: z.literal(UserTypeSchema.enum.cloud),\n id: uuidSchema,\n});\nexport type CloudUser = z.infer<typeof cloudUserSchema>;\n\nexport const userFileSchema = z.union([localUserSchema, cloudUserSchema]);\nexport type UserFile = z.infer<typeof userFileSchema>;\n\nexport const userSchema = userFileSchema;\nexport type User = z.infer<typeof userSchema>;\n\nexport const setUserSchema = userSchema;\nexport type SetUserProps = z.infer<typeof setUserSchema>;\n","import { z } from 'zod';\nimport { uuidSchema } from './baseSchema.js';\n\nconst outDirSchema = z.string().default('./.elek.io');\nconst languageSchema = z.enum(['ts', 'js']).default('ts');\nconst formatSchema = z.enum(['esm', 'cjs']).default('esm');\nconst targetSchema = z\n .enum([\n 'es3',\n 'es5',\n 'es6',\n 'es2015',\n 'es2016',\n 'es2017',\n 'es2018',\n 'es2019',\n 'es2020',\n 'es2021',\n 'es2022',\n 'es2023',\n 'es2024',\n 'esnext',\n ])\n .default('es2020');\nconst projectsSchema = z\n .string()\n .default('all')\n .transform((value) => {\n if (value === 'all') {\n return 'all';\n }\n\n return value.split(',').map((v) => uuidSchema.parse(v.trim()));\n });\nconst generateApiClientOptionsSchema = z.object({\n watch: z.boolean().default(false),\n});\nconst exportProjectsOptionsSchema = generateApiClientOptionsSchema.extend({\n watch: z.boolean().default(false),\n});\n\nexport const generateApiClientSchema = z.object({\n outDir: outDirSchema,\n language: languageSchema,\n format: formatSchema,\n target: targetSchema,\n options: generateApiClientOptionsSchema,\n});\nexport type GenerateApiClientProps = z.infer<typeof generateApiClientSchema>;\n\nconst portSchema = z\n .string()\n .default('31310')\n .transform((value, context) => {\n try {\n const parsed = parseInt(value);\n\n return parsed;\n } catch (_error) {\n context.addIssue({\n code: 'custom',\n message: 'Invalid port number',\n input: value,\n });\n\n // this is a special constant with type `never`\n // returning it lets you exit the transform without impacting the inferred return type\n return z.NEVER;\n }\n });\n\nexport const apiStartSchema = z.object({\n port: portSchema,\n});\nexport type ApiStartProps = z.infer<typeof apiStartSchema>;\n\nexport const exportSchema = z.object({\n outDir: outDirSchema,\n projects: projectsSchema,\n template: z.enum(['nested', 'separate']).default('nested'),\n options: exportProjectsOptionsSchema,\n});\nexport type ExportProps = z.infer<typeof exportSchema>;\n","import { z } from '@hono/zod-openapi';\n\nexport const logSourceSchema = z.enum(['core', 'desktop']);\nexport type LogSource = z.infer<typeof logSourceSchema>;\n\nexport const logSchema = z.object({\n source: logSourceSchema,\n message: z.string(),\n /**\n * Additional metadata for the log entry\n *\n * @example { userId: '12345', action: 'login' }\n */\n meta: z.record(z.string(), z.unknown()).optional(),\n});\nexport type LogProps = z.infer<typeof logSchema>;\n\nexport const logConsoleTransportSchema = logSchema.extend({\n timestamp: z.string(),\n level: z.string(),\n});\nexport type LogConsoleTransportProps = z.infer<\n typeof logConsoleTransportSchema\n>;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n paginatedListOf,\n projectSchema,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Projects',\n description: 'Lists all Projects you currently have access to',\n method: 'get',\n path: '/',\n tags,\n request: {\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: 15,\n description: 'The maximum number of Projects to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: 0,\n description:\n 'The number of Projects to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(projectSchema),\n },\n },\n description: 'A list of Projects you have access to',\n },\n },\n }),\n async (c) => {\n const { limit, offset } = c.req.valid('query');\n const projects = await c.var.projectService.list({ limit, offset });\n\n return c.json(projects, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Projects',\n description: 'Counts all Projects you currently have access to',\n method: 'get',\n path: '/count',\n tags,\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Projects you have access to',\n },\n },\n }),\n async (c) => {\n const count = await c.var.projectService.count();\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Project',\n description: 'Retrieve a Project by ID',\n method: 'get',\n path: '/{projectId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: projectSchema,\n },\n },\n description: 'The requested Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const project = await c.var.projectService.read({ id: projectId });\n\n return c.json(project, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n collectionSchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Collections',\n description: 'Lists all Collections of the given Project',\n method: 'get',\n path: '/{projectId}/collections',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Collections to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Collections to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(collectionSchema),\n },\n },\n description: 'A list of Collections for the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const collections = await c.var.collectionService.list({\n projectId,\n limit,\n offset,\n });\n\n return c.json(collections, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Collections',\n description: 'Counts all Collections of the given Project',\n method: 'get',\n path: '/{projectId}/collections/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Collections of the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const count = await c.var.collectionService.count({ projectId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Collection',\n description: 'Retrieve a Collection by ID',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: collectionSchema,\n },\n },\n description: 'The requested Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const collection = await c.var.collectionService.read({\n projectId,\n id: collectionId,\n });\n\n return c.json(collection, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n entrySchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Entries',\n description: 'Lists all Entries of the given Projects Collection',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Entries to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Entries to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(entrySchema),\n },\n },\n description: 'A list of Entries for the given Projects Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const entries = await c.var.entryService.list({\n projectId,\n collectionId,\n limit,\n offset,\n });\n\n return c.json(entries, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Entries',\n description: 'Counts all Entries of the given Projects Collection',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Entries of the given Projects Collection',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId } = c.req.valid('param');\n const count = await c.var.entryService.count({ projectId, collectionId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Entry',\n description: 'Retrieve an Entry by ID',\n method: 'get',\n path: '/{projectId}/collections/{collectionId}/entries/{entryId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n collectionId: uuidSchema.openapi({\n param: {\n name: 'collectionId',\n in: 'path',\n },\n }),\n entryId: uuidSchema.openapi({\n param: {\n name: 'entryId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: entrySchema,\n },\n },\n description: 'The requested Entry',\n },\n },\n }),\n async (c) => {\n const { projectId, collectionId, entryId } = c.req.valid('param');\n const entry = await c.var.entryService.read({\n projectId,\n collectionId,\n id: entryId,\n });\n\n return c.json(entry, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport { createRoute, z } from '@hono/zod-openapi';\nimport {\n assetSchema,\n paginatedListOf,\n uuidSchema,\n} from '../../../../schema/index.js';\n\nconst tags = ['Content API v1'];\n\nconst router = createRouter()\n .openapi(\n createRoute({\n summary: 'List Assets',\n description: 'Lists all Assets of the given Project',\n method: 'get',\n path: '/{projectId}/assets',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n query: z.object({\n limit: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '15',\n description: 'The maximum number of Assets to return',\n }),\n offset: z.string().pipe(z.coerce.number()).optional().openapi({\n default: '0',\n description:\n 'The number of Assets to skip before starting to collect the result set',\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: paginatedListOf(assetSchema),\n },\n },\n description: 'A list of Assets for the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const { limit, offset } = c.req.valid('query');\n const assets = await c.var.assetService.list({\n projectId,\n limit,\n offset,\n });\n\n return c.json(assets, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Count Assets',\n description: 'Counts all Assets of the given Project',\n method: 'get',\n path: '/{projectId}/assets/count',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: z.number(),\n },\n },\n description: 'The number of Assets of the given Project',\n },\n },\n }),\n async (c) => {\n const { projectId } = c.req.valid('param');\n const count = await c.var.assetService.count({ projectId });\n\n return c.json(count, 200);\n }\n )\n\n .openapi(\n createRoute({\n summary: 'Get one Asset',\n description: 'Retrieve an Asset by ID',\n method: 'get',\n path: '/{projectId}/assets/{assetId}',\n tags,\n request: {\n params: z.object({\n projectId: uuidSchema.openapi({\n param: {\n name: 'projectId',\n in: 'path',\n },\n }),\n assetId: uuidSchema.openapi({\n param: {\n name: 'assetId',\n in: 'path',\n },\n }),\n }),\n },\n responses: {\n [200]: {\n content: {\n 'application/json': {\n schema: assetSchema,\n },\n },\n description: 'The requested Asset',\n },\n },\n }),\n async (c) => {\n const { projectId, assetId } = c.req.valid('param');\n const asset = await c.var.assetService.read({\n projectId,\n id: assetId,\n });\n\n return c.json(asset, 200);\n }\n );\n\nexport default router;\n","import { createRouter } from '../../../lib/util.js';\nimport projectRoutes from './projects.js';\nimport collectionRoutes from './collections.js';\nimport entryRoutes from './entries.js';\nimport assetRoutes from './assets.js';\n\nconst router = createRouter()\n .route('/projects', projectRoutes)\n .route('/projects', collectionRoutes)\n .route('/projects', entryRoutes)\n .route('/projects', assetRoutes);\n\nexport default router;\n","import { createRouter } from '../../lib/util.js';\nimport v1Routes from './v1/index.js';\n\nconst router = createRouter().route('/v1', v1Routes);\n\nexport default router;\n","import { createRouter } from '../lib/util.js';\nimport contentRoutes from './content/index.js';\n\nconst router = createRouter().route('/content', contentRoutes);\n\nexport default router;\n","import { serve } from '@hono/node-server';\nimport type { OpenAPIHono } from '@hono/zod-openapi';\nimport type { Server } from 'node:http';\nimport type { Http2SecureServer, Http2Server } from 'node:http2';\nimport type {\n AssetService,\n CollectionService,\n EntryService,\n LogService,\n ProjectService,\n} from '../service/index.js';\nimport createApi from './lib/util.js';\nimport routes from './routes/index.js';\nimport type { ApiEnv } from './lib/types.js';\nimport { Scalar } from '@scalar/hono-api-reference';\n\nexport class LocalApi {\n private logService: LogService;\n private projectService: ProjectService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n private assetService: AssetService;\n private api: OpenAPIHono<ApiEnv>;\n private server: Server | Http2Server | Http2SecureServer | null = null;\n\n constructor(\n logService: LogService,\n projectService: ProjectService,\n collectionService: CollectionService,\n entryService: EntryService,\n assetService: AssetService\n ) {\n this.logService = logService;\n this.projectService = projectService;\n this.collectionService = collectionService;\n this.entryService = entryService;\n this.assetService = assetService;\n this.api = createApi(\n this.logService,\n this.projectService,\n this.collectionService,\n this.entryService,\n this.assetService\n )\n .route('/', routes)\n .doc('/openapi.json', {\n openapi: '3.0.0',\n externalDocs: { url: 'https://elek.io/docs' },\n info: {\n version: '0.1.0',\n title: 'elek.io local API',\n description:\n 'This API allows reading content from local elek.io Projects. You can use this API for development and building static websites and applications locally.',\n },\n servers: [\n {\n url: 'http://localhost:{port}',\n description: 'elek.io local API',\n variables: {\n port: {\n default: 31310,\n description:\n 'The port specified in elek.io Clients user configuration',\n },\n },\n },\n ],\n tags: [\n {\n name: 'Content API v1',\n description:\n 'Version 1 of the elek.io content API lets you read Projects, Collections, Entries and Assets. \\n### Resources\\n - [Projects](https://elek.io/docs/projects)\\n - [Collections](https://elek.io/docs/collections)\\n - [Entries](https://elek.io/docs/entries)\\n - [Assets](https://elek.io/docs/assets)',\n },\n // {\n // name: 'Projects',\n // description: 'Retrieve information about Projects',\n // externalDocs: { url: 'https://elek.io/docs/projects' },\n // },\n // {\n // name: 'Collections',\n // description: 'Retrieve information about Collections',\n // externalDocs: { url: 'https://elek.io/docs/collections' },\n // },\n // {\n // name: 'Entries',\n // description: 'Retrieve information about Entries',\n // externalDocs: { url: 'https://elek.io/docs/entries' },\n // },\n // {\n // name: 'Assets',\n // description: 'Retrieve information about Assets',\n // externalDocs: { url: 'https://elek.io/docs/assets' },\n // },\n ],\n });\n\n this.api.get(\n '/',\n Scalar({\n pageTitle: 'elek.io local API',\n url: '/openapi.json',\n theme: 'kepler',\n layout: 'modern',\n defaultHttpClient: {\n targetKey: 'js',\n clientKey: 'fetch',\n },\n })\n );\n }\n\n /**\n * Starts the local API on given port\n */\n public start(port: number) {\n this.server = serve(\n {\n fetch: this.api.fetch,\n port,\n },\n (info) => {\n this.logService.info({\n source: 'core',\n message: `Started local API on http://localhost:${info.port}`,\n });\n }\n );\n }\n\n /**\n * Stops the local API\n */\n public stop() {\n this.server?.close(() => {\n this.logService.info({ source: 'core', message: 'Stopped local API' });\n });\n }\n\n /**\n * Returns true if the local API is running\n */\n public isRunning() {\n if (this.server?.listening) {\n return true;\n }\n return false;\n }\n}\n","export class GitError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'GitError';\n }\n}\n","export 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","export class ProjectUpgradeError extends Error {\n constructor(message: string) {\n super(message);\n\n this.name = 'ProjectUpgradeError';\n }\n}\n","export class RequiredParameterMissingError extends Error {\n constructor(parameter: string) {\n super(`Missing required parameter \"${parameter}\"`);\n\n this.name = 'RequiredParameterMissingError';\n }\n}\n","import Fs from 'fs-extra';\nimport Os from 'node:os';\nimport Path from 'node:path';\nimport { execFile, type ExecFileOptions } from 'node:child_process';\nimport { projectFolderSchema } from '../schema/projectSchema.js';\nimport type { LogService } from '../service/LogService.js';\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: (projectId: string, collectionId: string, id: string) => {\n return Path.join(pathTo.entries(projectId, collectionId), `${id}.json`);\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): string => {\n return Path.join(pathTo.assets(projectId), `${id}.json`);\n },\n asset: (projectId: string, id: string, extension: string): string => {\n return Path.join(pathTo.lfs(projectId), `${id}.${extension}`);\n },\n tmpAsset: (id: string, commitHash: string, extension: string) => {\n return Path.join(pathTo.tmp, `${id}.${commitHash}.${extension}`);\n },\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 isNotEmpty<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\n/**\n * Used as parameter for filter() methods to assure,\n * only items that are not of type Error are returned\n *\n * @param item Item to check\n */\nexport function isNotAnError<T>(item: T | Error): item is T {\n return item instanceof Error !== true;\n}\n\n/**\n * Returns all folders of given path to a directory\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 to a directory,\n * 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 * Executes a shell command async and returns the output.\n *\n * When on Windows, it will automatically append `.cmd` to the command if it is in the `commandsToSuffix` list.\n */\nexport function execCommand({\n command,\n args,\n options,\n logger,\n}: {\n command: string;\n args: string[];\n options?: ExecFileOptions;\n logger: LogService;\n}) {\n return new Promise<{ stdout: string; stderr: string }>((resolve, reject) => {\n const commandsToSuffix = ['pnpm'];\n const isWindows = Os.platform() === 'win32';\n const suffixedCommand = isWindows\n ? command\n .split(' ')\n .map((cmd) => (commandsToSuffix.includes(cmd) ? `${cmd}.cmd` : cmd))\n .join(' ')\n : command;\n const fullCommand = `${suffixedCommand} ${args.join(' ')}`;\n const execOptions: ExecFileOptions = {\n ...options,\n shell: true,\n };\n const start = Date.now();\n\n execFile(suffixedCommand, args, execOptions, (error, stdout, stderr) => {\n const durationMs = Date.now() - start;\n if (error) {\n logger.error({\n source: 'core',\n message: `Error executing command \"${fullCommand}\" after ${durationMs}ms: ${error.message}`,\n meta: { error, stdout: stdout.toString(), stderr: stderr.toString() },\n });\n reject(error instanceof Error ? error : new Error(error.message));\n } else {\n logger.info({\n source: 'core',\n message: `Command \"${fullCommand}\" executed successfully in ${durationMs}ms.`,\n meta: { stdout: stdout.toString(), stderr: stderr.toString() },\n });\n resolve({ stdout: stdout.toString(), stderr: stderr.toString() });\n }\n });\n });\n}\n","import { RequiredParameterMissingError } from '../error/index.js';\nimport {\n fileReferenceSchema,\n objectTypeSchema,\n type ElekIoCoreOptions,\n type FileReference,\n type ObjectType,\n type ServiceType,\n} from '../schema/index.js';\nimport {\n files,\n folders,\n isNotAnError,\n isNotEmpty,\n pathTo,\n} from '../util/node.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * A base service that provides properties for most other services\n */\nexport abstract class AbstractCrudService {\n public readonly type: ServiceType;\n public readonly options: ElekIoCoreOptions;\n protected readonly logService: LogService;\n\n /**\n * Do not instantiate directly as this is an abstract class\n */\n protected constructor(\n type: ServiceType,\n options: ElekIoCoreOptions,\n logService: LogService\n ) {\n this.type = type;\n this.options = options;\n this.logService = logService;\n }\n\n /**\n * Basically a Promise.all() without rejecting if one promise fails to resolve\n */\n protected async returnResolved<T>(promises: Promise<T>[]) {\n const toCheck: Promise<T | Error>[] = [];\n\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\n // Here comes the trick:\n // By using \"then\" and \"catch\" we are able to create an array of T 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 const actualError =\n error instanceof Error ? error : new Error(String(error));\n\n this.logService.warn({\n source: 'core',\n message: `Function \"returnResolved\" catched an error while resolving a promise: ${actualError.message}`,\n meta: { error: actualError, promise },\n });\n\n return actualError;\n })\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\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(isNotAnError);\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(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(pathTo.projects);\n\n case objectTypeSchema.enum.collection:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFolderReferences(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 pathTo.collection(projectId, collectionId)\n );\n\n case objectTypeSchema.enum.sharedValue:\n if (!projectId) {\n throw new RequiredParameterMissingError('projectId');\n }\n return this.getFileReferences(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 folders(path);\n\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 {\n this.logService.warn({\n source: 'core',\n message: `Function \"getFolderReferences\" is ignoring folder \"${possibleFolder.name}\" in \"${path}\" as it does not match the expected format`,\n });\n\n return null;\n }\n });\n\n return results.filter(isNotEmpty);\n }\n\n /**\n * Searches for all files inside given folder,\n * parses their names and returns them as FileReference\n *\n * Ignores files if the extension is not supported.\n */\n private async getFileReferences(path: string): Promise<FileReference[]> {\n const possibleFiles = await files(path);\n\n const results = possibleFiles.map((possibleFile) => {\n const fileNameArray = possibleFile.name.split('.');\n\n const fileReference = {\n id: fileNameArray[0],\n extension: fileNameArray[1],\n };\n\n try {\n return fileReferenceSchema.parse(fileReference);\n } catch {\n this.logService.warn({\n source: 'core',\n message: `Function \"getFileReferences\" is ignoring file \"${possibleFile.name}\" in \"${path}\" as it does not match the expected format`,\n });\n\n return null;\n }\n });\n\n return results.filter(isNotEmpty);\n }\n}\n","import slugify from '@sindresorhus/slugify';\nimport { v4 as generateUuid } from 'uuid';\nimport { type Uuid } from '../schema/baseSchema.js';\n\n/**\n * Returns a new UUID\n */\nexport function uuid(): Uuid {\n return generateUuid();\n}\n\n/**\n * Returns a string representing date and time\n * in a simplified format based on ISO 8601.\n * The timezone is always UTC.\n *\n * - If value is not given, the current date and time is used\n * - If value is given, it's converted to above representation and UTC timezone\n *\n * @example 'YYYY-MM-DDTHH:mm:ss.sssZ'\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString\n * @see https://en.wikipedia.org/wiki/ISO_8601\n */\nexport function datetime(value?: number | string | Date) {\n if (!value) {\n return new Date().toISOString();\n }\n return new Date(value).toISOString();\n}\n\n/**\n * Returns the slug of given string\n */\nexport function slug(string: string): string {\n return slugify(string, {\n separator: '-',\n lowercase: true,\n decamelize: true,\n });\n}\n","import Fs from 'fs-extra';\nimport mime from 'mime';\nimport type { SaveAssetProps } from '../schema/index.js';\nimport {\n assetFileSchema,\n assetSchema,\n countAssetsSchema,\n createAssetSchema,\n deleteAssetSchema,\n listAssetsSchema,\n objectTypeSchema,\n readAssetSchema,\n saveAssetSchema,\n serviceTypeSchema,\n updateAssetSchema,\n type Asset,\n type AssetFile,\n type CountAssetsProps,\n type CreateAssetProps,\n type CrudServiceWithListCount,\n type DeleteAssetProps,\n type ElekIoCoreOptions,\n type ListAssetsProps,\n type PaginatedList,\n type ReadAssetProps,\n type UpdateAssetProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, slug, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Asset files on disk\n */\nexport class AssetService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Asset>\n{\n private readonly jsonFileService: JsonFileService;\n private readonly gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.enum.Asset, options, logService);\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 = pathTo.project(props.projectId);\n const fileType = this.getFileType(props.filePath);\n const size = await this.getFileSize(props.filePath);\n const assetPath = pathTo.asset(props.projectId, id, fileType.extension);\n const assetFilePath = pathTo.assetFile(props.projectId, id);\n\n const assetFile: AssetFile = {\n ...props,\n name: slug(props.name),\n objectType: 'asset',\n id,\n created: datetime(),\n updated: null,\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, {\n method: 'create',\n reference: { objectType: 'asset', id },\n });\n\n return this.toAsset(props.projectId, assetFile);\n }\n\n /**\n * Returns an Asset by ID\n *\n * If a commit hash is provided, the Asset is read from history\n */\n public async read(props: ReadAssetProps): Promise<Asset> {\n readAssetSchema.parse(props);\n\n if (!props.commitHash) {\n const assetFile = await this.jsonFileService.read(\n pathTo.assetFile(props.projectId, props.id),\n assetFileSchema\n );\n\n return this.toAsset(props.projectId, assetFile);\n } else {\n const assetFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.assetFile(props.projectId, props.id),\n props.commitHash\n )\n )\n );\n\n const assetBlob = await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.asset(props.projectId, props.id, assetFile.extension),\n props.commitHash,\n 'binary'\n );\n await Fs.writeFile(\n pathTo.tmpAsset(assetFile.id, props.commitHash, assetFile.extension),\n assetBlob,\n 'binary'\n );\n\n return this.toAsset(props.projectId, assetFile, props.commitHash);\n }\n }\n\n /**\n * Copies an Asset to given file path on disk\n */\n public async save(props: SaveAssetProps) {\n saveAssetSchema.parse(props);\n\n const asset = await this.read(props);\n await Fs.copyFile(asset.absolutePath, props.filePath);\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 = pathTo.project(props.projectId);\n const assetFilePath = pathTo.assetFile(props.projectId, props.id);\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 name: slug(props.name),\n updated: datetime(),\n };\n\n if (props.newFilePath) {\n // Overwrite the file itself (in LFS folder)...\n\n const fileType = this.getFileType(props.newFilePath);\n const size = await this.getFileSize(props.newFilePath);\n const prevAssetPath = pathTo.asset(\n props.projectId,\n props.id,\n prevAssetFile.extension\n );\n const assetPath = pathTo.asset(\n props.projectId,\n props.id,\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 await this.gitService.add(projectPath, [prevAssetPath, 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, {\n method: 'update',\n reference: { objectType: 'asset', id: assetFile.id },\n });\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 = pathTo.project(props.projectId);\n const assetFilePath = pathTo.assetFile(props.projectId, props.id);\n const assetPath = pathTo.asset(props.projectId, props.id, props.extension);\n await Fs.remove(assetPath);\n await Fs.remove(assetFilePath);\n await this.gitService.add(projectPath, [assetFilePath, assetPath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: { objectType: 'asset', id: props.id },\n });\n }\n\n public async list(props: ListAssetsProps): Promise<PaginatedList<Asset>> {\n listAssetsSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const assetReferences = await this.listReferences(\n objectTypeSchema.enum.asset,\n props.projectId\n );\n\n const partialAssetReferences =\n limit === 0\n ? assetReferences.slice(offset)\n : assetReferences.slice(offset, offset + limit);\n\n const assets = await this.returnResolved(\n partialAssetReferences.map((assetReference) => {\n return this.read({\n projectId: props.projectId,\n id: assetReference.id,\n });\n })\n );\n\n return {\n total: assetReferences.length,\n limit,\n offset,\n list: assets,\n };\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: unknown): obj is Asset {\n return assetSchema.safeParse(obj).success;\n }\n\n /**\n * Returns the size of an file in bytes\n *\n * @param path Path of the file to get the size from\n */\n private async getFileSize(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 commitHash?: string\n ): Promise<Asset> {\n const assetPath = commitHash\n ? pathTo.tmpAsset(assetFile.id, commitHash, assetFile.extension)\n : pathTo.asset(projectId, assetFile.id, assetFile.extension);\n\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.assetFile(projectId, assetFile.id),\n });\n\n const asset: Asset = {\n ...assetFile,\n absolutePath: assetPath,\n history,\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 getFileType(filePath: string) {\n const mimeType = mime.getType(filePath);\n\n if (mimeType === null) {\n throw new Error(`Unsupported MIME type of file \"${filePath}\"`);\n }\n\n const extension = mime.getExtension(mimeType);\n\n if (extension === null) {\n throw new Error(\n `Unsupported extension for MIME type \"${mimeType}\" of file \"${filePath}\"`\n );\n }\n\n return {\n extension,\n mimeType,\n };\n }\n\n /**\n * Migrates an potentially outdated Asset file to the current schema\n */\n public migrate(potentiallyOutdatedAssetFile: unknown) {\n // @todo\n\n return assetFileSchema.parse(potentiallyOutdatedAssetFile);\n }\n}\n","import Fs from 'fs-extra';\nimport {\n collectionFileSchema,\n countCollectionsSchema,\n createCollectionSchema,\n deleteCollectionSchema,\n listCollectionsSchema,\n objectTypeSchema,\n readCollectionSchema,\n serviceTypeSchema,\n updateCollectionSchema,\n type Collection,\n type CollectionFile,\n type CountCollectionsProps,\n type CreateCollectionProps,\n type CrudServiceWithListCount,\n type DeleteCollectionProps,\n type ElekIoCoreOptions,\n type ListCollectionsProps,\n type PaginatedList,\n type ReadCollectionProps,\n type UpdateCollectionProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, slug, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Collection files on disk\n */\nexport class CollectionService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Collection>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService\n ) {\n super(serviceTypeSchema.enum.Collection, options, logService);\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 = pathTo.project(props.projectId);\n const collectionPath = pathTo.collection(props.projectId, id);\n const collectionFilePath = pathTo.collectionFile(props.projectId, id);\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: datetime(),\n updated: null,\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, {\n method: 'create',\n reference: { objectType: 'collection', id },\n });\n\n return this.toCollection(props.projectId, collectionFile);\n }\n\n /**\n * Returns a Collection by ID\n *\n * If a commit hash is provided, the Collection is read from history\n */\n public async read(props: ReadCollectionProps): Promise<Collection> {\n readCollectionSchema.parse(props);\n\n if (!props.commitHash) {\n const collectionFile = await this.jsonFileService.read(\n pathTo.collectionFile(props.projectId, props.id),\n collectionFileSchema\n );\n\n return this.toCollection(props.projectId, collectionFile);\n } else {\n const collectionFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.collectionFile(props.projectId, props.id),\n props.commitHash\n )\n )\n );\n\n return this.toCollection(props.projectId, collectionFile);\n }\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 = pathTo.project(props.projectId);\n const collectionFilePath = pathTo.collectionFile(props.projectId, props.id);\n const prevCollectionFile = await this.read(props);\n\n const collectionFile: CollectionFile = {\n ...prevCollectionFile,\n ...props,\n updated: datetime(),\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 = 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, {\n method: 'update',\n reference: { objectType: 'collection', id: collectionFile.id },\n });\n\n return this.toCollection(props.projectId, 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 = pathTo.project(props.projectId);\n const collectionPath = pathTo.collection(props.projectId, props.id);\n\n await Fs.remove(collectionPath);\n await this.gitService.add(projectPath, [collectionPath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: { objectType: 'collection', id: props.id },\n });\n }\n\n public async list(\n props: ListCollectionsProps\n ): Promise<PaginatedList<Collection>> {\n listCollectionsSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const collectionReferences = await this.listReferences(\n objectTypeSchema.enum.collection,\n props.projectId\n );\n\n const partialCollectionReferences =\n limit === 0\n ? collectionReferences.slice(offset)\n : collectionReferences.slice(offset, offset + limit);\n\n const collections = await this.returnResolved(\n partialCollectionReferences.map((reference) => {\n return this.read({\n projectId: props.projectId,\n id: reference.id,\n });\n })\n );\n\n return {\n total: collectionReferences.length,\n limit,\n offset,\n list: collections,\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: unknown): obj is Collection {\n return collectionFileSchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Collection file to the current schema\n */\n public migrate(potentiallyOutdatedCollectionFile: unknown) {\n // @todo\n\n return collectionFileSchema.parse(potentiallyOutdatedCollectionFile);\n }\n\n /**\n * Creates an Collection from given CollectionFile\n *\n * @param projectId The project's ID\n * @param collectionFile The CollectionFile to convert\n */\n private async toCollection(\n projectId: string,\n collectionFile: CollectionFile\n ): Promise<Collection> {\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.collectionFile(projectId, collectionFile.id),\n });\n\n const collection: Collection = {\n ...collectionFile,\n history,\n };\n\n return collection;\n }\n}\n","import Fs from 'fs-extra';\nimport {\n countEntriesSchema,\n createEntrySchema,\n deleteEntrySchema,\n entryFileSchema,\n entrySchema,\n getCreateEntrySchemaFromFieldDefinitions,\n getUpdateEntrySchemaFromFieldDefinitions,\n listEntriesSchema,\n objectTypeSchema,\n readEntrySchema,\n serviceTypeSchema,\n updateEntrySchema,\n type CountEntriesProps,\n type CreateEntryProps,\n type CrudServiceWithListCount,\n type DeleteEntryProps,\n type ElekIoCoreOptions,\n type Entry,\n type EntryFile,\n type ListEntriesProps,\n type ReadEntryProps,\n type UpdateEntryProps,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { CollectionService } from './CollectionService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Entry files on disk\n */\nexport class EntryService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Entry>\n{\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private collectionService: CollectionService;\n // private sharedValueService: SharedValueService;\n\n constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService,\n collectionService: CollectionService\n // sharedValueService: SharedValueService\n ) {\n super(serviceTypeSchema.enum.Entry, options, logService);\n\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\n this.collectionService = collectionService;\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n id\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 values: props.values,\n created: datetime(),\n updated: null,\n };\n\n const entry = await this.toEntry(\n props.projectId,\n props.collectionId,\n entryFile\n );\n\n // Validate all Values against their Field Definitions\n const createEntrySchemaFromFieldDefinitions =\n getCreateEntrySchemaFromFieldDefinitions(collection.fieldDefinitions);\n createEntrySchemaFromFieldDefinitions.parse(props);\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, {\n method: 'create',\n reference: {\n objectType: 'entry',\n id: entryFile.id,\n collectionId: props.collectionId,\n },\n });\n\n return entry;\n }\n\n /**\n * Returns an Entry from given Collection by ID\n *\n * If a commit hash is provided, the Entry is read from history\n */\n public async read(props: ReadEntryProps): Promise<Entry> {\n readEntrySchema.parse(props);\n\n if (!props.commitHash) {\n const entryFile: EntryFile = await this.jsonFileService.read(\n pathTo.entryFile(props.projectId, props.collectionId, props.id),\n entryFileSchema\n );\n\n return this.toEntry(props.projectId, props.collectionId, entryFile);\n } else {\n const entryFile = this.migrate(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.projectId),\n pathTo.entryFile(props.projectId, props.collectionId, props.id),\n props.commitHash\n )\n )\n );\n\n return this.toEntry(props.projectId, props.collectionId, entryFile);\n }\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id\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 });\n\n const entryFile: EntryFile = {\n ...prevEntryFile,\n values: props.values,\n updated: datetime(),\n };\n\n const entry = await this.toEntry(\n props.projectId,\n props.collectionId,\n entryFile\n );\n\n // Validate all Values against their Field Definitions\n const updateEntrySchemaFromFieldDefinitions =\n getUpdateEntrySchemaFromFieldDefinitions(collection.fieldDefinitions);\n updateEntrySchemaFromFieldDefinitions.parse(props);\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, {\n method: 'update',\n reference: {\n objectType: 'entry',\n id: entryFile.id,\n collectionId: props.collectionId,\n },\n });\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 = pathTo.project(props.projectId);\n const entryFilePath = pathTo.entryFile(\n props.projectId,\n props.collectionId,\n props.id\n );\n\n await Fs.remove(entryFilePath);\n await this.gitService.add(projectPath, [entryFilePath]);\n await this.gitService.commit(projectPath, {\n method: 'delete',\n reference: {\n objectType: 'entry',\n id: props.id,\n collectionId: props.collectionId,\n },\n });\n }\n\n public async list(props: ListEntriesProps) {\n listEntriesSchema.parse(props);\n\n const offset = props.offset || 0;\n const limit = props.limit ?? 15;\n\n const entryReferences = await this.listReferences(\n objectTypeSchema.enum.entry,\n props.projectId,\n props.collectionId\n );\n\n const partialEntryReferences =\n limit === 0\n ? entryReferences.slice(offset)\n : entryReferences.slice(offset, offset + limit);\n\n const entries = await this.returnResolved(\n partialEntryReferences.map((reference) => {\n return this.read({\n projectId: props.projectId,\n collectionId: props.collectionId,\n id: reference.id,\n });\n })\n );\n\n return {\n total: entryReferences.length,\n limit,\n offset,\n list: entries,\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: unknown): obj is Entry {\n return entrySchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Entry file to the current schema\n */\n public migrate(potentiallyOutdatedEntryFile: unknown) {\n // @todo\n\n return entryFileSchema.parse(potentiallyOutdatedEntryFile);\n }\n\n /**\n * Creates an Entry from given EntryFile by resolving it's Values\n */\n private async toEntry(\n projectId: string,\n collectionId: string,\n entryFile: EntryFile\n ): Promise<Entry> {\n const history = await this.gitService.log(pathTo.project(projectId), {\n filePath: pathTo.entryFile(projectId, collectionId, entryFile.id),\n });\n\n return {\n ...entryFile,\n history,\n };\n }\n}\n","import { GitError } from '../error/index.js';\nimport {\n countGitTagsSchema,\n createGitTagSchema,\n deleteGitTagSchema,\n gitTagSchema,\n listGitTagsSchema,\n readGitTagSchema,\n serviceTypeSchema,\n type CountGitTagsProps,\n type CreateGitTagProps,\n type CrudServiceWithListCount,\n type DeleteGitTagProps,\n type ElekIoCoreOptions,\n type GitTag,\n type ListGitTagsProps,\n type PaginatedList,\n type ReadGitTagProps,\n} from '../schema/index.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { GitService } from './GitService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for GitTags\n */\nexport class GitTagService\n extends AbstractCrudService\n implements CrudServiceWithListCount<GitTag>\n{\n private git: GitService['git'];\n\n public constructor(\n options: ElekIoCoreOptions,\n git: GitService['git'],\n logService: LogService\n ) {\n super(serviceTypeSchema.enum.GitTag, options, logService);\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() but only returns the tag with matching ID.\n */\n public async read(props: ReadGitTagProps): Promise<GitTag> {\n readGitTagSchema.parse(props);\n\n const tags = await this.list({ path: props.path });\n const tag = tags.list.find((tag) => {\n return tag.id === props.id;\n });\n\n if (!tag) {\n throw new GitError(\n `Provided tag with UUID \"${props.id}\" did not match any known tags`\n );\n }\n\n return tag;\n }\n\n /**\n * Updating a git tag is not supported.\n * Please delete the old and create a new one\n *\n * @deprecated\n * @see https://git-scm.com/docs/git-tag#_on_re_tagging\n */\n public update(): 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 when 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:iso-strict)',\n ];\n const result = await this.git(props.path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n const lineObjArr = noEmptyLinesArr.map((line) => {\n const lineArray = line.split('|');\n\n // Remove the '<' and '>' enclosing the email\n // @todo is there another format like authoremail that returns the original email?\n if (lineArray[3]?.startsWith('<') && lineArray[3]?.endsWith('>')) {\n lineArray[3] = lineArray[3].slice(1, -1);\n lineArray[3] = lineArray[3].slice(0, -1);\n }\n\n return {\n id: lineArray[0],\n message: lineArray[1],\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n datetime: datetime(lineArray[4]),\n };\n });\n\n const gitTags = lineObjArr.filter(this.isGitTag.bind(this));\n\n return {\n total: gitTags.length,\n limit: 0,\n offset: 0,\n list: gitTags,\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 type { ChildProcess } from 'node:child_process';\nimport type { IGitExecutionOptions, IGitStringResult } from 'dugite';\nimport { exec as gitExec } from 'dugite';\nimport PQueue from 'p-queue';\nimport Path from 'node:path';\nimport { GitError, NoCurrentUserError } from '../error/index.js';\nimport type { GitMergeOptions, GitMessage } from '../schema/index.js';\nimport {\n gitCommitSchema,\n gitMessageSchema,\n uuidSchema,\n type ElekIoCoreOptions,\n type GitCloneOptions,\n type GitCommit,\n type GitInitOptions,\n type GitLogOptions,\n type GitSwitchOptions,\n} from '../schema/index.js';\nimport { datetime } from '../util/shared.js';\nimport { GitTagService } from './GitTagService.js';\nimport type { LogService } from './LogService.js';\nimport type { UserService } from './UserService.js';\nimport type { LogProps } from '../schema/index.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 *\n * @todo All public methods should recieve only a single object as parameter and the type should be defined through the shared library to be accessible in Core and Client\n */\nexport class GitService {\n private version: string | null;\n private gitPath: string | null;\n private queue: PQueue;\n private logService: LogService;\n private gitTagService: GitTagService;\n private userService: UserService;\n\n public constructor(\n options: ElekIoCoreOptions,\n logService: LogService,\n userService: UserService\n ) {\n this.version = null;\n this.gitPath = null;\n this.queue = new PQueue({\n concurrency: 1, // No concurrency because git operations are sequencial\n });\n this.gitTagService = new GitTagService(\n options,\n this.git.bind(this),\n logService\n );\n this.logService = logService;\n this.userService = userService;\n\n void this.updateVersion();\n void this.updateGitPath();\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 * 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 }\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?.bare) {\n args = [...args, '--bare'];\n }\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('', [...args, url, path]);\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 relativePathsFromRepositoryRoot = files.map((filePath) => {\n return filePath.replace(`${path}${Path.sep}`, '');\n });\n\n const args = ['add', '--', ...relativePathsFromRepositoryRoot];\n\n await this.git(path, args);\n }\n\n public async status(path: string) {\n const args = ['status', '--porcelain=2'];\n const result = await this.git(path, args);\n\n const normalizedLinesArr = result.stdout\n .split('\\n')\n .filter((line) => {\n return line.trim() !== '';\n })\n .map((line) => {\n const lineArr = line.trim().split(' ');\n\n return {\n filePath: lineArr[8],\n };\n });\n\n return normalizedLinesArr;\n }\n\n public branches = {\n /**\n * List branches\n *\n * @see https://www.git-scm.com/docs/git-branch\n *\n * @param path Path to the repository\n */\n list: async (path: string) => {\n const args = ['branch', '--list', '--all'];\n const result = await this.git(path, args);\n\n const normalizedLinesArr = result.stdout\n .split('\\n')\n .filter((line) => {\n return line.trim() !== '';\n })\n .map((line) => {\n return line.trim().replace('* ', '');\n });\n\n const local: string[] = [];\n const remote: string[] = [];\n normalizedLinesArr.forEach((line) => {\n if (line.startsWith('remotes/')) {\n remote.push(line.replace('remotes/', ''));\n } else {\n local.push(line);\n }\n });\n return {\n local,\n remote,\n };\n },\n /**\n * Returns the name of the current branch. In detached HEAD state, an empty string is returned.\n *\n * @see https://www.git-scm.com/docs/git-branch#Documentation/git-branch.txt---show-current\n *\n * @param path Path to the repository\n */\n current: async (path: string) => {\n const args = ['branch', '--show-current'];\n const result = await this.git(path, args);\n\n return result.stdout.trim();\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 branch Name of the branch to switch to\n * @param options Options specific to the switch operation\n */\n switch: async (\n path: string,\n branch: string,\n options?: GitSwitchOptions\n ) => {\n await this.checkBranchOrTagName(path, branch);\n\n let args = ['switch'];\n\n if (options?.isNew === true) {\n args = [...args, '--create', branch];\n } else {\n args = [...args, branch];\n }\n\n await this.git(path, args);\n },\n /**\n * Delete a branch\n *\n * @see https://git-scm.com/docs/git-branch#Documentation/git-branch.txt---delete\n *\n * @param path Path to the repository\n * @param branch Name of the branch to delete\n */\n delete: async (path: string, branch: string, force?: boolean) => {\n let args = ['branch', '--delete'];\n\n if (force === true) {\n args = [...args, '--force'];\n }\n\n await this.git(path, [...args, branch]);\n },\n };\n\n public remotes = {\n /**\n * Returns a list of currently tracked remotes\n *\n * @see https://git-scm.com/docs/git-remote\n *\n * @param path Path to the repository\n */\n list: async (path: string) => {\n const args = ['remote'];\n const result = await this.git(path, args);\n const normalizedLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n return normalizedLinesArr;\n },\n /**\n * Returns true if the `origin` remote exists, otherwise false\n *\n * @param path Path to the repository\n */\n hasOrigin: async (path: string) => {\n const remotes = await this.remotes.list(path);\n\n if (remotes.includes('origin')) {\n return true;\n }\n return false;\n },\n /**\n * Adds the `origin` remote with given URL\n *\n * Throws if `origin` remote is added already.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emaddem\n *\n * @param path Path to the repository\n */\n addOrigin: async (path: string, url: string) => {\n const args = ['remote', 'add', 'origin', url.trim()];\n await this.git(path, args);\n },\n /**\n * Returns the current `origin` remote URL\n *\n * Throws if no `origin` remote is added yet.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem\n *\n * @param path Path to the repository\n */\n getOriginUrl: async (path: string) => {\n const args = ['remote', 'get-url', 'origin'];\n const result = (await this.git(path, args)).stdout.trim();\n\n return result.length === 0 ? null : result;\n },\n /**\n * Sets the current `origin` remote URL\n *\n * Throws if no `origin` remote is added yet.\n *\n * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem\n *\n * @param path Path to the repository\n */\n setOriginUrl: async (path: string, url: string) => {\n const args = ['remote', 'set-url', 'origin', url.trim()];\n await this.git(path, args);\n },\n };\n\n /**\n * Join two development histories together\n *\n * @see https://git-scm.com/docs/git-merge\n */\n public async merge(\n path: string,\n branch: string,\n options?: Partial<GitMergeOptions>\n ) {\n let args = ['merge'];\n\n if (options?.squash === true) {\n args = [...args, '--squash'];\n }\n\n args = [...args, branch];\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 * Download objects and refs from remote `origin`\n *\n * @see https://www.git-scm.com/docs/git-fetch\n *\n * @param path Path to the repository\n */\n public async fetch(path: string): Promise<void> {\n const args = ['fetch'];\n await this.git(path, args);\n }\n\n /**\n * Fetch from and integrate (rebase or merge) with 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\n await this.git(path, args);\n }\n\n /**\n * Update remote refs along with associated objects to remote `origin`\n *\n * @see https://git-scm.com/docs/git-push\n *\n * @param path Path to the repository\n */\n public async push(\n path: string,\n // branch: string,\n options?: Partial<{ all: boolean; force: boolean }>\n ): Promise<void> {\n let args = ['push', 'origin'];\n\n // if (options?.trackRemoteBranch === true) {\n // args = [...args, '--set-upstream'];\n // }\n\n // args = [...args, 'origin'];\n\n if (options?.all === true) {\n args = [...args, '--all'];\n }\n\n if (options?.force === true) {\n args = [...args, '--force'];\n }\n\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 An object describing the changes\n */\n public async commit(path: string, message: GitMessage): Promise<void> {\n gitMessageSchema.parse(message);\n\n const user = await this.userService.get();\n if (!user) {\n throw new NoCurrentUserError();\n }\n\n const args = [\n 'commit',\n `--message=${JSON.stringify(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 args = [...args, '--format=%H|%s|%an|%ae|%aI|%D'];\n\n if (options?.filePath) {\n args = [...args, '--', options.filePath];\n }\n\n const result = await this.git(path, args);\n\n const noEmptyLinesArr = result.stdout.split('\\n').filter((line) => {\n return line.trim() !== '';\n });\n\n const lineObjArr = await Promise.all(\n noEmptyLinesArr.map(async (line) => {\n const lineArray = line.split('|');\n const tagId = this.refNameToTagName(lineArray[5] || '');\n const tag = tagId ? await this.tags.read({ path, id: tagId }) : null;\n\n return {\n hash: lineArray[0],\n // We don't want to parse the message because it could throw.\n // Filtering it through isGitCommit ensures it's valid as a whole.\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n message: JSON.parse(lineArray[1] || ''),\n author: {\n name: lineArray[2],\n email: lineArray[3],\n },\n datetime: datetime(lineArray[4]),\n tag,\n };\n })\n );\n\n return lineObjArr.filter(this.isGitCommit.bind(this));\n }\n\n /**\n * Retrieves the content of a file at a specific commit\n *\n * @see https://git-scm.com/docs/git-show\n */\n public async getFileContentAtCommit(\n path: string,\n filePath: string,\n commitHash: string,\n encoding: 'utf8' | 'binary' = 'utf8'\n ) {\n const relativePathFromRepositoryRoot = filePath.replace(\n `${path}${Path.sep}`,\n ''\n );\n const normalizedPath = relativePathFromRepositoryRoot.split('\\\\').join('/');\n const args = ['show', `${commitHash}:${normalizedPath}`];\n const setEncoding: (process: ChildProcess) => void = (cb) => {\n if (cb.stdout) {\n cb.stdout.setEncoding(encoding);\n }\n };\n\n return (\n await this.git(path, args, {\n processCallback: setEncoding,\n })\n ).stdout;\n }\n\n public refNameToTagName(refName: string) {\n const tagName = refName.replace('tag: ', '').trim();\n\n // Return null for anything else than UUIDs (tag names are UUIDs)\n if (tagName === '' || uuidSchema.safeParse(tagName).success === false) {\n return null;\n }\n\n return tagName;\n }\n\n /**\n * Reads the currently used version of Git\n *\n * This can help debugging\n */\n private async updateVersion(): Promise<void> {\n const result = await this.git('', ['--version']);\n this.version = result.stdout.replace('git version', '').trim();\n }\n\n /**\n * Reads the path to the executable of Git that is used\n *\n * This can help debugging, since dugite is shipping their own executable\n * but in some cases resolves another executable\n * @see https://github.com/desktop/dugite/blob/main/lib/git-environment.ts\n */\n private async updateGitPath(): Promise<void> {\n const result = await this.git('', ['--exec-path']);\n this.gitPath = result.stdout.trim();\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 * 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 // Setup the local User\n const userNameArgs = ['config', '--local', 'user.name', user.name];\n const userEmailArgs = ['config', '--local', 'user.email', user.email];\n // By default new branches that are pushed are automatically tracking\n // their remote without the need of using the `--set-upstream` argument of `git push`\n const autoSetupRemoteArgs = [\n 'config',\n '--local',\n 'push.autoSetupRemote',\n 'true',\n ];\n // By default `git pull` will try to rebase first\n // to reduce the amount of merge commits\n const pullRebaseArgs = ['config', '--local', 'pull.rebase', 'true'];\n\n await this.git(path, userNameArgs);\n await this.git(path, userEmailArgs);\n await this.git(path, autoSetupRemoteArgs);\n await this.git(path, pullRebaseArgs);\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(\n path: string,\n args: string[],\n options?: IGitExecutionOptions\n ): Promise<IGitStringResult> {\n const result = await this.queue.add(async () => {\n const start = Date.now();\n const gitResult = await gitExec(args, path, options);\n const durationMs = Date.now() - start;\n return {\n gitResult,\n durationMs,\n };\n });\n\n if (!result) {\n throw new GitError(\n `Git ${this.version} (${this.gitPath}) command \"git ${args.join(\n ' '\n )}\" executed for \"${path}\" failed to return a result`\n );\n }\n\n const gitLog: LogProps = {\n source: 'core',\n message: `Executed \"git ${args.join(' ')}\" in ${result.durationMs}ms`,\n meta: { command: `git ${args.join(' ')}` },\n };\n if (result.durationMs >= 100) {\n this.logService.warn(gitLog);\n } else {\n this.logService.debug(gitLog);\n }\n\n if (result.gitResult.exitCode !== 0) {\n throw new GitError(\n `Git ${this.version} (${this.gitPath}) command \"git ${args.join(\n ' '\n )}\" executed for \"${path}\" failed with exit code \"${\n result.gitResult.exitCode\n }\" and message \"${\n result.gitResult.stderr.toString().trim() ||\n result.gitResult.stdout.toString().trim()\n }\"`\n );\n }\n\n return {\n ...result.gitResult,\n stdout: result.gitResult.stdout.toString(),\n stderr: result.gitResult.stderr.toString(),\n };\n }\n}\n","import Fs from 'fs-extra';\nimport type { z } from '@hono/zod-openapi';\nimport type { ElekIoCoreOptions } from '../schema/coreSchema.js';\nimport type { BaseFile } from '../schema/fileSchema.js';\nimport { serviceTypeSchema } from '../schema/serviceSchema.js';\nimport type { UserFile } from '../schema/userSchema.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for JSON files on disk\n */\nexport class JsonFileService extends AbstractCrudService {\n private cache: Map<string, unknown> = new Map();\n\n constructor(options: ElekIoCoreOptions, logService: LogService) {\n super(serviceTypeSchema.enum.JsonFile, options, logService);\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n this.logService.debug({\n source: 'core',\n message: `Created file \"${path}\"`,\n });\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.options.file.cache === true && this.cache.has(path)) {\n this.logService.debug({\n source: 'core',\n message: `Cache hit reading file \"${path}\"`,\n });\n const json = this.cache.get(path);\n const parsedData = schema.parse(json);\n return parsedData;\n }\n\n this.logService.debug({\n source: 'core',\n message: `Cache miss reading file \"${path}\"`,\n });\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n\n return parsedData;\n }\n\n /**\n * Reads the content of a file on disk. Fails if path does not exist.\n * Does not validate the content of the file against a schema and\n * therefore is only to be used when retrieving data we do not have\n * a current schema for. E.g. reading from history or while upgrading\n * the old schema of a file to a new, current schema.\n *\n * Does not read from or write to cache.\n *\n * @param path Path to read the file from\n * @returns Unvalidated content of the file from disk\n */\n public async unsafeRead(path: string): Promise<unknown> {\n this.logService.warn({\n source: 'core',\n message: `Unsafe reading of file \"${path}\"`,\n });\n const data = await Fs.readFile(path, {\n flag: 'r',\n encoding: 'utf8',\n });\n const json = this.deserialize(data);\n\n return json;\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 if (this.options.file.cache === true) {\n this.cache.set(path, parsedData);\n }\n this.logService.debug({\n source: 'core',\n message: `Updated file \"${path}\"`,\n });\n\n return parsedData;\n }\n\n private serialize(data: unknown): string {\n return JSON.stringify(data, null, 2);\n }\n\n private deserialize(data: string): unknown {\n return JSON.parse(data);\n }\n}\n","import type { Logger } from 'winston';\nimport { createLogger, format, transports } from 'winston';\nimport DailyRotateFile from 'winston-daily-rotate-file';\nimport { type ElekIoCoreOptions } from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport type { LogProps } from '../schema/logSchema.js';\nimport { logConsoleTransportSchema, logSchema } from '../schema/logSchema.js';\n\n/**\n * Service that handles logging to file and console\n */\nexport class LogService {\n private readonly logger: Logger;\n\n constructor(options: ElekIoCoreOptions) {\n const rotatingFileTransport = new DailyRotateFile({\n dirname: pathTo.logs,\n filename: '%DATE%.log',\n datePattern: 'YYYY-MM-DD',\n zippedArchive: true,\n maxFiles: '30d',\n handleExceptions: true,\n handleRejections: true,\n format: format.combine(format.timestamp(), format.json()),\n });\n\n rotatingFileTransport.on('rotate', (oldFilename, newFilename) => {\n this.info({\n message: `Rotated log file from ${oldFilename} to ${newFilename}`,\n source: 'core',\n });\n });\n\n rotatingFileTransport.on('error', (error) => {\n this.error({\n message: `Error rotating log file: ${error.message}`,\n source: 'core',\n meta: { error },\n });\n });\n\n const consoleTransport = new transports.Console({\n handleExceptions: true,\n handleRejections: true,\n format: format.combine(\n format.colorize(),\n format.timestamp({ format: 'HH:mm:ss' }),\n format.printf((props) => {\n const splatArgs = props[Symbol.for('splat') as unknown as string] as\n | Record<string, unknown>[]\n | undefined;\n const result = logConsoleTransportSchema.safeParse({\n ...(splatArgs?.[0] ?? {}),\n timestamp: props['timestamp'],\n level: props.level,\n message: props.message,\n });\n\n if (result.success) {\n const { timestamp, level, source, message } = result.data;\n return `${timestamp} [${source}] ${level}: ${message}`;\n }\n\n // Fallback for logs not originating from LogService (e.g. unhandled exceptions caught by winston)\n return `${String(props['timestamp'])} ${props.level}: ${String(props.message)}`;\n })\n ),\n });\n\n this.logger = createLogger({\n level: options.log.level,\n transports: [rotatingFileTransport, consoleTransport],\n });\n }\n\n public debug(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.debug(message, { source, meta });\n }\n\n public info(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.info(message, { source, meta });\n }\n\n public warn(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.warn(message, { source, meta });\n }\n\n public error(props: LogProps) {\n const { source, message, meta } = logSchema.parse(props);\n\n this.logger.error(message, { source, meta });\n }\n}\n","export class RemoteOriginMissingError extends Error {\n constructor(projectId: string) {\n super(\n `Tried to delete Project \"${projectId}\" but it does not have a remote origin. Deleting a Project without a remote origin could lead to data loss. Use the \"force\" option to delete it anyway.`\n );\n\n this.name = 'RemoteOriginMissingError';\n }\n}\n","export class SynchronizeLocalChangesError extends Error {\n constructor(projectId: string) {\n super(\n `Tried to delete Project \"${projectId}\" but it has local changes that are not yet pushed to the remote origin. Deleting a Project with local changes could lead to data loss. Use the \"force\" option to delete it anyway.`\n );\n\n this.name = 'SynchronizeLocalChangesError';\n }\n}\n","import Fs from 'fs-extra';\nimport Os from 'node:os';\nimport Path from 'node:path';\nimport Semver from 'semver';\nimport {\n ProjectUpgradeError,\n RequiredParameterMissingError,\n} from '../error/index.js';\nimport { RemoteOriginMissingError } from '../error/RemoteOriginMissingError.js';\nimport { SynchronizeLocalChangesError } from '../error/SynchronizeLocalChangesError.js';\nimport type {\n FileReference,\n ObjectType,\n MigrateProjectProps,\n Version,\n} from '../schema/index.js';\nimport {\n cloneProjectSchema,\n createProjectSchema,\n currentBranchProjectSchema,\n deleteProjectSchema,\n getChangesProjectSchema,\n listBranchesProjectSchema,\n listProjectsSchema,\n objectTypeSchema,\n migrateProjectSchema,\n projectBranchSchema,\n projectFileSchema,\n projectFolderSchema,\n readProjectSchema,\n serviceTypeSchema,\n setRemoteOriginUrlProjectSchema,\n switchBranchProjectSchema,\n synchronizeProjectSchema,\n updateProjectSchema,\n upgradeProjectSchema,\n type CloneProjectProps,\n type CreateProjectProps,\n type CrudServiceWithListCount,\n type CurrentBranchProjectProps,\n type DeleteProjectProps,\n type ElekIoCoreOptions,\n type GetChangesProjectProps,\n type ListBranchesProjectProps,\n type ListProjectsProps,\n type PaginatedList,\n type Project,\n type ProjectFile,\n type ReadProjectProps,\n type SetRemoteOriginUrlProjectProps,\n type SwitchBranchProjectProps,\n type SynchronizeProjectProps,\n type UpdateProjectProps,\n type UpgradeProjectProps,\n} from '../schema/index.js';\nimport { isNotEmpty, pathTo } from '../util/node.js';\nimport { datetime, uuid } from '../util/shared.js';\nimport { AbstractCrudService } from './AbstractCrudService.js';\nimport type { AssetService } from './AssetService.js';\nimport type { CollectionService } from './CollectionService.js';\nimport type { EntryService } from './EntryService.js';\nimport type { GitService } from './GitService.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service that manages CRUD functionality for Project files on disk\n */\nexport class ProjectService\n extends AbstractCrudService\n implements CrudServiceWithListCount<Project>\n{\n private coreVersion: Version;\n private jsonFileService: JsonFileService;\n private gitService: GitService;\n private assetService: AssetService;\n private collectionService: CollectionService;\n private entryService: EntryService;\n\n constructor(\n coreVersion: Version,\n options: ElekIoCoreOptions,\n logService: LogService,\n jsonFileService: JsonFileService,\n gitService: GitService,\n assetService: AssetService,\n collectionService: CollectionService,\n entryService: EntryService\n ) {\n super(serviceTypeSchema.enum.Project, options, logService);\n\n this.coreVersion = coreVersion;\n this.jsonFileService = jsonFileService;\n this.gitService = gitService;\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 id = uuid();\n\n const projectFile: ProjectFile = {\n ...props,\n objectType: 'project',\n id,\n created: datetime(),\n updated: null,\n coreVersion: this.coreVersion,\n status: 'todo',\n version: '0.0.1',\n };\n\n const projectPath = 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, {\n initialBranch: projectBranchSchema.enum.production,\n });\n await this.jsonFileService.create(\n projectFile,\n pathTo.projectFile(id),\n projectFileSchema\n );\n await this.gitService.add(projectPath, ['.']);\n await this.gitService.commit(projectPath, {\n method: 'create',\n reference: { objectType: 'project', id },\n });\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work,\n {\n isNew: true,\n }\n );\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 force: true,\n });\n throw error;\n }\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Clones a Project by URL\n */\n public async clone(props: CloneProjectProps): Promise<Project> {\n cloneProjectSchema.parse(props);\n\n const tmpId = uuid();\n const tmpProjectPath = Path.join(pathTo.tmp, tmpId);\n // await Fs.ensureDir(tmpProjectPath);\n await this.gitService.clone(props.url, tmpProjectPath);\n\n // Check if it is actually a Project by trying to read it\n const projectFile = await this.jsonFileService.read(\n Path.join(tmpProjectPath, 'project.json'),\n projectFileSchema\n );\n\n // If so, copy it into the correct directory\n const projectPath = pathTo.project(projectFile.id);\n const alreadyExists = await Fs.pathExists(projectPath);\n if (alreadyExists) {\n throw new Error(\n `Tried to clone Project \"${projectFile.id}\" from \"${props.url}\" - but the Project already exists locally`\n );\n }\n await Fs.copy(tmpProjectPath, projectPath);\n await Fs.remove(tmpProjectPath);\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Returns a Project by ID\n *\n * If a commit hash is provided, the Project is read from history\n */\n public async read(props: ReadProjectProps): Promise<Project> {\n readProjectSchema.parse(props);\n\n if (!props.commitHash) {\n const projectFile = await this.jsonFileService.read(\n pathTo.projectFile(props.id),\n projectFileSchema\n );\n\n return await this.toProject(projectFile);\n } else {\n const projectFile = this.migrate(\n migrateProjectSchema.parse(\n JSON.parse(\n await this.gitService.getFileContentAtCommit(\n pathTo.project(props.id),\n pathTo.projectFile(props.id),\n props.commitHash\n )\n )\n )\n );\n\n return await this.toProject(projectFile);\n }\n }\n\n /**\n * Updates given Project\n */\n public async update(props: UpdateProjectProps): Promise<Project> {\n updateProjectSchema.parse(props);\n\n const projectPath = pathTo.project(props.id);\n const filePath = pathTo.projectFile(props.id);\n const prevProjectFile = await this.read(props);\n\n const projectFile: ProjectFile = {\n ...prevProjectFile,\n ...props,\n updated: datetime(),\n };\n\n await this.jsonFileService.update(projectFile, filePath, projectFileSchema);\n await this.gitService.add(projectPath, [filePath]);\n await this.gitService.commit(projectPath, {\n method: 'update',\n reference: { objectType: 'project', id: projectFile.id },\n });\n\n return await this.toProject(projectFile);\n }\n\n /**\n * Upgrades given Project to the current version of Core\n *\n * Needed when a new Core version is requiring changes to existing files or structure.\n */\n public async upgrade(props: UpgradeProjectProps): Promise<void> {\n upgradeProjectSchema.parse(props);\n\n const projectPath = pathTo.project(props.id);\n const projectFilePath = pathTo.projectFile(props.id);\n const currentBranch = await this.gitService.branches.current(projectPath);\n\n if (currentBranch !== projectBranchSchema.enum.work) {\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n }\n\n // Get the current Project file\n const currentProjectFile = migrateProjectSchema.parse(\n await this.jsonFileService.unsafeRead(projectFilePath)\n );\n\n if (Semver.gt(currentProjectFile.coreVersion, this.coreVersion)) {\n // Upgrade of the client needed before the project can be upgraded\n throw new ProjectUpgradeError(\n `The Projects Core version \"${currentProjectFile.coreVersion}\" is higher than the current Core version \"${this.coreVersion}\".`\n );\n }\n\n if (\n Semver.eq(currentProjectFile.coreVersion, this.coreVersion) &&\n props.force !== true\n ) {\n // Nothing, since both are equal\n throw new ProjectUpgradeError(\n `The Projects Core version \"${currentProjectFile.coreVersion}\" is already up to date.`\n );\n }\n\n const assetReferences = await this.listReferences('asset', props.id);\n const collectionReferences = await this.listReferences(\n 'collection',\n props.id\n );\n\n this.logService.info({\n source: 'core',\n message: `Attempting to upgrade Project \"${props.id}\" from Core version ${currentProjectFile.coreVersion} to ${this.coreVersion}`,\n });\n\n // Create a new branch to work on this migration\n const upgradeBranchName = `upgrade/core-${currentProjectFile.coreVersion}-to-${this.coreVersion}`;\n await this.gitService.branches.switch(projectPath, upgradeBranchName, {\n isNew: true,\n });\n\n try {\n await Promise.all(\n assetReferences.map(async (reference) => {\n await this.upgradeObjectFile(props.id, 'asset', reference);\n })\n );\n\n await Promise.all(\n collectionReferences.map(async (reference) => {\n await this.upgradeObjectFile(props.id, 'collection', reference);\n })\n );\n\n await Promise.all(\n collectionReferences.map(async (collectionReference) => {\n const entryReferences = await this.listReferences(\n 'entry',\n props.id,\n collectionReference.id\n );\n\n await Promise.all(\n entryReferences.map(async (reference) => {\n await this.upgradeObjectFile(\n props.id,\n 'entry',\n reference,\n collectionReference.id\n );\n })\n );\n })\n );\n\n // Upgrade the Project file itself\n const migratedProjectFile = this.migrate(currentProjectFile);\n await this.update(migratedProjectFile);\n\n // Merge the upgrade branch back into the work branch\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n await this.gitService.merge(projectPath, upgradeBranchName, {\n squash: true,\n });\n await this.gitService.commit(projectPath, {\n method: 'upgrade',\n reference: { objectType: 'project', id: migratedProjectFile.id },\n });\n await this.gitService.tags.create({\n path: projectPath,\n message: `Upgraded Project to Core version ${migratedProjectFile.coreVersion}`,\n });\n await this.gitService.branches.delete(\n projectPath,\n upgradeBranchName,\n true\n );\n\n this.logService.info({\n source: 'core',\n message: `Successfully upgraded Project \"${props.id}\" to Core version \"${this.coreVersion}\"`,\n meta: {\n previous: currentProjectFile,\n migrated: migratedProjectFile,\n },\n });\n } catch (error) {\n // Revert back to the work branch and delete the upgrade branch\n await this.gitService.branches.switch(\n projectPath,\n projectBranchSchema.enum.work\n );\n await this.gitService.branches.delete(\n projectPath,\n upgradeBranchName,\n true\n );\n\n throw error;\n }\n }\n\n public branches = {\n list: async (props: ListBranchesProjectProps) => {\n listBranchesProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (hasOrigin) {\n await this.gitService.fetch(projectPath);\n }\n return await this.gitService.branches.list(projectPath);\n },\n current: async (props: CurrentBranchProjectProps) => {\n currentBranchProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n return await this.gitService.branches.current(projectPath);\n },\n switch: async (props: SwitchBranchProjectProps) => {\n switchBranchProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n return await this.gitService.branches.switch(\n projectPath,\n props.branch,\n props.options\n );\n },\n };\n\n /**\n * Updates the remote origin URL of given Project\n *\n * @todo maybe add this logic to the update method\n */\n public async setRemoteOriginUrl(props: SetRemoteOriginUrlProjectProps) {\n setRemoteOriginUrlProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (!hasOrigin) {\n await this.gitService.remotes.addOrigin(projectPath, props.url);\n } else {\n await this.gitService.remotes.setOriginUrl(projectPath, props.url);\n }\n }\n\n /**\n * Returns the differences of the given Projects current branch\n * between the local and remote `origin` (commits ahead & behind)\n *\n * Throws an error if the Project does not have a remote origin.\n *\n * - `behind` contains a list of commits on the current branch that are available on the remote `origin` but not yet locally\n * - `ahead` contains a list of commits on the current branch that are available locally but not yet on the remote `origin`\n */\n public async getChanges(props: GetChangesProjectProps) {\n getChangesProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n const hasRemoteOrigin =\n await this.gitService.remotes.hasOrigin(projectPath);\n if (hasRemoteOrigin === false) {\n throw new Error(`Project \"${props.id}\" does not have a remote origin`);\n }\n const currentBranch = await this.gitService.branches.current(projectPath);\n\n await this.gitService.fetch(projectPath);\n const behind = await this.gitService.log(projectPath, {\n between: { from: currentBranch, to: `origin/${currentBranch}` },\n });\n const ahead = await this.gitService.log(projectPath, {\n between: { from: `origin/${currentBranch}`, to: currentBranch },\n });\n\n return {\n behind,\n ahead,\n };\n }\n\n /**\n * Pulls remote changes of `origin` down to the local repository\n * and then pushes local commits to the upstream branch\n */\n public async synchronize(props: SynchronizeProjectProps) {\n synchronizeProjectSchema.parse(props);\n const projectPath = pathTo.project(props.id);\n\n await this.gitService.pull(projectPath);\n await this.gitService.push(projectPath);\n }\n\n /**\n * Deletes given Project\n *\n * Deletes the whole Project folder including the history, not only the config file.\n * Throws in case a Project is only available locally and could be lost forever,\n * or changes are not pushed to a remote yet.\n */\n public async delete(props: DeleteProjectProps): Promise<void> {\n deleteProjectSchema.parse(props);\n\n const hasRemoteOrigin = await this.gitService.remotes.hasOrigin(\n pathTo.project(props.id)\n );\n\n if (hasRemoteOrigin === false && props.force !== true) {\n throw new RemoteOriginMissingError(props.id);\n }\n\n if (hasRemoteOrigin === true && props.force !== true) {\n const changes = await this.getChanges({ id: props.id });\n if (changes.ahead.length > 0) {\n throw new SynchronizeLocalChangesError(props.id);\n }\n }\n\n await Fs.remove(pathTo.project(props.id));\n }\n\n /**\n * Lists outdated Projects that need to be upgraded\n */\n public async listOutdated(): Promise<MigrateProjectProps[]> {\n const projectReferences = await this.listReferences(\n objectTypeSchema.enum.project\n );\n\n const result = await Promise.all(\n projectReferences.map(async (reference) => {\n const json = await this.jsonFileService.unsafeRead(\n pathTo.projectFile(reference.id)\n );\n const projectFile = migrateProjectSchema.parse(json);\n\n if (projectFile.coreVersion !== this.coreVersion) {\n return projectFile;\n }\n\n return null;\n })\n );\n\n return result.filter(isNotEmpty);\n }\n\n public async list(\n props?: ListProjectsProps\n ): Promise<PaginatedList<Project>> {\n if (props) {\n listProjectsSchema.parse(props);\n }\n\n const offset = props?.offset || 0;\n const limit = props?.limit ?? 15;\n\n const projectReferences = await this.listReferences(\n objectTypeSchema.enum.project\n );\n\n const partialProjectReferences =\n limit === 0\n ? projectReferences.slice(offset)\n : projectReferences.slice(offset, offset + limit);\n\n const projects = await this.returnResolved(\n partialProjectReferences.map((reference) => {\n return this.read({ id: reference.id });\n })\n );\n\n return {\n total: projectReferences.length,\n limit,\n offset,\n list: projects,\n };\n }\n\n public async count(): Promise<number> {\n return (await this.listReferences(objectTypeSchema.enum.project)).length;\n }\n\n /**\n * Checks if given object is of type Project\n */\n public isProject(obj: unknown): obj is Project {\n return projectFileSchema.safeParse(obj).success;\n }\n\n /**\n * Migrates an potentially outdated Project file to the current schema\n */\n public migrate(props: MigrateProjectProps) {\n // @todo\n\n props.coreVersion = this.coreVersion;\n\n return projectFileSchema.parse(props);\n }\n\n /**\n * Creates a Project from given ProjectFile\n */\n private async toProject(projectFile: ProjectFile): Promise<Project> {\n const projectPath = pathTo.project(projectFile.id);\n\n let remoteOriginUrl = null;\n const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);\n if (hasOrigin) {\n remoteOriginUrl = await this.gitService.remotes.getOriginUrl(projectPath);\n }\n\n const fullHistory = await this.gitService.log(\n pathTo.project(projectFile.id)\n );\n const history = await this.gitService.log(pathTo.project(projectFile.id), {\n filePath: pathTo.projectFile(projectFile.id),\n });\n\n return {\n ...projectFile,\n remoteOriginUrl,\n history,\n fullHistory,\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.enum);\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 private async upgradeObjectFile(\n projectId: string,\n objectType: ObjectType,\n reference: FileReference,\n collectionId?: string\n ) {\n switch (objectType) {\n case 'asset': {\n const assetFilePath = pathTo.assetFile(projectId, reference.id);\n const prevAssetFile =\n await this.jsonFileService.unsafeRead(assetFilePath);\n const migratedAssetFile = this.assetService.migrate(prevAssetFile);\n await this.assetService.update({ projectId, ...migratedAssetFile });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${assetFilePath}\"`,\n meta: {\n previous: prevAssetFile,\n migrated: migratedAssetFile,\n },\n });\n return;\n }\n case 'collection': {\n const collectionFilePath = pathTo.collectionFile(\n projectId,\n reference.id\n );\n const prevCollectionFile =\n await this.jsonFileService.unsafeRead(collectionFilePath);\n const migratedCollectionFile =\n this.collectionService.migrate(prevCollectionFile);\n await this.collectionService.update({\n projectId,\n ...migratedCollectionFile,\n });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${collectionFilePath}\"`,\n meta: {\n previous: prevCollectionFile,\n migrated: migratedCollectionFile,\n },\n });\n return;\n }\n case 'entry': {\n if (!collectionId) {\n throw new RequiredParameterMissingError('collectionId');\n }\n const entryFilePath = pathTo.entryFile(\n projectId,\n collectionId,\n reference.id\n );\n const prevEntryFile =\n await this.jsonFileService.unsafeRead(entryFilePath);\n const migratedEntryFile = this.entryService.migrate(prevEntryFile);\n await this.entryService.update({\n projectId,\n collectionId,\n ...migratedEntryFile,\n });\n this.logService.info({\n source: 'core',\n message: `Upgraded ${objectType} \"${entryFilePath}\"`,\n meta: {\n previous: prevEntryFile,\n migrated: migratedEntryFile,\n },\n });\n return;\n }\n default:\n throw new Error(\n `Trying to upgrade unsupported object file of type \"${objectType}\"`\n );\n }\n }\n}\n","import {\n UserTypeSchema,\n setUserSchema,\n userFileSchema,\n type SetUserProps,\n type User,\n type UserFile,\n} from '../schema/index.js';\nimport { pathTo } from '../util/node.js';\nimport type { JsonFileService } from './JsonFileService.js';\nimport type { LogService } from './LogService.js';\n\n/**\n * Service to handle the User that is currently working with Core\n */\nexport class UserService {\n private readonly logService: LogService;\n private readonly jsonFileService: JsonFileService;\n\n constructor(logService: LogService, jsonFileService: JsonFileService) {\n this.logService = logService;\n this.jsonFileService = jsonFileService;\n }\n\n /**\n * Returns the User currently working with Core\n */\n public async get(): Promise<User | null> {\n try {\n return await this.jsonFileService.read(pathTo.userFile, userFileSchema);\n } catch {\n this.logService.info({ source: 'core', message: 'No User found' });\n\n return null;\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 = 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 this.logService.debug({\n source: 'core',\n message: 'Updated User',\n });\n\n return userFile;\n }\n}\n","import Fs from 'fs-extra';\nimport * as packageJson from '../package.json' with { type: 'json' };\nimport { LocalApi } from './api/index.js';\nimport type { Version } from './schema/index.js';\nimport {\n constructorElekIoCoreSchema,\n type ConstructorElekIoCoreProps,\n type ElekIoCoreOptions,\n} from './schema/index.js';\nimport {\n AssetService,\n CollectionService,\n EntryService,\n GitService,\n JsonFileService,\n ProjectService,\n UserService,\n} from './service/index.js';\nimport { LogService } from './service/LogService.js';\nimport * as Util from './util/node.js';\n\n// Export all schemas and shared code that works inside node environments,\n// including code that requires filesystem access / git integration etc.\nexport * from './schema/index.js';\nexport * from './util/shared.js';\n\n/**\n * elek.io Core\n *\n * Provides access to all services Core is offering\n */\nexport default class ElekIoCore {\n public readonly coreVersion: Version;\n public readonly options: ElekIoCoreOptions;\n private readonly logService: LogService;\n private readonly userService: UserService;\n private readonly gitService: GitService;\n private readonly jsonFileService: JsonFileService;\n private readonly assetService: AssetService;\n private readonly projectService: ProjectService;\n private readonly collectionService: CollectionService;\n private readonly entryService: EntryService;\n private readonly localApi: LocalApi;\n\n constructor(props?: ConstructorElekIoCoreProps) {\n this.coreVersion = packageJson.default.version;\n const parsedProps = constructorElekIoCoreSchema.parse(props);\n\n const defaults: ElekIoCoreOptions = {\n log: {\n level: 'info',\n },\n file: {\n cache: true,\n },\n };\n this.options = Object.assign({}, defaults, parsedProps);\n\n this.logService = new LogService(this.options);\n this.jsonFileService = new JsonFileService(this.options, this.logService);\n this.userService = new UserService(this.logService, this.jsonFileService);\n this.gitService = new GitService(\n this.options,\n this.logService,\n this.userService\n );\n this.assetService = new AssetService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService\n );\n this.collectionService = new CollectionService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService\n );\n this.entryService = new EntryService(\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService,\n this.collectionService\n );\n this.projectService = new ProjectService(\n this.coreVersion,\n this.options,\n this.logService,\n this.jsonFileService,\n this.gitService,\n this.assetService,\n this.collectionService,\n this.entryService\n );\n this.localApi = new LocalApi(\n this.logService,\n this.projectService,\n this.collectionService,\n this.entryService,\n this.assetService\n );\n\n this.logService.info({\n source: 'core',\n message: `Initializing elek.io Core ${this.coreVersion}`,\n meta: { options: this.options },\n });\n\n Fs.mkdirpSync(Util.pathTo.projects);\n Fs.mkdirpSync(Util.pathTo.tmp);\n Fs.emptyDirSync(Util.pathTo.tmp);\n }\n\n /**\n * Exposes the logger\n */\n public get logger() {\n return this.logService;\n }\n\n /**\n * Utility / helper functions\n */\n public get util() {\n return Util;\n }\n\n /**\n * Exposes git functions\n */\n public get git(): GitService {\n return this.gitService;\n }\n\n /**\n * Getter and setter methods for the User currently working with Core\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 * Allows starting and stopping a REST API\n * to allow developers to read local Project data\n */\n public get api(): LocalApi {\n return this.localApi;\n }\n}\n","import { z } from '@hono/zod-openapi';\nimport type { FieldDefinition } from '../schema/fieldSchema.js';\nimport {\n getTranslatableBooleanValueContentSchemaFromFieldDefinition,\n getTranslatableNumberValueContentSchemaFromFieldDefinition,\n getTranslatableReferenceValueContentSchemaFromFieldDefinition,\n getTranslatableStringValueContentSchemaFromFieldDefinition,\n} from '../schema/schemaFromFieldDefinition.js';\nimport { ValueTypeSchema } from '../schema/valueSchema.js';\n\n/**\n * Generates a flat Zod object schema from collection field definitions\n * for use with Astro's `parseData` validation.\n *\n * Each key is the field definition ID (UUID) and each value schema\n * is the translatable content schema for that field type.\n */\nexport function buildEntryValuesSchema(fieldDefinitions: FieldDefinition[]) {\n const shape: Record<string, z.ZodTypeAny> = {};\n\n for (const fieldDef of fieldDefinitions) {\n switch (fieldDef.valueType) {\n case ValueTypeSchema.enum.string:\n shape[fieldDef.id] =\n getTranslatableStringValueContentSchemaFromFieldDefinition(fieldDef);\n break;\n case ValueTypeSchema.enum.number:\n shape[fieldDef.id] =\n getTranslatableNumberValueContentSchemaFromFieldDefinition(fieldDef);\n break;\n case ValueTypeSchema.enum.boolean:\n shape[fieldDef.id] =\n getTranslatableBooleanValueContentSchemaFromFieldDefinition();\n break;\n case ValueTypeSchema.enum.reference:\n shape[fieldDef.id] =\n getTranslatableReferenceValueContentSchemaFromFieldDefinition(\n fieldDef\n );\n break;\n }\n }\n\n return z.object(shape);\n}\n\n/**\n * Generates a TypeScript type string from collection field definitions\n * for use with Astro's `createSchema` API.\n *\n * The generated string is written by Astro to a `.ts` file and imported\n * as the `Entry` type for the collection.\n */\nexport function buildEntryValuesTypeString(\n fieldDefinitions: FieldDefinition[]\n): string {\n if (fieldDefinitions.length === 0) {\n return 'export type Entry = Record<string, never>;';\n }\n\n const fields = fieldDefinitions.map((fieldDef) => {\n const tsType = valueTypeToTsType(fieldDef.valueType);\n return ` \"${fieldDef.id}\": Partial<Record<SupportedLanguage, ${tsType}>>`;\n });\n\n return [\n `type SupportedLanguage = \"bg\" | \"cs\" | \"da\" | \"de\" | \"el\" | \"en\" | \"es\" | \"et\" | \"fi\" | \"fr\" | \"hu\" | \"it\" | \"ja\" | \"ko\" | \"lt\" | \"lv\" | \"nb\" | \"nl\" | \"pl\" | \"pt\" | \"ro\" | \"ru\" | \"sk\" | \"sl\" | \"sv\" | \"tr\" | \"uk\" | \"zh\";`,\n `export type Entry = {`,\n fields.join(';\\n') + ';',\n `};`,\n ].join('\\n');\n}\n\nfunction valueTypeToTsType(valueType: string): string {\n switch (valueType) {\n case 'string':\n return 'string';\n case 'number':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'reference':\n return 'Array<{ id: string; objectType: string }>';\n default:\n return 'unknown';\n }\n}\n","import type { Value } from '../schema/valueSchema.js';\n\n/**\n * Transforms an elek.io Entry's values array into a flat object\n * keyed by field definition ID. Each value's translatable content\n * is preserved as-is.\n */\nexport function transformEntryValues(values: Value[]): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const value of values) {\n result[value.fieldDefinitionId] = value.content;\n }\n return result;\n}\n","import type { Loader } from 'astro/loaders';\nimport Path from 'node:path';\nimport Fs from 'fs-extra';\nimport ElekIoCore, { assetSchema } from './index.node.js';\nimport {\n buildEntryValuesSchema,\n buildEntryValuesTypeString,\n} from './astro/schema.js';\nimport { transformEntryValues } from './astro/transform.js';\n\ninterface ElekAssetsProps {\n projectId: string;\n outDir: string;\n}\n\ninterface ElekEntriesOptions {\n projectId: string;\n collectionId: string;\n}\n\nconst core = new ElekIoCore({\n log: { level: 'info' },\n});\n\n/**\n * Astro content loader for elek.io Assets.\n *\n * Reads and saves Assets from a Project and exposes them through\n * Astro's content collection system.\n *\n * @example\n * ```ts\n * // src/content.config.ts\n * import { defineCollection } from 'astro:content';\n * import { elekAssets } from '@elek-io/core/astro';\n *\n * export const collections = {\n * assets: defineCollection({\n * loader: elekAssets({\n * projectId: 'abc-123-...',\n * outDir: './content/assets',\n * }),\n * });\n * };\n * ```\n */\nexport function elekAssets(props: ElekAssetsProps): Loader {\n return {\n name: 'elek-assets',\n schema: assetSchema,\n load: async (context) => {\n context.logger.info(\n `Loading elek.io Assets for Project \"${props.projectId}\", saving to \"${props.outDir}\"`\n );\n context.store.clear();\n\n const { list: assets, total } = await core.assets.list({\n projectId: props.projectId,\n limit: 0,\n });\n if (total === 0) {\n context.logger.warn('No Assets found');\n } else {\n context.logger.info(`Found ${total} Assets`);\n }\n\n for (const asset of assets) {\n const absoluteAssetFilePath = Path.resolve(\n Path.join(props.outDir, `${asset.id}.${asset.extension}`)\n );\n await Fs.ensureDir(Path.dirname(absoluteAssetFilePath));\n await core.assets.save({\n projectId: props.projectId,\n id: asset.id,\n filePath: absoluteAssetFilePath,\n });\n\n const parsed = await context.parseData({\n id: asset.id,\n data: {\n ...asset,\n absolutePath: absoluteAssetFilePath,\n },\n });\n context.store.set({ id: asset.id, data: parsed });\n }\n\n context.logger.info('Finished loading Assets');\n },\n };\n}\n\n/**\n * Astro content loader for elek.io Collection Entries.\n *\n * Reads all Entries from a Collection and exposes them through\n * Astro's content collection system.\n *\n * @example\n * ```ts\n * // src/content.config.ts\n * import { defineCollection } from 'astro:content';\n * import { elekEntries } from '@elek-io/core/astro';\n *\n * export const collections = {\n * entries: defineCollection({\n * loader: elekEntries({\n * projectId: 'abc-123-...',\n * collectionId: 'def-456-...',\n * }),\n * });\n * };\n * ```\n */\nexport function elekEntries(props: ElekEntriesOptions): Loader {\n return {\n name: 'elek-entries',\n createSchema: async () => {\n const collection = await core.collections.read({\n projectId: props.projectId,\n id: props.collectionId,\n });\n\n return {\n schema: buildEntryValuesSchema(collection.fieldDefinitions),\n types: buildEntryValuesTypeString(collection.fieldDefinitions),\n };\n },\n load: async (context) => {\n context.logger.info(\n `Loading elek.io Entries of Collection \"${props.collectionId}\" and Project \"${props.projectId}\"`\n );\n context.store.clear();\n\n const { list: entries, total } = await core.entries.list({\n projectId: props.projectId,\n collectionId: props.collectionId,\n limit: 0,\n });\n if (total === 0) {\n context.logger.warn('No Entries found');\n } else {\n context.logger.info(`Found ${total} Entries`);\n }\n\n for (const entry of entries) {\n const values = transformEntryValues(entry.values);\n\n const parsed = await context.parseData({ id: entry.id, data: values });\n context.store.set({ id: entry.id, data: parsed });\n }\n\n context.logger.info('Finished loading Entries');\n },\n };\n}\n"],"mappings":"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"}
|