@elek-io/core 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -33,11 +33,9 @@ __export(src_exports, {
33
33
  default: () => ElekIoCore
34
34
  });
35
35
  module.exports = __toCommonJS(src_exports);
36
- var import_shared12 = require("@elek-io/shared");
37
36
  var import_fs_extra7 = __toESM(require("fs-extra"), 1);
38
37
 
39
38
  // src/service/AssetService.ts
40
- var import_shared7 = require("@elek-io/shared");
41
39
  var import_fs_extra3 = __toESM(require("fs-extra"), 1);
42
40
  var import_is_svg = __toESM(require("is-svg"), 1);
43
41
 
@@ -49,10 +47,332 @@ var RequiredParameterMissingError = class extends Error {
49
47
  }
50
48
  };
51
49
 
50
+ // src/schema/assetSchema.ts
51
+ var import_zod3 = __toESM(require("zod"), 1);
52
+
53
+ // src/schema/baseSchema.ts
54
+ var import_zod = __toESM(require("zod"), 1);
55
+ var environmentSchema = import_zod.default.enum(["production", "development", "test"]);
56
+ var supportedLanguageSchema = import_zod.default.enum([
57
+ /**
58
+ * Bulgarian
59
+ */
60
+ "bg",
61
+ //
62
+ "cs",
63
+ // Czech
64
+ "da",
65
+ // Danish
66
+ "de",
67
+ // German
68
+ "el",
69
+ // Greek
70
+ "en",
71
+ // (US) English
72
+ "es",
73
+ // Spanish
74
+ "et",
75
+ // Estonian
76
+ "fi",
77
+ // Finnish
78
+ "fr",
79
+ // French
80
+ "hu",
81
+ // Hungarian
82
+ "it",
83
+ // Italian
84
+ "ja",
85
+ // Japanese
86
+ "lt",
87
+ // Lithuanian
88
+ "lv",
89
+ // Latvian
90
+ "nl",
91
+ // Dutch
92
+ "pl",
93
+ // Polish
94
+ "pt",
95
+ // Portuguese
96
+ "ro",
97
+ // Romanian
98
+ "ru",
99
+ // Russian
100
+ "sk",
101
+ // Slovak
102
+ "sl",
103
+ // Slovenian
104
+ "sv",
105
+ // Swedish
106
+ "zh"
107
+ // (Simplified) Chinese
108
+ ]);
109
+ var supportedIconSchema = import_zod.default.enum(["home", "plus", "foobar"]);
110
+ var supportedAssetMimeTypeSchema = import_zod.default.enum([
111
+ "image/avif",
112
+ "image/gif",
113
+ "image/jpeg",
114
+ "image/png",
115
+ "image/svg+xml",
116
+ "image/webp",
117
+ "application/pdf",
118
+ "application/zip",
119
+ "video/mp4",
120
+ "video/webm",
121
+ "audio/webm",
122
+ "audio/flac"
123
+ ]);
124
+ var supportedAssetExtensionSchema = import_zod.default.enum([
125
+ "avif",
126
+ "gif",
127
+ "jpg",
128
+ "jpeg",
129
+ "png",
130
+ "svg",
131
+ "webp",
132
+ "pdf",
133
+ "zip",
134
+ "mp4",
135
+ "webm",
136
+ "flac",
137
+ "json"
138
+ ]);
139
+ var supportedAssetTypeSchema = import_zod.default.object({
140
+ extension: supportedAssetExtensionSchema,
141
+ mimeType: supportedAssetMimeTypeSchema
142
+ });
143
+ var objectTypeSchema = import_zod.default.enum([
144
+ "project",
145
+ "asset",
146
+ "collection",
147
+ "entry",
148
+ "value",
149
+ "sharedValue"
150
+ ]);
151
+ var versionSchema = import_zod.default.string();
152
+ var uuidSchema = import_zod.default.string().uuid("shared.invalidUuid");
153
+ var translatableStringSchema = import_zod.default.record(
154
+ supportedLanguageSchema,
155
+ import_zod.default.string().trim().min(1, "shared.translatableStringRequired")
156
+ );
157
+ var translatableNumberSchema = import_zod.default.record(
158
+ supportedLanguageSchema,
159
+ import_zod.default.number({ required_error: "shared.translatableNumberRequired" })
160
+ );
161
+ var translatableBooleanSchema = import_zod.default.record(
162
+ supportedLanguageSchema,
163
+ import_zod.default.boolean({ required_error: "shared.translatableBooleanRequired" })
164
+ );
165
+ function translatableArrayOf(schema) {
166
+ return import_zod.default.record(supportedLanguageSchema, import_zod.default.array(schema));
167
+ }
168
+
169
+ // src/schema/fileSchema.ts
170
+ var import_zod2 = __toESM(require("zod"), 1);
171
+ var baseFileSchema = import_zod2.default.object({
172
+ /**
173
+ * The ID of the file
174
+ *
175
+ * The ID is part of the files name.
176
+ */
177
+ id: uuidSchema.readonly(),
178
+ /**
179
+ * The timestamp of the file being created is set by the service of "objectType" while creating it
180
+ */
181
+ created: import_zod2.default.number().readonly(),
182
+ /**
183
+ * The timestamp of the file being updated is set by the service of "objectType" while updating it
184
+ */
185
+ updated: import_zod2.default.number().nullable()
186
+ });
187
+ var baseFileWithLanguageSchema = baseFileSchema.extend({
188
+ /**
189
+ * The language of the file
190
+ *
191
+ * The language is part of the files name and together with it's ID the only unique identifier.
192
+ * That's why the language cannot be changed after creating the file.
193
+ *
194
+ * @todo Maybe remove the above restriction by implementing logic to handle changing the files language inside all services
195
+ */
196
+ language: supportedLanguageSchema.readonly()
197
+ });
198
+ var fileReferenceSchema = import_zod2.default.object({
199
+ id: uuidSchema,
200
+ language: supportedLanguageSchema.optional(),
201
+ extension: supportedAssetExtensionSchema.optional()
202
+ });
203
+
204
+ // src/schema/assetSchema.ts
205
+ var assetFileSchema = baseFileWithLanguageSchema.extend({
206
+ objectType: import_zod3.default.literal(objectTypeSchema.Enum.asset).readonly(),
207
+ name: import_zod3.default.string(),
208
+ description: import_zod3.default.string(),
209
+ extension: supportedAssetExtensionSchema.readonly(),
210
+ mimeType: supportedAssetMimeTypeSchema.readonly(),
211
+ /**
212
+ * Total size in bytes
213
+ */
214
+ size: import_zod3.default.number().readonly()
215
+ });
216
+ var assetSchema = assetFileSchema.extend({
217
+ /**
218
+ * Absolute path on this filesystem
219
+ */
220
+ absolutePath: import_zod3.default.string().readonly()
221
+ });
222
+ var assetExportSchema = assetSchema.extend({});
223
+ var createAssetSchema = assetFileSchema.pick({
224
+ name: true,
225
+ description: true,
226
+ language: true
227
+ }).extend({
228
+ projectId: uuidSchema.readonly(),
229
+ /**
230
+ * Path of the file to add as a new Asset
231
+ */
232
+ filePath: import_zod3.default.string().readonly()
233
+ });
234
+ var readAssetSchema = assetFileSchema.pick({
235
+ id: true,
236
+ language: true
237
+ }).extend({
238
+ projectId: uuidSchema.readonly()
239
+ });
240
+ var updateAssetSchema = assetFileSchema.pick({
241
+ id: true,
242
+ name: true,
243
+ description: true,
244
+ language: true
245
+ }).extend({
246
+ projectId: uuidSchema.readonly(),
247
+ /**
248
+ * Path of the new file to update the Asset with
249
+ */
250
+ newFilePath: import_zod3.default.string().readonly().optional()
251
+ });
252
+ var deleteAssetSchema = assetFileSchema.pick({
253
+ id: true,
254
+ language: true,
255
+ extension: true
256
+ }).extend({
257
+ projectId: uuidSchema.readonly()
258
+ });
259
+ var countAssetsSchema = import_zod3.default.object({ projectId: uuidSchema.readonly() });
260
+
261
+ // src/schema/serviceSchema.ts
262
+ var import_zod5 = require("zod");
263
+
264
+ // src/schema/gitSchema.ts
265
+ var import_zod4 = require("zod");
266
+ var gitRepositoryPathSchema = import_zod4.z.string();
267
+ var gitSignatureSchema = import_zod4.z.object({
268
+ name: import_zod4.z.string(),
269
+ email: import_zod4.z.string()
270
+ });
271
+ var gitCommitSchema = import_zod4.z.object({
272
+ /**
273
+ * SHA-1 hash of the commit
274
+ */
275
+ hash: import_zod4.z.string(),
276
+ message: import_zod4.z.string(),
277
+ author: gitSignatureSchema,
278
+ timestamp: import_zod4.z.number(),
279
+ tag: import_zod4.z.string().nullable()
280
+ });
281
+ var GitCommitIconNative = /* @__PURE__ */ ((GitCommitIconNative2) => {
282
+ GitCommitIconNative2["INIT"] = ":tada:";
283
+ GitCommitIconNative2["CREATE"] = ":heavy_plus_sign:";
284
+ GitCommitIconNative2["UPDATE"] = ":wrench:";
285
+ GitCommitIconNative2["DELETE"] = ":fire:";
286
+ return GitCommitIconNative2;
287
+ })(GitCommitIconNative || {});
288
+ var gitCommitIconSchema = import_zod4.z.nativeEnum(GitCommitIconNative);
289
+ var gitInitOptionsSchema = import_zod4.z.object({
290
+ /**
291
+ * 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).
292
+ */
293
+ initialBranch: import_zod4.z.string()
294
+ });
295
+ var gitCloneOptionsSchema = import_zod4.z.object({
296
+ /**
297
+ * 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.
298
+ */
299
+ depth: import_zod4.z.number(),
300
+ /**
301
+ * 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.
302
+ */
303
+ singleBranch: import_zod4.z.boolean(),
304
+ /**
305
+ * 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.
306
+ */
307
+ branch: import_zod4.z.string()
308
+ });
309
+ var gitSwitchOptionsSchema = import_zod4.z.object({
310
+ /**
311
+ * If true, creates a new local branch and then switches to it
312
+ *
313
+ * @see https://git-scm.com/docs/git-switch#Documentation/git-switch.txt---createltnew-branchgt
314
+ */
315
+ isNew: import_zod4.z.boolean().optional()
316
+ });
317
+ var gitLogOptionsSchema = import_zod4.z.object({
318
+ /**
319
+ * Limit the result to given number of commits
320
+ */
321
+ limit: import_zod4.z.number().optional(),
322
+ /**
323
+ * Only list commits that are between given SHAs or tag names
324
+ *
325
+ * Note that the commits of from and to are not included in the result
326
+ */
327
+ between: import_zod4.z.object({
328
+ /**
329
+ * From the oldest commit
330
+ */
331
+ from: import_zod4.z.string(),
332
+ /**
333
+ * To the newest commit
334
+ *
335
+ * Defaults to the current HEAD
336
+ */
337
+ to: import_zod4.z.string().optional()
338
+ })
339
+ });
340
+
341
+ // src/schema/serviceSchema.ts
342
+ var serviceTypeSchema = import_zod5.z.enum([
343
+ "Git",
344
+ "GitTag",
345
+ "User",
346
+ "Project",
347
+ "Asset",
348
+ "JsonFile",
349
+ "Search",
350
+ "Collection",
351
+ "Entry",
352
+ "Value"
353
+ ]);
354
+ var listSchema = import_zod5.z.object({
355
+ projectId: uuidSchema,
356
+ limit: import_zod5.z.number().optional(),
357
+ offset: import_zod5.z.number().optional()
358
+ });
359
+ var listCollectionsSchema = listSchema;
360
+ var listEntriesSchema = listSchema.extend({
361
+ collectionId: uuidSchema
362
+ });
363
+ var listAssetsSchema = listSchema;
364
+ var listProjectsSchema = listSchema.omit({
365
+ projectId: true
366
+ });
367
+ var listGitTagsSchema = import_zod5.z.object({
368
+ path: gitRepositoryPathSchema
369
+ });
370
+
52
371
  // src/util/index.ts
53
372
  var util_exports = {};
