@content-collections/core 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,244 +1,109 @@
1
- // src/config.ts
2
- import { z } from "zod";
3
-
4
- // src/utils.ts
5
- import camelcase from "camelcase";
6
- import pluralize from "pluralize";
7
- function generateTypeName(name) {
8
- const singularName = pluralize.singular(name);
9
- return camelcase(singularName, { pascalCase: true });
10
- }
11
- function isDefined(value) {
12
- return value !== void 0 && value !== null;
13
- }
14
- function orderByPath(a, b) {
15
- return a.path.localeCompare(b.path);
16
- }
17
- function removeChildPaths(paths) {
18
- return Array.from(
19
- new Set(
20
- paths.filter((path8) => {
21
- return !paths.some((otherPath) => {
22
- if (path8 === otherPath) {
23
- return false;
24
- }
25
- return path8.startsWith(otherPath);
26
- });
27
- })
28
- )
29
- );
30
- }
31
-
32
- // src/config.ts
33
- var InvalidReturnTypeSymbol = Symbol(`InvalidReturnType`);
34
- function defineCollection(collection) {
35
- let typeName = collection.typeName;
36
- if (!typeName) {
37
- typeName = generateTypeName(collection.name);
38
- }
39
- let parser = collection.parser;
40
- if (!parser) {
41
- parser = "frontmatter";
42
- }
43
- return {
44
- ...collection,
45
- typeName,
46
- parser,
47
- schema: collection.schema(z)
48
- };
49
- }
50
- function defineConfig(config) {
51
- return config;
52
- }
53
-
54
- // src/configurationReader.ts
55
- import fs from "fs/promises";
56
- import path from "path";
57
- import { existsSync } from "fs";
58
- import { createHash } from "crypto";
1
+ // src/builder.ts
2
+ import path8 from "node:path";
59
3
 
