@harperfast/harper 5.2.0-alpha.4 → 5.2.0-alpha.6
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/agent/agent.ts +152 -10
- package/agent/bestPractices.ts +58 -0
- package/agent/mcpTools.ts +122 -0
- package/agent/operations.ts +10 -1
- package/agent/registryTools.ts +117 -0
- package/agent/session.ts +16 -7
- package/agent/tools/fsTools.ts +74 -27
- package/agent/tools/inspectorTool.ts +459 -0
- package/agent/toolset.ts +27 -7
- package/agent/types.ts +2 -0
- package/components/Application.ts +566 -85
- package/components/OptionsWatcher.ts +62 -2
- package/components/Scope.ts +31 -8
- package/components/componentLoader.ts +5 -1
- package/components/componentSecrets.ts +514 -55
- package/components/deploymentRecorder.ts +7 -6
- package/components/gitCredentialHelper.js +115 -0
- package/components/gitCredentialServer.ts +251 -0
- package/components/mcp/tools/application.ts +197 -23
- package/components/mcp/tools/operations.ts +1 -1
- package/components/mcp/tools/schemas/derive.ts +6 -2
- package/components/operations.js +21 -19
- package/components/operationsValidation.js +86 -21
- package/components/secretOperations.ts +110 -30
- package/config/harperConfigEnvVars.ts +90 -5
- package/config-root.schema.json +4 -0
- package/dist/agent/agent.d.ts +24 -3
- package/dist/agent/agent.js +172 -10
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/bestPractices.d.ts +24 -0
- package/dist/agent/bestPractices.js +60 -0
- package/dist/agent/bestPractices.js.map +1 -0
- package/dist/agent/mcpTools.d.ts +24 -0
- package/dist/agent/mcpTools.js +115 -0
- package/dist/agent/mcpTools.js.map +1 -0
- package/dist/agent/operations.js +10 -1
- package/dist/agent/operations.js.map +1 -1
- package/dist/agent/registryTools.d.ts +45 -0
- package/dist/agent/registryTools.js +113 -0
- package/dist/agent/registryTools.js.map +1 -0
- package/dist/agent/session.js +16 -7
- package/dist/agent/session.js.map +1 -1
- package/dist/agent/tools/fsTools.js +70 -28
- package/dist/agent/tools/fsTools.js.map +1 -1
- package/dist/agent/tools/inspectorTool.d.ts +40 -0
- package/dist/agent/tools/inspectorTool.js +428 -0
- package/dist/agent/tools/inspectorTool.js.map +1 -0
- package/dist/agent/toolset.d.ts +16 -6
- package/dist/agent/toolset.js +17 -7
- package/dist/agent/toolset.js.map +1 -1
- package/dist/agent/types.d.ts +2 -0
- package/dist/components/Application.d.ts +73 -18
- package/dist/components/Application.js +475 -64
- package/dist/components/Application.js.map +1 -1
- package/dist/components/OptionsWatcher.d.ts +1 -1
- package/dist/components/OptionsWatcher.js +65 -2
- package/dist/components/OptionsWatcher.js.map +1 -1
- package/dist/components/Scope.d.ts +8 -6
- package/dist/components/Scope.js +22 -6
- package/dist/components/Scope.js.map +1 -1
- package/dist/components/componentLoader.js +5 -1
- package/dist/components/componentLoader.js.map +1 -1
- package/dist/components/componentSecrets.d.ts +33 -7
- package/dist/components/componentSecrets.js +473 -59
- package/dist/components/componentSecrets.js.map +1 -1
- package/dist/components/deploymentRecorder.d.ts +2 -2
- package/dist/components/deploymentRecorder.js +1 -1
- package/dist/components/deploymentRecorder.js.map +1 -1
- package/dist/components/gitCredentialHelper.d.ts +1 -0
- package/dist/components/gitCredentialHelper.js +113 -0
- package/dist/components/gitCredentialHelper.js.map +1 -0
- package/dist/components/gitCredentialServer.d.ts +33 -0
- package/dist/components/gitCredentialServer.js +236 -0
- package/dist/components/gitCredentialServer.js.map +1 -0
- package/dist/components/mcp/tools/application.d.ts +19 -0
- package/dist/components/mcp/tools/application.js +180 -22
- package/dist/components/mcp/tools/application.js.map +1 -1
- package/dist/components/mcp/tools/operations.d.ts +13 -0
- package/dist/components/mcp/tools/operations.js +1 -0
- package/dist/components/mcp/tools/operations.js.map +1 -1
- package/dist/components/mcp/tools/schemas/derive.js +6 -2
- package/dist/components/mcp/tools/schemas/derive.js.map +1 -1
- package/dist/components/operations.js +23 -21
- package/dist/components/operations.js.map +1 -1
- package/dist/components/operationsValidation.js +84 -21
- package/dist/components/operationsValidation.js.map +1 -1
- package/dist/components/secretOperations.d.ts +33 -11
- package/dist/components/secretOperations.js +90 -26
- package/dist/components/secretOperations.js.map +1 -1
- package/dist/config/harperConfigEnvVars.d.ts +21 -0
- package/dist/config/harperConfigEnvVars.js +95 -5
- package/dist/config/harperConfigEnvVars.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/resources/Resource.d.ts +19 -0
- package/dist/resources/Resource.js +93 -2
- package/dist/resources/Resource.js.map +1 -1
- package/dist/resources/Table.d.ts +9 -0
- package/dist/resources/Table.js +256 -50
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/read.js +28 -25
- package/dist/resources/analytics/read.js.map +1 -1
- package/dist/resources/defineResource.d.ts +180 -0
- package/dist/resources/defineResource.js +505 -0
- package/dist/resources/defineResource.js.map +1 -0
- package/dist/resources/defineTable.d.ts +221 -0
- package/dist/resources/defineTable.js +227 -0
- package/dist/resources/defineTable.js.map +1 -0
- package/dist/resources/jsonSchemaTypes.d.ts +2 -0
- package/dist/resources/jsonSchemaTypes.js +12 -4
- package/dist/resources/jsonSchemaTypes.js.map +1 -1
- package/dist/resources/openApi.js +69 -13
- package/dist/resources/openApi.js.map +1 -1
- package/dist/resources/search.js +6 -8
- package/dist/resources/search.js.map +1 -1
- package/dist/server/graphqlQuerying.js +4 -2
- package/dist/server/graphqlQuerying.js.map +1 -1
- package/dist/server/http.d.ts +12 -0
- package/dist/server/http.js +35 -15
- package/dist/server/http.js.map +1 -1
- package/dist/server/serverHelpers/serverUtilities.js +8 -5
- package/dist/server/serverHelpers/serverUtilities.js.map +1 -1
- package/dist/server/serverHelpers/uwsServer.js +23 -0
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/utility/errors/hdbError.d.ts +21 -0
- package/dist/utility/errors/hdbError.js +23 -1
- package/dist/utility/errors/hdbError.js.map +1 -1
- package/dist/validation/configValidator.js +22 -6
- package/dist/validation/configValidator.js.map +1 -1
- package/index.ts +33 -0
- package/npm-shrinkwrap.json +9197 -15236
- package/package.json +5 -3
- package/resources/DESIGN.md +42 -15
- package/resources/Resource.ts +99 -2
- package/resources/Table.ts +275 -71
- package/resources/analytics/read.ts +30 -25
- package/resources/defineResource.ts +651 -0
- package/resources/defineTable.ts +407 -0
- package/resources/jsonSchemaTypes.ts +12 -4
- package/resources/openApi.ts +68 -16
- package/resources/search.ts +5 -8
- package/server/graphqlQuerying.ts +4 -2
- package/server/http.ts +40 -16
- package/server/serverHelpers/serverUtilities.ts +19 -6
- package/server/serverHelpers/uwsServer.ts +24 -0
- package/studio/web/assets/{Chat-D4FIaBu7.js → Chat-CTjtL8Z4.js} +2 -2
- package/studio/web/assets/{Chat-D4FIaBu7.js.map → Chat-CTjtL8Z4.js.map} +1 -1
- package/studio/web/assets/{FloatingChat-DGUC3L4r.js → FloatingChat-CafHR4Ur.js} +4 -4
- package/studio/web/assets/{FloatingChat-DGUC3L4r.js.map → FloatingChat-CafHR4Ur.js.map} +1 -1
- package/studio/web/assets/{applications-D8Am9ikM.js → applications-Buh_q0Vj.js} +2 -2
- package/studio/web/assets/{applications-D8Am9ikM.js.map → applications-Buh_q0Vj.js.map} +1 -1
- package/studio/web/assets/{index-HGL4WHdb.js → index-0hXeECkS.js} +6 -6
- package/studio/web/assets/{index-HGL4WHdb.js.map → index-0hXeECkS.js.map} +1 -1
- package/studio/web/assets/{index.lazy-Dk5j1AoQ.js → index.lazy-B00B7VBT.js} +4 -4
- package/studio/web/assets/{index.lazy-Dk5j1AoQ.js.map → index.lazy-B00B7VBT.js.map} +1 -1
- package/studio/web/assets/{profile-7bu_CF1f.js → profile-Cg2wwYPn.js} +2 -2
- package/studio/web/assets/{profile-7bu_CF1f.js.map → profile-Cg2wwYPn.js.map} +1 -1
- package/studio/web/assets/{setComponentFile-MfYm9F94.js → setComponentFile-DCaDIvyB.js} +2 -2
- package/studio/web/assets/{setComponentFile-MfYm9F94.js.map → setComponentFile-DCaDIvyB.js.map} +1 -1
- package/studio/web/assets/{setup-SKA4UhdE.js → setup-CAVcAQjK.js} +2 -2
- package/studio/web/assets/{setup-SKA4UhdE.js.map → setup-CAVcAQjK.js.map} +1 -1
- package/studio/web/assets/{status-DetVLUxR.js → status-BRXorNdD.js} +2 -2
- package/studio/web/assets/{status-DetVLUxR.js.map → status-BRXorNdD.js.map} +1 -1
- package/studio/web/assets/{swagger-ui-react-DLeYARY2.js → swagger-ui-react-Dy1D62vO.js} +2 -2
- package/studio/web/assets/{swagger-ui-react-DLeYARY2.js.map → swagger-ui-react-Dy1D62vO.js.map} +1 -1
- package/studio/web/assets/{tsMode-DGO-jIF7.js → tsMode-A8gbL74v.js} +2 -2
- package/studio/web/assets/{tsMode-DGO-jIF7.js.map → tsMode-A8gbL74v.js.map} +1 -1
- package/studio/web/assets/{useEntityRestURL-4M2i6bo4.js → useEntityRestURL-cDodrVcQ.js} +2 -2
- package/studio/web/assets/{useEntityRestURL-4M2i6bo4.js.map → useEntityRestURL-cDodrVcQ.js.map} +1 -1
- package/studio/web/index.html +1 -1
- package/utility/errors/hdbError.ts +32 -0
- package/validation/configValidator.ts +23 -6
|
@@ -8,6 +8,7 @@ import { isDeepStrictEqual } from 'util';
|
|
|
8
8
|
import { DEFAULT_CONFIG } from './DEFAULT_CONFIG.ts';
|
|
9
9
|
import { cloneDeep } from 'lodash';
|
|
10
10
|
import { POLLING_FALLBACK_OPTIONS, isWatcherExhaustionError, warnWatcherFallback } from '../utility/watcherFallback.ts';
|
|
11
|
+
import { overlayRootEnvConfig, isRootConfigFilename } from '../config/harperConfigEnvVars.ts';
|
|
11
12
|
|
|
12
13
|
export interface Config {
|
|
13
14
|
[key: string]: ConfigValue;
|
|
@@ -86,6 +87,7 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
86
87
|
#watcher!: FSWatcher;
|
|
87
88
|
#scopedConfig?: ConfigValue;
|
|
88
89
|
#rootConfig?: Config;
|
|
90
|
+
#isRootConfig: boolean;
|
|
89
91
|
#name: string;
|
|
90
92
|
#logger: Logger;
|
|
91
93
|
#usingPolling: boolean;
|
|
@@ -94,10 +96,14 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
94
96
|
#pendingReads: Set<Promise<void>> = new Set();
|
|
95
97
|
ready: Promise<any[]>;
|
|
96
98
|
|
|
97
|
-
constructor(name: string, filePath: string, logger?: Logger) {
|
|
99
|
+
constructor(name: string, filePath: string, logger?: Logger, isRootConfig?: boolean) {
|
|
98
100
|
super();
|
|
99
101
|
this.#name = name;
|
|
100
102
|
this.#filePath = filePath;
|
|
103
|
+
// Root-config watchers must see runtime env config (HARPER_SET_CONFIG et al.)
|
|
104
|
+
// even when it hasn't been flushed to disk yet — see #handleChange (#1618).
|
|
105
|
+
// Application scopes watch their own config.yaml and are never overlaid.
|
|
106
|
+
this.#isRootConfig = isRootConfig ?? isRootConfigFilename(filePath);
|
|
101
107
|
this.#logger = logger || loggerWithTag(name);
|
|
102
108
|
this.#usingPolling = false;
|
|
103
109
|
this.#closed = false;
|
|
@@ -122,7 +128,15 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
122
128
|
#handleChange() {
|
|
123
129
|
const read: Promise<void> = readFile(this.#filePath, 'utf-8')
|
|
124
130
|
.then((contents) => {
|
|
125
|
-
|
|
131
|
+
let parsed = yaml.parse(contents);
|
|
132
|
+
// The on-disk root config is not guaranteed to include runtime env config at
|
|
133
|
+
// boot: the file flush races component loading, so a scope's boot-time reads
|
|
134
|
+
// (e.g. an `enabled` gate in handleApplication) could observe pre-env values
|
|
135
|
+
// the componentLoader itself never saw. Ask the config layer to overlay env
|
|
136
|
+
// config onto EVERY root-config read so scope.options matches the resolved
|
|
137
|
+
// view (#1618). Non-root scopes and the no-env-vars case are untouched
|
|
138
|
+
// (overlayRootEnvConfig is a no-op there).
|
|
139
|
+
if (this.#isRootConfig) parsed = overlayRootEnvConfig(parsed);
|
|
126
140
|
this.#rootConfig = parsed && typeof parsed === 'object' ? parsed : undefined;
|
|
127
141
|
// If the extension is in the config file
|
|
128
142
|
if (this.#rootConfig && this.#name in this.#rootConfig) {
|
|
@@ -150,6 +164,14 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
150
164
|
.catch((error) => {
|
|
151
165
|
// If the config file does not exist
|
|
152
166
|
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
167
|
+
// A readFile ENOENT here is the install window (file not written yet) or a
|
|
168
|
+
// transient read race — NOT a real deletion, which chokidar routes to
|
|
169
|
+
// `#handleUnlink`. Env config is file-independent, so when it provides this
|
|
170
|
+
// scope the missing file must not discard it (#1618). When it does not, fall
|
|
171
|
+
// through to the original ENOENT handling with #rootConfig untouched, so a
|
|
172
|
+
// first boot still emits `ready` (not `remove`, which nothing consumes at
|
|
173
|
+
// boot → `ready` would hang forever).
|
|
174
|
+
if (this.#applyEnvOnlyConfig()) return;
|
|
153
175
|
// And a config already exists, reset it to the default
|
|
154
176
|
if (this.#rootConfig) {
|
|
155
177
|
this.#resetConfig();
|
|
@@ -196,6 +218,15 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
196
218
|
}
|
|
197
219
|
|
|
198
220
|
#handleUnlink(path: string) {
|
|
221
|
+
// A real deletion still leaves env-var config in force: an env-defined scope must
|
|
222
|
+
// survive it exactly as on the ENOENT read path — same fallback, same error routing
|
|
223
|
+
// (#1618, #1726 review).
|
|
224
|
+
if (this.#applyEnvOnlyConfig()) {
|
|
225
|
+
this.#logger.warn?.(
|
|
226
|
+
`Configuration file ${path} was deleted; the env-var-defined configuration for '${this.#name}' remains in effect.`
|
|
227
|
+
);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
199
230
|
this.#logger.warn?.(
|
|
200
231
|
`Configuration file ${path} was deleted. Reverting to default configuration. Recreate it to restore the options watcher.`
|
|
201
232
|
);
|
|
@@ -203,6 +234,35 @@ export class OptionsWatcher extends EventEmitter<OptionsWatcherEventMap> {
|
|
|
203
234
|
this.emit('remove');
|
|
204
235
|
}
|
|
205
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Shared fallback for the ENOENT read path and `#handleUnlink`: when config env vars
|
|
239
|
+
* define this scope, apply the env-only overlay (first application → `ready`; already
|
|
240
|
+
* configured → `merge`, never reset). Returns true when the event was handled —
|
|
241
|
+
* including the malformed-env case, which routes to `error` like the file-read path
|
|
242
|
+
* rather than an unhandled rejection. Returns false (root config untouched) when this
|
|
243
|
+
* is not a root config or the env config does not provide the scope, so callers keep
|
|
244
|
+
* their own reset semantics.
|
|
245
|
+
*/
|
|
246
|
+
#applyEnvOnlyConfig(): boolean {
|
|
247
|
+
if (!this.#isRootConfig) return false;
|
|
248
|
+
let composed: Config | undefined;
|
|
249
|
+
try {
|
|
250
|
+
composed = overlayRootEnvConfig(undefined) as Config | undefined;
|
|
251
|
+
} catch (composeError) {
|
|
252
|
+
this.emit('error', composeError);
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
if (!composed || !(this.#name in composed)) return false;
|
|
256
|
+
this.#rootConfig = composed;
|
|
257
|
+
if (!this.#scopedConfig) {
|
|
258
|
+
this.#scopedConfig = composed[this.#name];
|
|
259
|
+
this.emit('ready', this.#scopedConfig);
|
|
260
|
+
} else {
|
|
261
|
+
this.#merge(composed[this.#name], this.#scopedConfig);
|
|
262
|
+
}
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
|
|
206
266
|
#resetConfig() {
|
|
207
267
|
this.#rootConfig = DEFAULT_CONFIG;
|
|
208
268
|
this.#scopedConfig = this.#rootConfig[this.#name];
|
package/components/Scope.ts
CHANGED
|
@@ -12,7 +12,12 @@ import { FilesOption } from './deriveGlobOptions.ts';
|
|
|
12
12
|
import { requestRestart } from './requestRestart.ts';
|
|
13
13
|
import { resolveBaseURLPath } from './resolveBaseURLPath.ts';
|
|
14
14
|
import { ApplicationScope } from './ApplicationScope.ts';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
getSecretsForComponent,
|
|
17
|
+
retainComponentSubscriptions,
|
|
18
|
+
releaseComponentSubscriptions,
|
|
19
|
+
} from './componentSecrets.ts';
|
|
20
|
+
import type { SecretsView } from './componentSecrets.ts';
|
|
16
21
|
import { deployLifecycle } from './deployLifecycle.ts';
|
|
17
22
|
|
|
18
23
|
export class MissingDefaultFilesOptionError extends Error {
|
|
@@ -54,6 +59,7 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
54
59
|
#entryHandler?: EntryHandler;
|
|
55
60
|
#entryHandlers: EntryHandler[];
|
|
56
61
|
#logger: Logger;
|
|
62
|
+
#secretsReleased = false;
|
|
57
63
|
#pendingInitialLoads: Set<Promise<void>>;
|
|
58
64
|
#deployStartHandler: (name: string) => void;
|
|
59
65
|
#deployEndHandler: (name: string) => void;
|
|
@@ -77,7 +83,8 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
77
83
|
directory: string,
|
|
78
84
|
configFilePath: string,
|
|
79
85
|
applicationScope: ApplicationScope,
|
|
80
|
-
origin: string = appName
|
|
86
|
+
origin: string = appName,
|
|
87
|
+
isRootConfig?: boolean
|
|
81
88
|
) {
|
|
82
89
|
super();
|
|
83
90
|
|
|
@@ -90,6 +97,9 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
90
97
|
|
|
91
98
|
this.databaseEvents = databaseEventsEmitter;
|
|
92
99
|
this.applicationScope = applicationScope;
|
|
100
|
+
// Hold this identity's live secret subscriptions (#1776) for as long as this Scope is open, so a
|
|
101
|
+
// throwaway deploy-validation Scope closing can't tear down a sibling/running Scope's streams.
|
|
102
|
+
retainComponentSubscriptions(applicationScope?.name ?? appName);
|
|
93
103
|
this.resources = applicationScope?.resources ?? resources;
|
|
94
104
|
this.models = modelsSingleton;
|
|
95
105
|
|
|
@@ -125,7 +135,10 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
125
135
|
this.ready = once(this, 'ready');
|
|
126
136
|
|
|
127
137
|
// Create the options instance for the scope immediately
|
|
128
|
-
|
|
138
|
+
// isRootConfig is the loader's authoritative isRoot signal — it decides whether the
|
|
139
|
+
// watcher overlays runtime env config (#1618). When a caller doesn't provide it,
|
|
140
|
+
// OptionsWatcher falls back to its root-config filename heuristic.
|
|
141
|
+
this.options = new OptionsWatcher(pluginName, configFilePath, this.#logger, isRootConfig)
|
|
129
142
|
.on('error', this.#handleError.bind(this))
|
|
130
143
|
.on('change', this.#optionsWatcherChangeListener.bind(this)())
|
|
131
144
|
.on('ready', this.#handleOptionsWatcherReady.bind(this));
|
|
@@ -149,12 +162,13 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
149
162
|
|
|
150
163
|
/**
|
|
151
164
|
* The application's secrets view (#1550): hdb_secret rows granted to this application plus its
|
|
152
|
-
* declared global-tier env names.
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
165
|
+
* declared global-tier env names. A live, read-only view (#1776) — scoped values reflect the latest
|
|
166
|
+
* store state on each read and it carries the reserved `subscribe(name)` method. Keyed by the
|
|
167
|
+
* ApplicationScope's name (the application directory name — the identity grants and env declarations
|
|
168
|
+
* use, and the same binding `import { secrets } from 'harper'` resolves); `#appName` can differ on
|
|
169
|
+
* paths like RUN_HDB_APP, where it is the full directory path.
|
|
156
170
|
*/
|
|
157
|
-
get secrets():
|
|
171
|
+
get secrets(): SecretsView {
|
|
158
172
|
return getSecretsForComponent(this.applicationScope?.name ?? this.#appName);
|
|
159
173
|
}
|
|
160
174
|
|
|
@@ -223,6 +237,15 @@ export class Scope extends EventEmitter<ScopeEventsMap> {
|
|
|
223
237
|
|
|
224
238
|
this.removeAllListeners();
|
|
225
239
|
|
|
240
|
+
// Release this identity's subscription hold (#1776), AFTER the close listeners (so a subscription a
|
|
241
|
+
// close listener created is still accounted for). Streams end only when the LAST holder of the
|
|
242
|
+
// identity releases — so a discarded validation-load Scope can't kill a still-running app's streams.
|
|
243
|
+
// Guarded so a double close() can't underflow the refcount.
|
|
244
|
+
if (!this.#secretsReleased) {
|
|
245
|
+
this.#secretsReleased = true;
|
|
246
|
+
releaseComponentSubscriptions(this.applicationScope?.name ?? this.#appName);
|
|
247
|
+
}
|
|
248
|
+
|
|
226
249
|
return this;
|
|
227
250
|
}
|
|
228
251
|
|
|
@@ -548,7 +548,11 @@ export async function loadComponent(
|
|
|
548
548
|
componentDirectory,
|
|
549
549
|
configPath,
|
|
550
550
|
applicationScope,
|
|
551
|
-
origin
|
|
551
|
+
origin,
|
|
552
|
+
// authoritative root-ness: only root-load scopes watch THE root config and
|
|
553
|
+
// get the runtime env-config overlay (#1618) — an app component that happens
|
|
554
|
+
// to ship a root-named config file does not
|
|
555
|
+
isRoot
|
|
552
556
|
);
|
|
553
557
|
|
|
554
558
|
if (options.collectScopes) {
|