54
373
  __export(util_exports, {
55
374
  assignDefaultIfMissing: () => assignDefaultIfMissing,
375
+ currentTimestamp: () => currentTimestamp,
56
376
  files: () => files,
57
377
  folders: () => folders,
58
378
  fromPath: () => fromPath,
@@ -62,15 +382,543 @@ __export(util_exports, {
62
382
  notEmpty: () => notEmpty,
63
383
  pathTo: () => pathTo,
64
384
  returnResolved: () => returnResolved,
385
+ slug: () => slug,
65
386
  spawnChildProcess: () => spawnChildProcess,
387
+ uuid: () => uuid,
66
388
  workingDirectory: () => workingDirectory
67
389
  });
68
- var import_shared = require("@elek-io/shared");
69
390
  var import_child_process = require("child_process");
70
391
  var import_fs_extra = __toESM(require("fs-extra"), 1);
71
392
  var import_lodash_es = require("lodash-es");
72
393
  var import_os = __toESM(require("os"), 1);
73
394
  var import_path = __toESM(require("path"), 1);
395
+ var import_slugify = __toESM(require("slugify"), 1);
396
+ var import_uuid = require("uuid");
397
+
398
+ // src/schema/projectSchema.ts
399
+ var import_zod9 = require("zod");
400
+
401
+ // src/schema/collectionSchema.ts
402
+ var import_zod8 = __toESM(require("zod"), 1);
403
+
404
+ // src/schema/entrySchema.ts
405
+ var import_zod7 = __toESM(require("zod"), 1);
406
+
407
+ // src/schema/valueSchema.ts
408
+ var import_zod6 = __toESM(require("zod"), 1);
409
+ var ValueTypeSchema = import_zod6.default.enum([
410
+ "string",
411
+ "number",
412
+ "boolean",
413
+ "reference"
414
+ ]);
415
+ var ValueInputTypeSchema = import_zod6.default.enum([
416
+ // String
417
+ "text",
418
+ "textarea",
419
+ "email",
420
+ // 'password', @todo maybe if there is a usecase
421
+ "url",
422
+ "ip",
423
+ "date",
424
+ "time",
425
+ "datetime",
426
+ "telephone",
427
+ // Number
428
+ "number",
429
+ "range",
430
+ // Boolean
431
+ "toggle",
432
+ // Reference
433
+ "asset",
434
+ "entry"
435
+ // 'sharedValue', // @todo
436
+ ]);
437
+ var ValueInputWidthSchema = import_zod6.default.enum(["12", "6", "4", "3"]);
438
+ var ValueDefinitionBaseSchema = import_zod6.default.object({
439
+ id: uuidSchema.readonly(),
440
+ label: translatableStringSchema,
441
+ description: translatableStringSchema,
442
+ isRequired: import_zod6.default.boolean(),
443
+ isDisabled: import_zod6.default.boolean(),
444
+ isUnique: import_zod6.default.boolean(),
445
+ inputWidth: ValueInputWidthSchema
446
+ });
447
+ var StringValueDefinitionBaseSchema = ValueDefinitionBaseSchema.extend(
448
+ {
449
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.string),
450
+ defaultValue: import_zod6.default.string().nullable()
451
+ }
452
+ );
453
+ var textValueDefinitionSchema = StringValueDefinitionBaseSchema.extend(
454
+ {
455
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.text),
456
+ min: import_zod6.default.number().nullable(),
457
+ max: import_zod6.default.number().nullable()
458
+ }
459
+ );
460
+ var textareaValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
461
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.textarea),
462
+ min: import_zod6.default.number().nullable(),
463
+ max: import_zod6.default.number().nullable()
464
+ });
465
+ var emailValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
466
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.email),
467
+ defaultValue: import_zod6.default.string().email().nullable()
468
+ });
469
+ var urlValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
470
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.url),
471
+ defaultValue: import_zod6.default.string().url().nullable()
472
+ });
473
+ var ipValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
474
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.ip),
475
+ defaultValue: import_zod6.default.string().ip().nullable()
476
+ });
477
+ var dateValueDefinitionSchema = StringValueDefinitionBaseSchema.extend(
478
+ {
479
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.date),
480
+ defaultValue: import_zod6.default.string().date().nullable()
481
+ }
482
+ );
483
+ var timeValueDefinitionSchema = StringValueDefinitionBaseSchema.extend(
484
+ {
485
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.time),
486
+ defaultValue: import_zod6.default.string().time().nullable()
487
+ }
488
+ );
489
+ var datetimeValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
490
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.datetime),
491
+ defaultValue: import_zod6.default.string().datetime().nullable()
492
+ });
493
+ var telephoneValueDefinitionSchema = StringValueDefinitionBaseSchema.extend({
494
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.telephone)
495
+ // defaultValue: z.string().e164(), @todo when zod v4 releases @see https://github.com/colinhacks/zod/pull/3476
496
+ });
497
+ var stringValueDefinitionSchema = import_zod6.default.union([
498
+ textValueDefinitionSchema,
499
+ textareaValueDefinitionSchema,
500
+ emailValueDefinitionSchema,
501
+ urlValueDefinitionSchema,
502
+ ipValueDefinitionSchema,
503
+ dateValueDefinitionSchema,
504
+ timeValueDefinitionSchema,
505
+ datetimeValueDefinitionSchema,
506
+ telephoneValueDefinitionSchema
507
+ ]);
508
+ var NumberValueDefinitionBaseSchema = ValueDefinitionBaseSchema.extend(
509
+ {
510
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.number),
511
+ min: import_zod6.default.number().nullable(),
512
+ max: import_zod6.default.number().nullable(),
513
+ isUnique: import_zod6.default.literal(false),
514
+ defaultValue: import_zod6.default.number().nullable()
515
+ }
516
+ );
517
+ var numberValueDefinitionSchema = NumberValueDefinitionBaseSchema.extend({
518
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.number)
519
+ });
520
+ var rangeValueDefinitionSchema = NumberValueDefinitionBaseSchema.extend({
521
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.range),
522
+ // Overwrite from nullable to required because a range needs min, max and default to work and is required, since it always returns a number
523
+ isRequired: import_zod6.default.literal(true),
524
+ min: import_zod6.default.number(),
525
+ max: import_zod6.default.number(),
526
+ defaultValue: import_zod6.default.number()
527
+ });
528
+ var BooleanValueDefinitionBaseSchema = ValueDefinitionBaseSchema.extend({
529
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.boolean),
530
+ // Overwrite from nullable to required because a boolean needs a default to work and is required, since it always is either true or false
531
+ isRequired: import_zod6.default.literal(true),
532
+ defaultValue: import_zod6.default.boolean(),
533
+ isUnique: import_zod6.default.literal(false)
534
+ });
535
+ var toggleValueDefinitionSchema = BooleanValueDefinitionBaseSchema.extend({
536
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.toggle)
537
+ });
538
+ var ReferenceValueDefinitionBaseSchema = ValueDefinitionBaseSchema.extend({
539
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.reference)
540
+ });
541
+ var assetValueDefinitionSchema = ReferenceValueDefinitionBaseSchema.extend({
542
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.asset),
543
+ allowedMimeTypes: import_zod6.default.array(supportedAssetMimeTypeSchema).min(1),
544
+ min: import_zod6.default.number().nullable(),
545
+ max: import_zod6.default.number().nullable()
546
+ });
547
+ var entryValueDefinitionSchema = ReferenceValueDefinitionBaseSchema.extend({
548
+ inputType: import_zod6.default.literal(ValueInputTypeSchema.Enum.entry),
549
+ ofCollections: import_zod6.default.array(uuidSchema),
550
+ min: import_zod6.default.number().nullable(),
551
+ max: import_zod6.default.number().nullable()
552
+ });
553
+ var valueDefinitionSchema = import_zod6.default.union([
554
+ stringValueDefinitionSchema,
555
+ numberValueDefinitionSchema,
556
+ rangeValueDefinitionSchema,
557
+ toggleValueDefinitionSchema,
558
+ assetValueDefinitionSchema,
559
+ entryValueDefinitionSchema
560
+ // sharedValueDefinitionSchema,
561
+ ]);
562
+ var valueContentReferenceBase = import_zod6.default.object({
563
+ id: uuidSchema
564
+ });
565
+ var valueContentReferenceWithLanguageBase = valueContentReferenceBase.extend({
566
+ language: supportedLanguageSchema
567
+ });
568
+ var valueContentReferenceToAssetSchema = valueContentReferenceWithLanguageBase.extend({
569
+ objectType: import_zod6.default.literal(objectTypeSchema.Enum.asset)
570
+ });
571
+ var valueContentReferenceToCollectionSchema = valueContentReferenceBase.extend({
572
+ objectType: import_zod6.default.literal(objectTypeSchema.Enum.collection)
573
+ });
574
+ var valueContentReferenceToEntrySchema = valueContentReferenceBase.extend({
575
+ objectType: import_zod6.default.literal(objectTypeSchema.Enum.entry)
576
+ });
577
+ var valueContentReferenceSchema = import_zod6.default.union([
578
+ valueContentReferenceToAssetSchema,
579
+ valueContentReferenceToCollectionSchema,
580
+ valueContentReferenceToEntrySchema
581
+ // valueContentReferenceToSharedValueSchema,
582
+ ]);
583
+ var resolvedValueContentReferenceSchema = import_zod6.default.union([
584
+ assetSchema,
585
+ import_zod6.default.lazy(() => entrySchema)
586
+ // Circular dependency / recursive type @see https://github.com/colinhacks/zod?tab=readme-ov-file#recursive-types
587
+ // resolvedValueContentReferenceToSharedValueSchema,
588
+ ]);
589
+ var directValueBaseSchema = import_zod6.default.object({
590
+ objectType: import_zod6.default.literal(objectTypeSchema.Enum.value).readonly(),
591
+ definitionId: uuidSchema.readonly()
592
+ });
593
+ var directStringValueSchema = directValueBaseSchema.extend({
594
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.string).readonly(),
595
+ content: translatableStringSchema
596
+ });
597
+ var directNumberValueSchema = directValueBaseSchema.extend({
598
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.number).readonly(),
599
+ content: translatableNumberSchema
600
+ });
601
+ var directBooleanValueSchema = directValueBaseSchema.extend({
602
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.boolean).readonly(),
603
+ content: translatableBooleanSchema
604
+ });
605
+ var directValueSchema = import_zod6.default.union([
606
+ directStringValueSchema,
607
+ directNumberValueSchema,
608
+ directBooleanValueSchema
609
+ ]);
610
+ var referencedValueSchema = import_zod6.default.object({
611
+ objectType: import_zod6.default.literal(objectTypeSchema.Enum.value).readonly(),
612
+ definitionId: uuidSchema.readonly(),
613
+ valueType: import_zod6.default.literal(ValueTypeSchema.Enum.reference).readonly(),
614
+ content: translatableArrayOf(valueContentReferenceSchema)
615
+ });
616
+ var valueSchema = import_zod6.default.union([directValueSchema, referencedValueSchema]);
617
+ var resolvedReferencedValueSchema = referencedValueSchema.extend({
618
+ content: translatableArrayOf(resolvedValueContentReferenceSchema)
619
+ });
620
+ var resolvedValueSchema = import_zod6.default.union([
621
+ directValueSchema,
622
+ resolvedReferencedValueSchema
623
+ ]);
624
+ function getValueContentSchemaFromDefinition(definition) {
625
+ switch (definition.valueType) {
626
+ case ValueTypeSchema.Enum.boolean:
627
+ return getBooleanValueContentSchema(definition);
628
+ case ValueTypeSchema.Enum.number:
629
+ return getNumberValueContentSchema(definition);
630
+ case ValueTypeSchema.Enum.string:
631
+ return getStringValueContentSchema(definition);
632
+ case ValueTypeSchema.Enum.reference:
633
+ return getReferenceValueContentSchema(definition);
634
+ default:
635
+ throw new Error(
636
+ // @ts-expect-error
637
+ `Error generating schema for unsupported ValueType "${definition.valueType}"`
638
+ );
639
+ }
640
+ }
641
+ function getBooleanValueContentSchema(definition) {
642
+ return import_zod6.default.boolean();
643
+ }
644
+ function getNumberValueContentSchema(definition) {
645
+ let schema = import_zod6.default.number();
646
+ if (definition.min) {
647
+ schema = schema.min(definition.min);
648
+ }
649
+ if (definition.max) {
650
+ schema = schema.max(definition.max);
651
+ }
652
+ if (definition.isRequired === false) {
653
+ return schema.nullable();
654
+ }
655
+ return schema;
656
+ }
657
+ function getStringValueContentSchema(definition) {
658
+ let schema = import_zod6.default.string().trim();
659
+ if ("min" in definition && definition.min) {
660
+ schema = schema.min(definition.min);
661
+ }
662
+ if ("max" in definition && definition.max) {
663
+ schema = schema.max(definition.max);
664
+ }
665
+ switch (definition.inputType) {
666
+ case ValueInputTypeSchema.Enum.email:
667
+ schema = schema.email();
668
+ break;
669
+ case ValueInputTypeSchema.Enum.url:
670
+ schema = schema.url();
671
+ break;
672
+ case ValueInputTypeSchema.Enum.ip:
673
+ schema = schema.ip();
674
+ break;
675
+ case ValueInputTypeSchema.Enum.date:
676
+ schema = schema.date();
677
+ break;
678
+ case ValueInputTypeSchema.Enum.time:
679
+ schema = schema.time();
680
+ break;
681
+ case ValueInputTypeSchema.Enum.datetime:
682
+ schema = schema.datetime();
683
+ break;
684
+ case ValueInputTypeSchema.Enum.telephone:
685
+ break;
686
+ }
687
+ if (definition.isRequired === false) {
688
+ return schema.nullable();
689
+ }
690
+ return schema.min(1, "shared.stringValueRequired");
691
+ }
692
+ function getReferenceValueContentSchema(definition) {
693
+ let schema;
694
+ switch (definition.inputType) {
695
+ case ValueInputTypeSchema.Enum.asset:
696
+ {
697
+ schema = import_zod6.default.array(valueContentReferenceToAssetSchema);
698
+ }
699
+ break;
700
+ case ValueInputTypeSchema.Enum.entry:
701
+ {
702
+ schema = import_zod6.default.array(valueContentReferenceToEntrySchema);
703
+ }
704
+ break;
705
+ }
706
+ if (definition.isRequired) {
707
+ schema = schema.min(1, "shared.referenceRequired");
708
+ }
709
+ if (definition.min) {
710
+ schema = schema.min(definition.min);
711
+ }
712
+ if (definition.max) {
713
+ schema = schema.max(definition.max);
714
+ }
715
+ return schema;
716
+ }
717
+
718
+ // src/schema/entrySchema.ts
719
+ var entryFileSchema = baseFileSchema.extend({
720
+ objectType: import_zod7.default.literal(objectTypeSchema.Enum.entry).readonly(),
721
+ values: import_zod7.default.array(valueSchema)
722
+ });
723
+ var entrySchema = entryFileSchema.extend({
724
+ values: import_zod7.default.array(import_zod7.default.lazy(() => resolvedValueSchema))
725
+ });
726
+ var entryExportSchema = entrySchema.extend({});
727
+ var createEntrySchema = entryFileSchema.omit({
728
+ id: true,
729
+ objectType: true,
730
+ created: true,
731
+ updated: true
732
+ }).extend({
733
+ projectId: uuidSchema.readonly(),
734
+ collectionId: uuidSchema.readonly(),
735
+ values: import_zod7.default.array(valueSchema)
736
+ });
737
+ var readEntrySchema = import_zod7.default.object({
738
+ id: uuidSchema.readonly(),
739
+ projectId: uuidSchema.readonly(),
740
+ collectionId: uuidSchema.readonly()
741
+ });
742
+ var updateEntrySchema = entrySchema.omit({
743
+ objectType: true,
744
+ created: true,
745
+ updated: true
746
+ }).extend({
747
+ projectId: uuidSchema.readonly(),
748
+ collectionId: uuidSchema.readonly()
749
+ });
750
+ var deleteEntrySchema = readEntrySchema.extend({});
751
+ var countEntriesSchema = import_zod7.default.object({
752
+ projectId: uuidSchema.readonly(),
753
+ collectionId: uuidSchema.readonly()
754
+ });
755
+
756
+ // src/schema/collectionSchema.ts
757
+ var collectionFileSchema = baseFileSchema.extend({
758
+ objectType: import_zod8.default.literal(objectTypeSchema.Enum.collection).readonly(),
759
+ name: import_zod8.default.object({
760
+ singular: translatableStringSchema,
761
+ plural: translatableStringSchema
762
+ }),
763
+ slug: import_zod8.default.object({
764
+ singular: import_zod8.default.string(),
765
+ plural: import_zod8.default.string()
766
+ }),
767
+ description: translatableStringSchema,
768
+ icon: supportedIconSchema,
769
+ valueDefinitions: import_zod8.default.array(valueDefinitionSchema)
770
+ });
771
+ var collectionSchema = collectionFileSchema.extend({});
772
+ var collectionExportSchema = collectionSchema.extend({
773
+ entries: import_zod8.default.array(entryExportSchema)
774
+ });
775
+ var createCollectionSchema = collectionSchema.omit({
776
+ id: true,
777
+ objectType: true,
778
+ created: true,
779
+ updated: true
780
+ }).extend({
781
+ projectId: uuidSchema.readonly()
782
+ });
783
+ var readCollectionSchema = import_zod8.default.object({
784
+ id: uuidSchema.readonly(),
785
+ projectId: uuidSchema.readonly()
786
+ });
787
+ var updateCollectionSchema = collectionFileSchema.pick({
788
+ id: true,
789
+ name: true,
790
+ slug: true,
791
+ description: true,
792
+ icon: true,
793
+ valueDefinitions: true
794
+ }).extend({
795
+ projectId: uuidSchema.readonly()
796
+ });
797
+ var deleteCollectionSchema = readCollectionSchema.extend({});
798
+ var countCollectionsSchema = import_zod8.default.object({
799
+ projectId: uuidSchema.readonly()
800
+ });
801
+
802
+ // src/schema/projectSchema.ts
803
+ var projectStatusSchema = import_zod9.z.enum(["foo", "bar", "todo"]);
804
+ var projectSettingsSchema = import_zod9.z.object({
805
+ language: import_zod9.z.object({
806
+ default: supportedLanguageSchema,
807
+ supported: import_zod9.z.array(supportedLanguageSchema)
808
+ })
809
+ });
810
+ var projectFolderSchema = import_zod9.z.enum([
811
+ "assets",
812
+ "collections",
813
+ "shared-values",
814
+ "lfs"
815
+ // 'logs',
816
+ // 'public',
817
+ // 'theme',
818
+ ]);
819
+ var projectFileSchema = baseFileSchema.extend({
820
+ objectType: import_zod9.z.literal(objectTypeSchema.Enum.project).readonly(),
821
+ coreVersion: versionSchema,
822
+ name: import_zod9.z.string().trim().min(1, "shared.projectNameRequired"),
823
+ description: import_zod9.z.string().trim().min(1, "shared.projectDescriptionRequired"),
824
+ version: versionSchema,
825
+ status: projectStatusSchema,
826
+ settings: projectSettingsSchema
827
+ });
828
+ var projectSchema = projectFileSchema.extend({});
829
+ var projectExportSchema = projectSchema.extend({
830
+ assets: import_zod9.z.array(assetExportSchema),
831
+ collections: import_zod9.z.array(collectionExportSchema)
832
+ });
833
+ var createProjectSchema = projectSchema.pick({
834
+ name: true,
835
+ description: true,
836
+ settings: true
837
+ }).partial({
838
+ description: true,
839
+ settings: true
840
+ });
841
+ var readProjectSchema = import_zod9.z.object({
842
+ id: uuidSchema.readonly()
843
+ });
844
+ var updateProjectSchema = projectSchema.pick({
845
+ id: true,
846
+ name: true,
847
+ description: true,
848
+ settings: true
849
+ }).partial({
850
+ name: true,
851
+ description: true,
852
+ settings: true
853
+ });
854
+ var upgradeProjectSchema = import_zod9.z.object({
855
+ id: uuidSchema.readonly()
856
+ });
857
+ var deleteProjectSchema = readProjectSchema.extend({});
858
+ var projectUpgradeSchema = import_zod9.z.object({
859
+ /**
860
+ * The Core version the Project will be upgraded to
861
+ */
862
+ to: versionSchema.readonly(),
863
+ /**
864
+ * Function that will be executed in the process of upgrading a Project
865
+ */
866
+ run: import_zod9.z.function().args(projectFileSchema).returns(import_zod9.z.promise(import_zod9.z.void()))
867
+ });
868
+ var cloneProjectSchema = import_zod9.z.object({
869
+ url: import_zod9.z.string()
870
+ });
871
+ var listBranchesProjectSchema = import_zod9.z.object({
872
+ id: uuidSchema.readonly()
873
+ });
874
+ var currentBranchProjectSchema = import_zod9.z.object({
875
+ id: uuidSchema.readonly()
876
+ });
877
+ var switchBranchProjectSchema = import_zod9.z.object({
878
+ id: uuidSchema.readonly(),
879
+ branch: import_zod9.z.string(),
880
+ options: gitSwitchOptionsSchema.optional()
881
+ });
882
+ var getRemoteOriginUrlProjectSchema = import_zod9.z.object({
883
+ id: uuidSchema.readonly()
884
+ });
885
+ var setRemoteOriginUrlProjectSchema = import_zod9.z.object({
886
+ id: uuidSchema.readonly(),
887
+ url: import_zod9.z.string()
888
+ });
889
+ var getChangesProjectSchema = import_zod9.z.object({
890
+ id: uuidSchema.readonly()
891
+ });
892
+ var synchronizeProjectSchema = import_zod9.z.object({
893
+ id: uuidSchema.readonly()
894
+ });
895
+ var searchProjectSchema = import_zod9.z.object({
896
+ id: uuidSchema.readonly(),
897
+ query: import_zod9.z.string(),
898
+ language: supportedLanguageSchema,
899
+ type: import_zod9.z.array(objectTypeSchema).optional()
900
+ });
901
+
902
+ // src/util/index.ts
903
+ var Slugify = import_slugify.default.default || import_slugify.default;
904
+ function uuid() {
905
+ return (0, import_uuid.v4)();
906
+ }
907
+ function currentTimestamp() {
908
+ return Math.floor(Date.now() / 1e3);
909
+ }
910
+ function slug(string) {
911
+ return Slugify(string, {
912
+ replacement: "-",
913
+ // replace spaces with replacement character, defaults to `-`
914
+ remove: void 0,
915
+ // remove characters that match regex, defaults to `undefined`
916
+ lower: true,
917
+ // convert to lower case, defaults to `false`
918
+ strict: true
919
+ // strip special characters except replacement, defaults to `false`
920
+ });
921
+ }
74
922
  var workingDirectory = import_path.default.join(import_os.default.homedir(), "elek.io");
