@nitrogenbuilder/connector-payload 1.1.0 → 1.2.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.
@@ -0,0 +1,563 @@
1
+ /**
2
+ * Localization support — locale threading for read endpoints, dynamic-data
3
+ * translation metadata, and per-language translation status for builder
4
+ * content.
5
+ *
6
+ * Two independent layers cooperate here:
7
+ *
8
+ * 1. **Payload-native localization** (field data). When the host project's
9
+ * Payload config has `localization` configured (either directly or injected
10
+ * from the plugin's `localization` option), eligible text fields are
11
+ * localized and read endpoints thread `?lang=` through to
12
+ * `payload.find`/`findByID` as `locale` + `fallbackLocale`.
13
+ * 2. **Nitrogen settings localization** (builder content). Site languages live
14
+ * in the `nitrogen-settings` global under `nitrogenConfig.localization`.
15
+ * Translatable prop values inside `nitrogenData` are stored language-keyed
16
+ * with the language as the OUTER key (`{ en: ..., es: ... }`); legacy bare
17
+ * values read as the default language.
18
+ *
19
+ * Everything is gated: with no localization configured anywhere, every helper
20
+ * returns null/empty and callers behave exactly as before.
21
+ */
22
+ import { NITROGEN_COMPONENT_CATALOG_COLLECTION, findAllDocs, } from './inventory/indexing.js';
23
+ /**
24
+ * Reads the sanitized Payload localization config at runtime. Returns null
25
+ * when the project has no Payload-level localization configured.
26
+ */
27
+ export function getPayloadLocalization(payload) {
28
+ const localization = payload.config.localization;
29
+ if (!localization || typeof localization !== 'object')
30
+ return null;
31
+ const value = localization;
32
+ let locales = [];
33
+ if (Array.isArray(value.localeCodes)) {
34
+ locales = value.localeCodes.map(String).filter(Boolean);
35
+ }
36
+ else if (Array.isArray(value.locales)) {
37
+ locales = value.locales
38
+ .map((locale) => typeof locale === 'string'
39
+ ? locale
40
+ : String(locale?.code ?? ''))
41
+ .filter(Boolean);
42
+ }
43
+ const defaultLocale = typeof value.defaultLocale === 'string' ? value.defaultLocale : '';
44
+ if (locales.length === 0 || !defaultLocale)
45
+ return null;
46
+ return { locales, defaultLocale };
47
+ }
48
+ /** Reads `?lang=` (alias `?locale=`) off a request URL. */
49
+ export function getRequestLanguage(req) {
50
+ try {
51
+ const url = new URL(req.url || '', 'http://localhost');
52
+ const lang = url.searchParams.get('lang') || url.searchParams.get('locale') || '';
53
+ return lang.trim() || null;
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ /**
60
+ * Turns a requested language into `locale`/`fallbackLocale` options for
61
+ * `payload.find`/`findByID`. Returns `{}` (default behavior) when no language
62
+ * was requested, the project has no Payload localization, or the language is
63
+ * not a configured locale.
64
+ */
65
+ export function resolveLocaleOptions(payload, lang) {
66
+ if (!lang)
67
+ return {};
68
+ const localization = getPayloadLocalization(payload);
69
+ if (!localization || !localization.locales.includes(lang))
70
+ return {};
71
+ return { locale: lang, fallbackLocale: localization.defaultLocale };
72
+ }
73
+ export function getCollectionConfig(payload, collectionSlug) {
74
+ return (payload.config.collections || []).find((collection) => collection.slug === collectionSlug);
75
+ }
76
+ /** Text-bearing field types eligible for translation. */
77
+ const LOCALIZABLE_FIELD_TYPES = new Set(['text', 'textarea', 'richText']);
78
+ /**
79
+ * Dot-paths of localized text-typed fields of a collection config. Walks
80
+ * groups, rows, collapsibles, and tabs; named groups/tabs contribute a path
81
+ * segment.
82
+ */
83
+ export function getLocalizedTextFieldPaths(fields, prefix = '') {
84
+ const paths = [];
85
+ for (const field of fields || []) {
86
+ const f = field;
87
+ const name = typeof f.name === 'string' && f.name ? f.name : undefined;
88
+ if (name && LOCALIZABLE_FIELD_TYPES.has(f.type) && f.localized) {
89
+ paths.push(`${prefix}${name}`);
90
+ continue;
91
+ }
92
+ // Array/blocks rows can't be addressed by a dot-path (getByPath cannot
93
+ // index rows), so only non-repeating containers are walked.
94
+ if (Array.isArray(f.fields) && f.type !== 'array') {
95
+ const nestedPrefix = name && f.type === 'group' ? `${prefix}${name}.` : prefix;
96
+ paths.push(...getLocalizedTextFieldPaths(f.fields, nestedPrefix));
97
+ }
98
+ if (Array.isArray(f.tabs)) {
99
+ for (const tab of f.tabs) {
100
+ const nestedPrefix = tab.name ? `${prefix}${tab.name}.` : prefix;
101
+ paths.push(...getLocalizedTextFieldPaths(tab.fields || [], nestedPrefix));
102
+ }
103
+ }
104
+ }
105
+ return paths;
106
+ }
107
+ // ---------------------------------------------------------------------------
108
+ // Nitrogen settings localization (builder content)
109
+ // ---------------------------------------------------------------------------
110
+ /**
111
+ * The site language config from the `nitrogen-settings` global. Null when
112
+ * localization is absent or disabled — callers must treat null as
113
+ * "no localization behavior at all".
114
+ */
115
+ export function getLocalizationSettings(settings) {
116
+ const localization = settings.nitrogenConfig?.localization;
117
+ if (!localization || typeof localization !== 'object')
118
+ return null;
119
+ const value = localization;
120
+ if (!value.enabled ||
121
+ !value.defaultLanguage ||
122
+ !Array.isArray(value.languages) ||
123
+ value.languages.length === 0) {
124
+ return null;
125
+ }
126
+ return value;
127
+ }
128
+ // ---------------------------------------------------------------------------
129
+ // Shared value helpers
130
+ // ---------------------------------------------------------------------------
131
+ function hasContent(value) {
132
+ if (value === undefined || value === null)
133
+ return false;
134
+ if (typeof value === 'string')
135
+ return value.trim() !== '';
136
+ return true;
137
+ }
138
+ function getByPath(obj, path) {
139
+ let current = obj;
140
+ for (const part of path.split('.')) {
141
+ if (!current || typeof current !== 'object')
142
+ return undefined;
143
+ current = current[part];
144
+ }
145
+ return current;
146
+ }
147
+ function isPlainObject(value) {
148
+ return !!value && typeof value === 'object' && !Array.isArray(value);
149
+ }
150
+ /**
151
+ * A stored translatable value: every key is a configured language code.
152
+ * (Responsive values keyed by breakpoint names never collide because
153
+ * breakpoint names are not language codes.)
154
+ */
155
+ function isLangMap(value, codes) {
156
+ const keys = Object.keys(value);
157
+ return keys.length > 0 && keys.every((key) => codes.has(key));
158
+ }
159
+ // ---------------------------------------------------------------------------
160
+ // Dynamic data meta
161
+ // ---------------------------------------------------------------------------
162
+ /** `Post.`-namespaced dynamic-data keys for a doc field path. */
163
+ function dynamicDataKeysForField(path) {
164
+ const keys = [`Post.${path}`];
165
+ if (path === 'title')
166
+ keys.push('Post.post_title');
167
+ return keys;
168
+ }
169
+ /**
170
+ * Fetches a doc with every locale's value for localized fields (one
171
+ * `locale: 'all'` query). Returns null when the project has no Payload
172
+ * localization configured or the doc can't be read — advisory callers keep
173
+ * their default behavior in that case.
174
+ */
175
+ export async function fetchLocaleAllDoc(payload, collectionSlug, docId) {
176
+ if (!getPayloadLocalization(payload))
177
+ return null;
178
+ try {
179
+ return (await payload.findByID({
180
+ collection: collectionSlug,
181
+ id: docId,
182
+ depth: 0,
183
+ locale: 'all',
184
+ overrideAccess: true,
185
+ disableErrors: true,
186
+ }));
187
+ }
188
+ catch {
189
+ return null;
190
+ }
191
+ }
192
+ /**
193
+ * The default-locale title from a `locale: 'all'` doc, for editor-facing
194
+ * single-doc responses. The editor edits default-language field data only
195
+ * (the CMS admin owns field translations), so the `title` it displays and
196
+ * PATCHes back on save must never be a locale-resolved one. Returns null when
197
+ * there is nothing to override (no localization, title not localized, or no
198
+ * stored title) — callers then keep the response title as-is.
199
+ */
200
+ export function getDefaultLocaleTitle(payload, localeAllDoc) {
201
+ const localization = getPayloadLocalization(payload);
202
+ if (!localization || !localeAllDoc)
203
+ return null;
204
+ const title = localeAllDoc.title;
205
+ if (!isPlainObject(title))
206
+ return null;
207
+ const value = title[localization.defaultLocale];
208
+ if (typeof value === 'string')
209
+ return value;
210
+ // No default-locale title stored — first stored one, matching the
211
+ // renderer's language-resolution fallback chain.
212
+ for (const candidate of Object.values(title)) {
213
+ if (typeof candidate === 'string' && candidate)
214
+ return candidate;
215
+ }
216
+ return null;
217
+ }
218
+ /**
219
+ * Builds the connector-provided metadata the editor uses to badge
220
+ * untranslated CMS fields. Eligible keys are the localized text-typed fields
221
+ * of the collection config; translated keys per language are the fields whose
222
+ * locale-specific value exists (checked via one `locale: 'all'` fetch, or a
223
+ * caller-preloaded `localeAllDoc` to avoid a duplicate query).
224
+ *
225
+ * Returns null when the project has no Payload localization configured, so
226
+ * callers can attach `dynamic_data_meta` conditionally with zero change to
227
+ * the default response shape.
228
+ */
229
+ export async function buildDynamicDataMeta(payload, collectionSlug, docId, localeAllDoc) {
230
+ const localization = getPayloadLocalization(payload);
231
+ if (!localization)
232
+ return null;
233
+ const collection = getCollectionConfig(payload, collectionSlug);
234
+ if (!collection)
235
+ return null;
236
+ const fieldPaths = getLocalizedTextFieldPaths(collection.fields);
237
+ const meta = {
238
+ eligibleKeys: fieldPaths.flatMap(dynamicDataKeysForField),
239
+ translatedKeys: {},
240
+ perPostNamespaces: ['Post'],
241
+ };
242
+ if (fieldPaths.length === 0)
243
+ return meta;
244
+ const doc = localeAllDoc !== undefined
245
+ ? localeAllDoc
246
+ : docId !== undefined
247
+ ? await fetchLocaleAllDoc(payload, collectionSlug, docId)
248
+ : null;
249
+ if (!doc)
250
+ return meta;
251
+ for (const lang of localization.locales) {
252
+ const translated = [];
253
+ for (const path of fieldPaths) {
254
+ const value = getByPath(doc, path);
255
+ if (isPlainObject(value) && hasContent(value[lang])) {
256
+ translated.push(...dynamicDataKeysForField(path));
257
+ }
258
+ }
259
+ meta.translatedKeys[lang] = translated;
260
+ }
261
+ return meta;
262
+ }
263
+ /**
264
+ * Loads component prop definitions from the nitrogen-component-catalog
265
+ * collection so translatable props can be identified precisely. Returns an
266
+ * empty map when the catalog is unavailable — the walk then falls back to the
267
+ * lang-map heuristic.
268
+ */
269
+ export async function loadTranslatablePropDefs(payload) {
270
+ const defs = new Map();
271
+ try {
272
+ const docs = await findAllDocs(payload, NITROGEN_COMPONENT_CATALOG_COLLECTION);
273
+ for (const doc of docs) {
274
+ const definition = doc.definition;
275
+ if (!definition?.categories)
276
+ continue;
277
+ const byGroup = {};
278
+ for (const category of Object.values(definition.categories)) {
279
+ for (const [groupKey, group] of Object.entries(category?.groups || {})) {
280
+ if (!group?.props || Object.keys(group.props).length === 0)
281
+ continue;
282
+ byGroup[groupKey] = { ...byGroup[groupKey], ...group.props };
283
+ }
284
+ }
285
+ if (Object.keys(byGroup).length > 0) {
286
+ defs.set(doc.componentName, byGroup);
287
+ }
288
+ }
289
+ }
290
+ catch {
291
+ // Catalog unavailable — heuristic fallback.
292
+ }
293
+ return defs;
294
+ }
295
+ function countLangMap(value, ctx, counter) {
296
+ const hasDefault = hasContent(value[ctx.defaultLanguage]);
297
+ const hasLang = hasContent(value[ctx.lang]);
298
+ if (!hasDefault && !hasLang)
299
+ return;
300
+ counter.total += 1;
301
+ if (hasDefault && !hasLang)
302
+ counter.untranslated += 1;
303
+ }
304
+ /** A DynamicValue binding: `{ key, before?, fallback?, after? }`. */
305
+ function isDynamicValue(value) {
306
+ if (typeof value.key !== 'string')
307
+ return false;
308
+ const keys = Object.keys(value);
309
+ return keys.every((key) => ['key', 'before', 'fallback', 'after'].includes(key));
310
+ }
311
+ function countDynamicValueSlots(value, ctx, counter) {
312
+ for (const slot of ['before', 'fallback', 'after']) {
313
+ const slotValue = value[slot];
314
+ if (slotValue === undefined || typeof slotValue === 'boolean')
315
+ continue;
316
+ if (isPlainObject(slotValue) && isLangMap(slotValue, ctx.codes)) {
317
+ // Language-keyed boolean toggles (`fallback: { en: true }`) are
318
+ // settings, not text — mirror the bare-boolean skip above.
319
+ if (typeof slotValue[ctx.defaultLanguage] === 'boolean' ||
320
+ typeof slotValue[ctx.lang] === 'boolean') {
321
+ continue;
322
+ }
323
+ countLangMap(slotValue, ctx, counter);
324
+ }
325
+ else if (hasContent(slotValue)) {
326
+ // Legacy bare value = default language only.
327
+ counter.total += 1;
328
+ counter.untranslated += 1;
329
+ }
330
+ }
331
+ }
332
+ /**
333
+ * Heuristic walk for props without catalog definitions: any nested object
334
+ * whose keys are all configured language codes counts as a translatable
335
+ * value; it is untranslated in L when it has a default-language value but no
336
+ * L value. Bare values are NOT counted here (we cannot know they are
337
+ * translatable without a definition).
338
+ */
339
+ function walkValueHeuristic(value, ctx, counter) {
340
+ if (!value || typeof value !== 'object')
341
+ return;
342
+ if (Array.isArray(value)) {
343
+ for (const item of value)
344
+ walkValueHeuristic(item, ctx, counter);
345
+ return;
346
+ }
347
+ const record = value;
348
+ if (isLangMap(record, ctx.codes)) {
349
+ countLangMap(record, ctx, counter);
350
+ return;
351
+ }
352
+ for (const [key, nested] of Object.entries(record)) {
353
+ if (key === 'children')
354
+ continue;
355
+ walkValueHeuristic(nested, ctx, counter);
356
+ }
357
+ }
358
+ /** Editor storage convention: `props[group][propKey + '___dynamic']` holds a
359
+ * DynamicValue binding for the base prop. */
360
+ const DYNAMIC_KEY_SUFFIX = '___dynamic';
361
+ /**
362
+ * One stored prop entry, dispatching on the editor's key conventions.
363
+ * `<key>___dynamic` entries hold DynamicValue bindings whose text slots are
364
+ * page content regardless of the base prop's own translatability (the
365
+ * renderer language-resolves every dynamic slot).
366
+ */
367
+ function countPropEntry(key, value, defs, ctx, counter) {
368
+ if (key.endsWith(DYNAMIC_KEY_SUFFIX)) {
369
+ if (isPlainObject(value) && isDynamicValue(value)) {
370
+ countDynamicValueSlots(value, ctx, counter);
371
+ }
372
+ else {
373
+ walkValueHeuristic(value, ctx, counter);
374
+ }
375
+ return;
376
+ }
377
+ countPropValue(value, defs?.[key], ctx, counter);
378
+ }
379
+ function countPropValue(value, def, ctx, counter) {
380
+ if (def?.translatable) {
381
+ if (isPlainObject(value)) {
382
+ if (isLangMap(value, ctx.codes)) {
383
+ countLangMap(value, ctx, counter);
384
+ return;
385
+ }
386
+ if (isDynamicValue(value)) {
387
+ countDynamicValueSlots(value, ctx, counter);
388
+ return;
389
+ }
390
+ }
391
+ if (hasContent(value)) {
392
+ // Legacy bare value = default language only.
393
+ counter.total += 1;
394
+ counter.untranslated += 1;
395
+ }
396
+ return;
397
+ }
398
+ if (def?.type === 'array' && Array.isArray(value)) {
399
+ for (const item of value) {
400
+ if (!isPlainObject(item))
401
+ continue;
402
+ for (const [key, nested] of Object.entries(item)) {
403
+ countPropEntry(key, nested, def.props, ctx, counter);
404
+ }
405
+ }
406
+ return;
407
+ }
408
+ if (def?.props && isPlainObject(value)) {
409
+ for (const [key, nested] of Object.entries(value)) {
410
+ countPropEntry(key, nested, def.props, ctx, counter);
411
+ }
412
+ return;
413
+ }
414
+ if (!def)
415
+ walkValueHeuristic(value, ctx, counter);
416
+ }
417
+ function moduleNameFromNode(node) {
418
+ for (const key of ['module', 'moduleId']) {
419
+ const value = node[key];
420
+ if (typeof value === 'string')
421
+ return value;
422
+ if (isPlainObject(value) &&
423
+ typeof value.name === 'string') {
424
+ return value.name;
425
+ }
426
+ }
427
+ return null;
428
+ }
429
+ /**
430
+ * Walks the module tree counting translatable prop values for one language.
431
+ * Modules hidden in that language are skipped entirely, including their
432
+ * subtree. The editor stores hidden languages at `props.__hiddenLanguages`
433
+ * (canonical); module-level `hiddenLanguages` is the legacy fallback.
434
+ */
435
+ function walkModules(modules, ctx, defs, counter) {
436
+ if (!Array.isArray(modules))
437
+ return;
438
+ for (const maybeNode of modules) {
439
+ if (!isPlainObject(maybeNode))
440
+ continue;
441
+ const node = maybeNode;
442
+ const props = node.props;
443
+ const hiddenLanguages = (isPlainObject(props) ? props.__hiddenLanguages : undefined) ??
444
+ node.hiddenLanguages;
445
+ if (Array.isArray(hiddenLanguages) && hiddenLanguages.includes(ctx.lang)) {
446
+ continue;
447
+ }
448
+ const componentName = moduleNameFromNode(node);
449
+ const componentDefs = componentName ? defs.get(componentName) : undefined;
450
+ if (isPlainObject(props)) {
451
+ // Prop values are stored group-keyed: props[groupKey][propKey].
452
+ // `__`-prefixed keys are instance metadata (__label, __hiddenLanguages).
453
+ for (const [groupKey, groupValue] of Object.entries(props)) {
454
+ if (groupKey === 'children' || groupKey.startsWith('__'))
455
+ continue;
456
+ if (isPlainObject(groupValue)) {
457
+ if (isLangMap(groupValue, ctx.codes)) {
458
+ // Flat (ungrouped) translatable value — count it directly.
459
+ countLangMap(groupValue, ctx, counter);
460
+ continue;
461
+ }
462
+ const groupDefs = componentDefs?.[groupKey];
463
+ for (const [propKey, propValue] of Object.entries(groupValue)) {
464
+ countPropEntry(propKey, propValue, groupDefs, ctx, counter);
465
+ }
466
+ }
467
+ else {
468
+ walkValueHeuristic(groupValue, ctx, counter);
469
+ }
470
+ }
471
+ const children = props.children;
472
+ if (Array.isArray(children)) {
473
+ walkModules(children, ctx, defs, counter);
474
+ }
475
+ else if (isPlainObject(children)) {
476
+ for (const slotChildren of Object.values(children)) {
477
+ walkModules(slotChildren, ctx, defs, counter);
478
+ }
479
+ }
480
+ }
481
+ if (Array.isArray(node.children)) {
482
+ walkModules(node.children, ctx, defs, counter);
483
+ }
484
+ }
485
+ }
486
+ /**
487
+ * Computes per-language translation status for one page/template. Returns a
488
+ * `{ [langCode]: LanguageStatus }` map covering every configured non-default
489
+ * language, or null when there is nothing to compute.
490
+ */
491
+ export async function computeDocTranslationStatus(args) {
492
+ const { payload, collectionSlug, docId, nitrogenData, localization } = args;
493
+ const defaultLanguage = localization.defaultLanguage;
494
+ const languages = (localization.languages || [])
495
+ .map((language) => language.code)
496
+ .filter(Boolean);
497
+ const nonDefault = languages.filter((code) => code !== defaultLanguage);
498
+ if (!defaultLanguage || nonDefault.length === 0)
499
+ return null;
500
+ const codes = new Set(languages.concat(defaultLanguage));
501
+ const propDefs = args.propDefs ?? (await loadTranslatablePropDefs(payload));
502
+ // Field-side coverage relies on Payload-native localization.
503
+ let fieldPaths = [];
504
+ let localeAllDoc = args.localeAllDoc ?? null;
505
+ if (getPayloadLocalization(payload)) {
506
+ const collection = getCollectionConfig(payload, collectionSlug);
507
+ fieldPaths = collection ? getLocalizedTextFieldPaths(collection.fields) : [];
508
+ if (fieldPaths.length > 0 && localeAllDoc === null && args.localeAllDoc === undefined) {
509
+ localeAllDoc = await fetchLocaleAllDoc(payload, collectionSlug, docId);
510
+ }
511
+ }
512
+ const statuses = {};
513
+ for (const lang of nonDefault) {
514
+ const ctx = { lang, defaultLanguage, codes };
515
+ const propCounter = { total: 0, untranslated: 0 };
516
+ walkModules(nitrogenData, ctx, propDefs, propCounter);
517
+ const fieldCounter = { total: 0, untranslated: 0 };
518
+ let slugTranslated;
519
+ let seoTranslated;
520
+ if (localeAllDoc) {
521
+ let seoTotal = 0;
522
+ let seoUntranslated = 0;
523
+ for (const path of fieldPaths) {
524
+ const value = getByPath(localeAllDoc, path);
525
+ if (!isPlainObject(value))
526
+ continue;
527
+ const hasDefault = hasContent(value[defaultLanguage]);
528
+ const hasLang = hasContent(value[lang]);
529
+ if (path === 'slug') {
530
+ slugTranslated = hasLang;
531
+ continue;
532
+ }
533
+ if (!hasDefault && !hasLang)
534
+ continue;
535
+ fieldCounter.total += 1;
536
+ if (hasDefault && !hasLang) {
537
+ fieldCounter.untranslated += 1;
538
+ if (path.startsWith('meta.'))
539
+ seoUntranslated += 1;
540
+ }
541
+ if (path.startsWith('meta.'))
542
+ seoTotal += 1;
543
+ }
544
+ if (seoTotal > 0)
545
+ seoTranslated = seoUntranslated === 0;
546
+ }
547
+ const total = propCounter.total + fieldCounter.total;
548
+ const untranslated = propCounter.untranslated + fieldCounter.untranslated;
549
+ const state = total === 0 || untranslated === 0
550
+ ? 'complete'
551
+ : untranslated >= total
552
+ ? 'none'
553
+ : 'partial';
554
+ statuses[lang] = {
555
+ state,
556
+ untranslatedProps: propCounter.untranslated,
557
+ untranslatedFields: fieldCounter.untranslated,
558
+ ...(slugTranslated !== undefined ? { slugTranslated } : {}),
559
+ ...(seoTranslated !== undefined ? { seoTranslated } : {}),
560
+ };
561
+ }
562
+ return statuses;
563
+ }
package/dist/types.d.ts CHANGED
@@ -123,8 +123,11 @@ interface TemplateUpdateData {
123
123
  }
124
124
  export interface SlugLookupRequestBody {
125
125
  slug?: string;
126
+ /** Language to resolve localized fields/slugs in (alias of ?lang=). */
127
+ lang?: string;
126
128
  data?: {
127
129
  slug?: string;
130
+ lang?: string;
128
131
  };
129
132
  }
130
133
  export interface MediaUpdateRequestBody {
@@ -152,7 +155,6 @@ export interface NitrogenComponentUsageDoc {
152
155
  id: string | number;
153
156
  usageKey: string;
154
157
  componentName: string;
155
- depth?: number;
156
158
  sourceCollection: string;
157
159
  sourceType: string;
158
160
  sourceDocumentId: string;
@@ -160,10 +162,6 @@ export interface NitrogenComponentUsageDoc {
160
162
  sourceSlug?: string;
161
163
  sourceStatus?: string;
162
164
  moduleId?: string;
163
- modulePath: string;
164
- parentComponentName?: string;
165
- parentModuleId?: string;
166
- parentModulePath?: string;
167
165
  }
168
166
  export interface NitrogenInventorySourceDoc {
169
167
  id: string | number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitrogenbuilder/connector-payload",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Nitrogen page builder connector plugin for Payload CMS 3.x",
5
5
  "author": "Leonardo Dentzien <leo@torchmedia.ca>",
6
6
  "type": "module",