@docupace/ihub-config 1.1.24-admin.2 → 1.1.25

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.
@@ -11,228 +11,8 @@ import { builtInProviders } from './providers/index.js';
11
11
  import { deepMergeResolvers, } from './resolvers/index.js';
12
12
  import { dump, load } from 'js-yaml';
13
13
  import { buildQuery } from '@docupace/ihub-core/query';
14
- import jp from 'jsonpath';
15
14
  const FULL_OBJECT_EXPRESSION_PATTERN = /^\${(.*?)}$/;
16
15
  const INLINE_OBJECT_EXPRESSION_PATTERN = /\${(.*?)}/g;
17
- function isNamedObjectArray(value) {
18
- return (Array.isArray(value) &&
19
- value.every((item) => item !== null &&
20
- typeof item === 'object' &&
21
- typeof item.name === 'string'));
22
- }
23
- // An override element counts as "self-contained" when it carries enough of
24
- // its own definition to render on its own — a real attribute path (or paths)
25
- // or a computed expression — as opposed to a thin `{ name, visible }`-style
26
- // reference that only makes sense resolved against a base/predefined
27
- // counterpart of the same name. `paths` (plural) is `Column`'s shape;
28
- // `path` (singular) is `TableCriteria`'s — both must count, or a resolved
29
- // filter-criterion `$ref` (which only ever has a singular `path`) is wrongly
30
- // treated as a dangling reference and silently dropped, even though it just
31
- // resolved successfully.
32
- function isSelfContainedOverrideElement(item) {
33
- const paths = item.paths;
34
- return ((Array.isArray(paths) && paths.length > 0) ||
35
- (typeof item.path === 'string' && item.path.length > 0) ||
36
- (typeof item.expression === 'string' && item.expression.length > 0));
37
- }
38
- /**
39
- * Merge semantics for a config sub-path override against the value already
40
- * at that JSONPath. Generic — used for any typename/sub-path the
41
- * configPath/subPath mechanism resolves, not just `Table.columns`.
42
- *
43
- * When both the current value and the override value are arrays of objects
44
- * each carrying a string `name`, override elements are merged onto their
45
- * base counterpart by name (override wins per-attribute, everything else
46
- * inherited) instead of the override replacing the array wholesale. This is
47
- * what makes a saved override non-destructive:
48
- * - Reordering falls out of the override array's own element order.
49
- * - "Hiding" an element is an attribute override (e.g. `visible: false`) on
50
- * an element that's still present, not a deletion.
51
- * - A base element the override never mentions is appended unchanged, so a
52
- * base element added later still surfaces for someone with an existing
53
- * override, instead of being permanently absent from their frozen array.
54
- * - An override element naming something not found in the base is kept
55
- * as-is when it's self-contained (has its own path(s)/expression — e.g. a
56
- * hand-authored column), or silently dropped when it's a thin reference
57
- * whose target (e.g. a predefined column) no longer exists — this never
58
- * throws; the stale reference just doesn't round-trip into the next save.
59
- *
60
- * Any other shape (scalars, plain objects, arrays without a `name` key) is
61
- * returned untouched, so the caller's plain whole-value replace applies
62
- * exactly as it did before this merge existed.
63
- */
64
- function mergeSubPathOverrideValue(base, override) {
65
- if (!isNamedObjectArray(override) || !isNamedObjectArray(base)) {
66
- return override;
67
- }
68
- const baseByName = new Map(base.map((item) => [item.name, item]));
69
- const merged = [];
70
- const seenNames = new Set();
71
- for (const overrideItem of override) {
72
- // Guard against a corrupted/hand-edited override array carrying two
73
- // elements with the same name — only the first is kept, so the merged
74
- // result never has duplicate names.
75
- if (seenNames.has(overrideItem.name)) {
76
- continue;
77
- }
78
- seenNames.add(overrideItem.name);
79
- const baseItem = baseByName.get(overrideItem.name);
80
- if (baseItem) {
81
- merged.push({ ...baseItem, ...overrideItem });
82
- }
83
- else if (isSelfContainedOverrideElement(overrideItem)) {
84
- merged.push(overrideItem);
85
- }
86
- // else: a thin reference to a name that no longer resolves — drop it.
87
- }
88
- const mergedNames = new Set(merged.map((item) => item.name));
89
- const untouchedBaseItems = base.filter((item) => !mergedNames.has(item.name));
90
- return [...merged, ...untouchedBaseItems];
91
- }
92
- // Marks each element of a fully-folded named-object array with whether it
93
- // would still show up — present *and* not hidden — without the layer stored
94
- // at the identity's own scope tier (`withoutOwnScope`, the same
95
- // broadest-to-narrowest fold as `mergedValue` minus that one layer; see
96
- // `applyConfigPathOverride`, where both folds are computed).
97
- //
98
- // This drives two decisions in the editing client, both about what its own
99
- // scope's override has to say explicitly to get the effect the user asked
100
- // for:
101
- // - Removing an entry: `inherited` means hiding it (`visible: false`) is
102
- // required, since deleting it from this scope's override would just have
103
- // the next resolution fold bring it back from a broader layer. Not
104
- // inherited means a plain delete suffices.
105
- // - Adding/re-showing an entry: not inherited means the client must pin
106
- // `visible: true` on it, since the broader fold either doesn't have it at
107
- // all or has it hidden — and per-attribute merge semantics would otherwise
108
- // inherit that `visible: false` straight through this scope's own
109
- // override, leaving the entry invisible no matter how it's re-added.
110
- // Hidden-ness is folded into `inherited` (rather than reported as a separate
111
- // flag) precisely because both decisions only ever care whether the entry
112
- // would be *there*, and a broader-hidden entry is exactly as absent from the
113
- // user's view as a missing one.
114
- //
115
- // Only stamps when both values are named-object arrays; any other shape
116
- // (scalar, plain object, unnamed array) is returned unchanged, mirroring
117
- // `mergeSubPathOverrideValue`'s own shape guard.
118
- function stampInherited(mergedValue, withoutOwnScope) {
119
- if (!isNamedObjectArray(mergedValue) ||
120
- !isNamedObjectArray(withoutOwnScope)) {
121
- return mergedValue;
122
- }
123
- const inheritedByName = new Map(withoutOwnScope.map((item) => [item.name, item]));
124
- return mergedValue.map((item) => {
125
- const counterpart = inheritedByName.get(item.name);
126
- return {
127
- ...item,
128
- inherited: !!counterpart && counterpart.visible !== false,
129
- };
130
- });
131
- }
132
- function isRefElement(item) {
133
- return (item !== null &&
134
- typeof item === 'object' &&
135
- typeof item.$ref === 'string');
136
- }
137
- // Resolves a config-path override array element's fragment-only `$ref`
138
- // (e.g. `"#$.predefinedColumns[?(@.name=='email')]"`) against `refRoot` —
139
- // the config-path's own sibling fields, not another file. This is
140
- // deliberately narrower than `template`'s YAML `$ref` (processed by
141
- // `processReferencedObject`/`getRefConfig`, which loads another config
142
- // file): an override-array `$ref` only ever supports the `#<jsonpath>`
143
- // self-reference form, resolved with the already-vendored `jsonpath`
144
- // package (the same one `applyConfigPathOverride` uses for `subPath`
145
- // strings). A ref that doesn't start with `#`, resolves to nothing, or
146
- // resolves to a non-object is treated the same as any other unresolved
147
- // override reference elsewhere in this module — silently dropped rather
148
- // than thrown, so a stale reference just doesn't round-trip into the next
149
- // save. Multiple matches take the first, in JSONPath document order.
150
- //
151
- // The resolved object keeps the original fragment string under `ref` (not
152
- // `$ref` — GraphQL field names can't start with `$`) rather than dropping
153
- // it once resolved. Without this, a client re-saving the array unchanged
154
- // (e.g. reordering a different column) would have no way to tell this
155
- // element apart from a plain inline column and would flatten it back into
156
- // a frozen copy on that save — exactly the staleness problem `$ref` exists
157
- // to avoid. `Column.ref` (the GraphQL field) surfaces it back to the client
158
- // so `docupace-ui-main` can keep re-emitting the same `$ref` indefinitely.
159
- function resolveOverrideElementRef(item, refRoot) {
160
- const ref = item.$ref;
161
- if (!ref.startsWith('#')) {
162
- return undefined;
163
- }
164
- const [match] = jp.query(refRoot, ref.slice(1));
165
- if (match === null || typeof match !== 'object') {
166
- return undefined;
167
- }
168
- const { $ref: _unusedRef, ...localOverrides } = item;
169
- return {
170
- ...match,
171
- ...localOverrides,
172
- ref,
173
- };
174
- }
175
- // Expands any `$ref` elements of a config-path override array into the
176
- // full object they point at (merged with whatever local attributes the
177
- // element carries alongside `$ref`, e.g. `visible`) before the array is
178
- // handed to `mergeSubPathOverrideValue`. Runs first so that a `{ $ref,
179
- // visible }` stub — which has no `name` of its own — always arrives at the
180
- // name-keyed merge as a proper named object; `mergeSubPathOverrideValue`
181
- // itself needs no `$ref` awareness.
182
- function expandRefOverrideElements(value, refRoot) {
183
- if (!Array.isArray(value)) {
184
- return value;
185
- }
186
- return value
187
- .map((item) => isRefElement(item) ? resolveOverrideElementRef(item, refRoot) : item)
188
- .filter((item) => item !== undefined);
189
- }
190
- // Builds the object a config-path override's `$ref` fragments resolve
191
- // against: the config being overridden, overlaid with the *raw* (not yet
192
- // merged) override value of every other simple top-level subPath in this
193
- // same patch (e.g. `$.predefinedColumns`). Using the raw override value
194
- // rather than depending on loop order elsewhere in
195
- // `applyConfigPathOverride` means a `$.columns` override's `$ref` into
196
- // `$.predefinedColumns` resolves correctly regardless of which subPath
197
- // happens to be processed first. Only single-segment paths (`$.foo`) are
198
- // overlaid — nested subPaths (`$.filter.criteria`) fall back to whatever
199
- // value is already on `config`, which is fine since nothing currently
200
- // needs to `$ref` into a nested subPath.
201
- //
202
- // `subPathPatch` (the `all` half of `SubPathOverrideLayers`) carries an
203
- // *ordered* array of layers per jsonPath
204
- // (broadest to narrowest — see `ConfigurationOverrideResult.subPaths`), not
205
- // a single already-resolved value. The overlay uses only the narrowest
206
- // (last) layer, same approximation as before cascading existed: a catalog
207
- // like `$.predefinedColumns`/`$.predefinedFilters` is always saved as a full
208
- // replacement at a single scope in practice (never a partial patch spread
209
- // across tiers), so the narrowest present layer already *is* effectively
210
- // the whole value — exactly what this overlay used before this function
211
- // took an array at all.
212
- function buildRefResolutionRoot(config, subPathPatch) {
213
- const overlay = {};
214
- for (const [jsonPath, layers] of Object.entries(subPathPatch)) {
215
- const topLevelMatch = /^\$\.([^.[]+)$/.exec(jsonPath);
216
- if (topLevelMatch && layers.length) {
217
- overlay[topLevelMatch[1]] = layers[layers.length - 1];
218
- }
219
- }
220
- return { ...config, ...overlay };
221
- }
222
- // Normalizes a provider's resolve() result into the pair of folds
223
- // `applyConfigPathOverride` works with. `inherited` stays `null` (rather
224
- // than defaulting to `{}`) when the provider doesn't report it, so the
225
- // fallback there stays distinguishable from "reported, but this path has no
226
- // broader layer".
227
- function toSubPathOverrideLayers(override) {
228
- if (!override.subPaths) {
229
- return null;
230
- }
231
- return {
232
- all: override.subPaths,
233
- inherited: override.inheritedSubPaths ?? null,
234
- };
235
- }
236
16
  export class ConfigFileStore {
237
17
  localPath;
238
18
  remotePath;
@@ -375,7 +155,6 @@ class ConfigService {
375
155
  configInjectorResolvers;
376
156
  providers;
377
157
  resolvers;
378
- configurationOverrideProvider;
379
158
  constructor(model, configStores, extensionOptions = {}) {
380
159
  this.configStores = configStores;
381
160
  this.model = model;
@@ -388,8 +167,6 @@ class ConfigService {
388
167
  this.resolvers = extensionOptions.resolvers
389
168
  ? { ...extensionOptions.resolvers }
390
169
  : {};
391
- this.configurationOverrideProvider =
392
- extensionOptions.configurationOverrideProvider;
393
170
  if (this.model) {
394
171
  this.generateResolvers();
395
172
  }
@@ -455,34 +232,12 @@ class ConfigService {
455
232
  }
456
233
  return processedData;
457
234
  }
458
- applyReferenceExtensions(processedData, referenceConfig) {
459
- if (typeof referenceConfig?.extend !== 'object') {
460
- return processedData;
461
- }
462
- const { extend } = referenceConfig;
463
- for (const key in extend) {
464
- const extensionValue = extend[key];
465
- if (!Array.isArray(extensionValue)) {
466
- throw new GraphQLError(`$ref.extend.${key} must be an array; received ${typeof extensionValue}`);
467
- }
468
- const baseValue = processedData[key];
469
- if (baseValue === undefined) {
470
- processedData[key] = extensionValue;
471
- continue;
472
- }
473
- if (!Array.isArray(baseValue)) {
474
- throw new GraphQLError(`$ref.extend.${key} can only extend an array property; "${key}" resolved to ${typeof baseValue}`);
475
- }
476
- processedData[key] = [...baseValue, ...extensionValue];
477
- }
478
- return processedData;
479
- }
480
235
  async processReferencedObject(configPath, obj, context, values) {
481
236
  const referenceConfig = obj.$ref;
482
237
  const refConfigPath = typeof referenceConfig === 'object' && referenceConfig.refPath
483
238
  ? referenceConfig.refPath
484
239
  : referenceConfig;
485
- const imageData = await this.processImageReference(refConfigPath, context);
240
+ const imageData = await this.processImageReference(refConfigPath);
486
241
  if (imageData) {
487
242
  return imageData;
488
243
  }
@@ -491,7 +246,6 @@ class ConfigService {
491
246
  ? this.updatePathValues(referencedData, referenceConfig.path)
492
247
  : referencedData;
493
248
  processedData = this.applyReferenceOverrides(processedData, referenceConfig);
494
- processedData = this.applyReferenceExtensions(processedData, referenceConfig);
495
249
  processedData = await this.processObjectExpressions(processedData, values, context);
496
250
  return this.processObject(configPath, processedData, context, values);
497
251
  }
@@ -508,16 +262,7 @@ class ConfigService {
508
262
  const builtInQueryResolvers = {
509
263
  pages: () => ({
510
264
  getPageConfig: async (obj, context) => {
511
- // `impersonateRoleId`/`impersonateGeneral` are a plain
512
- // pass-through onto context here — this engine never inspects
513
- // identity itself; the host's resolveCurrentIdentity is what
514
- // interprets them and enforces the admin-only restriction.
515
- const impersonation = obj.impersonateRoleId
516
- ? { impersonateRoleId: obj.impersonateRoleId }
517
- : obj.impersonateGeneral
518
- ? { impersonateGeneral: true }
519
- : null;
520
- const pageConfig = await this.getPageConfig(obj.path, impersonation ? { ...context, ...impersonation } : context, true, obj.context);
265
+ const pageConfig = await this.getPageConfig(obj.path, context, true, obj.context);
521
266
  return pageConfig;
522
267
  },
523
268
  getAIConfig: async (obj, context) => {
@@ -601,37 +346,29 @@ class ConfigService {
601
346
  return deepMergeResolvers(builtInMutationResolvers, hostMutationResolvers);
602
347
  };
603
348
  }
604
- // Applies any stored config-path sub-path overrides across the whole
605
- // config tree before processConfig's own recursive walk runs, so that
606
- // overridden values (which may introduce new sub-config) still go
607
- // through provider injection/__typename dispatch below.
608
- //
609
- // rootSubPathOverrides lets a caller that already resolved overrides for
610
- // the root config (e.g. getConfigFromStore, which fetches the whole-object
611
- // and sub-path overrides together in one round trip) hand them in directly
612
- // instead of having the root node re-resolved a second time below; nested
613
- // nodes discovered deeper in the tree are still resolved individually,
614
- // since their configPaths aren't known until the tree has been loaded.
615
- async processConfig(config, context, processProviders, rootSubPathOverrides) {
616
- const overriddenConfig = await this.applyConfigPathOverride(config, context, processProviders, rootSubPathOverrides);
617
- return this.processConfigTree(overriddenConfig, context, processProviders);
618
- }
619
- async processConfigTree(config, context, processProviders) {
349
+ async processConfig(config, context, processProviders) {
620
350
  if (!config) {
621
351
  return config;
622
352
  }
623
353
  // Handle arrays
624
354
  if (Array.isArray(config)) {
625
- return Promise.all(config.map((item) => this.processConfigTree(item, context, processProviders)));
355
+ return Promise.all(config.map((item) => this.processConfig(item, context, processProviders)));
626
356
  }
627
357
  // Handle objects
628
358
  if (typeof config === 'object') {
629
359
  // Recursively process all properties of config
630
360
  let processedConfig = { ...config };
631
361
  for (const key in processedConfig) {
632
- processedConfig[key] = await this.processConfigTree(processedConfig[key], context, processProviders);
362
+ processedConfig[key] = await this.processConfig(processedConfig[key], context, processProviders);
363
+ }
364
+ // First process the current object if it has __typename
365
+ if (processedConfig?.__typename && processProviders) {
366
+ const providerClass = this.providers[processedConfig.__typename];
367
+ if (providerClass) {
368
+ const provider = new providerClass();
369
+ processedConfig = await provider.processConfig(processedConfig, this, context);
370
+ }
633
371
  }
634
- processedConfig = await this.applyTypenameProvider(processedConfig, context, processProviders);
635
372
  return processedConfig;
636
373
  }
637
374
  if (processProviders) {
@@ -639,104 +376,6 @@ class ConfigService {
639
376
  }
640
377
  return config;
641
378
  }
642
- // Walks the whole config tree up front (pre-order) and, for every object
643
- // that declares a configPath, deep-sets any stored sub-path overrides
644
- // (JSONPath-addressed, e.g. "$.columns" or "$.filter.criteria").
645
- //
646
- // preFetchedSubPaths is only honored for the root node of the walk (the
647
- // one being called with a defined third argument); nested calls always
648
- // omit it so their own configPath gets resolved fresh.
649
- async applyConfigPathOverride(config, context, processProviders, preFetchedSubPaths) {
650
- if (!config) {
651
- return config;
652
- }
653
- if (Array.isArray(config)) {
654
- return Promise.all(config.map((item) => this.applyConfigPathOverride(item, context, processProviders)));
655
- }
656
- if (typeof config !== 'object') {
657
- return config;
658
- }
659
- let result = config;
660
- if (processProviders) {
661
- const subPathPatch = preFetchedSubPaths !== undefined
662
- ? preFetchedSubPaths
663
- : result.configPath && this.configurationOverrideProvider
664
- ? toSubPathOverrideLayers(await this.configurationOverrideProvider.resolve(result.configPath, context))
665
- : null;
666
- if (subPathPatch) {
667
- const refRoot = buildRefResolutionRoot(result, subPathPatch.all);
668
- // Deep-clone once, up front — `jp.value` mutates its target in
669
- // place, and a shallow `{ ...result }` per jsonPath only protects
670
- // the top level. A nested subPath (e.g. `$.filter.criteria`) would
671
- // otherwise still mutate `result.filter`, which is the *same*
672
- // object reference as the original, potentially-shared config
673
- // (e.g. reused across tables via `extend`/fragment composition).
674
- // Config values are always plain JSON (from YAML/domain storage),
675
- // so a JSON round-trip clone is sufficient and avoids
676
- // `structuredClone`'s cross-realm `instanceof` pitfalls (its output
677
- // fails `instanceof Object` checks — e.g. inside the `jsonpath`
678
- // package — when the calling code runs in a different VM
679
- // realm/context, as test sandboxes commonly do).
680
- result = JSON.parse(JSON.stringify(result));
681
- for (const [jsonPath, layers] of Object.entries(subPathPatch.all)) {
682
- // A single malformed override (an unparseable `$ref` JSONPath, or
683
- // a jsonPath that doesn't resolve to a settable location) must not
684
- // abort resolution of the rest of this config tree — that would
685
- // take down the page for every user over one bad admin-authored
686
- // row. Log and skip just this jsonPath instead.
687
- try {
688
- const currentValue = jp.value(result, jsonPath);
689
- const expandedLayers = layers.map((layer) => expandRefOverrideElements(layer, refRoot));
690
- // `layers` is ordered broadest to narrowest (general, tenant,
691
- // role, user — see `ConfigurationOverrideResult.subPaths`), so
692
- // folding them in order onto `currentValue` cascades correctly:
693
- // each layer only patches what it mentions, inheriting
694
- // everything else from the fold so far.
695
- const mergedValue = expandedLayers.reduce(mergeSubPathOverrideValue, currentValue);
696
- // The same fold minus the identity's own-scope layer — "what
697
- // this identity would see with no override of its own", which
698
- // is what `inherited` is stamped against. The provider reports
699
- // those layers explicitly (`inheritedSubPaths`) because the
700
- // tier a layer is stored at isn't recoverable from the values
701
- // alone; dropping the last layer is only a fallback for a
702
- // provider that doesn't, and is wrong whenever the identity has
703
- // no row of its own yet (the layer dropped is then a broader
704
- // one that very much still applies).
705
- const inheritedLayers = subPathPatch.inherited
706
- ? (subPathPatch.inherited[jsonPath] ?? [])
707
- : layers.slice(0, -1);
708
- const withoutOwnScope = inheritedLayers
709
- .map((layer) => expandRefOverrideElements(layer, refRoot))
710
- .reduce(mergeSubPathOverrideValue, currentValue);
711
- const finalValue = stampInherited(mergedValue, withoutOwnScope);
712
- const applied = jp.value(result, jsonPath, finalValue);
713
- if (applied === undefined) {
714
- throw new Error(`does not resolve to a settable location: "${jsonPath}"`);
715
- }
716
- }
717
- catch (error) {
718
- log.warn(`Skipping configuration override for "${result.configPath}" at "${jsonPath}": ${error.message}`);
719
- }
720
- }
721
- }
722
- }
723
- const overriddenEntries = await Promise.all(Object.entries(result).map(async ([key, value]) => [
724
- key,
725
- await this.applyConfigPathOverride(value, context, processProviders),
726
- ]));
727
- return Object.fromEntries(overriddenEntries);
728
- }
729
- async applyTypenameProvider(processedConfig, context, processProviders) {
730
- if (!processedConfig?.__typename || !processProviders) {
731
- return processedConfig;
732
- }
733
- const providerClass = this.providers[processedConfig.__typename];
734
- if (!providerClass) {
735
- return processedConfig;
736
- }
737
- const provider = new providerClass();
738
- return await provider.processConfig(processedConfig, this, context);
739
- }
740
379
  async getRefConfig(configPath, refConfigPath, context, values) {
741
380
  let fullPath;
742
381
  if (refConfigPath.startsWith('.')) {
@@ -823,21 +462,13 @@ class ConfigService {
823
462
  };
824
463
  return await processValue(object);
825
464
  }
826
- async processImageReference(refConfigPath, context) {
465
+ async processImageReference(refConfigPath) {
827
466
  const SUPPORTED_IMAGE_FORMATS = ['.jpg', '.jpeg', '.png', '.svg'];
828
467
  // Check if the reference is an image file
829
468
  const ext = path.extname(refConfigPath).toLowerCase();
830
469
  if (!SUPPORTED_IMAGE_FORMATS.includes(ext)) {
831
470
  return null;
832
471
  }
833
- const override = await this.configurationOverrideProvider?.resolve(refConfigPath, context);
834
- if (override?.whole?.contentType) {
835
- return {
836
- data: override.whole.value,
837
- mimeType: override.whole.contentType,
838
- hash: createHash('sha256').update(override.whole.value).digest('hex'),
839
- };
840
- }
841
472
  let standardStore;
842
473
  for (const store of this.configStores) {
843
474
  if (store instanceof ConfigFileStore) {
@@ -889,33 +520,19 @@ class ConfigService {
889
520
  return 'application/octet-stream';
890
521
  }
891
522
  }
892
- // Resolves the whole-object override and any sub-path overrides for
893
- // configPath together, in one provider round trip, instead of fetching
894
- // them separately at different points of the processing pipeline. The
895
- // sub-path overrides are handed back alongside the config so callers can
896
- // thread them into processConfig rather than re-resolving them later.
897
- async getConfigFromStore(configPath, context) {
898
- const override = await this.configurationOverrideProvider?.resolve(configPath, context);
899
- const subPathOverrides = override
900
- ? toSubPathOverrideLayers(override)
901
- : null;
902
- if (override?.whole && !override.whole.contentType) {
903
- return { config: load(override.whole.value), subPathOverrides };
904
- }
523
+ async getConfigFromStore(path) {
905
524
  const exceptions = [];
906
525
  for (const [index, configStore] of this.configStores.entries()) {
907
526
  try {
908
- const config = await configStore.getConfig(configPath);
909
- return { config, subPathOverrides };
527
+ return await configStore.getConfig(path);
910
528
  }
911
529
  catch (e) {
912
530
  exceptions.push(e);
913
531
  if (index == this.configStores.length - 1) {
914
- throw new GraphQLError(`Config not found in path in any store: ${configPath}`, { originalError: exceptions });
532
+ throw new GraphQLError(`Config not found in path in any store: ${path}`, { originalError: exceptions });
915
533
  }
916
534
  }
917
535
  }
918
- return { config: undefined, subPathOverrides };
919
536
  }
920
537
  async hasConfig(configPath) {
921
538
  return (await Promise.all(this.configStores.map((configStore) => configStore.hasConfig(configPath)))).some(Boolean);
@@ -925,9 +542,9 @@ class ConfigService {
925
542
  return this.getDirectConfig(globalPath, context, values, processProviders);
926
543
  }
927
544
  async getDirectConfig(configPath, context, values, processProviders) {
928
- const { config: obj, subPathOverrides } = await this.getConfigFromStore(configPath, context);
545
+ const obj = await this.getConfigFromStore(configPath);
929
546
  const fullObj = await this.processObject(configPath, obj, context, values);
930
- const processedObj = await this.processConfig(fullObj, context, processProviders, subPathOverrides);
547
+ const processedObj = await this.processConfig(fullObj, context, processProviders);
931
548
  return processedObj;
932
549
  }
933
550
  async listDirectConfigs(configPath) {
@@ -1278,22 +895,21 @@ class ConfigService {
1278
895
  }
1279
896
  async getPageConfig(pagePath, context, processConfig, rulesContext) {
1280
897
  const globalPath = path.join('global', 'pages', pagePath);
1281
- const { config: obj, subPathOverrides } = await this.getConfigFromStore(globalPath, context);
898
+ const obj = await this.getConfigFromStore(globalPath);
1282
899
  const fullObj = await this.processObject(globalPath, obj, context, null);
1283
900
  const matchingRuleGroups = await this.getRuleGroups(rulesContext, context);
1284
901
  const configToProcess = this.applyFieldRuleOverrides(fullObj, matchingRuleGroups);
1285
- return await this.processConfig(configToProcess, context, processConfig, subPathOverrides);
902
+ return await this.processConfig(configToProcess, context, processConfig);
1286
903
  }
1287
904
  async init() {
1288
905
  return Promise.all(this.configStores.map((configStore) => configStore.init()));
1289
906
  }
1290
907
  }
1291
- export const defaultConfigService = ({ model, configStores, configInjectorResolvers, providers, resolvers, configurationOverrideProvider, }) => {
908
+ export const defaultConfigService = ({ model, configStores, configInjectorResolvers, providers, resolvers, }) => {
1292
909
  const extensionOptions = {
1293
910
  configInjectorResolvers,
1294
911
  providers,
1295
912
  resolvers,
1296
- configurationOverrideProvider,
1297
913
  };
1298
914
  return new ConfigService(model, configStores.map((configStore) => new ConfigFileStore(configStore)), extensionOptions);
1299
915
  };