60
- // src/esbuild.ts
61
- import { build } from "esbuild";
62
- import { match, loadTsConfig, tsconfigPathsToRegExp } from "bundle-require";
63
- import { dirname, join } from "path";
64
- function tsconfigResolvePaths(configPath) {
65
- let tsconfig = loadTsConfig(dirname(configPath));
66
- if (!tsconfig) {
67
- tsconfig = loadTsConfig();
68
- }
69
- return tsconfig?.data?.compilerOptions?.paths || {};
70
- }
71
- function createExternalsPlugin(configPath) {
72
- const resolvedPaths = tsconfigResolvePaths(configPath);
73
- const resolvePatterns = tsconfigPathsToRegExp(resolvedPaths);
74
- return {
75
- name: "external-packages",
76
- setup: (build3) => {
77
- const filter = /^[^.\/]|^\.[^.\/]|^\.\.[^\/]/;
78
- build3.onResolve({ filter }, ({ path: path8, kind }) => {
79
- if (match(path8, resolvePatterns)) {
80
- if (kind === "dynamic-import") {
81
- return { path: path8, external: true };
82
- }
83
- return;
84
- }
85
- return { path: path8, external: true };
86
- });
87
- }
88
- };
4
+ // src/cache.ts
5
+ import { createHash } from "node:crypto";
6
+ import { existsSync } from "node:fs";
7
+ import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
8
+ import path, { join } from "node:path";
9
+ function createKey(config, input) {
10
+ return createHash("sha256").update(config).update(JSON.stringify(input)).digest("hex");
89
11
  }
90
- var importPathPlugin = {
91
- name: "import-path",
92
- setup(build3) {
93
- build3.onResolve({ filter: /^\@content-collections\/core$/ }, () => {
94
- return { path: join(__dirname, "index.ts"), external: true };
95
- });
96
- }
97
- };
98
- async function compile(configurationPath, outfile) {
99
- const plugins = [createExternalsPlugin(configurationPath)];
100
- if (process.env.NODE_ENV === "test") {
101
- plugins.push(importPathPlugin);
12
+ async function createCacheDirectory(directory) {
13
+ const cacheDirectory = path.join(directory, ".content-collections", "cache");
14
+ if (!existsSync(cacheDirectory)) {
15
+ await mkdir(cacheDirectory, { recursive: true });
102
16
  }
103
- const result = await build({
104
- entryPoints: [configurationPath],
105
- packages: "external",
106
- bundle: true,
107
- platform: "node",
108
- format: "esm",
109
- plugins,
110
- outfile,
111
- metafile: true
112
- });
113
- return Object.keys(result.metafile.inputs);
17
+ return cacheDirectory;
114
18
  }
115
-
116
- // src/configurationReader.ts
117
- var ConfigurationError = class extends Error {
118
- type;
119
- constructor(type, message) {
120
- super(message);
121
- this.type = type;
122
- }
123
- };
124
- var defaultConfigName = "content-collection-config.mjs";
125
- function resolveCacheDir(config, options) {
126
- if (options.cacheDir) {
127
- return options.cacheDir;
128
- }
129
- return path.join(path.dirname(config), ".content-collections", "cache");
19
+ function fileName(input) {
20
+ return input.replace(/[^a-z0-9]/gi, "_").toLowerCase();
130
21
  }
131
- function createConfigurationReader() {
132
- return async (configurationPath, options = {
133
- configName: defaultConfigName
134
- }) => {
135
- if (!existsSync(configurationPath)) {
136
- throw new ConfigurationError(
137
- "Read",
138
- `configuration file ${configurationPath} does not exist`
139
- );
140
- }
141
- const cacheDir = resolveCacheDir(configurationPath, options);
142
- await fs.mkdir(cacheDir, { recursive: true });
143
- const outfile = path.join(cacheDir, options.configName);
22
+ async function readMapping(mappingPath) {
23
+ if (existsSync(mappingPath)) {
144
24
  try {
145
- const configurationPaths = await compile(configurationPath, outfile);
146
- const module = await import(`file://${path.resolve(outfile)}?x=${Date.now()}`);
147
- const hash = createHash("sha256");
148
- hash.update(await fs.readFile(outfile, "utf-8"));
149
- const checksum = hash.digest("hex");
150
- return {
151
- ...module.default,
152
- path: configurationPath,
153
- inputPaths: configurationPaths.map((p) => path.resolve(p)),
154
- generateTypes: true,
155
- checksum
156
- };
157
- } catch (error) {
158
- throw new ConfigurationError(
159
- "Compile",
160
- `configuration file ${configurationPath} is invalid: ${error}`
25
+ return JSON.parse(await readFile(mappingPath, "utf-8"));
26
+ } catch (e) {
27
+ console.error(
28
+ "Failed to parse the cache mapping. We will recreate the cache."
161
29
  );
162
30
  }
163
- };
31
+ }
32
+ return {};
164
33
  }
165
-
166
- // src/builder.ts
167
- import path7 from "path";
168
-
169
- // src/watcher.ts
170
- import * as watcher from "@parcel/watcher";
171
- import path2, { dirname as dirname2, resolve } from "path";
172
- async function createWatcher(emitter, baseDirectory, configuration, sync) {
173
- const onChange = async (error, events) => {
174
- if (error) {
175
- emitter.emit("watcher:subscribe-error", {
176
- paths,
177
- error
178
- });
179
- return;
34
+ async function createCacheManager(baseDirectory, configChecksum) {
35
+ const cacheDirectory = await createCacheDirectory(baseDirectory);
36
+ const mappingPath = join(cacheDirectory, "mapping.json");
37
+ const mapping = await readMapping(mappingPath);
38
+ async function flush() {
39
+ await writeFile(mappingPath, JSON.stringify(mapping));
40
+ }
41
+ function cache(collection, file) {
42
+ const directory = join(
43
+ cacheDirectory,
44
+ fileName(collection),
45
+ fileName(file)
46
+ );
47
+ let collectionMapping = mapping[collection];
48
+ if (!collectionMapping) {
49
+ collectionMapping = {};
50
+ mapping[collection] = collectionMapping;
180
51
  }
181
- for (const event of events) {
182
- await sync(event.type, event.path);
52
+ let fileMapping = collectionMapping[file];
53
+ if (!fileMapping) {
54
+ fileMapping = [];
55
+ collectionMapping[file] = fileMapping;
183
56
  }
184
- };
185
- const paths = removeChildPaths([
186
- ...configuration.collections.map((collection) => path2.join(baseDirectory, collection.directory)).map((p) => resolve(p)),
187
- ...configuration.inputPaths.map((p) => dirname2(p))
188
- ]);
189
- const subscriptions = (await Promise.all(paths.map((path8) => watcher.subscribe(path8, onChange)))).filter(isDefined);
190
- emitter.emit("watcher:subscribed", {
191
- paths
192
- });
193
- return {
194
- unsubscribe: async () => {
195
- if (!subscriptions || subscriptions.length === 0) {
196
- return;
57
+ let newFileMapping = [];
58
+ const cacheFn = async (input, fn) => {
59
+ const key = createKey(configChecksum, input);
60
+ newFileMapping.push(key);
61
+ const filePath = join(directory, `${key}.cache`);
62
+ if (fileMapping?.includes(key) || newFileMapping.includes(key)) {
63
+ if (existsSync(filePath)) {
64
+ try {
65
+ return JSON.parse(await readFile(filePath, "utf-8"));
66
+ } catch (e) {
67
+ console.error(
68
+ "Failed to parse the cache file. We will recompute the value."
69
+ );
70
+ }
71
+ }
197
72
  }
198
- await Promise.all(
199
- subscriptions.map((subscription) => subscription.unsubscribe())
200
- );
201
- emitter.emit("watcher:unsubscribed", {
202
- paths
203
- });
204
- return;
205
- }
206
- };
207
- }
208
-
209
- // src/events.ts
210
- import { EventEmitter } from "events";
211
- function isEventWithError(event) {
212
- return typeof event === "object" && event !== null && "error" in event;
213
- }
214
- function createEmitter() {
215
- const emitter = new EventEmitter();
216
- function on(key, listener) {
217
- emitter.on(key, listener);
218
- }
219
- function emit(key, event) {
220
- emitter.emit(key, event);
221
- if (isEventWithError(event)) {
222
- emitter.emit("_error", {
223
- ...event,
224
- _event: key
225
- });
226
- }
227
- emitter.emit("_all", {
228
- ...event,
229
- _event: key
230
- });
73
+ const output = await fn(input);
74
+ if (!existsSync(directory)) {
75
+ await mkdir(directory, { recursive: true });
76
+ }
77
+ await writeFile(filePath, JSON.stringify(output));
78
+ return output;
79
+ };
80
+ const tidyUp = async () => {
81
+ const filesToDelete = fileMapping?.filter((key) => !newFileMapping.includes(key)) || [];
82
+ for (const key of filesToDelete) {
83
+ const filePath = join(directory, `${key}.cache`);
84
+ if (existsSync(filePath)) {
85
+ await unlink(filePath);
86
+ }
87
+ }
88
+ if (collectionMapping) {
89
+ collectionMapping[file] = newFileMapping;
90
+ }
91
+ };
92
+ return {
93
+ cacheFn,
94
+ tidyUp
95
+ };
231
96
  }
232
97
  return {
233
- on,
234
- emit
98
+ cache,
99
+ flush
235
100
  };
236
101
  }
237
102
 
238
103
  // src/collector.ts
104
+ import { readFile as readFile2 } from "fs/promises";
105
+ import path2 from "path";
239
106
  import { glob } from "tinyglobby";
240
- import { readFile } from "fs/promises";
241
- import path3 from "path";
242
107
 
243
108
  // src/parser.ts
244
109
  import matter from "gray-matter";
@@ -260,20 +125,48 @@ function frontmatterParser(fileContent) {
260
125
  content: content.trim()
261
126
  };
262
127
  }
263
- var parsers = {
264
- frontmatter: {
265
- hasContent: true,
266
- parse: frontmatterParser
267
- },
268
- json: {
269
- hasContent: false,
270
- parse: JSON.parse
271
- },
272
- yaml: {
273
- hasContent: false,
274
- parse: parseYaml
275
- }
276
- };
128
+ var parsers = {
129
+ frontmatter: {
130
+ hasContent: true,
131
+ parse: frontmatterParser
132
+ },
133
+ json: {
134
+ hasContent: false,
135
+ parse: JSON.parse
136
+ },
137
+ yaml: {
138
+ hasContent: false,
139
+ parse: parseYaml
140
+ }
141
+ };
142
+
143
+ // src/utils.ts
144
+ import camelcase from "camelcase";
145
+ import pluralize from "pluralize";
146
+ function generateTypeName(name) {
147
+ const singularName = pluralize.singular(name);
148
+ return camelcase(singularName, { pascalCase: true });
149
+ }
150
+ function isDefined(value) {
151
+ return value !== void 0 && value !== null;
152
+ }
153
+ function orderByPath(a, b) {
154
+ return a.path.localeCompare(b.path);
155
+ }
156
+ function removeChildPaths(paths) {
157
+ return Array.from(
158
+ new Set(
159
+ paths.filter((path9) => {
160
+ return !paths.some((otherPath) => {
161
+ if (path9 === otherPath) {
162
+ return false;
163
+ }
164
+ return path9.startsWith(otherPath);
165
+ });
166
+ })
167
+ )
168
+ );
169
+ }
277
170
 
278
171
  // src/collector.ts
279
172
  var CollectError = class extends Error {
@@ -286,7 +179,7 @@ var CollectError = class extends Error {
286
179
  function createCollector(emitter, baseDirectory = ".") {
287
180
  async function read(filePath) {
288
181
  try {
289
- return await readFile(filePath, "utf-8");
182
+ return await readFile2(filePath, "utf-8");
290
183
  } catch (error) {
291
184
  emitter.emit("collector:read-error", {
292
185
  filePath,
@@ -296,7 +189,11 @@ function createCollector(emitter, baseDirectory = ".") {
296
189
  }
297
190
  }
298
191
  async function collectFile(collection, filePath) {
299
- const absolutePath = path3.join(baseDirectory, collection.directory, filePath);
192
+ const absolutePath = path2.join(
193
+ baseDirectory,
194
+ collection.directory,
195
+ filePath
196
+ );
300
197
  const file = await read(absolutePath);
301
198
  if (!file) {
302
199
  return null;
@@ -309,7 +206,7 @@ function createCollector(emitter, baseDirectory = ".") {
309
206
  };
310
207
  } catch (error) {
311
208
  emitter.emit("collector:parse-error", {
312
- filePath: path3.join(collection.directory, filePath),
209
+ filePath: path2.join(collection.directory, filePath),
313
210
  error: new CollectError("Parse", String(error))
314
211
  });
315
212
  return null;
@@ -326,7 +223,7 @@ function createCollector(emitter, baseDirectory = ".") {
326
223
  return void 0;
327
224
  }
328
225
  async function resolveCollection(collection) {
329
- const collectionDirectory = path3.join(baseDirectory, collection.directory);
226
+ const collectionDirectory = path2.join(baseDirectory, collection.directory);
330
227
  const include = Array.isArray(collection.include) ? collection.include : [collection.include];
331
228
  const filePaths = await glob(include, {
332
229
  cwd: collectionDirectory,
@@ -355,135 +252,24 @@ function createCollector(emitter, baseDirectory = ".") {
355
252
  };
356
253
  }
357
254
 
358
- // src/writer.ts
359
- import fs2 from "fs/promises";
360
- import path4 from "path";
361
- import pluralize2 from "pluralize";
362
-
363
- // src/serializer.ts
364
- import z2 from "zod";
365
- import serializeJs from "serialize-javascript";
366
- var literalSchema = z2.union([
367
- // json
368
- z2.string(),
369
- z2.number(),
370
- z2.boolean(),
371
- z2.null(),
372
- // serializable-javascript
373
- z2.undefined(),
374
- z2.date(),
375
- z2.map(z2.unknown(), z2.unknown()),
376
- z2.set(z2.unknown()),
377
- z2.bigint()
378
- ]);
379
- var schema = z2.lazy(
380
- () => z2.union([literalSchema, z2.array(schema), z2.record(schema)])
381
- );
382
- var extension = "js";
383
- var serializableSchema = z2.record(schema);
384
- function serialize(value) {
385
- const serializedValue = serializeJs(value, {
386
- space: 2,
387
- unsafe: true,
388
- ignoreFunction: true
389
- });
390
- return `export default ${serializedValue};`;
391
- }
392
-
393
- // src/writer.ts
394
- function createArrayConstName(name) {
395
- let suffix = name.charAt(0).toUpperCase() + name.slice(1);
396
- return "all" + pluralize2(suffix);
397
- }
398
- async function createDataFile(directory, collection) {
399
- const dataPath = path4.join(
400
- directory,
401
- `${createArrayConstName(collection.name)}.${extension}`
402
- );
403
- await fs2.writeFile(
404
- dataPath,
405
- serialize(collection.documents.map((doc) => doc.document))
406
- );
407
- }
408
- function createDataFiles(directory, collections) {
409
- return Promise.all(
410
- collections.map((collection) => createDataFile(directory, collection))
411
- );
412
- }
413
- async function createJavaScriptFile(directory, configuration) {
414
- const collections = configuration.collections.map(
415
- ({ name }) => createArrayConstName(name)
416
- );
417
- let content = `// generated by content-collections at ${/* @__PURE__ */ new Date()}
418
-
419
- `;
420
- for (const name of collections) {
421
- content += `import ${name} from "./${name}.${extension}";
422
- `;
423
- }
424
- content += "\n";
425
- content += "export { " + collections.join(", ") + " };\n";
426
- await fs2.writeFile(path4.join(directory, "index.js"), content, "utf-8");
427
- }
428
- function createImportPath(directory, target) {
429
- let importPath = path4.posix.join(
430
- ...path4.relative(directory, target).split(path4.sep)
431
- );
432
- if (!importPath.startsWith(".")) {
433
- importPath = "./" + importPath;
434
- }
435
- return importPath;
436
- }
437
- async function createTypeDefinitionFile(directory, configuration) {
438
- if (!configuration.generateTypes) {
439
- return;
440
- }
441
- const importPath = createImportPath(directory, configuration.path);
442
- let content = `import configuration from "${importPath}";
443
- import { GetTypeByName } from "@content-collections/core";
444
- `;
445
- const collections = configuration.collections;
446
- for (const collection of collections) {
447
- content += `
448
- `;
449
- content += `export type ${collection.typeName} = GetTypeByName<typeof configuration, "${collection.name}">;
450
- `;
451
- content += `export declare const ${createArrayConstName(
452
- collection.name
453
- )}: Array<${collection.typeName}>;
454
- `;
455
- }
456
- content += "\n";
457
- content += "export {};\n";
458
- await fs2.writeFile(path4.join(directory, "index.d.ts"), content, "utf-8");
459
- }
460
- async function createWriter(directory) {
461
- await fs2.mkdir(directory, { recursive: true });
462
- return {
463
- createJavaScriptFile: (configuration) => createJavaScriptFile(directory, configuration),
464
- createTypeDefinitionFile: (configuration) => createTypeDefinitionFile(directory, configuration),
465
- createDataFiles: (collections) => createDataFiles(directory, collections)
466
- };
467
- }
468
-
469
255
  // src/synchronizer.ts
256
+ import path3 from "node:path";
470
257
  import picomatch from "picomatch";
471
- import path5 from "path";
472
258
  function createSynchronizer(readCollectionFile, collections, baseDirectory = ".") {
473
259
  function findCollections(filePath) {
474
- const resolvedFilePath = path5.resolve(filePath);
260
+ const resolvedFilePath = path3.resolve(filePath);
475
261
  return collections.filter((collection) => {
476
262
  return resolvedFilePath.startsWith(
477
- path5.resolve(baseDirectory, collection.directory)
263
+ path3.resolve(baseDirectory, collection.directory)
478
264
  );
479
265
  });
480
266
  }
481
267
  function createRelativePath(collectionPath, filePath) {
482
- const resolvedCollectionPath = path5.resolve(baseDirectory, collectionPath);
483
- const resolvedFilePath = path5.resolve(filePath);
268
+ const resolvedCollectionPath = path3.resolve(baseDirectory, collectionPath);
269
+ const resolvedFilePath = path3.resolve(filePath);
484
270
  let relativePath = resolvedFilePath.slice(resolvedCollectionPath.length);
485
- if (relativePath.startsWith(path5.sep)) {
486
- relativePath = relativePath.slice(path5.sep.length);
271
+ if (relativePath.startsWith(path3.sep)) {
272
+ relativePath = relativePath.slice(path3.sep.length);
487
273
  }
488
274
  return relativePath;
489
275
  }
@@ -547,110 +333,43 @@ function createSynchronizer(readCollectionFile, collections, baseDirectory = "."
547
333
  };
548
334
  }
549
335
 
550
- // src/cache.ts
551
- import path6, { join as join2 } from "path";
552
- import { mkdir, readFile as readFile2, unlink, writeFile } from "fs/promises";
553
- import { existsSync as existsSync2 } from "fs";
554
- import { createHash as createHash2 } from "crypto";
555
- function createKey(config, input) {
556
- return createHash2("sha256").update(config).update(JSON.stringify(input)).digest("hex");
557
- }
558
- async function createCacheDirectory(directory) {
559
- const cacheDirectory = path6.join(directory, ".content-collections", "cache");
560
- if (!existsSync2(cacheDirectory)) {
561
- await mkdir(cacheDirectory, { recursive: true });
562
- }
563
- return cacheDirectory;
564
- }
565
- function fileName(input) {
566
- return input.replace(/[^a-z0-9]/gi, "_").toLowerCase();
567
- }
568
- async function readMapping(mappingPath) {
569
- if (existsSync2(mappingPath)) {
570
- try {
571
- return JSON.parse(await readFile2(mappingPath, "utf-8"));
572
- } catch (e) {
573
- console.error(
574
- "Failed to parse the cache mapping. We will recreate the cache."
575
- );
576
- }
577
- }
578
- return {};
579
- }
580
- async function createCacheManager(baseDirectory, configChecksum) {
581
- const cacheDirectory = await createCacheDirectory(baseDirectory);
582
- const mappingPath = join2(cacheDirectory, "mapping.json");
583
- const mapping = await readMapping(mappingPath);
584
- async function flush() {
585
- await writeFile(mappingPath, JSON.stringify(mapping));
586
- }
587
- function cache(collection, file) {
588
- const directory = join2(
589
- cacheDirectory,
590
- fileName(collection),
591
- fileName(file)
592
- );
593
- let collectionMapping = mapping[collection];
594
- if (!collectionMapping) {
595
- collectionMapping = {};
596
- mapping[collection] = collectionMapping;
597
- }
598
- let fileMapping = collectionMapping[file];
599
- if (!fileMapping) {
600
- fileMapping = [];
601
- collectionMapping[file] = fileMapping;
602
- }
603
- let newFileMapping = [];
604
- const cacheFn = async (input, fn) => {
605
- const key = createKey(configChecksum, input);
606
- newFileMapping.push(key);
607
- const filePath = join2(directory, `${key}.cache`);
608
- if (fileMapping?.includes(key) || newFileMapping.includes(key)) {
609
- if (existsSync2(filePath)) {
610
- try {
611
- return JSON.parse(await readFile2(filePath, "utf-8"));
612
- } catch (e) {
613
- console.error(
614
- "Failed to parse the cache file. We will recompute the value."
615
- );
616
- }
617
- }
618
- }
619
- const output = await fn(input);
620
- if (!existsSync2(directory)) {
621
- await mkdir(directory, { recursive: true });
622
- }
623
- await writeFile(filePath, JSON.stringify(output));
624
- return output;
625
- };
626
- const tidyUp = async () => {
627
- const filesToDelete = fileMapping?.filter((key) => !newFileMapping.includes(key)) || [];
628
- for (const key of filesToDelete) {
629
- const filePath = join2(directory, `${key}.cache`);
630
- if (existsSync2(filePath)) {
631
- await unlink(filePath);
632
- }
633
- }
634
- if (collectionMapping) {
635
- collectionMapping[file] = newFileMapping;
636
- }
637
- };
638
- return {
639
- cacheFn,
640
- tidyUp
641
- };
642
- }
643
- return {
644
- cache,
645
- flush
646
- };
336
+ // src/transformer.ts
337
+ import os from "node:os";
338
+ import { basename, dirname, extname } from "node:path";
339
+ import pLimit from "p-limit";
340
+ import { z as z2 } from "zod";
341
+
342
+ // src/serializer.ts
343
+ import serializeJs from "serialize-javascript";
344
+ import z from "zod";
345
+ var literalSchema = z.union([
346
+ // json
347
+ z.string(),
348
+ z.number(),
349
+ z.boolean(),
350
+ z.null(),
351
+ // serializable-javascript
352
+ z.undefined(),
353
+ z.date(),
354
+ z.map(z.unknown(), z.unknown()),
355
+ z.set(z.unknown()),
356
+ z.bigint()
357
+ ]);
358
+ var schema = z.lazy(
359
+ () => z.union([literalSchema, z.array(schema), z.record(schema)])
360
+ );
361
+ var extension = "js";
362
+ var serializableSchema = z.record(schema);
363
+ function serialize(value) {
364
+ const serializedValue = serializeJs(value, {
365
+ space: 2,
366
+ unsafe: true,
367
+ ignoreFunction: true
368
+ });
369
+ return `export default ${serializedValue};`;
647
370
  }
648
371
 
649
372
  // src/transformer.ts
650
- import { basename, dirname as dirname3, extname } from "path";
651
- import { z as z3 } from "zod";
652
- import os from "os";
653
- import pLimit from "p-limit";
654
373
  var TransformError = class extends Error {
655
374
  type;
656
375
  constructor(type, message) {
@@ -658,8 +377,8 @@ var TransformError = class extends Error {
658
377
  this.type = type;
659
378
  }
660
379
  };
661
- function createPath(path8, ext) {
662
- let p = path8.slice(0, -ext.length);
380
+ function createPath(path9, ext) {
381
+ let p = path9.slice(0, -ext.length);
663
382
  if (p.endsWith("/index")) {
664
383
  p = p.slice(0, -6);
665
384
  }
@@ -669,15 +388,15 @@ function createTransformer(emitter, cacheManager) {
669
388
  function createSchema(parserName, schema2) {
670
389
  const parser = parsers[parserName];
671
390
  if (!parser.hasContent) {
672
- return z3.object(schema2);
391
+ return z2.object(schema2);
673
392
  }
674
- return z3.object({
675
- content: z3.string(),
393
+ return z2.object({
394
+ content: z2.string(),
676
395
  ...schema2
677
396
  });
678
397
  }
679
398
  async function parseFile(collection, file) {
680
- const { data, path: path8 } = file;
399
+ const { data, path: path9 } = file;
681
400
  const schema2 = createSchema(collection.parser, collection.schema);
682
401
  let parsedData = await schema2.safeParseAsync(data);
683
402
  if (!parsedData.success) {
@@ -688,7 +407,7 @@ function createTransformer(emitter, cacheManager) {
688
407
  });
689
408
  return null;
690
409
  }
691
- const ext = extname(path8);
410
+ const ext = extname(path9);
692
411
  let extension2 = ext;
693
412
  if (extension2.startsWith(".")) {
694
413
  extension2 = extension2.slice(1);
@@ -696,11 +415,11 @@ function createTransformer(emitter, cacheManager) {
696
415
  const document = {
697
416
  ...parsedData.data,
698
417
  _meta: {
699
- filePath: path8,
700
- fileName: basename(path8),
701
- directory: dirname3(path8),
418
+ filePath: path9,
419
+ fileName: basename(path9),
420
+ directory: dirname(path9),
702
421
  extension: extension2,
703
- path: createPath(path8, ext)
422
+ path: createPath(path9, ext)
704
423
  }
705
424
  };
706
425
  return {
@@ -740,9 +459,9 @@ function createTransformer(emitter, cacheManager) {
740
459
  }
741
460
  async function transformDocument(collections, collection, transform, doc) {
742
461
  const cache = cacheManager.cache(collection.name, doc.document._meta.path);
743
- const context = createContext(collections, collection, cache);
462
+ const context2 = createContext(collections, collection, cache);
744
463
  try {
745
- const document = await transform(doc.document, context);
464
+ const document = await transform(doc.document, context2);
746
465
  await cache.tidyUp();
747
466
  return {
748
467
  ...doc,
@@ -791,16 +510,95 @@ function createTransformer(emitter, cacheManager) {
791
510
  }
792
511
  return docs;
793
512
  }
794
- return async (untransformedCollections) => {
795
- const promises = untransformedCollections.map(
796
- (collection) => parseCollection(collection)
797
- );
798
- const collections = await Promise.all(promises);
799
- for (const collection of collections) {
800
- const documents = await transformCollection(collections, collection);
801
- collection.documents = await validateDocuments(collection, documents);
802
- }
803
- return collections;
513
+ return async (untransformedCollections) => {
514
+ const promises = untransformedCollections.map(
515
+ (collection) => parseCollection(collection)
516
+ );
517
+ const collections = await Promise.all(promises);
518
+ for (const collection of collections) {
519
+ const documents = await transformCollection(collections, collection);
520
+ collection.documents = await validateDocuments(collection, documents);
521
+ }
522
+ return collections;
523
+ };
524
+ }
525
+
526
+ // src/writer.ts
527
+ import fs from "node:fs/promises";
528
+ import path4 from "node:path";
529
+ import pluralize2 from "pluralize";
530
+ function createArrayConstName(name) {
531
+ let suffix = name.charAt(0).toUpperCase() + name.slice(1);
532
+ return "all" + pluralize2(suffix);
533
+ }
534
+ async function createDataFile(directory, collection) {
535
+ const dataPath = path4.join(
536
+ directory,
537
+ `${createArrayConstName(collection.name)}.${extension}`
538
+ );
539
+ await fs.writeFile(
540
+ dataPath,
541
+ serialize(collection.documents.map((doc) => doc.document))
542
+ );
543
+ }
544
+ function createDataFiles(directory, collections) {
545
+ return Promise.all(
546
+ collections.map((collection) => createDataFile(directory, collection))
547
+ );
548
+ }
549
+ async function createJavaScriptFile(directory, configuration) {
550
+ const collections = configuration.collections.map(
551
+ ({ name }) => createArrayConstName(name)
552
+ );
553
+ let content = `// generated by content-collections at ${/* @__PURE__ */ new Date()}
554
+
555
+ `;
556
+ for (const name of collections) {
557
+ content += `import ${name} from "./${name}.${extension}";
558
+ `;
559
+ }
560
+ content += "\n";
561
+ content += "export { " + collections.join(", ") + " };\n";
562
+ await fs.writeFile(path4.join(directory, "index.js"), content, "utf-8");
563
+ }
564
+ function createImportPath(directory, target) {
565
+ let importPath = path4.posix.join(
566
+ ...path4.relative(directory, target).split(path4.sep)
567
+ );
568
+ if (!importPath.startsWith(".")) {
569
+ importPath = "./" + importPath;
570
+ }
571
+ return importPath;
572
+ }
573
+ async function createTypeDefinitionFile(directory, configuration) {
574
+ if (!configuration.generateTypes) {
575
+ return;
576
+ }
577
+ const importPath = createImportPath(directory, configuration.path);
578
+ let content = `import configuration from "${importPath}";
579
+ import { GetTypeByName } from "@content-collections/core";
580
+ `;
581
+ const collections = configuration.collections;
582
+ for (const collection of collections) {
583
+ content += `
584
+ `;
585
+ content += `export type ${collection.typeName} = GetTypeByName<typeof configuration, "${collection.name}">;
586
+ `;
587
+ content += `export declare const ${createArrayConstName(
588
+ collection.name
589
+ )}: Array<${collection.typeName}>;
590
+ `;
591
+ }
592
+ content += "\n";
593
+ content += "export {};\n";
594
+ await fs.writeFile(path4.join(directory, "index.d.ts"), content, "utf-8");
595
+ }
596
+ async function createWriter(directory) {
597
+ await fs.mkdir(directory, { recursive: true });
598
+ return {
599
+ createJavaScriptFile: (configuration) => createJavaScriptFile(directory, configuration),
600
+ createTypeDefinitionFile: (configuration) => createTypeDefinitionFile(directory, configuration),
601
+ createDataFiles: (collections) => createDataFiles(directory, collections)
804
602
  };
805
603
  }
806
604
 
@@ -833,7 +631,7 @@ async function createBuildContext({
833
631
  configuration
834
632
  };
835
633
  }
836
- async function build2({
634
+ async function build({
837
635
  emitter,
838
636
  transform,
839
637
  resolved,
@@ -872,12 +670,386 @@ async function build2({
872
670
  });
873
671
  }
874
672
 
673
+ // src/configurationReader.ts
674
+ import { createHash as createHash2 } from "node:crypto";
675
+ import { existsSync as existsSync2 } from "node:fs";
676
+ import fs3 from "node:fs/promises";
677
+ import path6 from "node:path";
678
+
679
+ // ../../node_modules/.pnpm/bundle-require@5.0.0_esbuild@0.21.4/node_modules/bundle-require/dist/index.js
680
+ import {
681
+ build as build2,
682
+ context
683
+ } from "esbuild";
684
+
685
+ // ../../node_modules/.pnpm/load-tsconfig@0.2.5/node_modules/load-tsconfig/dist/index.js
686
+ import path5 from "path";
687
+ import fs2 from "fs";
688
+ import { createRequire } from "module";
689
+ var singleComment = Symbol("singleComment");
690
+ var multiComment = Symbol("multiComment");
691
+ var stripWithoutWhitespace = () => "";
692
+ var stripWithWhitespace = (string, start, end) => string.slice(start, end).replace(/\S/g, " ");
693
+ var isEscaped = (jsonString, quotePosition) => {
694
+ let index = quotePosition - 1;
695
+ let backslashCount = 0;
696
+ while (jsonString[index] === "\\") {
697
+ index -= 1;
698
+ backslashCount += 1;
699
+ }
700
+ return Boolean(backslashCount % 2);
701
+ };
702
+ function stripJsonComments(jsonString, { whitespace = true, trailingCommas = false } = {}) {
703
+ if (typeof jsonString !== "string") {
704
+ throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``);
705
+ }
706
+ const strip = whitespace ? stripWithWhitespace : stripWithoutWhitespace;
707
+ let isInsideString = false;
708
+ let isInsideComment = false;
709
+ let offset = 0;
710
+ let buffer = "";
711
+ let result = "";
712
+ let commaIndex = -1;
713
+ for (let index = 0; index < jsonString.length; index++) {
714
+ const currentCharacter = jsonString[index];
715
+ const nextCharacter = jsonString[index + 1];
716
+ if (!isInsideComment && currentCharacter === '"') {
717
+ const escaped = isEscaped(jsonString, index);
718
+ if (!escaped) {
719
+ isInsideString = !isInsideString;
720
+ }
721
+ }
722
+ if (isInsideString) {
723
+ continue;
724
+ }
725
+ if (!isInsideComment && currentCharacter + nextCharacter === "//") {
726
+ buffer += jsonString.slice(offset, index);
727
+ offset = index;
728
+ isInsideComment = singleComment;
729
+ index++;
730
+ } else if (isInsideComment === singleComment && currentCharacter + nextCharacter === "\r\n") {
731
+ index++;
732
+ isInsideComment = false;
733
+ buffer += strip(jsonString, offset, index);
734
+ offset = index;
735
+ continue;
736
+ } else if (isInsideComment === singleComment && currentCharacter === "\n") {
737
+ isInsideComment = false;
738
+ buffer += strip(jsonString, offset, index);
739
+ offset = index;
740
+ } else if (!isInsideComment && currentCharacter + nextCharacter === "/*") {
741
+ buffer += jsonString.slice(offset, index);
742
+ offset = index;
743
+ isInsideComment = multiComment;
744
+ index++;
745
+ continue;
746
+ } else if (isInsideComment === multiComment && currentCharacter + nextCharacter === "*/") {
747
+ index++;
748
+ isInsideComment = false;
749
+ buffer += strip(jsonString, offset, index + 1);
750
+ offset = index + 1;
751
+ continue;
752
+ } else if (trailingCommas && !isInsideComment) {
753
+ if (commaIndex !== -1) {
754
+ if (currentCharacter === "}" || currentCharacter === "]") {
755
+ buffer += jsonString.slice(offset, index);
756
+ result += strip(buffer, 0, 1) + buffer.slice(1);
757
+ buffer = "";
758
+ offset = index;
759
+ commaIndex = -1;
760
+ } else if (currentCharacter !== " " && currentCharacter !== " " && currentCharacter !== "\r" && currentCharacter !== "\n") {
761
+ buffer += jsonString.slice(offset, index);
762
+ offset = index;
763
+ commaIndex = -1;
764
+ }
765
+ } else if (currentCharacter === ",") {
766
+ result += buffer + jsonString.slice(offset, index);
767
+ buffer = "";
768
+ offset = index;
769
+ commaIndex = index;
770
+ }
771
+ }
772
+ }
773
+ return result + buffer + (isInsideComment ? strip(jsonString.slice(offset)) : jsonString.slice(offset));
774
+ }
775
+ function jsoncParse(data) {
776
+ try {
777
+ return new Function("return " + stripJsonComments(data).trim())();
778
+ } catch (_) {
779
+ return {};
780
+ }
781
+ }
782
+ var req = true ? createRequire(import.meta.url) : __require;
783
+ var findUp = (name, startDir, stopDir = path5.parse(startDir).root) => {
784
+ let dir = startDir;
785
+ while (dir !== stopDir) {
786
+ const file = path5.join(dir, name);
787
+ if (fs2.existsSync(file))
788
+ return file;
789
+ if (!file.endsWith(".json")) {
790
+ const fileWithExt = file + ".json";
791
+ if (fs2.existsSync(fileWithExt))
792
+ return fileWithExt;
793
+ }
794
+ dir = path5.dirname(dir);
795
+ }
796
+ return null;
797
+ };
798
+ var resolveTsConfigFromFile = (cwd, filename) => {
799
+ if (path5.isAbsolute(filename))
800
+ return fs2.existsSync(filename) ? filename : null;
801
+ return findUp(filename, cwd);
802
+ };
803
+ var resolveTsConfigFromExtends = (cwd, name) => {
804
+ if (path5.isAbsolute(name))
805
+ return fs2.existsSync(name) ? name : null;
806
+ if (name.startsWith("."))
807
+ return findUp(name, cwd);
808
+ const id = req.resolve(name, { paths: [cwd] });
809
+ return id;
810
+ };
811
+ var loadTsConfigInternal = (dir = process.cwd(), name = "tsconfig.json", isExtends = false) => {
812
+ var _a, _b;
813
+ dir = path5.resolve(dir);
814
+ const id = isExtends ? resolveTsConfigFromExtends(dir, name) : resolveTsConfigFromFile(dir, name);
815
+ if (!id)
816
+ return null;
817
+ const data = jsoncParse(fs2.readFileSync(id, "utf-8"));
818
+ const configDir = path5.dirname(id);
819
+ if ((_a = data.compilerOptions) == null ? void 0 : _a.baseUrl) {
820
+ data.compilerOptions.baseUrl = path5.join(
821
+ configDir,
822
+ data.compilerOptions.baseUrl
823
+ );
824
+ }
825
+ let extendsFiles = [];
826
+ if (data.extends) {
827
+ const extendsList = Array.isArray(data.extends) ? data.extends : [data.extends];
828
+ const extendsData = {};
829
+ for (const name2 of extendsList) {
830
+ const parentConfig = loadTsConfigInternal(configDir, name2, true);
831
+ if (parentConfig) {
832
+ Object.assign(extendsData, {
833
+ ...parentConfig == null ? void 0 : parentConfig.data,
834
+ compilerOptions: {
835
+ ...extendsData.compilerOptions,
836
+ ...(_b = parentConfig == null ? void 0 : parentConfig.data) == null ? void 0 : _b.compilerOptions
837
+ }
838
+ });
839
+ extendsFiles.push(...parentConfig.files);
840
+ }
841
+ }
842
+ Object.assign(data, {
843
+ ...extendsData,
844
+ ...data,
845
+ compilerOptions: {
846
+ ...extendsData.compilerOptions,
847
+ ...data.compilerOptions
848
+ }
849
+ });
850
+ }
851
+ delete data.extends;
852
+ return { path: id, data, files: [...extendsFiles, id] };
853
+ };
854
+ var loadTsConfig = (dir, name) => loadTsConfigInternal(dir, name);
855
+
856
+ // ../../node_modules/.pnpm/bundle-require@5.0.0_esbuild@0.21.4/node_modules/bundle-require/dist/index.js
857
+ var tsconfigPathsToRegExp = (paths) => {
858
+ return Object.keys(paths || {}).map((key) => {
859
+ return new RegExp(`^${key.replace(/\*/, ".*")}$`);
860
+ });
861
+ };
862
+ var match = (id, patterns) => {
863
+ if (!patterns)
864
+ return false;
865
+ return patterns.some((p) => {
866
+ if (p instanceof RegExp) {
867
+ return p.test(id);
868
+ }
869
+ return id === p || id.startsWith(p + "/");
870
+ });
871
+ };
872
+
873
+ // src/esbuild.ts
874
+ import { build as build3 } from "esbuild";
875
+ import { dirname as dirname2, join as join2 } from "node:path";
876
+ function tsconfigResolvePaths(configPath) {
877
+ let tsconfig = loadTsConfig(dirname2(configPath));
878
+ if (!tsconfig) {
879
+ tsconfig = loadTsConfig();
880
+ }
881
+ return tsconfig?.data?.compilerOptions?.paths || {};
882
+ }
883
+ function createExternalsPlugin(configPath) {
884
+ const resolvedPaths = tsconfigResolvePaths(configPath);
885
+ const resolvePatterns = tsconfigPathsToRegExp(resolvedPaths);
886
+ return {
887
+ name: "external-packages",
888
+ setup: (build4) => {
889
+ const filter = /^[^.\/]|^\.[^.\/]|^\.\.[^\/]/;
890
+ build4.onResolve({ filter }, ({ path: path9, kind }) => {
891
+ if (match(path9, resolvePatterns)) {
892
+ if (kind === "dynamic-import") {
893
+ return { path: path9, external: true };
894
+ }
895
+ return;
896
+ }
897
+ return { path: path9, external: true };
898
+ });
899
+ }
900
+ };
901
+ }
902
+ var importPathPlugin = {
903
+ name: "import-path",
904
+ setup(build4) {
905
+ build4.onResolve({ filter: /^\@content-collections\/core$/ }, () => {
906
+ return { path: join2(__dirname, "index.ts"), external: true };
907
+ });
908
+ }
909
+ };
910
+ async function compile(configurationPath, outfile) {
911
+ const plugins = [createExternalsPlugin(configurationPath)];
912
+ if (process.env.NODE_ENV === "test") {
913
+ plugins.push(importPathPlugin);
914
+ }
915
+ const result = await build3({
916
+ entryPoints: [configurationPath],
917
+ packages: "external",
918
+ bundle: true,
919
+ platform: "node",
920
+ format: "esm",
921
+ plugins,
922
+ outfile,
923
+ metafile: true
924
+ });
925
+ return Object.keys(result.metafile.inputs);
926
+ }
927
+
928
+ // src/configurationReader.ts
929
+ var ConfigurationError = class extends Error {
930
+ type;
931
+ constructor(type, message) {
932
+ super(message);
933
+ this.type = type;
934
+ }
935
+ };
936
+ var defaultConfigName = "content-collection-config.mjs";
937
+ function resolveCacheDir(config, options) {
938
+ if (options.cacheDir) {
939
+ return options.cacheDir;
940
+ }
941
+ return path6.join(path6.dirname(config), ".content-collections", "cache");
942
+ }
943
+ function createConfigurationReader() {
944
+ return async (configurationPath, options = {
945
+ configName: defaultConfigName
946
+ }) => {
947
+ if (!existsSync2(configurationPath)) {
948
+ throw new ConfigurationError(
949
+ "Read",
950
+ `configuration file ${configurationPath} does not exist`
951
+ );
952
+ }
953
+ const cacheDir = resolveCacheDir(configurationPath, options);
954
+ await fs3.mkdir(cacheDir, { recursive: true });
955
+ const outfile = path6.join(cacheDir, options.configName);
956
+ try {
957
+ const configurationPaths = await compile(configurationPath, outfile);
958
+ const module = await import(`file://${path6.resolve(outfile)}?x=${Date.now()}`);
959
+ const hash = createHash2("sha256");
960
+ hash.update(await fs3.readFile(outfile, "utf-8"));
961
+ const checksum = hash.digest("hex");
962
+ return {
963
+ ...module.default,
964
+ path: configurationPath,
965
+ inputPaths: configurationPaths.map((p) => path6.resolve(p)),
966
+ generateTypes: true,
967
+ checksum
968
+ };
969
+ } catch (error) {
970
+ throw new ConfigurationError(
971
+ "Compile",
972
+ `configuration file ${configurationPath} is invalid: ${error}`
973
+ );
974
+ }
975
+ };
976
+ }
977
+
978
+ // src/events.ts
979
+ import { EventEmitter } from "node:events";
980
+ function isEventWithError(event) {
981
+ return typeof event === "object" && event !== null && "error" in event;
982
+ }
983
+ function createEmitter() {
984
+ const emitter = new EventEmitter();
985
+ function on(key, listener) {
986
+ emitter.on(key, listener);
987
+ }
988
+ function emit(key, event) {
989
+ emitter.emit(key, event);
990
+ if (isEventWithError(event)) {
991
+ emitter.emit("_error", {
992
+ ...event,
993
+ _event: key
994
+ });
995
+ }
996
+ emitter.emit("_all", {
997
+ ...event,
998
+ _event: key
999
+ });
1000
+ }
1001
+ return {
1002
+ on,
1003
+ emit
1004
+ };
1005
+ }
1006
+
1007
+ // src/watcher.ts
1008
+ import * as watcher from "@parcel/watcher";
1009
+ import path7, { dirname as dirname3, resolve } from "node:path";
1010
+ async function createWatcher(emitter, baseDirectory, configuration, sync) {
1011
+ const onChange = async (error, events) => {
1012
+ if (error) {
1013
+ emitter.emit("watcher:subscribe-error", {
1014
+ paths,
1015
+ error
1016
+ });
1017
+ return;
1018
+ }
1019
+ for (const event of events) {
1020
+ await sync(event.type, event.path);
1021
+ }
1022
+ };
1023
+ const paths = removeChildPaths([
1024
+ ...configuration.collections.map((collection) => path7.join(baseDirectory, collection.directory)).map((p) => resolve(p)),
1025
+ ...configuration.inputPaths.map((p) => dirname3(p))
1026
+ ]);
1027
+ const subscriptions = (await Promise.all(paths.map((path9) => watcher.subscribe(path9, onChange)))).filter(isDefined);
1028
+ emitter.emit("watcher:subscribed", {
1029
+ paths
1030
+ });
1031
+ return {
1032
+ unsubscribe: async () => {
1033
+ if (!subscriptions || subscriptions.length === 0) {
1034
+ return;
1035
+ }
1036
+ await Promise.all(
1037
+ subscriptions.map((subscription) => subscription.unsubscribe())
1038
+ );
1039
+ emitter.emit("watcher:unsubscribed", {
1040
+ paths
1041
+ });
1042
+ return;
1043
+ }
1044
+ };
1045
+ }
1046
+
875
1047
  // src/builder.ts
876
1048
  function resolveOutputDir(baseDirectory, options) {
877
1049
  if (options.outputDir) {
878
1050
  return options.outputDir;
879
1051
  }
880
- return path7.join(baseDirectory, ".content-collections", "generated");
1052
+ return path8.join(baseDirectory, ".content-collections", "generated");
881
1053
  }
882
1054
  var ConfigurationReloadError = class extends Error {
883
1055
  constructor(message) {
@@ -888,7 +1060,7 @@ async function createBuilder(configurationPath, options = {
888
1060
  configName: defaultConfigName
889
1061
  }, emitter = createEmitter()) {
890
1062
  const readConfiguration = createConfigurationReader();
891
- const baseDirectory = path7.dirname(configurationPath);
1063
+ const baseDirectory = path8.dirname(configurationPath);
892
1064
  const outputDirectory = resolveOutputDir(baseDirectory, options);
893
1065
  emitter.emit("builder:created", {
894
1066
  createdAt: Date.now(),
@@ -897,7 +1069,7 @@ async function createBuilder(configurationPath, options = {
897
1069
  });
898
1070
  let configuration = await readConfiguration(configurationPath, options);
899
1071
  let watcher2 = null;
900
- let context = await createBuildContext({
1072
+ let context2 = await createBuildContext({
901
1073
  emitter,
902
1074
  baseDirectory,
903
1075
  outputDirectory,
@@ -910,7 +1082,7 @@ async function createBuilder(configurationPath, options = {
910
1082
  filePath,
911
1083
  modification
912
1084
  });
913
- await build2(context);
1085
+ await build(context2);
914
1086
  return true;
915
1087
  }
916
1088
  } else {
@@ -919,7 +1091,7 @@ async function createBuilder(configurationPath, options = {
919
1091
  filePath,
920
1092
  modification
921
1093
  });
922
- await build2(context);
1094
+ await build(context2);
923
1095
  return true;
924
1096
  }
925
1097
  }
@@ -940,7 +1112,7 @@ async function createBuilder(configurationPath, options = {
940
1112
  if (watcher2) {
941
1113
  await watcher2.unsubscribe();
942
1114
  }
943
- context = await createBuildContext({
1115
+ context2 = await createBuildContext({
944
1116
  emitter,
945
1117
  baseDirectory,
946
1118
  outputDirectory,
@@ -957,7 +1129,7 @@ async function createBuilder(configurationPath, options = {
957
1129
  return true;
958
1130
  }
959
1131
  async function onFileChange(modification, filePath) {
960
- const { synchronizer } = context;
1132
+ const { synchronizer } = context2;
961
1133
  if (modification === "delete") {
962
1134
  return synchronizer.deleted(filePath);
963
1135
  } else {
@@ -975,12 +1147,35 @@ async function createBuilder(configurationPath, options = {
975
1147
  };
976
1148
  }
977
1149
  return {
978
- build: () => build2(context),
1150
+ build: () => build(context2),
979
1151
  sync,
980
1152
  watch,
981
1153
  on: emitter.on
982
1154
  };
983
1155
  }
1156
+
1157
+ // src/config.ts
1158
+ import { z as z3 } from "zod";
1159
+ var InvalidReturnTypeSymbol = Symbol(`InvalidReturnType`);
1160
+ function defineCollection(collection) {
1161
+ let typeName = collection.typeName;
1162
+ if (!typeName) {
1163
+ typeName = generateTypeName(collection.name);
1164
+ }
1165
+ let parser = collection.parser;
1166
+ if (!parser) {
1167
+ parser = "frontmatter";
1168
+ }
1169
+ return {
1170
+ ...collection,
1171
+ typeName,
1172
+ parser,
1173
+ schema: collection.schema(z3)
1174
+ };
1175
+ }
1176
+ function defineConfig(config) {
1177
+ return config;
1178
+ }
984
1179
  export {
985
1180
  CollectError,
986
1181
  ConfigurationError,