@magicpages/ghost-typesense-config 1.3.0 → 1.3.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.d.mts CHANGED
@@ -20,7 +20,7 @@ declare const GhostConfigSchema: z.ZodObject<{
20
20
  * Typesense node configuration schema
21
21
  */
22
22
  declare const TypesenseNodeSchema: z.ZodObject<{
23
- host: z.ZodString;
23
+ host: z.ZodEffects<z.ZodString, string, string>;
24
24
  port: z.ZodNumber;
25
25
  protocol: z.ZodEnum<["http", "https"]>;
26
26
  path: z.ZodOptional<z.ZodString>;
@@ -40,7 +40,7 @@ declare const TypesenseNodeSchema: z.ZodObject<{
40
40
  */
41
41
  declare const TypesenseConfigSchema: z.ZodObject<{
42
42
  nodes: z.ZodArray<z.ZodObject<{
43
- host: z.ZodString;
43
+ host: z.ZodEffects<z.ZodString, string, string>;
44
44
  port: z.ZodNumber;
45
45
  protocol: z.ZodEnum<["http", "https"]>;
46
46
  path: z.ZodOptional<z.ZodString>;
@@ -155,12 +155,16 @@ declare const REQUIRED_FIELDS: {
155
155
  readonly description: "Post last update timestamp";
156
156
  };
157
157
  };
158
+ /**
159
+ * Default collection fields that should be included
160
+ */
161
+ declare const DEFAULT_COLLECTION_FIELDS: CollectionField[];
158
162
  /**
159
163
  * Collection configuration schema with strict validation
160
164
  */
161
165
  declare const CollectionConfigSchema: z.ZodObject<{
162
166
  name: z.ZodString;
163
- fields: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodObject<{
167
+ fields: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
164
168
  name: z.ZodString;
165
169
  type: z.ZodEnum<["string", "int32", "int64", "float", "bool", "string[]", "int32[]", "int64[]", "float[]", "bool[]"]>;
166
170
  facet: z.ZodOptional<z.ZodBoolean>;
@@ -195,7 +199,21 @@ declare const CollectionConfigSchema: z.ZodObject<{
195
199
  facet?: boolean | undefined;
196
200
  index?: boolean | undefined;
197
201
  optional?: boolean | undefined;
198
- }>, "many">, {
202
+ }>, "many">>, {
203
+ optional: boolean;
204
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
205
+ name: string;
206
+ sort?: boolean | undefined;
207
+ facet?: boolean | undefined;
208
+ index?: boolean | undefined;
209
+ }[], {
210
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
211
+ name: string;
212
+ sort?: boolean | undefined;
213
+ facet?: boolean | undefined;
214
+ index?: boolean | undefined;
215
+ optional?: boolean | undefined;
216
+ }[] | undefined>, {
199
217
  optional: boolean;
200
218
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
201
219
  name: string;
@@ -209,7 +227,7 @@ declare const CollectionConfigSchema: z.ZodObject<{
209
227
  facet?: boolean | undefined;
210
228
  index?: boolean | undefined;
211
229
  optional?: boolean | undefined;
212
- }[]>;
230
+ }[] | undefined>;
213
231
  default_sorting_field: z.ZodOptional<z.ZodString>;
214
232
  }, "strip", z.ZodTypeAny, {
215
233
  name: string;
@@ -224,14 +242,14 @@ declare const CollectionConfigSchema: z.ZodObject<{
224
242
  default_sorting_field?: string | undefined;
225
243
  }, {
226
244
  name: string;
227
- fields: {
245
+ fields?: {
228
246
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
229
247
  name: string;
230
248
  sort?: boolean | undefined;
231
249
  facet?: boolean | undefined;
232
250
  index?: boolean | undefined;
233
251
  optional?: boolean | undefined;
234
- }[];
252
+ }[] | undefined;
235
253
  default_sorting_field?: string | undefined;
236
254
  }>;
237
255
  /**
@@ -253,7 +271,7 @@ declare const ConfigSchema: z.ZodObject<{
253
271
  }>;
254
272
  typesense: z.ZodObject<{
255
273
  nodes: z.ZodArray<z.ZodObject<{
256
- host: z.ZodString;
274
+ host: z.ZodEffects<z.ZodString, string, string>;
257
275
  port: z.ZodNumber;
258
276
  protocol: z.ZodEnum<["http", "https"]>;
259
277
  path: z.ZodOptional<z.ZodString>;
@@ -294,7 +312,7 @@ declare const ConfigSchema: z.ZodObject<{
294
312
  }>;
295
313
  collection: z.ZodObject<{
296
314
  name: z.ZodString;
297
- fields: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodObject<{
315
+ fields: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
298
316
  name: z.ZodString;
299
317
  type: z.ZodEnum<["string", "int32", "int64", "float", "bool", "string[]", "int32[]", "int64[]", "float[]", "bool[]"]>;
300
318
  facet: z.ZodOptional<z.ZodBoolean>;
@@ -329,7 +347,21 @@ declare const ConfigSchema: z.ZodObject<{
329
347
  facet?: boolean | undefined;
330
348
  index?: boolean | undefined;
331
349
  optional?: boolean | undefined;
332
- }>, "many">, {
350
+ }>, "many">>, {
351
+ optional: boolean;
352
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
353
+ name: string;
354
+ sort?: boolean | undefined;
355
+ facet?: boolean | undefined;
356
+ index?: boolean | undefined;
357
+ }[], {
358
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
359
+ name: string;
360
+ sort?: boolean | undefined;
361
+ facet?: boolean | undefined;
362
+ index?: boolean | undefined;
363
+ optional?: boolean | undefined;
364
+ }[] | undefined>, {
333
365
  optional: boolean;
334
366
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
335
367
  name: string;
@@ -343,7 +375,7 @@ declare const ConfigSchema: z.ZodObject<{
343
375
  facet?: boolean | undefined;
344
376
  index?: boolean | undefined;
345
377
  optional?: boolean | undefined;
346
- }[]>;
378
+ }[] | undefined>;
347
379
  default_sorting_field: z.ZodOptional<z.ZodString>;
348
380
  }, "strip", z.ZodTypeAny, {
349
381
  name: string;
@@ -358,14 +390,14 @@ declare const ConfigSchema: z.ZodObject<{
358
390
  default_sorting_field?: string | undefined;
359
391
  }, {
360
392
  name: string;
361
- fields: {
393
+ fields?: {
362
394
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
363
395
  name: string;
364
396
  sort?: boolean | undefined;
365
397
  facet?: boolean | undefined;
366
398
  index?: boolean | undefined;
367
399
  optional?: boolean | undefined;
368
- }[];
400
+ }[] | undefined;
369
401
  default_sorting_field?: string | undefined;
370
402
  }>;
371
403
  }, "strip", z.ZodTypeAny, {
@@ -416,14 +448,14 @@ declare const ConfigSchema: z.ZodObject<{
416
448
  };
417
449
  collection: {
418
450
  name: string;
419
- fields: {
451
+ fields?: {
420
452
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
421
453
  name: string;
422
454
  sort?: boolean | undefined;
423
455
  facet?: boolean | undefined;
424
456
  index?: boolean | undefined;
425
457
  optional?: boolean | undefined;
426
- }[];
458
+ }[] | undefined;
427
459
  default_sorting_field?: string | undefined;
428
460
  };
429
461
  }>;
@@ -443,10 +475,6 @@ type Config = z.infer<typeof ConfigSchema>;
443
475
  * @throws {ZodError} If validation fails
444
476
  */
445
477
  declare function validateConfig(config: unknown): Config;
446
- /**
447
- * Default collection fields that should be included
448
- */
449
- declare const DEFAULT_COLLECTION_FIELDS: CollectionField[];
450
478
  /**
451
479
  * Creates a default configuration object
452
480
  * @param ghostUrl The URL of the Ghost instance
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ declare const GhostConfigSchema: z.ZodObject<{
20
20
  * Typesense node configuration schema
21
21
  */
22
22
  declare const TypesenseNodeSchema: z.ZodObject<{
23
- host: z.ZodString;
23
+ host: z.ZodEffects<z.ZodString, string, string>;
24
24
  port: z.ZodNumber;
25
25
  protocol: z.ZodEnum<["http", "https"]>;
26
26
  path: z.ZodOptional<z.ZodString>;
@@ -40,7 +40,7 @@ declare const TypesenseNodeSchema: z.ZodObject<{
40
40
  */
41
41
  declare const TypesenseConfigSchema: z.ZodObject<{
42
42
  nodes: z.ZodArray<z.ZodObject<{
43
- host: z.ZodString;
43
+ host: z.ZodEffects<z.ZodString, string, string>;
44
44
  port: z.ZodNumber;
45
45
  protocol: z.ZodEnum<["http", "https"]>;
46
46
  path: z.ZodOptional<z.ZodString>;
@@ -155,12 +155,16 @@ declare const REQUIRED_FIELDS: {
155
155
  readonly description: "Post last update timestamp";
156
156
  };
157
157
  };
158
+ /**
159
+ * Default collection fields that should be included
160
+ */
161
+ declare const DEFAULT_COLLECTION_FIELDS: CollectionField[];
158
162
  /**
159
163
  * Collection configuration schema with strict validation
160
164
  */
161
165
  declare const CollectionConfigSchema: z.ZodObject<{
162
166
  name: z.ZodString;
163
- fields: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodObject<{
167
+ fields: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
164
168
  name: z.ZodString;
165
169
  type: z.ZodEnum<["string", "int32", "int64", "float", "bool", "string[]", "int32[]", "int64[]", "float[]", "bool[]"]>;
166
170
  facet: z.ZodOptional<z.ZodBoolean>;
@@ -195,7 +199,21 @@ declare const CollectionConfigSchema: z.ZodObject<{
195
199
  facet?: boolean | undefined;
196
200
  index?: boolean | undefined;
197
201
  optional?: boolean | undefined;
198
- }>, "many">, {
202
+ }>, "many">>, {
203
+ optional: boolean;
204
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
205
+ name: string;
206
+ sort?: boolean | undefined;
207
+ facet?: boolean | undefined;
208
+ index?: boolean | undefined;
209
+ }[], {
210
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
211
+ name: string;
212
+ sort?: boolean | undefined;
213
+ facet?: boolean | undefined;
214
+ index?: boolean | undefined;
215
+ optional?: boolean | undefined;
216
+ }[] | undefined>, {
199
217
  optional: boolean;
200
218
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
201
219
  name: string;
@@ -209,7 +227,7 @@ declare const CollectionConfigSchema: z.ZodObject<{
209
227
  facet?: boolean | undefined;
210
228
  index?: boolean | undefined;
211
229
  optional?: boolean | undefined;
212
- }[]>;
230
+ }[] | undefined>;
213
231
  default_sorting_field: z.ZodOptional<z.ZodString>;
214
232
  }, "strip", z.ZodTypeAny, {
215
233
  name: string;
@@ -224,14 +242,14 @@ declare const CollectionConfigSchema: z.ZodObject<{
224
242
  default_sorting_field?: string | undefined;
225
243
  }, {
226
244
  name: string;
227
- fields: {
245
+ fields?: {
228
246
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
229
247
  name: string;
230
248
  sort?: boolean | undefined;
231
249
  facet?: boolean | undefined;
232
250
  index?: boolean | undefined;
233
251
  optional?: boolean | undefined;
234
- }[];
252
+ }[] | undefined;
235
253
  default_sorting_field?: string | undefined;
236
254
  }>;
237
255
  /**
@@ -253,7 +271,7 @@ declare const ConfigSchema: z.ZodObject<{
253
271
  }>;
254
272
  typesense: z.ZodObject<{
255
273
  nodes: z.ZodArray<z.ZodObject<{
256
- host: z.ZodString;
274
+ host: z.ZodEffects<z.ZodString, string, string>;
257
275
  port: z.ZodNumber;
258
276
  protocol: z.ZodEnum<["http", "https"]>;
259
277
  path: z.ZodOptional<z.ZodString>;
@@ -294,7 +312,7 @@ declare const ConfigSchema: z.ZodObject<{
294
312
  }>;
295
313
  collection: z.ZodObject<{
296
314
  name: z.ZodString;
297
- fields: z.ZodEffects<z.ZodArray<z.ZodEffects<z.ZodObject<{
315
+ fields: z.ZodEffects<z.ZodEffects<z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodObject<{
298
316
  name: z.ZodString;
299
317
  type: z.ZodEnum<["string", "int32", "int64", "float", "bool", "string[]", "int32[]", "int64[]", "float[]", "bool[]"]>;
300
318
  facet: z.ZodOptional<z.ZodBoolean>;
@@ -329,7 +347,21 @@ declare const ConfigSchema: z.ZodObject<{
329
347
  facet?: boolean | undefined;
330
348
  index?: boolean | undefined;
331
349
  optional?: boolean | undefined;
332
- }>, "many">, {
350
+ }>, "many">>, {
351
+ optional: boolean;
352
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
353
+ name: string;
354
+ sort?: boolean | undefined;
355
+ facet?: boolean | undefined;
356
+ index?: boolean | undefined;
357
+ }[], {
358
+ type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
359
+ name: string;
360
+ sort?: boolean | undefined;
361
+ facet?: boolean | undefined;
362
+ index?: boolean | undefined;
363
+ optional?: boolean | undefined;
364
+ }[] | undefined>, {
333
365
  optional: boolean;
334
366
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
335
367
  name: string;
@@ -343,7 +375,7 @@ declare const ConfigSchema: z.ZodObject<{
343
375
  facet?: boolean | undefined;
344
376
  index?: boolean | undefined;
345
377
  optional?: boolean | undefined;
346
- }[]>;
378
+ }[] | undefined>;
347
379
  default_sorting_field: z.ZodOptional<z.ZodString>;
348
380
  }, "strip", z.ZodTypeAny, {
349
381
  name: string;
@@ -358,14 +390,14 @@ declare const ConfigSchema: z.ZodObject<{
358
390
  default_sorting_field?: string | undefined;
359
391
  }, {
360
392
  name: string;
361
- fields: {
393
+ fields?: {
362
394
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
363
395
  name: string;
364
396
  sort?: boolean | undefined;
365
397
  facet?: boolean | undefined;
366
398
  index?: boolean | undefined;
367
399
  optional?: boolean | undefined;
368
- }[];
400
+ }[] | undefined;
369
401
  default_sorting_field?: string | undefined;
370
402
  }>;
371
403
  }, "strip", z.ZodTypeAny, {
@@ -416,14 +448,14 @@ declare const ConfigSchema: z.ZodObject<{
416
448
  };
417
449
  collection: {
418
450
  name: string;
419
- fields: {
451
+ fields?: {
420
452
  type: "string" | "float" | "int32" | "int64" | "bool" | "string[]" | "int32[]" | "int64[]" | "float[]" | "bool[]";
421
453
  name: string;
422
454
  sort?: boolean | undefined;
423
455
  facet?: boolean | undefined;
424
456
  index?: boolean | undefined;
425
457
  optional?: boolean | undefined;
426
- }[];
458
+ }[] | undefined;
427
459
  default_sorting_field?: string | undefined;
428
460
  };
429
461
  }>;
@@ -443,10 +475,6 @@ type Config = z.infer<typeof ConfigSchema>;
443
475
  * @throws {ZodError} If validation fails
444
476
  */
445
477
  declare function validateConfig(config: unknown): Config;
446
- /**
447
- * Default collection fields that should be included
448
- */
449
- declare const DEFAULT_COLLECTION_FIELDS: CollectionField[];
450
478
  /**
451
479
  * Creates a default configuration object
452
480
  * @param ghostUrl The URL of the Ghost instance
package/dist/index.js CHANGED
@@ -38,8 +38,12 @@ var GhostConfigSchema = import_zod.z.object({
38
38
  key: import_zod.z.string().min(1),
39
39
  version: import_zod.z.literal("v5.0").default("v5.0")
40
40
  });
41
+ function cleanUrl(url) {
42
+ const withoutProtocol = url.replace(/^https?:\/\//i, "");
43
+ return withoutProtocol.replace(/\/+$/, "");
44
+ }
41
45
  var TypesenseNodeSchema = import_zod.z.object({
42
- host: import_zod.z.string(),
46
+ host: import_zod.z.string().transform(cleanUrl),
43
47
  port: import_zod.z.number(),
44
48
  protocol: import_zod.z.enum(["http", "https"]),
45
49
  path: import_zod.z.string().optional()
@@ -71,47 +75,6 @@ var REQUIRED_FIELDS = {
71
75
  published_at: { type: "int64", description: "Post publication timestamp" },
72
76
  updated_at: { type: "int64", description: "Post last update timestamp" }
73
77
  };
74
- var CollectionConfigSchema = import_zod.z.object({
75
- name: import_zod.z.string().min(1, "Collection name cannot be empty"),
76
- fields: import_zod.z.array(CollectionFieldSchema).min(1, "At least one field must be defined").refine(
77
- (fields) => {
78
- const missingOrInvalidFields = Object.entries(REQUIRED_FIELDS).filter(([fieldName, spec]) => {
79
- const field = fields.find((f) => f.name === fieldName);
80
- return !field || field.type !== spec.type || field.optional === true;
81
- });
82
- if (missingOrInvalidFields.length > 0) {
83
- const errors = missingOrInvalidFields.map(([fieldName, spec]) => {
84
- const field = fields.find((f) => f.name === fieldName);
85
- if (!field) {
86
- return `Missing required field "${fieldName}" (${spec.description})`;
87
- }
88
- if (field.type !== spec.type) {
89
- return `Field "${fieldName}" must be of type "${spec.type}" (${spec.description})`;
90
- }
91
- if (field.optional === true) {
92
- return `Field "${fieldName}" cannot be optional (${spec.description})`;
93
- }
94
- return `Invalid configuration for "${fieldName}"`;
95
- });
96
- throw new Error(`Invalid collection configuration:
97
- - ${errors.join("\n- ")}`);
98
- }
99
- return true;
100
- },
101
- {
102
- message: "Collection configuration is invalid"
103
- }
104
- ),
105
- default_sorting_field: import_zod.z.string().optional()
106
- });
107
- var ConfigSchema = import_zod.z.object({
108
- ghost: GhostConfigSchema,
109
- typesense: TypesenseConfigSchema,
110
- collection: CollectionConfigSchema
111
- });
112
- function validateConfig(config) {
113
- return ConfigSchema.parse(config);
114
- }
115
78
  var DEFAULT_COLLECTION_FIELDS = [
116
79
  { name: "id", type: "string", optional: false },
117
80
  { name: "title", type: "string", index: true, sort: true, optional: false },
@@ -125,7 +88,40 @@ var DEFAULT_COLLECTION_FIELDS = [
125
88
  { name: "tags", type: "string[]", facet: true, optional: true },
126
89
  { name: "authors", type: "string[]", facet: true, optional: true }
127
90
  ];
91
+ var CollectionConfigSchema = import_zod.z.object({
92
+ name: import_zod.z.string().min(1, "Collection name cannot be empty"),
93
+ fields: import_zod.z.array(CollectionFieldSchema).optional().transform((fields) => fields || DEFAULT_COLLECTION_FIELDS).transform((fields) => {
94
+ const fieldMap = new Map(fields.map((f) => [f.name, f]));
95
+ Object.entries(REQUIRED_FIELDS).forEach(([fieldName, spec]) => {
96
+ const existingField = fieldMap.get(fieldName);
97
+ if (!existingField) {
98
+ const defaultField = DEFAULT_COLLECTION_FIELDS.find((f) => f.name === fieldName);
99
+ if (defaultField) {
100
+ fieldMap.set(fieldName, defaultField);
101
+ }
102
+ } else {
103
+ if (existingField.type !== spec.type) {
104
+ throw new Error(`Field "${fieldName}" must be of type "${spec.type}" (${spec.description})`);
105
+ }
106
+ if (existingField.optional === true) {
107
+ throw new Error(`Field "${fieldName}" cannot be optional (${spec.description})`);
108
+ }
109
+ }
110
+ });
111
+ return Array.from(fieldMap.values());
112
+ }),
113
+ default_sorting_field: import_zod.z.string().optional()
114
+ });
115
+ var ConfigSchema = import_zod.z.object({
116
+ ghost: GhostConfigSchema,
117
+ typesense: TypesenseConfigSchema,
118
+ collection: CollectionConfigSchema
119
+ });
120
+ function validateConfig(config) {
121
+ return ConfigSchema.parse(config);
122
+ }
128
123
  function createDefaultConfig(ghostUrl, ghostKey, typesenseHost, typesenseApiKey, collectionName = "posts") {
124
+ const cleanedHost = cleanUrl(typesenseHost);
129
125
  return {
130
126
  ghost: {
131
127
  url: ghostUrl,
@@ -135,7 +131,7 @@ function createDefaultConfig(ghostUrl, ghostKey, typesenseHost, typesenseApiKey,
135
131
  typesense: {
136
132
  nodes: [
137
133
  {
138
- host: typesenseHost,
134
+ host: cleanedHost,
139
135
  port: 443,
140
136
  protocol: "https"
141
137
  }
package/dist/index.mjs CHANGED
@@ -5,8 +5,12 @@ var GhostConfigSchema = z.object({
5
5
  key: z.string().min(1),
6
6
  version: z.literal("v5.0").default("v5.0")
7
7
  });
8
+ function cleanUrl(url) {
9
+ const withoutProtocol = url.replace(/^https?:\/\//i, "");
10
+ return withoutProtocol.replace(/\/+$/, "");
11
+ }
8
12
  var TypesenseNodeSchema = z.object({
9
- host: z.string(),
13
+ host: z.string().transform(cleanUrl),
10
14
  port: z.number(),
11
15
  protocol: z.enum(["http", "https"]),
12
16
  path: z.string().optional()
@@ -38,47 +42,6 @@ var REQUIRED_FIELDS = {
38
42
  published_at: { type: "int64", description: "Post publication timestamp" },
39
43
  updated_at: { type: "int64", description: "Post last update timestamp" }
40
44
  };
41
- var CollectionConfigSchema = z.object({
42
- name: z.string().min(1, "Collection name cannot be empty"),
43
- fields: z.array(CollectionFieldSchema).min(1, "At least one field must be defined").refine(
44
- (fields) => {
45
- const missingOrInvalidFields = Object.entries(REQUIRED_FIELDS).filter(([fieldName, spec]) => {
46
- const field = fields.find((f) => f.name === fieldName);
47
- return !field || field.type !== spec.type || field.optional === true;
48
- });
49
- if (missingOrInvalidFields.length > 0) {
50
- const errors = missingOrInvalidFields.map(([fieldName, spec]) => {
51
- const field = fields.find((f) => f.name === fieldName);
52
- if (!field) {
53
- return `Missing required field "${fieldName}" (${spec.description})`;
54
- }
55
- if (field.type !== spec.type) {
56
- return `Field "${fieldName}" must be of type "${spec.type}" (${spec.description})`;
57
- }
58
- if (field.optional === true) {
59
- return `Field "${fieldName}" cannot be optional (${spec.description})`;
60
- }
61
- return `Invalid configuration for "${fieldName}"`;
62
- });
63
- throw new Error(`Invalid collection configuration:
64
- - ${errors.join("\n- ")}`);
65
- }
66
- return true;
67
- },
68
- {
69
- message: "Collection configuration is invalid"
70
- }
71
- ),
72
- default_sorting_field: z.string().optional()
73
- });
74
- var ConfigSchema = z.object({
75
- ghost: GhostConfigSchema,
76
- typesense: TypesenseConfigSchema,
77
- collection: CollectionConfigSchema
78
- });
79
- function validateConfig(config) {
80
- return ConfigSchema.parse(config);
81
- }
82
45
  var DEFAULT_COLLECTION_FIELDS = [
83
46
  { name: "id", type: "string", optional: false },
84
47
  { name: "title", type: "string", index: true, sort: true, optional: false },
@@ -92,7 +55,40 @@ var DEFAULT_COLLECTION_FIELDS = [
92
55
  { name: "tags", type: "string[]", facet: true, optional: true },
93
56
  { name: "authors", type: "string[]", facet: true, optional: true }
94
57
  ];
58
+ var CollectionConfigSchema = z.object({
59
+ name: z.string().min(1, "Collection name cannot be empty"),
60
+ fields: z.array(CollectionFieldSchema).optional().transform((fields) => fields || DEFAULT_COLLECTION_FIELDS).transform((fields) => {
61
+ const fieldMap = new Map(fields.map((f) => [f.name, f]));
62
+ Object.entries(REQUIRED_FIELDS).forEach(([fieldName, spec]) => {
63
+ const existingField = fieldMap.get(fieldName);
64
+ if (!existingField) {
65
+ const defaultField = DEFAULT_COLLECTION_FIELDS.find((f) => f.name === fieldName);
66
+ if (defaultField) {
67
+ fieldMap.set(fieldName, defaultField);
68
+ }
69
+ } else {
70
+ if (existingField.type !== spec.type) {
71
+ throw new Error(`Field "${fieldName}" must be of type "${spec.type}" (${spec.description})`);
72
+ }
73
+ if (existingField.optional === true) {
74
+ throw new Error(`Field "${fieldName}" cannot be optional (${spec.description})`);
75
+ }
76
+ }
77
+ });
78
+ return Array.from(fieldMap.values());
79
+ }),
80
+ default_sorting_field: z.string().optional()
81
+ });
82
+ var ConfigSchema = z.object({
83
+ ghost: GhostConfigSchema,
84
+ typesense: TypesenseConfigSchema,
85
+ collection: CollectionConfigSchema
86
+ });
87
+ function validateConfig(config) {
88
+ return ConfigSchema.parse(config);
89
+ }
95
90
  function createDefaultConfig(ghostUrl, ghostKey, typesenseHost, typesenseApiKey, collectionName = "posts") {
91
+ const cleanedHost = cleanUrl(typesenseHost);
96
92
  return {
97
93
  ghost: {
98
94
  url: ghostUrl,
@@ -102,7 +98,7 @@ function createDefaultConfig(ghostUrl, ghostKey, typesenseHost, typesenseApiKey,
102
98
  typesense: {
103
99
  nodes: [
104
100
  {
105
- host: typesenseHost,
101
+ host: cleanedHost,
106
102
  port: 443,
107
103
  protocol: "https"
108
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magicpages/ghost-typesense-config",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Configuration types and utilities for Ghost-Typesense integration",
5
5
  "author": "MagicPages",
6
6
  "license": "MIT",