75
923
  var pathTo = {
76
924
  tmp: import_path.default.join(workingDirectory, "tmp"),
@@ -90,12 +938,12 @@ var pathTo = {
90
938
  // return Path.join(pathTo.project(projectId), 'public');
91
939
  // },
92
940
  lfs: (projectId) => {
93
- return import_path.default.join(pathTo.project(projectId), import_shared.projectFolderSchema.Enum.lfs);
941
+ return import_path.default.join(pathTo.project(projectId), projectFolderSchema.Enum.lfs);
94
942
  },
95
943
  collections: (projectId) => {
96
944
  return import_path.default.join(
97
945
  pathTo.project(projectId),
98
- import_shared.projectFolderSchema.Enum.collections
946
+ projectFolderSchema.Enum.collections
99
947
  );
100
948
  },
101
949
  collection: (projectId, id) => {
@@ -119,7 +967,7 @@ var pathTo = {
119
967
  assets: (projectId) => {
120
968
  return import_path.default.join(
121
969
  pathTo.project(projectId),
122
- import_shared.projectFolderSchema.Enum.assets
970
+ projectFolderSchema.Enum.assets
123
971
  );
124
972
  },
125
973
  assetFile: (projectId, id, language) => {
@@ -139,7 +987,7 @@ var fromPath = {
139
987
  }
140
988
  const end = path.indexOf(endsWith, start);
141
989
  const result = path.substring(start, end === -1 ? path.length : end);
142
- if (result && import_shared.uuidSchema.safeParse(result).success) {
990
+ if (result && uuidSchema.safeParse(result).success) {
143
991
  return result;
144
992
  }
145
993
  return void 0;
@@ -240,8 +1088,6 @@ function getDuplicates(arr, key) {
240
1088
  }
241
1089
 
242
1090
  // src/service/AbstractCrudService.ts
243
- var import_shared2 = require("@elek-io/shared");
244
- var import_lodash_es2 = require("lodash-es");
245
1091
  var AbstractCrudService = class {
246
1092
  /**
247
1093
  * Do not instantiate directly as this is an abstract class
@@ -250,56 +1096,9 @@ var AbstractCrudService = class {
250
1096
  this.type = type;
251
1097
  this.options = options;
252
1098
  this.gitMessage = {
253
- create: `${import_shared2.gitCommitIconSchema.enum.CREATE} Created ${this.type}`,
254
- update: `${import_shared2.gitCommitIconSchema.enum.UPDATE} Updated ${this.type}`,
255
- delete: `${import_shared2.gitCommitIconSchema.enum.DELETE} Deleted ${this.type}`
256
- };
257
- }
258
- /**
259
- * Returns the filtered, sorted and paginated version of given list
260
- *
261
- * @todo Sorting and filtering requires all models to be loaded
262
- * from disk. This results in a huge memory spike before the
263
- * filtering and pagination takes effect - removing most of it again.
264
- * This approach is still better than returning everything and
265
- * letting the frontend handle it, since the memory usage would then be constant.
266
- * But this still could fill the memory limit of node.js (default 1,4 GB).
267
- *
268
- * @param list Array to filter, sort and paginate
269
- * @param sort Array of sort objects containing information about what to sort and how
270
- * @param filter Filter all object values of `list` by this string
271
- * @param limit Limit the result to this amount. If 0 is given, no limit is applied
272
- * @param offset Start at this index instead of 0
273
- */
274
- async paginate(list, sort = [], filter2 = "", limit = 15, offset = 0) {
275
- let result = list;
276
- const total = list.length;
277
- const normalizedFilter = filter2.trim().toLowerCase();
278
- if (normalizedFilter !== "") {
279
- (0, import_lodash_es2.remove)(result, (model) => {
280
- let key;
281
- for (key in model) {
282
- const value = model[key];
283
- if (String(value).toLowerCase().includes(normalizedFilter)) {
284
- return false;
285
- }
286
- }
287
- return true;
288
- });
289
- }
290
- if (sort.length !== 0) {
291
- const keys = sort.map((value) => value.by);
292
- const orders = sort.map((value) => value.order);
293
- result = (0, import_lodash_es2.orderBy)(result, keys, orders);
294
- }
295
- if (limit !== 0) {
296
- result = result.slice(offset, offset + limit);
297
- }
298
- return {
299
- total,
300
- limit,
301
- offset,
302
- list: result
1099
+ create: `${gitCommitIconSchema.enum.CREATE} Created ${this.type}`,
1100
+ update: `${gitCommitIconSchema.enum.UPDATE} Updated ${this.type}`,
1101
+ delete: `${gitCommitIconSchema.enum.DELETE} Deleted ${this.type}`
303
1102
  };
304
1103
  }
305
1104
  /**
@@ -311,19 +1110,19 @@ var AbstractCrudService = class {
311
1110
  */
312
1111
  async listReferences(type, projectId, collectionId) {
313
1112
  switch (type) {
314
- case import_shared2.objectTypeSchema.Enum.asset:
1113
+ case objectTypeSchema.Enum.asset:
315
1114
  if (!projectId) {
316
1115
  throw new RequiredParameterMissingError("projectId");
317
1116
  }
318
1117
  return this.getFileReferences(pathTo.lfs(projectId));
319
- case import_shared2.objectTypeSchema.Enum.project:
1118
+ case objectTypeSchema.Enum.project:
320
1119
  return this.getFolderReferences(pathTo.projects);
321
- case import_shared2.objectTypeSchema.Enum.collection:
1120
+ case objectTypeSchema.Enum.collection:
322
1121
  if (!projectId) {
323
1122
  throw new RequiredParameterMissingError("projectId");
324
1123
  }
325
1124
  return this.getFolderReferences(pathTo.collections(projectId));
326
- case import_shared2.objectTypeSchema.Enum.entry:
1125
+ case objectTypeSchema.Enum.entry:
327
1126
  if (!projectId) {
328
1127
  throw new RequiredParameterMissingError("projectId");
329
1128
  }
@@ -333,7 +1132,7 @@ var AbstractCrudService = class {
333
1132
  return this.getFileReferences(
334
1133
  pathTo.collection(projectId, collectionId)
335
1134
  );
336
- case import_shared2.objectTypeSchema.Enum.sharedValue:
1135
+ case objectTypeSchema.Enum.sharedValue:
337
1136
  if (!projectId) {
338
1137
  throw new RequiredParameterMissingError("projectId");
339
1138
  }
@@ -349,7 +1148,7 @@ var AbstractCrudService = class {
349
1148
  id: possibleFolder.name
350
1149
  };
351
1150
  try {
352
- return import_shared2.fileReferenceSchema.parse(folderReference);
1151
+ return fileReferenceSchema.parse(folderReference);
353
1152
  } catch (error) {
354
1153
  return null;
355
1154
  }
@@ -374,7 +1173,7 @@ var AbstractCrudService = class {
374
1173
  extension: fileNameArray.length === 2 ? fileNameArray[1] : fileNameArray[2]
375
1174
  };
376
1175
  try {
377
- return import_shared2.fileReferenceSchema.parse(fileReference);
1176
+ return fileReferenceSchema.parse(fileReference);
378
1177
  } catch (error) {
379
1178
  return null;
380
1179
  }
@@ -385,8 +1184,8 @@ var AbstractCrudService = class {
385
1184
  };
386
1185
 
387
1186
  // src/service/GitService.ts
388
- var import_shared6 = require("@elek-io/shared");
389
1187
  var import_dugite = require("dugite");
1188
+ var import_os3 = require("os");
390
1189
  var import_p_queue = __toESM(require("p-queue"), 1);
391
1190
 
392
1191
  // src/error/GitError.ts
@@ -406,10 +1205,35 @@ var NoCurrentUserError = class extends Error {
406
1205
  };
407
1206
 
408
1207
  // src/service/GitTagService.ts
409
- var import_shared3 = require("@elek-io/shared");
1208
+ var import_os2 = require("os");
1209
+
1210
+ // src/schema/gitTagSchema.ts
1211
+ var import_zod10 = require("zod");
1212
+ var gitTagSchema = import_zod10.z.object({
1213
+ id: uuidSchema,
1214
+ message: import_zod10.z.string(),
1215
+ author: gitSignatureSchema,
1216
+ timestamp: import_zod10.z.number()
1217
+ });
1218
+ var createGitTagSchema = gitTagSchema.pick({
1219
+ message: true
1220
+ }).extend({
1221
+ path: gitRepositoryPathSchema,
1222
+ hash: gitCommitSchema.shape.hash.optional()
1223
+ });
1224
+ var readGitTagSchema = import_zod10.z.object({
1225
+ path: gitRepositoryPathSchema,
1226
+ id: uuidSchema.readonly()
1227
+ });
1228
+ var deleteGitTagSchema = readGitTagSchema.extend({});
1229
+ var countGitTagsSchema = import_zod10.z.object({
1230
+ path: gitRepositoryPathSchema
1231
+ });
1232
+
1233
+ // src/service/GitTagService.ts
410
1234
  var GitTagService = class extends AbstractCrudService {
411
1235
  constructor(options, git) {
412
- super(import_shared3.serviceTypeSchema.Enum.GitTag, options);
1236
+ super(serviceTypeSchema.Enum.GitTag, options);
413
1237
  this.git = git;
414
1238
  }
415
1239
  /**
@@ -418,8 +1242,8 @@ var GitTagService = class extends AbstractCrudService {
418
1242
  * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---annotate
419
1243
  */
420
1244
  async create(props) {
421
- import_shared3.createGitTagSchema.parse(props);
422
- const id = (0, import_shared3.uuid)();
1245
+ createGitTagSchema.parse(props);
1246
+ const id = uuid();
423
1247
  let args = ["tag", "--annotate", id];
424
1248
  if (props.hash) {
425
1249
  args = [...args, props.hash];
@@ -432,22 +1256,20 @@ var GitTagService = class extends AbstractCrudService {
432
1256
  /**
433
1257
  * Returns a tag by ID
434
1258
  *
435
- * Internally uses list() with id as pattern.
1259
+ * Internally uses list() but only returns the tag with matching ID.
436
1260
  */
437
1261
  async read(props) {
438
- import_shared3.readGitTagSchema.parse(props);
439
- const tags = await this.list({ path: props.path, filter: props.id });
440
- if (tags.total === 0) {
1262
+ readGitTagSchema.parse(props);
1263
+ const tags = await this.list({ path: props.path });
1264
+ const tag = tags.list.find((tag2) => {
1265
+ return tag2.id === props.id;
1266
+ });
1267
+ if (!tag) {
441
1268
  throw new GitError(
442
1269
  `Provided tag with UUID "${props.id}" did not match any known tags`
443
1270
  );
444
1271
  }
445
- if (tags.total > 1) {
446
- throw new GitError(
447
- `Provided tag with UUID "${props.id}" matched multiple known tags`
448
- );
449
- }
450
- return tags.list[0];
1272
+ return tag;
451
1273
  }
452
1274
  /**
453
1275
  * Updating a git tag is not supported.
@@ -469,7 +1291,7 @@ var GitTagService = class extends AbstractCrudService {
469
1291
  * @param id UUID of the tag to delete
470
1292
  */
471
1293
  async delete(props) {
472
- import_shared3.deleteGitTagSchema.parse(props);
1294
+ deleteGitTagSchema.parse(props);
473
1295
  const args = ["tag", "--delete", props.id];
474
1296
  await this.git(props.path, args);
475
1297
  }
@@ -482,7 +1304,7 @@ var GitTagService = class extends AbstractCrudService {
482
1304
  * @see https://git-scm.com/docs/git-tag#Documentation/git-tag.txt---list
483
1305
  */
484
1306
  async list(props) {
485
- import_shared3.listGitTagsSchema.parse(props);
1307
+ listGitTagsSchema.parse(props);
486
1308
  let args = ["tag", "--list"];
487
1309
  args = [
488
1310
  ...args,
@@ -490,8 +1312,8 @@ var GitTagService = class extends AbstractCrudService {
490
1312
  "--format=%(refname:short)|%(subject)|%(*authorname)|%(*authoremail)|%(*authordate:unix)"
491
1313
  ];
492
1314
  const result = await this.git(props.path, args);
493
- const noEmptyLinesArr = result.stdout.split("\n").filter((line) => {
494
- return line !== "";
1315
+ const noEmptyLinesArr = result.stdout.split(import_os2.EOL).filter((line) => {
1316
+ return line.trim() !== "";
495
1317
  });
496
1318
  const lineObjArr = noEmptyLinesArr.map((line) => {
497
1319
  const lineArray = line.split("|");
@@ -502,17 +1324,16 @@ var GitTagService = class extends AbstractCrudService {
502
1324
  name: lineArray[2],
503
1325
  email: lineArray[3]
504
1326
  },
505
- timestamp: typeof lineArray[4] === "string" ? parseInt(lineArray[4]) : void 0
1327
+ timestamp: parseInt(lineArray[4])
506
1328
  };
507
1329
  });
508
1330
  const gitTags = lineObjArr.filter(this.isGitTag.bind(this));
509
- return this.paginate(
510
- gitTags,
511
- props?.sort,
512
- props?.filter,
513
- props?.limit,
514
- props?.offset
515
- );
1331
+ return {
1332
+ total: gitTags.length,
1333
+ limit: 0,
1334
+ offset: 0,
1335
+ list: gitTags
1336
+ };
516
1337
  }
517
1338
  /**
518
1339
  * Returns the total number of tags inside given repository
@@ -523,7 +1344,7 @@ var GitTagService = class extends AbstractCrudService {
523
1344
  * @param path Path to the repository
524
1345
  */
525
1346
  async count(props) {
526
- import_shared3.countGitTagsSchema.parse(props);
1347
+ countGitTagsSchema.parse(props);
527
1348
  const gitTags = await this.list({ path: props.path });
528
1349
  return gitTags.total;
529
1350
  }
@@ -533,19 +1354,33 @@ var GitTagService = class extends AbstractCrudService {
533
1354
  * @param obj The object to check
534
1355
  */
535
1356
  isGitTag(obj) {
536
- return import_shared3.gitTagSchema.safeParse(obj).success;
1357
+ return gitTagSchema.safeParse(obj).success;
537
1358
  }
538
1359
  };
539
1360
 
540
- // src/service/UserService.ts
541
- var import_shared5 = require("@elek-io/shared");
1361
+ // src/schema/userSchema.ts
1362
+ var import_zod11 = __toESM(require("zod"), 1);
1363
+ var UserTypeSchema = import_zod11.default.enum(["local", "cloud"]);
1364
+ var baseUserSchema = gitSignatureSchema.extend({
1365
+ userType: UserTypeSchema,
1366
+ language: supportedLanguageSchema
1367
+ });
1368
+ var localUserSchema = baseUserSchema.extend({
1369
+ userType: import_zod11.default.literal(UserTypeSchema.Enum.local)
1370
+ });
1371
+ var cloudUserSchema = baseUserSchema.extend({
1372
+ userType: import_zod11.default.literal(UserTypeSchema.Enum.cloud),
1373
+ id: uuidSchema
1374
+ });
1375
+ var userFileSchema = import_zod11.default.union([localUserSchema, cloudUserSchema]);
1376
+ var userSchema = userFileSchema;
1377
+ var setUserSchema = userSchema;
542
1378
 
543
1379
  // src/service/JsonFileService.ts
544
- var import_shared4 = require("@elek-io/shared");
545
1380
  var import_fs_extra2 = __toESM(require("fs-extra"), 1);
546
1381
  var JsonFileService = class extends AbstractCrudService {
547
1382
  constructor(options) {
548
- super(import_shared4.serviceTypeSchema.Enum.JsonFile, options);
1383
+ super(serviceTypeSchema.Enum.JsonFile, options);
549
1384
  this.cache = /* @__PURE__ */ new Map();
550
1385
  }
551
1386
  /**
@@ -626,7 +1461,7 @@ var UserService = class {
626
1461
  try {
627
1462
  return await this.jsonFileService.read(
628
1463
  pathTo.userFile,
629
- import_shared5.userFileSchema
1464
+ userFileSchema
630
1465
  );
631
1466
  } catch (error) {
632
1467
  return void 0;
@@ -638,14 +1473,14 @@ var UserService = class {
638
1473
  * By doing so all git operations are done with the signature of this User
639
1474
  */
640
1475
  async set(props) {
641
- import_shared5.setUserSchema.parse(props);
1476
+ setUserSchema.parse(props);
642
1477
  const userFilePath = pathTo.userFile;
643
1478
  const userFile = {
644
1479
  ...props
645
1480
  };
646
- if (userFile.userType === import_shared5.UserTypeSchema.Enum.cloud) {
1481
+ if (userFile.userType === UserTypeSchema.Enum.cloud) {
647
1482
  }
648
- await this.jsonFileService.update(userFile, userFilePath, import_shared5.userFileSchema);
1483
+ await this.jsonFileService.update(userFile, userFilePath, userFileSchema);
649
1484
  return userFile;
650
1485
  }
651
1486
  };
@@ -653,13 +1488,147 @@ var UserService = class {
653
1488
  // src/service/GitService.ts
654
1489
  var GitService2 = class {
655
1490
  constructor(options, userService) {
656
- this.version = void 0;
1491
+ this.branches = {
1492
+ /**
1493
+ * List branches
1494
+ *
1495
+ * @see https://www.git-scm.com/docs/git-branch
1496
+ *
1497
+ * @param path Path to the repository
1498
+ */
1499
+ list: async (path) => {
1500
+ const args = ["branch", "--list", "--all"];
1501
+ const result = await this.git(path, args);
1502
+ const normalizedLinesArr = result.stdout.split(import_os3.EOL).filter((line) => {
1503
+ return line.trim() !== "";
1504
+ }).map((line) => {
1505
+ return line.trim().replace("* ", "");
1506
+ });
1507
+ const local = [];
1508
+ const remote = [];
1509
+ normalizedLinesArr.forEach((line) => {
1510
+ if (line.startsWith("remotes/")) {
1511
+ remote.push(line.replace("remotes/", ""));
1512
+ } else {
1513
+ local.push(line);
1514
+ }
1515
+ });
1516
+ return {
1517
+ local,
1518
+ remote
1519
+ };
1520
+ },
1521
+ /**
1522
+ * Returns the name of the current branch. In detached HEAD state, an empty string is returned.
1523
+ *
1524
+ * @see https://www.git-scm.com/docs/git-branch#Documentation/git-branch.txt---show-current
1525
+ *
1526
+ * @param path Path to the repository
1527
+ */
1528
+ current: async (path) => {
1529
+ const args = ["branch", "--show-current"];
1530
+ const result = await this.git(path, args);
1531
+ return result.stdout.trim();
1532
+ },
1533
+ /**
1534
+ * Switch branches
1535
+ *
1536
+ * @see https://git-scm.com/docs/git-switch/
1537
+ *
1538
+ * @param path Path to the repository
1539
+ * @param branch Name of the branch to switch to
1540
+ * @param options Options specific to the switch operation
1541
+ */
1542
+ switch: async (path, branch, options) => {
1543
+ await this.checkBranchOrTagName(path, branch);
1544
+ let args = ["switch"];
1545
+ if (options?.isNew === true) {
1546
+ args = [...args, "--create", branch];
1547
+ } else {
1548
+ args = [...args, branch];
1549
+ }
1550
+ await this.git(path, args);
1551
+ }
1552
+ };
1553
+ this.remotes = {
1554
+ /**
1555
+ * Returns a list of currently tracked remotes
1556
+ *
1557
+ * @see https://git-scm.com/docs/git-remote
1558
+ *
1559
+ * @param path Path to the repository
1560
+ */
1561
+ list: async (path) => {
1562
+ const args = ["remote"];
1563
+ const result = await this.git(path, args);
1564
+ const normalizedLinesArr = result.stdout.split(import_os3.EOL).filter((line) => {
1565
+ return line.trim() !== "";
1566
+ });
1567
+ return normalizedLinesArr;
1568
+ },
1569
+ /**
1570
+ * Returns true if the `origin` remote exists, otherwise false
1571
+ *
1572
+ * @param path Path to the repository
1573
+ */
1574
+ hasOrigin: async (path) => {
1575
+ const remotes = await this.remotes.list(path);
1576
+ if (remotes.includes("origin")) {
1577
+ return true;
1578
+ }
1579
+ return false;
1580
+ },
1581
+ /**
1582
+ * Adds the `origin` remote with given URL
1583
+ *
1584
+ * Throws if `origin` remote is added already.
1585
+ *
1586
+ * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emaddem
1587
+ *
1588
+ * @param path Path to the repository
1589
+ */
1590
+ addOrigin: async (path, url) => {
1591
+ const args = ["remote", "add", "origin", url];
1592
+ await this.git(path, args);
1593
+ },
1594
+ /**
1595
+ * Returns the current `origin` remote URL
1596
+ *
1597
+ * Throws if no `origin` remote is added yet.
1598
+ *
1599
+ * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emget-urlem
1600
+ *
1601
+ * @param path Path to the repository
1602
+ */
1603
+ getOriginUrl: async (path) => {
1604
+ const args = ["remote", "get-url", "origin"];
1605
+ const result = (await this.git(path, args)).stdout.trim();
1606
+ return result.length === 0 ? null : result;
1607
+ },
1608
+ /**
1609
+ * Sets the current `origin` remote URL
1610
+ *
1611
+ * Throws if no `origin` remote is added yet.
1612
+ *
1613
+ * @see https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-emset-urlem
1614
+ *
1615
+ * @param path Path to the repository
1616
+ */
1617
+ setOriginUrl: async (path, url) => {
1618
+ const args = ["remote", "set-url", "origin", url];
1619
+ await this.git(path, args);
1620
+ }
1621
+ };
1622
+ this.version = null;
1623
+ this.gitPath = null;
657
1624
  this.queue = new import_p_queue.default({
658
1625
  concurrency: 1
659
1626
  // No concurrency because git operations are sequencial
660
1627
  });
661
1628
  this.gitTagService = new GitTagService(options, this.git);
662
1629
  this.userService = userService;
1630
+ this.updateVersion();
1631
+ this.updateGitPath();
663
1632
  }
664
1633
  /**
665
1634
  * CRUD methods to work with git tags
@@ -667,13 +1636,6 @@ var GitService2 = class {
667
1636
  get tags() {
668
1637
  return this.gitTagService;
669
1638
  }
670
- /**
671
- * Reads the currently used version of Git
672
- */
673
- async getVersion() {
674
- const result = await this.git("", ["--version"]);
675
- this.version = result.stdout.replace("git version", "").trim();
676
- }
677
1639
  /**
678
1640
  * Create an empty Git repository or reinitialize an existing one
679
1641
  *
@@ -714,7 +1676,7 @@ var GitService2 = class {
714
1676
  if (options?.singleBranch === true) {
715
1677
  args = [...args, "--single-branch"];
716
1678
  }
717
- await this.git(path, [...args, url, "."]);
1679
+ await this.git("", [...args, url, path]);
718
1680
  await this.setLocalConfig(path);
719
1681
  }
720
1682
  /**
@@ -729,25 +1691,6 @@ var GitService2 = class {
729
1691
  const args = ["add", "--", ...files2];
730
1692
  await this.git(path, args);
731
1693
  }
732
- /**
733
- * Switch branches
734
- *
735
- * @see https://git-scm.com/docs/git-switch/
736
- *
737
- * @param path Path to the repository
738
- * @param name Name of the branch to switch to
739
- * @param options Options specific to the switch operation
740
- */
741
- async switch(path, name, options) {
742
- await this.checkBranchOrTagName(path, name);
743
- let args = ["switch"];
744
- if (options?.isNew === true) {
745
- args = [...args, "--create", name];
746
- } else {
747
- args = [...args, name];
748
- }
749
- await this.git(path, args);
750
- }
751
1694
  /**
752
1695
  * Reset current HEAD to the specified state
753
1696
  *
@@ -785,7 +1728,18 @@ var GitService2 = class {
785
1728
  // await this.git(path, args);
786
1729
  // }
787
1730
  /**
788
- * Fetch from and integrate with another repository or a local branch
1731
+ * Download objects and refs from remote `origin`
1732
+ *
1733
+ * @see https://www.git-scm.com/docs/git-fetch
1734
+ *
1735
+ * @param path Path to the repository
1736
+ */
1737
+ async fetch(path) {
1738
+ const args = ["fetch"];
1739
+ await this.git(path, args);
1740
+ }
1741
+ /**
1742
+ * Fetch from and integrate (rebase or merge) with a local branch
789
1743
  *
790
1744
  * @see https://git-scm.com/docs/git-pull
791
1745
  *
@@ -795,6 +1749,23 @@ var GitService2 = class {
795
1749
  const args = ["pull"];
796
1750
  await this.git(path, args);
797
1751
  }
1752
+ /**
1753
+ * Update remote refs along with associated objects to remote `origin`
1754
+ *
1755
+ * @see https://git-scm.com/docs/git-push
1756
+ *
1757
+ * @param path Path to the repository
1758
+ */
1759
+ async push(path, options) {
1760
+ let args = ["push", "origin"];
1761
+ if (options?.all === true) {
1762
+ args = [...args, "--all"];
1763
+ }
1764
+ if (options?.force === true) {
1765
+ args = [...args, "--force"];
1766
+ }
1767
+ await this.git(path, args);
1768
+ }
798
1769
  /**
799
1770
  * Record changes to the repository
800
1771
  *
@@ -831,7 +1802,7 @@ var GitService2 = class {
831
1802
  if (options?.between?.from) {
832
1803
  args = [
833
1804
  ...args,
834
- `${options.between.from}...${options.between.to || "HEAD"}`
1805
+ `${options.between.from}..${options.between.to || "HEAD"}`
835
1806
  ];
836
1807
  }
837
1808
  if (options?.limit) {
@@ -841,8 +1812,8 @@ var GitService2 = class {
841
1812
  ...args,
842
1813
  "--format=%H|%s|%an|%ae|%at|%D"
843
1814
  ]);
844
- const noEmptyLinesArr = result.stdout.split("\n").filter((line) => {
845
- return line !== "";
1815
+ const noEmptyLinesArr = result.stdout.split(import_os3.EOL).filter((line) => {
1816
+ return line.trim() !== "";
846
1817
  });
847
1818
  const lineObjArr = noEmptyLinesArr.map((line) => {
848
1819
  const lineArray = line.split("|");
@@ -860,10 +1831,9 @@ var GitService2 = class {
860
1831
  return lineObjArr.filter(this.isGitCommit.bind(this));
861
1832
  }
862
1833
  refNameToTagName(refName) {
863
- let tagName = "";
864
- tagName = refName.replace("tag: ", "");
865
- if (tagName.trim() === "" || import_shared6.uuidSchema.safeParse(tagName).success === false) {
866
- tagName = void 0;
1834
+ const tagName = refName.replace("tag: ", "").trim();
1835
+ if (tagName === "" || uuidSchema.safeParse(tagName).success === false) {
1836
+ return null;
867
1837
  }
868
1838
  return tagName;
869
1839
  }
@@ -923,6 +1893,26 @@ var GitService2 = class {
923
1893
  updated: meta[1]
924
1894
  };
925
1895
  }
1896
+ /**
1897
+ * Reads the currently used version of Git
1898
+ *
1899
+ * This can help debugging
1900
+ */
1901
+ async updateVersion() {
1902
+ const result = await this.git("", ["--version"]);
1903
+ this.version = result.stdout.replace("git version", "").trim();
1904
+ }
1905
+ /**
1906
+ * Reads the path to the executable of Git that is used
1907
+ *
1908
+ * This can help debugging, since dugite is shipping their own executable
1909
+ * but in some cases resolves another executable
1910
+ * @see https://github.com/desktop/dugite/blob/main/lib/git-environment.ts
1911
+ */
1912
+ async updateGitPath() {
1913
+ const result = await this.git("", ["--exec-path"]);
1914
+ this.gitPath = result.stdout.trim();
1915
+ }
926
1916
  /**
927
1917
  * A reference is used in Git to specify branches and tags.
928
1918
  * This method checks if given name matches the required format
@@ -957,8 +1947,15 @@ var GitService2 = class {
957
1947
  }
958
1948
  const userNameArgs = ["config", "--local", "user.name", user.name];
959
1949
  const userEmailArgs = ["config", "--local", "user.email", user.email];
1950
+ const autoSetupRemoteArgs = [
1951
+ "config",
1952
+ "--local",
1953
+ "push.autoSetupRemote",
1954
+ "true"
1955
+ ];
960
1956
  await this.git(path, userNameArgs);
961
1957
  await this.git(path, userEmailArgs);
1958
+ await this.git(path, autoSetupRemoteArgs);
962
1959
  }
963
1960
  /**
964
1961
  * Type guard for GitCommit
@@ -966,7 +1963,7 @@ var GitService2 = class {
966
1963
  * @param obj The object to check
967
1964
  */
968
1965
  isGitCommit(obj) {
969
- return import_shared6.gitCommitSchema.safeParse(obj).success;
1966
+ return gitCommitSchema.safeParse(obj).success;
970
1967
  }
971
1968
  /**
972
1969
  * Wraps the execution of any git command
@@ -976,14 +1973,29 @@ var GitService2 = class {
976
1973
  * @param args Arguments to append after the `git` command
977
1974
  */
978
1975
  async git(path, args) {
979
- const result = await this.queue.add(() => import_dugite.GitProcess.exec(args, path));
1976
+ const result = await this.queue.add(
1977
+ () => import_dugite.GitProcess.exec(args, path, {
1978
+ env: {
1979
+ // @todo Nasty stuff - remove after update to dugite with git > v2.45.2 once available
1980
+ // @see https://github.com/git-lfs/git-lfs/issues/5749
1981
+ GIT_CLONE_PROTECTION_ACTIVE: "false"
1982
+ }
1983
+ })
1984
+ );
980
1985
  if (!result) {
981
1986
  throw new GitError(
982
- `Git (${this.version}) command "git ${args.join(
1987
+ `Git ${this.version} (${this.gitPath}) command "git ${args.join(
983
1988
  " "
984
1989
  )}" failed to return a result`
985
1990
  );
986
1991
  }
1992
+ if (result.exitCode !== 0) {
1993
+ throw new GitError(
1994
+ `Git ${this.version} (${this.gitPath}) command "git ${args.join(
1995
+ " "
1996
+ )}" failed with exit code "${result.exitCode}" and message "${result.stderr}"`
1997
+ );
1998
+ }
987
1999
  return result;
988
2000
  }
989
2001
  };
@@ -991,7 +2003,7 @@ var GitService2 = class {
991
2003
  // src/service/AssetService.ts
992
2004
  var AssetService = class extends AbstractCrudService {
993
2005
  constructor(options, jsonFileService, gitService) {
994
- super(import_shared7.serviceTypeSchema.Enum.Asset, options);
2006
+ super(serviceTypeSchema.Enum.Asset, options);
995
2007
  this.jsonFileService = jsonFileService;
996
2008
  this.gitService = gitService;
997
2009
  }
@@ -999,8 +2011,8 @@ var AssetService = class extends AbstractCrudService {
999
2011
  * Creates a new Asset
1000
2012
  */
1001
2013
  async create(props) {
1002
- import_shared7.createAssetSchema.parse(props);
1003
- const id = (0, import_shared7.uuid)();
2014
+ createAssetSchema.parse(props);
2015
+ const id = uuid();
1004
2016
  const projectPath = pathTo.project(props.projectId);
1005
2017
  const fileType = await this.getSupportedFileTypeOrThrow(props.filePath);
1006
2018
  const size = await this.getAssetSize(props.filePath);
@@ -1019,7 +2031,8 @@ var AssetService = class extends AbstractCrudService {
1019
2031
  ...props,
1020
2032
  objectType: "asset",
1021
2033
  id,
1022
- created: (0, import_shared7.currentTimestamp)(),
2034
+ created: currentTimestamp(),
2035
+ updated: null,
1023
2036
  extension: fileType.extension,
1024
2037
  mimeType: fileType.mimeType,
1025
2038
  size
@@ -1029,7 +2042,7 @@ var AssetService = class extends AbstractCrudService {
1029
2042
  await this.jsonFileService.create(
1030
2043
  assetFile,
1031
2044
  assetFilePath,
1032
- import_shared7.assetFileSchema
2045
+ assetFileSchema
1033
2046
  );
1034
2047
  } catch (error) {
1035
2048
  await this.delete({ ...assetFile, projectId: props.projectId });
@@ -1043,10 +2056,10 @@ var AssetService = class extends AbstractCrudService {
1043
2056
  * Returns an Asset by ID and language
1044
2057
  */
1045
2058
  async read(props) {
1046
- import_shared7.readAssetSchema.parse(props);
2059
+ readAssetSchema.parse(props);
1047
2060
  const assetFile = await this.jsonFileService.read(
1048
2061
  pathTo.assetFile(props.projectId, props.id, props.language),
1049
- import_shared7.assetFileSchema
2062
+ assetFileSchema
1050
2063
  );
1051
2064
  return this.toAsset(props.projectId, assetFile);
1052
2065
  }
@@ -1056,7 +2069,7 @@ var AssetService = class extends AbstractCrudService {
1056
2069
  * Use the optional "newFilePath" prop to update the Asset itself
1057
2070
  */
1058
2071
  async update(props) {
1059
- import_shared7.updateAssetSchema.parse(props);
2072
+ updateAssetSchema.parse(props);
1060
2073
  const projectPath = pathTo.project(props.projectId);
1061
2074
  const assetFilePath = pathTo.assetFile(
1062
2075
  props.projectId,
@@ -1067,7 +2080,7 @@ var AssetService = class extends AbstractCrudService {
1067
2080
  const assetFile = {
1068
2081
  ...prevAssetFile,
1069
2082
  ...props,
1070
- updated: (0, import_shared7.currentTimestamp)()
2083
+ updated: currentTimestamp()
1071
2084
  };
1072
2085
  if (props.newFilePath) {
1073
2086
  const fileType = await this.getSupportedFileTypeOrThrow(
@@ -1095,7 +2108,7 @@ var AssetService = class extends AbstractCrudService {
1095
2108
  await this.jsonFileService.update(
1096
2109
  assetFile,
1097
2110
  assetFilePath,
1098
- import_shared7.assetFileSchema
2111
+ assetFileSchema
1099
2112
  );
1100
2113
  await this.gitService.add(projectPath, [assetFilePath]);
1101
2114
  await this.gitService.commit(projectPath, this.gitMessage.update);
@@ -1105,7 +2118,7 @@ var AssetService = class extends AbstractCrudService {
1105
2118
  * Deletes given Asset
1106
2119
  */
1107
2120
  async delete(props) {
1108
- import_shared7.deleteAssetSchema.parse(props);
2121
+ deleteAssetSchema.parse(props);
1109
2122
  const projectPath = pathTo.project(props.projectId);
1110
2123
  const assetFilePath = pathTo.assetFile(
1111
2124
  props.projectId,
@@ -1124,13 +2137,16 @@ var AssetService = class extends AbstractCrudService {
1124
2137
  await this.gitService.commit(projectPath, this.gitMessage.delete);
1125
2138
  }
1126
2139
  async list(props) {
1127
- import_shared7.listAssetsSchema.parse(props);
2140
+ listAssetsSchema.parse(props);
2141
+ const offset = props.offset || 0;
2142
+ const limit = props.limit || 15;
1128
2143
  const assetReferences = await this.listReferences(
1129
- import_shared7.objectTypeSchema.Enum.asset,
2144
+ objectTypeSchema.Enum.asset,
1130
2145
  props.projectId
1131
2146
  );
1132
- const list = await returnResolved(
1133
- assetReferences.map((assetReference) => {
2147
+ const partialAssetReferences = assetReferences.slice(offset, limit);
2148
+ const assets = await returnResolved(
2149
+ partialAssetReferences.map((assetReference) => {
1134
2150
  if (!assetReference.language) {
1135
2151
  throw new RequiredParameterMissingError("language");
1136
2152
  }
@@ -1141,25 +2157,23 @@ var AssetService = class extends AbstractCrudService {
1141
2157
  });
1142
2158
  })
1143
2159
  );
1144
- const paginatedResult = this.paginate(
1145
- list,
1146
- props.sort,
1147
- props.filter,
1148
- props.limit,
1149
- props.offset
1150
- );
1151
- return paginatedResult;
2160
+ return {
2161
+ total: assetReferences.length,
2162
+ limit,
2163
+ offset,
2164
+ list: assets
2165
+ };
1152
2166
  }
1153
2167
  async count(props) {
1154
- import_shared7.countAssetsSchema.parse(props);
1155
- const count = (await this.listReferences(import_shared7.objectTypeSchema.Enum.asset, props.projectId)).length;
2168
+ countAssetsSchema.parse(props);
2169
+ const count = (await this.listReferences(objectTypeSchema.Enum.asset, props.projectId)).length;
1156
2170
  return count;
1157
2171
  }
1158
2172
  /**
1159
2173
  * Checks if given object is of type Asset
1160
2174
  */
1161
2175
  isAsset(obj) {
1162
- return import_shared7.assetSchema.safeParse(obj).success;
2176
+ return assetSchema.safeParse(obj).success;
1163
2177
  }
1164
2178
  /**
1165
2179
  * Returns the size of an Asset in bytes
@@ -1200,14 +2214,14 @@ var AssetService = class extends AbstractCrudService {
1200
2214
  const fileBuffer = await import_fs_extra3.default.readFile(filePath);
1201
2215
  if ((0, import_is_svg.default)(fileBuffer.toString()) === true) {
1202
2216
  return {
1203
- extension: import_shared7.supportedAssetExtensionSchema.Enum.svg,
1204
- mimeType: import_shared7.supportedAssetMimeTypeSchema.Enum["image/svg+xml"]
2217
+ extension: supportedAssetExtensionSchema.Enum.svg,
2218
+ mimeType: supportedAssetMimeTypeSchema.Enum["image/svg+xml"]
1205
2219
  };
1206
2220
  }
1207
2221
  }
1208
2222
  const { fileTypeFromFile } = await import("file-type");
1209
2223
  const fileType = await fileTypeFromFile(filePath);
1210
- const result = import_shared7.supportedAssetTypeSchema.parse({
2224
+ const result = supportedAssetTypeSchema.parse({
1211
2225
  extension: fileType?.ext,
1212
2226
  mimeType: fileType?.mime
1213
2227
  });
@@ -1216,11 +2230,10 @@ var AssetService = class extends AbstractCrudService {
1216
2230
  };
1217
2231
 
1218
2232
  // src/service/CollectionService.ts
1219
- var import_shared8 = require("@elek-io/shared");
1220
2233
  var import_fs_extra4 = __toESM(require("fs-extra"), 1);
1221
2234
  var CollectionService = class extends AbstractCrudService {
1222
2235
  constructor(options, jsonFileService, gitService) {
1223
- super(import_shared8.serviceTypeSchema.Enum.Collection, options);
2236
+ super(serviceTypeSchema.Enum.Collection, options);
1224
2237
  this.jsonFileService = jsonFileService;
1225
2238
  this.gitService = gitService;
1226
2239
  }
@@ -1228,29 +2241,27 @@ var CollectionService = class extends AbstractCrudService {
1228
2241
  * Creates a new Collection
1229
2242
  */
1230
2243
  async create(props) {
1231
- import_shared8.createCollectionSchema.parse(props);
1232
- const id = (0, import_shared8.uuid)();
2244
+ createCollectionSchema.parse(props);
2245
+ const id = uuid();
1233
2246
  const projectPath = pathTo.project(props.projectId);
1234
2247
  const collectionPath = pathTo.collection(props.projectId, id);
1235
- const collectionFilePath = pathTo.collectionFile(
1236
- props.projectId,
1237
- id
1238
- );
2248
+ const collectionFilePath = pathTo.collectionFile(props.projectId, id);
1239
2249
  const collectionFile = {
1240
2250
  ...props,
1241
2251
  objectType: "collection",
1242
2252
  id,
1243
2253
  slug: {
1244
- singular: (0, import_shared8.slug)(props.slug.singular),
1245
- plural: (0, import_shared8.slug)(props.slug.plural)
2254
+ singular: slug(props.slug.singular),
2255
+ plural: slug(props.slug.plural)
1246
2256
  },
1247
- created: (0, import_shared8.currentTimestamp)()
2257
+ created: currentTimestamp(),
2258
+ updated: null
1248
2259
  };
1249
2260
  await import_fs_extra4.default.ensureDir(collectionPath);
1250
2261
  await this.jsonFileService.create(
1251
2262
  collectionFile,
1252
2263
  collectionFilePath,
1253
- import_shared8.collectionFileSchema
2264
+ collectionFileSchema
1254
2265
  );
1255
2266
  await this.gitService.add(projectPath, [collectionFilePath]);
1256
2267
  await this.gitService.commit(projectPath, this.gitMessage.create);
@@ -1260,10 +2271,10 @@ var CollectionService = class extends AbstractCrudService {
1260
2271
  * Returns a Collection by ID
1261
2272
  */
1262
2273
  async read(props) {
1263
- import_shared8.readCollectionSchema.parse(props);
2274
+ readCollectionSchema.parse(props);
1264
2275
  const collection = await this.jsonFileService.read(
1265
2276
  pathTo.collectionFile(props.projectId, props.id),
1266
- import_shared8.collectionFileSchema
2277
+ collectionFileSchema
1267
2278
  );
1268
2279
  return collection;
1269
2280
  }
@@ -1278,7 +2289,7 @@ var CollectionService = class extends AbstractCrudService {
1278
2289
  * before given update can be executed or void if the update was executed successfully
1279
2290
  */
1280
2291
  async update(props) {
1281
- import_shared8.updateCollectionSchema.parse(props);
2292
+ updateCollectionSchema.parse(props);
1282
2293
  const projectPath = pathTo.project(props.projectId);
1283
2294
  const collectionFilePath = pathTo.collectionFile(
1284
2295
  props.projectId,
@@ -1288,12 +2299,12 @@ var CollectionService = class extends AbstractCrudService {
1288
2299
  const collectionFile = {
1289
2300
  ...prevCollectionFile,
1290
2301
  ...props,
1291
- updated: (0, import_shared8.currentTimestamp)()
2302
+ updated: currentTimestamp()
1292
2303
  };
1293
2304
  await this.jsonFileService.update(
1294
2305
  collectionFile,
1295
2306
  collectionFilePath,
1296
- import_shared8.collectionFileSchema
2307
+ collectionFileSchema
1297
2308
  );
1298
2309
  await this.gitService.add(projectPath, [collectionFilePath]);
1299
2310
  await this.gitService.commit(projectPath, this.gitMessage.update);
@@ -1305,42 +2316,44 @@ var CollectionService = class extends AbstractCrudService {
1305
2316
  * The Fields that Collection used are not deleted.
1306
2317
  */
1307
2318
  async delete(props) {
1308
- import_shared8.deleteCollectionSchema.parse(props);
2319
+ deleteCollectionSchema.parse(props);
1309
2320
  const projectPath = pathTo.project(props.projectId);
1310
- const collectionPath = pathTo.collection(
1311
- props.projectId,
1312
- props.id
1313
- );
2321
+ const collectionPath = pathTo.collection(props.projectId, props.id);
1314
2322
  await import_fs_extra4.default.remove(collectionPath);
1315
2323
  await this.gitService.add(projectPath, [collectionPath]);
1316
2324
  await this.gitService.commit(projectPath, this.gitMessage.delete);
1317
2325
  }
1318
2326
  async list(props) {
1319
- import_shared8.listCollectionsSchema.parse(props);
1320
- const references = await this.listReferences(
1321
- import_shared8.objectTypeSchema.Enum.collection,
2327
+ listCollectionsSchema.parse(props);
2328
+ const offset = props.offset || 0;
2329
+ const limit = props.limit || 15;
2330
+ const collectionReferences = await this.listReferences(
2331
+ objectTypeSchema.Enum.collection,
1322
2332
  props.projectId
1323
2333
  );
1324
- const list = await returnResolved(
1325
- references.map((reference) => {
2334
+ const partialCollectionReferences = collectionReferences.slice(
2335
+ offset,
2336
+ limit
2337
+ );
2338
+ const collections = await returnResolved(
2339
+ partialCollectionReferences.map((reference) => {
1326
2340
  return this.read({
1327
2341
  projectId: props.projectId,
1328
2342
  id: reference.id
1329
2343
  });
1330
2344
  })
1331
2345
  );
1332
- return this.paginate(
1333
- list,
1334
- props.sort,
1335
- props.filter,
1336
- props.limit,
1337
- props.offset
1338
- );
2346
+ return {
2347
+ total: collectionReferences.length,
2348
+ limit,
2349
+ offset,
2350
+ list: collections
2351
+ };
1339
2352
  }
1340
2353
  async count(props) {
1341
- import_shared8.countCollectionsSchema.parse(props);
2354
+ countCollectionsSchema.parse(props);
1342
2355
  const count = (await this.listReferences(
1343
- import_shared8.objectTypeSchema.Enum.collection,
2356
+ objectTypeSchema.Enum.collection,
1344
2357
  props.projectId
1345
2358
  )).length;
1346
2359
  return count;
@@ -1349,17 +2362,16 @@ var CollectionService = class extends AbstractCrudService {
1349
2362
  * Checks if given object is of type Collection
1350
2363
  */
1351
2364
  isCollection(obj) {
1352
- return import_shared8.collectionFileSchema.safeParse(obj).success;
2365
+ return collectionFileSchema.safeParse(obj).success;
1353
2366
  }
1354
2367
  };
1355
2368
 
1356
2369
  // src/service/EntryService.ts
1357
- var import_shared9 = require("@elek-io/shared");
1358
2370
  var import_fs_extra5 = __toESM(require("fs-extra"), 1);
1359
2371
  var EntryService = class extends AbstractCrudService {
1360
2372
  // private sharedValueService: SharedValueService;
1361
2373
  constructor(options, jsonFileService, gitService, collectionService, assetService) {
1362
- super(import_shared9.serviceTypeSchema.Enum.Entry, options);
2374
+ super(serviceTypeSchema.Enum.Entry, options);
1363
2375
  this.jsonFileService = jsonFileService;
1364
2376
  this.gitService = gitService;
1365
2377
  this.collectionService = collectionService;
@@ -1369,8 +2381,8 @@ var EntryService = class extends AbstractCrudService {
1369
2381
  * Creates a new Entry for given Collection
1370
2382
  */
1371
2383
  async create(props) {
1372
- import_shared9.createEntrySchema.parse(props);
1373
- const id = (0, import_shared9.uuid)();
2384
+ createEntrySchema.parse(props);
2385
+ const id = uuid();
1374
2386
  const projectPath = pathTo.project(props.projectId);
1375
2387
  const entryFilePath = pathTo.entryFile(
1376
2388
  props.projectId,
@@ -1385,7 +2397,8 @@ var EntryService = class extends AbstractCrudService {
1385
2397
  objectType: "entry",
1386
2398
  id,
1387
2399
  values: props.values,
1388
- created: (0, import_shared9.currentTimestamp)()
2400
+ created: currentTimestamp(),
2401
+ updated: null
1389
2402
  };
1390
2403
  const entry = await this.toEntry({
1391
2404
  projectId: props.projectId,
@@ -1400,7 +2413,7 @@ var EntryService = class extends AbstractCrudService {
1400
2413
  await this.jsonFileService.create(
1401
2414
  entryFile,
1402
2415
  entryFilePath,
1403
- import_shared9.entryFileSchema
2416
+ entryFileSchema
1404
2417
  );
1405
2418
  await this.gitService.add(projectPath, [entryFilePath]);
1406
2419
  await this.gitService.commit(projectPath, this.gitMessage.create);
@@ -1410,10 +2423,10 @@ var EntryService = class extends AbstractCrudService {
1410
2423
  * Returns an Entry from given Collection by ID and language
1411
2424
  */
1412
2425
  async read(props) {
1413
- import_shared9.readEntrySchema.parse(props);
2426
+ readEntrySchema.parse(props);
1414
2427
  const entryFile = await this.jsonFileService.read(
1415
2428
  pathTo.entryFile(props.projectId, props.collectionId, props.id),
1416
- import_shared9.entryFileSchema
2429
+ entryFileSchema
1417
2430
  );
1418
2431
  return await this.toEntry({
1419
2432
  projectId: props.projectId,
@@ -1425,7 +2438,7 @@ var EntryService = class extends AbstractCrudService {
1425
2438
  * Updates an Entry of given Collection with new Values and shared Values
1426
2439
  */
1427
2440
  async update(props) {
1428
- import_shared9.updateEntrySchema.parse(props);
2441
+ updateEntrySchema.parse(props);
1429
2442
  const projectPath = pathTo.project(props.projectId);
1430
2443
  const entryFilePath = pathTo.entryFile(
1431
2444
  props.projectId,
@@ -1444,7 +2457,7 @@ var EntryService = class extends AbstractCrudService {
1444
2457
  const entryFile = {
1445
2458
  ...prevEntryFile,
1446
2459
  values: props.values,
1447
- updated: (0, import_shared9.currentTimestamp)()
2460
+ updated: currentTimestamp()
1448
2461
  };
1449
2462
  const entry = await this.toEntry({
1450
2463
  projectId: props.projectId,
@@ -1459,7 +2472,7 @@ var EntryService = class extends AbstractCrudService {
1459
2472
  await this.jsonFileService.update(
1460
2473
  entryFile,
1461
2474
  entryFilePath,
1462
- import_shared9.entryFileSchema
2475
+ entryFileSchema
1463
2476
  );
1464
2477
  await this.gitService.add(projectPath, [entryFilePath]);
1465
2478
  await this.gitService.commit(projectPath, this.gitMessage.update);
@@ -1469,7 +2482,7 @@ var EntryService = class extends AbstractCrudService {
1469
2482
  * Deletes given Entry from it's Collection
1470
2483
  */
1471
2484
  async delete(props) {
1472
- import_shared9.deleteEntrySchema.parse(props);
2485
+ deleteEntrySchema.parse(props);
1473
2486
  const projectPath = pathTo.project(props.projectId);
1474
2487
  const entryFilePath = pathTo.entryFile(
1475
2488
  props.projectId,
@@ -1481,14 +2494,17 @@ var EntryService = class extends AbstractCrudService {
1481
2494
  await this.gitService.commit(projectPath, this.gitMessage.delete);
1482
2495
  }
1483
2496
  async list(props) {
1484
- import_shared9.listEntriesSchema.parse(props);
1485
- const references = await this.listReferences(
1486
- import_shared9.objectTypeSchema.Enum.entry,
2497
+ listEntriesSchema.parse(props);
2498
+ const offset = props.offset || 0;
2499
+ const limit = props.limit || 15;
2500
+ const entryReferences = await this.listReferences(
2501
+ objectTypeSchema.Enum.entry,
1487
2502
  props.projectId,
1488
2503
  props.collectionId
1489
2504
  );
1490
- const list = await returnResolved(
1491
- references.map((reference) => {
2505
+ const partialEntryReferences = entryReferences.slice(offset, limit);
2506
+ const entries = await returnResolved(
2507
+ partialEntryReferences.map((reference) => {
1492
2508
  return this.read({
1493
2509
  projectId: props.projectId,
1494
2510
  collectionId: props.collectionId,
@@ -1496,18 +2512,17 @@ var EntryService = class extends AbstractCrudService {
1496
2512
  });
1497
2513
  })
1498
2514
  );
1499
- return this.paginate(
1500
- list,
1501
- props.sort,
1502
- props.filter,
1503
- props.limit,
1504
- props.offset
1505
- );
2515
+ return {
2516
+ total: entryReferences.length,
2517
+ limit,
2518
+ offset,
2519
+ list: entries
2520
+ };
1506
2521
  }
1507
2522
  async count(props) {
1508
- import_shared9.countEntriesSchema.parse(props);
2523
+ countEntriesSchema.parse(props);
1509
2524
  return (await this.listReferences(
1510
- import_shared9.objectTypeSchema.Enum.entry,
2525
+ objectTypeSchema.Enum.entry,
1511
2526
  props.projectId,
1512
2527
  props.collectionId
1513
2528
  )).length;
@@ -1516,7 +2531,7 @@ var EntryService = class extends AbstractCrudService {
1516
2531
  * Checks if given object is of type Entry
1517
2532
  */
1518
2533
  isEntry(obj) {
1519
- return import_shared9.entrySchema.safeParse(obj).success;
2534
+ return entrySchema.safeParse(obj).success;
1520
2535
  }
1521
2536
  /**
1522
2537
  * Returns a Value definition by ID
@@ -1545,14 +2560,10 @@ var EntryService = class extends AbstractCrudService {
1545
2560
  valueDefinitions: props.valueDefinitions,
1546
2561
  id: value.definitionId
1547
2562
  });
1548
- const schema = (0, import_shared9.getValueContentSchemaFromDefinition)(definition);
2563
+ const schema = getValueContentSchemaFromDefinition(definition);
1549
2564
  try {
1550
- if (value.valueType === "reference") {
1551
- schema.parse(value.content);
1552
- } else {
1553
- for (const [language, content] of Object.entries(value.content)) {
1554
- schema.parse(content);
1555
- }
2565
+ for (const [language, content] of Object.entries(value.content)) {
2566
+ schema.parse(content);
1556
2567
  }
1557
2568
  } catch (error) {
1558
2569
  console.log("Definition:", definition);
@@ -1580,17 +2591,18 @@ var EntryService = class extends AbstractCrudService {
1580
2591
  // });
1581
2592
  // }
1582
2593
  async resolveValueContentReference(props) {
1583
- switch (props.valueContentReference.referenceObjectType) {
1584
- case import_shared9.objectTypeSchema.Enum.asset:
1585
- return this.resolveValueContentReferenceToAsset({
2594
+ switch (props.valueContentReference.objectType) {
2595
+ case objectTypeSchema.Enum.asset:
2596
+ return await this.assetService.read({
1586
2597
  projectId: props.projectId,
1587
- valueContentReferenceToAsset: props.valueContentReference
2598
+ id: props.valueContentReference.id,
2599
+ language: props.valueContentReference.language
1588
2600
  });
1589
- case import_shared9.objectTypeSchema.Enum.entry:
1590
- return this.resolveValueContentReferenceToEntry({
2601
+ case objectTypeSchema.Enum.entry:
2602
+ return await this.read({
1591
2603
  projectId: props.projectId,
1592
2604
  collectionId: props.collectionId,
1593
- valueContentReferenceToEntry: props.valueContentReference
2605
+ id: props.valueContentReference.id
1594
2606
  });
1595
2607
  default:
1596
2608
  throw new Error(
@@ -1599,86 +2611,61 @@ var EntryService = class extends AbstractCrudService {
1599
2611
  );
1600
2612
  }
1601
2613
  }
1602
- async resolveValueContentReferenceToAsset(props) {
1603
- const resolvedReferences = await Promise.all(
1604
- props.valueContentReferenceToAsset.references.map(async (reference) => {
1605
- const resolvedAsset = await this.assetService.read({
1606
- projectId: props.projectId,
1607
- id: reference.id,
1608
- language: reference.language
1609
- });
1610
- return resolvedAsset;
1611
- })
1612
- );
1613
- return {
1614
- ...props.valueContentReferenceToAsset,
1615
- references: resolvedReferences
1616
- };
1617
- }
1618
- async resolveValueContentReferenceToEntry(props) {
1619
- const resolvedReferences = await Promise.all(
1620
- props.valueContentReferenceToEntry.references.map(async (reference) => {
1621
- const resolvedEntry = await this.read({
1622
- projectId: props.projectId,
1623
- collectionId: props.collectionId,
1624
- id: reference.id
1625
- });
1626
- return resolvedEntry;
1627
- })
1628
- );
1629
- return {
1630
- ...props.valueContentReferenceToEntry,
1631
- references: resolvedReferences
1632
- };
2614
+ async resolveValueContentReferences(props) {
2615
+ let resolvedContent = {};
2616
+ for (const language in props.valueReference.content) {
2617
+ const referencesOfLanguage = props.valueReference.content[language];
2618
+ if (!referencesOfLanguage) {
2619
+ throw new Error(
2620
+ `Trying to access content references by language "${language}" failed`
2621
+ );
2622
+ }
2623
+ const resolvedReferencesOfLanguage = await Promise.all(
2624
+ referencesOfLanguage.map(async (reference) => {
2625
+ return await this.resolveValueContentReference({
2626
+ projectId: props.projectId,
2627
+ collectionId: props.collectionId,
2628
+ valueContentReference: reference
2629
+ });
2630
+ })
2631
+ );
2632
+ resolvedContent = {
2633
+ ...resolvedContent,
2634
+ [language]: resolvedReferencesOfLanguage
2635
+ };
2636
+ }
2637
+ return resolvedContent;
1633
2638
  }
1634
- // private async resolveValueContentReferenceToSharedValue(props: {
1635
- // projectId: string;
1636
- // valueContentReferenceToSharedValue: ValueContentReferenceToSharedValue;
1637
- // }): Promise<ResolvedValueContentReferenceToSharedValue> {
1638
- // const resolvedSharedValue = await this.sharedValueService.read({
1639
- // projectId: props.projectId,
1640
- // id: props.valueContentReferenceToSharedValue.references.id,
1641
- // language: props.valueContentReferenceToSharedValue.references.language,
1642
- // });
1643
- // return {
1644
- // ...props.valueContentReferenceToSharedValue,
1645
- // references: {
1646
- // ...props.valueContentReferenceToSharedValue.references,
1647
- // resolved: resolvedSharedValue,
1648
- // },
1649
- // };
1650
- // }
1651
2639
  /**
1652
2640
  * Creates an Entry from given EntryFile by resolving it's Values
1653
2641
  */
1654
2642
  async toEntry(props) {
1655
- const entry = {
2643
+ return {
1656
2644
  ...props.entryFile,
2645
+ // @ts-ignore @todo fixme - I have no idea why this happens. The types seem to be compatible to me and they work
1657
2646
  values: await Promise.all(
1658
2647
  props.entryFile.values.map(async (value) => {
1659
- if (value.valueType === import_shared9.ValueTypeSchema.Enum.reference) {
1660
- const resolvedValueContentReference = await this.resolveValueContentReference({
2648
+ if (value.valueType === ValueTypeSchema.Enum.reference) {
2649
+ const resolvedContentReferences = await this.resolveValueContentReferences({
1661
2650
  projectId: props.projectId,
1662
2651
  collectionId: props.collectionId,
1663
- valueContentReference: value.content
2652
+ valueReference: value
1664
2653
  });
1665
2654
  return {
1666
2655
  ...value,
1667
- content: resolvedValueContentReference
2656
+ content: resolvedContentReferences
1668
2657
  };
1669
2658
  }
1670
2659
  return value;
1671
2660
  })
1672
2661
  )
1673
2662
  };
1674
- return entry;
1675
2663
  }
1676
2664
  };
1677
2665
 
1678
2666
  // src/service/ProjectService.ts
1679
- var import_shared11 = require("@elek-io/shared");
1680
2667
  var import_fs_extra6 = __toESM(require("fs-extra"), 1);
1681
- var import_os2 = __toESM(require("os"), 1);
2668
+ var import_os4 = __toESM(require("os"), 1);
1682
2669
  var import_path2 = __toESM(require("path"), 1);
1683
2670
  var import_semver = __toESM(require("semver"), 1);
1684
2671
 
@@ -1690,81 +2677,52 @@ var ProjectUpgradeError = class extends Error {
1690
2677
  }
1691
2678
  };
1692
2679
 
1693
- // src/service/SearchService.ts
1694
- var import_shared10 = require("@elek-io/shared");
1695
- var SearchService = class extends AbstractCrudService {
1696
- constructor(options, assetService, collectionService) {
1697
- super(import_shared10.serviceTypeSchema.enum.Search, options);
1698
- this.assetService = assetService;
1699
- this.collectionService = collectionService;
1700
- }
1701
- /**
1702
- * Search all models inside the project for given query
1703
- *
1704
- * @todo Implement SearchOptions parameter
1705
- *
1706
- * @param project Project to search in
1707
- * @param query Query to search for
1708
- */
1709
- async search(projectId, query, objectType) {
1710
- const results = [];
1711
- const normalizedQuery = query.trim();
1712
- if (normalizedQuery === "") {
1713
- return results;
1714
- }
1715
- const paginatedLists = (await Promise.all([this.assetService.list({ projectId, filter: query })])).flat();
1716
- paginatedLists.forEach((paginatedList) => {
1717
- paginatedList.list.flat().forEach((file) => {
1718
- const result = {
1719
- id: file.id,
1720
- language: file.language,
1721
- name: file.name,
1722
- type: file.objectType,
1723
- matches: []
1724
- };
1725
- for (const [key, value] of Object.entries(file)) {
1726
- const valueString = String(value);
1727
- if (valueString.toLowerCase().includes(normalizedQuery.toLowerCase())) {
1728
- const matchStart = valueString.toLowerCase().indexOf(normalizedQuery.toLowerCase());
1729
- const matchEnd = matchStart + normalizedQuery.length;
1730
- result.matches.push({
1731
- key,
1732
- prefix: this.truncate(
1733
- valueString.substring(0, matchStart),
1734
- "start"
1735
- ),
1736
- match: valueString.substring(matchStart, matchEnd),
1737
- suffix: this.truncate(
1738
- valueString.substring(matchEnd, valueString.length),
1739
- "end"
1740
- )
1741
- });
1742
- }
1743
- }
1744
- if (result.matches.length > 0) {
1745
- results.push(result);
1746
- }
1747
- });
1748
- });
1749
- return results;
1750
- }
1751
- truncate(value, at, limit = 15) {
1752
- if (at === "start") {
1753
- return `${value.substring(value.length - limit, value.length)}`;
1754
- } else {
1755
- return `${value.substring(0, limit)}`;
1756
- }
1757
- }
1758
- };
1759
-
1760
2680
  // src/service/ProjectService.ts
1761
2681
  var ProjectService = class extends AbstractCrudService {
1762
- constructor(options, jsonFileService, userService, gitService, searchService, assetService, collectionService, entryService) {
1763
- super(import_shared11.serviceTypeSchema.Enum.Project, options);
2682
+ constructor(options, jsonFileService, userService, gitService, assetService, collectionService, entryService) {
2683
+ super(serviceTypeSchema.Enum.Project, options);
2684
+ this.branches = {
2685
+ list: async (props) => {
2686
+ listBranchesProjectSchema.parse(props);
2687
+ const projectPath = pathTo.project(props.id);
2688
+ await this.gitService.fetch(projectPath);
2689
+ return await this.gitService.branches.list(projectPath);
2690
+ },
2691
+ current: async (props) => {
2692
+ currentBranchProjectSchema.parse(props);
2693
+ const projectPath = pathTo.project(props.id);
2694
+ return await this.gitService.branches.current(projectPath);
2695
+ },
2696
+ switch: async (props) => {
2697
+ switchBranchProjectSchema.parse(props);
2698
+ const projectPath = pathTo.project(props.id);
2699
+ return await this.gitService.branches.switch(
2700
+ projectPath,
2701
+ props.branch,
2702
+ props.options
2703
+ );
2704
+ }
2705
+ };
2706
+ this.remotes = {
2707
+ getOriginUrl: async (props) => {
2708
+ getRemoteOriginUrlProjectSchema.parse(props);
2709
+ const projectPath = pathTo.project(props.id);
2710
+ return await this.gitService.remotes.getOriginUrl(projectPath);
2711
+ },
2712
+ setOriginUrl: async (props) => {
2713
+ setRemoteOriginUrlProjectSchema.parse(props);
2714
+ const projectPath = pathTo.project(props.id);
2715
+ const hasOrigin = await this.gitService.remotes.hasOrigin(projectPath);
2716
+ if (!hasOrigin) {
2717
+ await this.gitService.remotes.addOrigin(projectPath, props.url);
2718
+ } else {
2719
+ await this.gitService.remotes.setOriginUrl(projectPath, props.url);
2720
+ }
2721
+ }
2722
+ };
1764
2723
  this.jsonFileService = jsonFileService;
1765
2724
  this.userService = userService;
1766
2725
  this.gitService = gitService;
1767
- this.searchService = searchService;
1768
2726
  this.assetService = assetService;
1769
2727
  this.collectionService = collectionService;
1770
2728
  this.entryService = entryService;
@@ -1773,12 +2731,12 @@ var ProjectService = class extends AbstractCrudService {
1773
2731
  * Creates a new Project
1774
2732
  */
1775
2733
  async create(props) {
1776
- import_shared11.createProjectSchema.parse(props);
2734
+ createProjectSchema.parse(props);
1777
2735
  const user = await this.userService.get();
1778
2736
  if (!user) {
1779
2737
  throw new NoCurrentUserError();
1780
2738
  }
1781
- const id = (0, import_shared11.uuid)();
2739
+ const id = uuid();
1782
2740
  const defaultSettings = {
1783
2741
  language: {
1784
2742
  default: user.language,
@@ -1791,7 +2749,8 @@ var ProjectService = class extends AbstractCrudService {
1791
2749
  id,
1792
2750
  description: props.description || "",
1793
2751
  settings: Object.assign({}, defaultSettings, props.settings),
1794
- created: (0, import_shared11.currentTimestamp)(),
2752
+ created: currentTimestamp(),
2753
+ updated: null,
1795
2754
  coreVersion: this.options.version,
1796
2755
  // @todo should be read from package.json to avoid duplicates
1797
2756
  status: "todo",
@@ -1806,50 +2765,83 @@ var ProjectService = class extends AbstractCrudService {
1806
2765
  await this.jsonFileService.create(
1807
2766
  projectFile,
1808
2767
  pathTo.projectFile(id),
1809
- import_shared11.projectFileSchema
2768
+ projectFileSchema
1810
2769
  );
1811
2770
  await this.gitService.add(projectPath, ["."]);
1812
2771
  await this.gitService.commit(
1813
2772
  projectPath,
1814
- `${import_shared11.gitCommitIconSchema.enum.INIT} Created this new elek.io project`
2773
+ `${gitCommitIconSchema.enum.INIT} Created this new elek.io project`
1815
2774
  );
1816
- await this.gitService.switch(projectPath, "stage", { isNew: true });
2775
+ await this.gitService.branches.switch(projectPath, "stage", {
2776
+ isNew: true
2777
+ });
1817
2778
  } catch (error) {
1818
2779
  await this.delete({
1819
2780
  id
1820
2781
  });
1821
2782
  throw error;
1822
2783
  }
1823
- return projectFile;
2784
+ return await this.toProject({
2785
+ projectFile
2786
+ });
2787
+ }
2788
+ /**
2789
+ * Clones a Project by URL
2790
+ */
2791
+ async clone(props) {
2792
+ cloneProjectSchema.parse(props);
2793
+ const tmpId = uuid();
2794
+ const tmpProjectPath = import_path2.default.join(pathTo.tmp, tmpId);
2795
+ await this.gitService.clone(props.url, tmpProjectPath);
2796
+ const projectFile = await this.jsonFileService.read(
2797
+ import_path2.default.join(tmpProjectPath, "project.json"),
2798
+ projectFileSchema
2799
+ );
2800
+ const projectPath = pathTo.project(projectFile.id);
2801
+ const alreadyExists = await import_fs_extra6.default.pathExists(projectPath);
2802
+ if (alreadyExists) {
2803
+ throw new Error(
2804
+ `Tried to clone Project "${projectFile.id}" from "${props.url}" - but the Project already exists locally`
2805
+ );
2806
+ }
2807
+ await import_fs_extra6.default.copy(tmpProjectPath, projectPath);
2808
+ await import_fs_extra6.default.remove(tmpProjectPath);
2809
+ return await this.toProject({
2810
+ projectFile
2811
+ });
1824
2812
  }
1825
2813
  /**
1826
2814
  * Returns a Project by ID
1827
2815
  */
1828
2816
  async read(props) {
1829
- import_shared11.readProjectSchema.parse(props);
2817
+ readProjectSchema.parse(props);
1830
2818
  const projectFile = await this.jsonFileService.read(
1831
2819
  pathTo.projectFile(props.id),
1832
- import_shared11.projectFileSchema
2820
+ projectFileSchema
1833
2821
  );
1834
- return projectFile;
2822
+ return await this.toProject({
2823
+ projectFile
2824
+ });
1835
2825
  }
1836
2826
  /**
1837
2827
  * Updates given Project
1838
2828
  */
1839
2829
  async update(props) {
1840
- import_shared11.updateProjectSchema.parse(props);
2830
+ updateProjectSchema.parse(props);
1841
2831
  const projectPath = pathTo.project(props.id);
1842
2832
  const filePath = pathTo.projectFile(props.id);
1843
2833
  const prevProjectFile = await this.read(props);
1844
2834
  const projectFile = {
1845
2835
  ...prevProjectFile,
1846
2836
  ...props,
1847
- updated: (0, import_shared11.currentTimestamp)()
2837
+ updated: currentTimestamp()
1848
2838
  };
1849
- await this.jsonFileService.update(projectFile, filePath, import_shared11.projectFileSchema);
2839
+ await this.jsonFileService.update(projectFile, filePath, projectFileSchema);
1850
2840
  await this.gitService.add(projectPath, [filePath]);
1851
2841
  await this.gitService.commit(projectPath, this.gitMessage.update);
1852
- return projectFile;
2842
+ return await this.toProject({
2843
+ projectFile
2844
+ });
1853
2845
  }
1854
2846
  /**
1855
2847
  * Upgrades given Project to the latest version of this client
@@ -1859,7 +2851,7 @@ var ProjectService = class extends AbstractCrudService {
1859
2851
  * @todo Find out why using this.snapshotService is throwing isObjWithKeyAndValueOfString of undefined error in gitService (maybe binding issue)
1860
2852
  */
1861
2853
  async upgrade(props) {
1862
- import_shared11.upgradeProjectSchema.parse(props);
2854
+ upgradeProjectSchema.parse(props);
1863
2855
  const project = await this.read(props);
1864
2856
  const projectPath = pathTo.project(project.id);
1865
2857
  if (import_semver.default.gt(project.coreVersion, this.options.version)) {
@@ -1917,6 +2909,39 @@ var ProjectService = class extends AbstractCrudService {
1917
2909
  }
1918
2910
  }
1919
2911
  }
2912
+ /**
2913
+ * Returns the differences of the given Projects current branch
2914
+ * between the local and remote `origin` (commits ahead & behind)
2915
+ *
2916
+ * - `behind` contains a list of commits on the current branch that are available on the remote `origin` but not yet locally
2917
+ * - `ahead` contains a list of commits on the current branch that are available locally but not yet on the remote `origin`
2918
+ */
2919
+ async getChanges(props) {
2920
+ getChangesProjectSchema.parse(props);
2921
+ const projectPath = pathTo.project(props.id);
2922
+ const currentBranch = await this.gitService.branches.current(projectPath);
2923
+ await this.gitService.fetch(projectPath);
2924
+ const behind = await this.gitService.log(projectPath, {
2925
+ between: { from: currentBranch, to: `origin/${currentBranch}` }
2926
+ });
2927
+ const ahead = await this.gitService.log(projectPath, {
2928
+ between: { from: `origin/${currentBranch}`, to: currentBranch }
2929
+ });
2930
+ return {
2931
+ behind,
2932
+ ahead
2933
+ };
2934
+ }
2935
+ /**
2936
+ * Pulls remote changes of `origin` down to the local repository
2937
+ * and then pushes local commits to the upstream branch
2938
+ */
2939
+ async synchronize(props) {
2940
+ synchronizeProjectSchema.parse(props);
2941
+ const projectPath = pathTo.project(props.id);
2942
+ await this.gitService.pull(projectPath);
2943
+ await this.gitService.push(projectPath);
2944
+ }
1920
2945
  /**
1921
2946
  * Deletes given Project
1922
2947
  *
@@ -1925,45 +2950,39 @@ var ProjectService = class extends AbstractCrudService {
1925
2950
  * Or changes that are not pushed to a remote yet, will be lost too.
1926
2951
  */
1927
2952
  async delete(props) {
1928
- import_shared11.deleteProjectSchema.parse(props);
2953
+ deleteProjectSchema.parse(props);
1929
2954
  await import_fs_extra6.default.remove(pathTo.project(props.id));
1930
2955
  }
1931
2956
  async list(props) {
1932
2957
  if (props) {
1933
- import_shared11.listProjectsSchema.parse(props);
2958
+ listProjectsSchema.parse(props);
1934
2959
  }
1935
- const references = await this.listReferences(import_shared11.objectTypeSchema.Enum.project);
1936
- const list = await returnResolved(
1937
- references.map((reference) => {
2960
+ const offset = props?.offset || 0;
2961
+ const limit = props?.limit || 15;
2962
+ const projectReferences = await this.listReferences(
2963
+ objectTypeSchema.Enum.project
2964
+ );
2965
+ const partialProjectReferences = projectReferences.slice(offset, limit);
2966
+ const projects = await returnResolved(
2967
+ partialProjectReferences.map((reference) => {
1938
2968
  return this.read({ id: reference.id });
1939
2969
  })
1940
2970
  );
1941
- return this.paginate(
1942
- list,
1943
- props?.sort,
1944
- props?.filter,
1945
- props?.limit,
1946
- props?.offset
1947
- );
2971
+ return {
2972
+ total: projectReferences.length,
2973
+ limit,
2974
+ offset,
2975
+ list: projects
2976
+ };
1948
2977
  }
1949
2978
  async count() {
1950
- return (await this.listReferences(import_shared11.objectTypeSchema.Enum.project)).length;
1951
- }
1952
- /**
1953
- * Search all models inside the project for given query
1954
- *
1955
- * @param projectId Project ID to search in
1956
- * @param query Query to search for
1957
- * @param type (Optional) specify the type to search for
1958
- */
1959
- async search(projectId, query, type) {
1960
- return this.searchService.search(projectId, query, type);
2979
+ return (await this.listReferences(objectTypeSchema.Enum.project)).length;
1961
2980
  }
1962
2981
  /**
1963
2982
  * Checks if given object is of type Project
1964
2983
  */
1965
2984
  isProject(obj) {
1966
- return import_shared11.projectFileSchema.safeParse(obj).success;
2985
+ return projectFileSchema.safeParse(obj).success;
1967
2986
  }
1968
2987
  /**
1969
2988
  * Exports given Project to JSON
@@ -1995,13 +3014,21 @@ var ProjectService = class extends AbstractCrudService {
1995
3014
  collections: collectionExport
1996
3015
  };
1997
3016
  }
3017
+ /**
3018
+ * Creates a Project from given ProjectFile by adding git information
3019
+ */
3020
+ async toProject(props) {
3021
+ return {
3022
+ ...props.projectFile
3023
+ };
3024
+ }
1998
3025
  /**
1999
3026
  * Creates the projects folder structure and makes sure to
2000
3027
  * write empty .gitkeep files inside them to ensure they are
2001
3028
  * committed
2002
3029
  */
2003
3030
  async createFolderStructure(path) {
2004
- const folders2 = Object.values(import_shared11.projectFolderSchema.Values);
3031
+ const folders2 = Object.values(projectFolderSchema.Values);
2005
3032
  await Promise.all(
2006
3033
  folders2.map(async (folder) => {
2007
3034
  await import_fs_extra6.default.mkdirp(import_path2.default.join(path, folder));
@@ -2029,15 +3056,44 @@ var ProjectService = class extends AbstractCrudService {
2029
3056
  // projectFolderSchema.Enum.public + '/',
2030
3057
  // projectFolderSchema.Enum.logs + '/',
2031
3058
  ];
2032
- await import_fs_extra6.default.writeFile(import_path2.default.join(path, ".gitignore"), lines.join(import_os2.default.EOL));
3059
+ await import_fs_extra6.default.writeFile(import_path2.default.join(path, ".gitignore"), lines.join(import_os4.default.EOL));
2033
3060
  }
2034
3061
  };
2035
3062
 
3063
+ // src/schema/coreSchema.ts
3064
+ var import_zod12 = require("zod");
3065
+ var elekIoCoreOptionsSchema = import_zod12.z.object({
3066
+ /**
3067
+ * The environment elek.io Core is currently running in
3068
+ */
3069
+ environment: environmentSchema,
3070
+ /**
3071
+ * The current version of elek.io Core
3072
+ */
3073
+ version: versionSchema,
3074
+ file: import_zod12.z.object({
3075
+ json: import_zod12.z.object({
3076
+ /**
3077
+ * If set, adds indentation with spaces (number) or escape character (string)
3078
+ * and line break characters to saved JSON files on disk, to make them easier to read.
3079
+ * Defaults to 2 spaces of indentation.
3080
+ */
3081
+ indentation: import_zod12.z.union([import_zod12.z.number(), import_zod12.z.string()])
3082
+ })
3083
+ })
3084
+ });
3085
+ var constructorElekIoCoreSchema = elekIoCoreOptionsSchema.omit({
3086
+ version: true
3087
+ }).partial({
3088
+ environment: true,
3089
+ file: true
3090
+ }).optional();
3091
+
2036
3092
  // src/index.ts
2037
3093
  var ElekIoCore = class {
2038
3094
  // private readonly sharedValueService: SharedValueService;
2039
3095
  constructor(props) {
2040
- const parsedProps = import_shared12.constructorElekIoCoreSchema.parse(props);
3096
+ const parsedProps = constructorElekIoCoreSchema.parse(props);
2041
3097
  const defaults = {
2042
3098
  environment: "production",
2043
3099
  version: "0.0.0",
@@ -2069,17 +3125,11 @@ var ElekIoCore = class {
2069
3125
  this.assetService
2070
3126
  // this.sharedValueService
2071
3127
  );
2072
- this.searchService = new SearchService(
2073
- this.options,
2074
- this.assetService,
2075
- this.collectionService
2076
- );
2077
3128
  this.projectService = new ProjectService(
2078
3129
  this.options,
2079
3130
  this.jsonFileService,
2080
3131
  this.userService,
2081
3132
  this.gitService,
2082
- this.searchService,
2083
3133
  this.assetService,
2084
3134
  this.collectionService,
2085
3135
  this.entryService
@@ -2103,7 +3153,13 @@ var ElekIoCore = class {
2103
3153
  return util_exports;
2104
3154
  }
2105
3155
  /**
2106
- *
3156
+ * Exposes git functions
3157
+ */
3158
+ get git() {
3159
+ return this.gitService;
3160
+ }
3161
+ /**
3162
+ * Getter and setter methods for the User currently working with Core
2107
3163
  */
2108
3164
  get user() {
2109
3165
  return this.userService;