ptech-shell-dev 1.7.0 → 1.8.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.
- package/dist/index.d.ts +70 -2
- package/dist/index.js +126 -4
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LogLevel, RealtimeEnvelope, UserService, RequestContextService, RealtimeService, Lang, User, I18nService, ApiClient, NavigationService, ConfigService, PermissionService, SharedStateService, ObservabilityService, NotificationService, AnalyticsService, ObservabilityConfigPatch, ApiErrorPayload, ApiValidationErrors, ApiRetryOptions, MsalAccountInfoLike, NavigationAction, NavigationTo, NavigationNavigateOptions } from 'ptech-shell-sdk';
|
|
1
|
+
import { LogLevel, RealtimeEnvelope, UserService, RequestContextService, RealtimeService, Lang, User, I18nService, ApiClient, NavigationService, ConfigService, PermissionService, SharedStateService, ObservabilityService, NotificationService, AnalyticsService, TenantService, AppSettingsService, ObservabilityConfigPatch, AppSettings, ApiErrorPayload, ApiValidationErrors, ApiRetryOptions, MsalAccountInfoLike, NavigationAction, NavigationTo, NavigationNavigateOptions } from 'ptech-shell-sdk';
|
|
2
2
|
|
|
3
3
|
type ObservabilityTelemetryEvent = {
|
|
4
4
|
level: LogLevel;
|
|
@@ -74,6 +74,8 @@ type StandaloneServices = {
|
|
|
74
74
|
observability: ObservabilityService;
|
|
75
75
|
notification: NotificationService;
|
|
76
76
|
analytics: AnalyticsService;
|
|
77
|
+
tenantService: TenantService;
|
|
78
|
+
appSettingsService: AppSettingsService;
|
|
77
79
|
};
|
|
78
80
|
type ServiceRegisterMode = 'if-missing' | 'always';
|
|
79
81
|
type StandaloneInitOptions = {
|
|
@@ -135,6 +137,23 @@ type StandaloneInitOptions = {
|
|
|
135
137
|
envName?: string;
|
|
136
138
|
apiBase?: string;
|
|
137
139
|
};
|
|
140
|
+
/**
|
|
141
|
+
* Seed values for the standalone tenant service.
|
|
142
|
+
* Defaults to `{ tenantId: 'dev-tenant', tenantSlug: 'dev' }`.
|
|
143
|
+
*/
|
|
144
|
+
tenant?: {
|
|
145
|
+
tenantId?: string | null;
|
|
146
|
+
tenantSlug?: string | null;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Seed/loader for the standalone app settings service.
|
|
150
|
+
* - `seed`: static per-appKey map returned by `load()`.
|
|
151
|
+
* - `fetcher`: override that takes precedence over seed.
|
|
152
|
+
*/
|
|
153
|
+
appSettings?: {
|
|
154
|
+
seed?: Readonly<Record<string, AppSettings>>;
|
|
155
|
+
fetcher?: (appKey: string) => Promise<AppSettings>;
|
|
156
|
+
};
|
|
138
157
|
};
|
|
139
158
|
|
|
140
159
|
/**
|
|
@@ -182,6 +201,12 @@ type CreateStandaloneApiClientOptions = {
|
|
|
182
201
|
*/
|
|
183
202
|
getRequestContext?: () => RequestContextService | undefined;
|
|
184
203
|
requestContext?: RequestContextService;
|
|
204
|
+
/**
|
|
205
|
+
* Optional dynamic lookup for tenant service; header `X-Tenant-Id` is injected
|
|
206
|
+
* when the resolved snapshot has a non-empty `tenantId`.
|
|
207
|
+
*/
|
|
208
|
+
getTenantService?: () => TenantService | undefined;
|
|
209
|
+
tenantService?: TenantService;
|
|
185
210
|
defaultAuthScopes?: string[];
|
|
186
211
|
defaultTimeoutMs?: number;
|
|
187
212
|
defaultRetries?: ApiRetryOptions | false;
|
|
@@ -233,6 +258,32 @@ declare function isApiError(value: unknown): value is ApiError;
|
|
|
233
258
|
*/
|
|
234
259
|
declare function createStandaloneApiClient(options: string | CreateStandaloneApiClientOptions): ApiClient;
|
|
235
260
|
|
|
261
|
+
type CreateStandaloneAppSettingsServiceOptions = {
|
|
262
|
+
/**
|
|
263
|
+
* Static seed settings keyed by appKey.
|
|
264
|
+
* Returned instantly from `load()` and `get()` for dev/test scenarios.
|
|
265
|
+
*/
|
|
266
|
+
seed?: Readonly<Record<string, AppSettings>>;
|
|
267
|
+
/**
|
|
268
|
+
* Optional async loader, overrides seed when provided.
|
|
269
|
+
* Useful when tests want to simulate latency or network failures.
|
|
270
|
+
*/
|
|
271
|
+
fetcher?: (appKey: string) => Promise<AppSettings>;
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* WHY:
|
|
275
|
+
* - In-memory per-appKey settings store for standalone remote development.
|
|
276
|
+
* WHEN TO USE:
|
|
277
|
+
* - Use via initStandaloneServices so remotes can call `load(appKey)` without a host.
|
|
278
|
+
* WHEN NOT TO USE:
|
|
279
|
+
* - Do not use in production — host fetches from backend and owns cache invalidation.
|
|
280
|
+
* INVARIANTS:
|
|
281
|
+
* - `get()` returns null until `load()` resolves for that appKey.
|
|
282
|
+
* - `invalidate()` with no args drops all cached entries.
|
|
283
|
+
* - Listeners are scoped per appKey; invalidate emits for affected keys only.
|
|
284
|
+
*/
|
|
285
|
+
declare function createStandaloneAppSettingsService(options?: CreateStandaloneAppSettingsServiceOptions): AppSettingsService;
|
|
286
|
+
|
|
236
287
|
type UiApiError = {
|
|
237
288
|
i18nKey: string;
|
|
238
289
|
params: Record<string, string | number>;
|
|
@@ -401,6 +452,23 @@ type CreateRequestContextServiceOptions = {
|
|
|
401
452
|
*/
|
|
402
453
|
declare function createRequestContextService(options?: CreateRequestContextServiceOptions): RequestContextService;
|
|
403
454
|
|
|
455
|
+
type CreateStandaloneTenantServiceOptions = {
|
|
456
|
+
tenantId?: string | null;
|
|
457
|
+
tenantSlug?: string | null;
|
|
458
|
+
};
|
|
459
|
+
/**
|
|
460
|
+
* WHY:
|
|
461
|
+
* - Provides a minimal in-memory TenantService for standalone remote dev.
|
|
462
|
+
* WHEN TO USE:
|
|
463
|
+
* - Use via initStandaloneServices when a remote runs without host.
|
|
464
|
+
* WHEN NOT TO USE:
|
|
465
|
+
* - Do not use in production — host registers its own tenant service.
|
|
466
|
+
* INVARIANTS:
|
|
467
|
+
* - getSnapshot returns a copy, never the mutable internal reference.
|
|
468
|
+
* - setTenant emits only when either field actually changes.
|
|
469
|
+
*/
|
|
470
|
+
declare function createStandaloneTenantService(options?: CreateStandaloneTenantServiceOptions): TenantService;
|
|
471
|
+
|
|
404
472
|
/**
|
|
405
473
|
* WHY:
|
|
406
474
|
* - Provides mock user/session/auth token behavior for standalone shell development.
|
|
@@ -415,4 +483,4 @@ declare function createRequestContextService(options?: CreateRequestContextServi
|
|
|
415
483
|
*/
|
|
416
484
|
declare function createStandaloneUserService(seedUser: User | null): UserService;
|
|
417
485
|
|
|
418
|
-
export { ApiError, type CreateMsalUserServiceOptions, type CreateReactRouterNavigationAdapterOptions, type CreateStandaloneApiClientOptions, type CreateStandaloneObservabilityServiceOptions, type CreateStandaloneRealtimeServiceOptions, type MsalBrowserInstanceLike, type ObservabilityTelemetryEvent, type ObservabilityTelemetrySink, type ReactRouterCreateHrefFunctionLike, type ReactRouterLocationLike, type ReactRouterNavigateFunctionLike, type ReactRouterNavigationAdapter, type ReactRouterNavigationCapabilities, type RealtimeReconnectOptions, type RealtimeTransport, type RealtimeTransportConnectContext, type ServiceRegisterMode, type StandaloneInitOptions, type StandaloneServices, type UiApiError, createDevPreset, createMsalUserService, createReactRouterNavigationAdapter, createRequestContextService, createStandaloneApiClient, createStandaloneI18nService, createStandaloneRealtimeService, createStandaloneUserService, createTestServices, initStandaloneServices, isApiError, mapApiErrorToUiError };
|
|
486
|
+
export { ApiError, type CreateMsalUserServiceOptions, type CreateReactRouterNavigationAdapterOptions, type CreateStandaloneApiClientOptions, type CreateStandaloneObservabilityServiceOptions, type CreateStandaloneRealtimeServiceOptions, type MsalBrowserInstanceLike, type ObservabilityTelemetryEvent, type ObservabilityTelemetrySink, type ReactRouterCreateHrefFunctionLike, type ReactRouterLocationLike, type ReactRouterNavigateFunctionLike, type ReactRouterNavigationAdapter, type ReactRouterNavigationCapabilities, type RealtimeReconnectOptions, type RealtimeTransport, type RealtimeTransportConnectContext, type ServiceRegisterMode, type StandaloneInitOptions, type StandaloneServices, type UiApiError, createDevPreset, createMsalUserService, createReactRouterNavigationAdapter, createRequestContextService, createStandaloneApiClient, createStandaloneAppSettingsService, createStandaloneI18nService, createStandaloneRealtimeService, createStandaloneTenantService, createStandaloneUserService, createTestServices, initStandaloneServices, isApiError, mapApiErrorToUiError };
|
package/dist/index.js
CHANGED
|
@@ -66,6 +66,7 @@ var DEFAULT_RETRY_OPTIONS = {
|
|
|
66
66
|
var TRACE_HEADER = "traceparent";
|
|
67
67
|
var CORRELATION_HEADER = "x-correlation-id";
|
|
68
68
|
var CORRELATION_HEADERS = ["x-correlation-id", "x-request-id"];
|
|
69
|
+
var TENANT_HEADER = "x-tenant-id";
|
|
69
70
|
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
70
71
|
function isApiError(value) {
|
|
71
72
|
return value instanceof ApiError;
|
|
@@ -418,6 +419,7 @@ function resolveCreateOptions(input) {
|
|
|
418
419
|
getUserService: input.getUserService ?? (input.userService ? () => input.userService : void 0),
|
|
419
420
|
getNotificationService: input.getNotificationService ?? (input.notificationService ? () => input.notificationService : void 0),
|
|
420
421
|
getRequestContext: input.getRequestContext ?? (input.requestContext ? () => input.requestContext : void 0),
|
|
422
|
+
getTenantService: input.getTenantService ?? (input.tenantService ? () => input.tenantService : void 0),
|
|
421
423
|
defaultAuthScopes: input.defaultAuthScopes ?? [],
|
|
422
424
|
defaultTimeoutMs: input.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS,
|
|
423
425
|
defaultRetries: input.defaultRetries ?? DEFAULT_RETRY_OPTIONS
|
|
@@ -439,6 +441,19 @@ function applyRequestContextHeaders(headers, options) {
|
|
|
439
441
|
headers.set(CORRELATION_HEADER, context.correlationId);
|
|
440
442
|
}
|
|
441
443
|
}
|
|
444
|
+
function applyTenantHeader(headers, options) {
|
|
445
|
+
if (headers.has(TENANT_HEADER)) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
const tenantService = options.getTenantService?.();
|
|
449
|
+
if (!tenantService) {
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
const tenantId = tenantService.getSnapshot().tenantId;
|
|
453
|
+
if (tenantId && tenantId.length > 0) {
|
|
454
|
+
headers.set(TENANT_HEADER, tenantId);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
442
457
|
function syncResponseContext(response, options) {
|
|
443
458
|
const contextService = options.getRequestContext?.();
|
|
444
459
|
if (!contextService) {
|
|
@@ -531,6 +546,7 @@ async function executeRaw(requestOptions, options) {
|
|
|
531
546
|
const timeoutMs = requestOptions.timeoutMs ?? options.defaultTimeoutMs;
|
|
532
547
|
const headers = new Headers(requestOptions.headers);
|
|
533
548
|
applyRequestContextHeaders(headers, options);
|
|
549
|
+
applyTenantHeader(headers, options);
|
|
534
550
|
await applyAuthorization(headers, requestOptions, options);
|
|
535
551
|
const url = resolveUrl(options.apiBase, requestOptions.url);
|
|
536
552
|
const body = resolveBody(requestOptions.body, headers);
|
|
@@ -611,6 +627,7 @@ function createStandaloneApiClient(options) {
|
|
|
611
627
|
fetch: async (input, init) => {
|
|
612
628
|
const headers = new Headers(init?.headers);
|
|
613
629
|
applyRequestContextHeaders(headers, resolvedOptions);
|
|
630
|
+
applyTenantHeader(headers, resolvedOptions);
|
|
614
631
|
await applyAuthorization(
|
|
615
632
|
headers,
|
|
616
633
|
{
|
|
@@ -645,6 +662,69 @@ function createStandaloneApiClient(options) {
|
|
|
645
662
|
};
|
|
646
663
|
}
|
|
647
664
|
|
|
665
|
+
// src/services/appSettings.ts
|
|
666
|
+
function createStandaloneAppSettingsService(options = {}) {
|
|
667
|
+
const cache = /* @__PURE__ */ new Map();
|
|
668
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
669
|
+
function emit(appKey) {
|
|
670
|
+
const group = listeners.get(appKey);
|
|
671
|
+
if (!group) return;
|
|
672
|
+
for (const listener of group) {
|
|
673
|
+
listener();
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
async function resolveSettings(appKey) {
|
|
677
|
+
if (options.fetcher) {
|
|
678
|
+
return options.fetcher(appKey);
|
|
679
|
+
}
|
|
680
|
+
return options.seed?.[appKey] ?? {};
|
|
681
|
+
}
|
|
682
|
+
return {
|
|
683
|
+
get: (appKey) => cache.get(appKey) ?? null,
|
|
684
|
+
load: async (appKey) => {
|
|
685
|
+
const existing = cache.get(appKey);
|
|
686
|
+
if (existing) {
|
|
687
|
+
return existing;
|
|
688
|
+
}
|
|
689
|
+
const settings = await resolveSettings(appKey);
|
|
690
|
+
const snapshot = {
|
|
691
|
+
settings,
|
|
692
|
+
version: 1
|
|
693
|
+
};
|
|
694
|
+
cache.set(appKey, snapshot);
|
|
695
|
+
emit(appKey);
|
|
696
|
+
return snapshot;
|
|
697
|
+
},
|
|
698
|
+
subscribe: (appKey, listener) => {
|
|
699
|
+
let group = listeners.get(appKey);
|
|
700
|
+
if (!group) {
|
|
701
|
+
group = /* @__PURE__ */ new Set();
|
|
702
|
+
listeners.set(appKey, group);
|
|
703
|
+
}
|
|
704
|
+
group.add(listener);
|
|
705
|
+
return () => {
|
|
706
|
+
group?.delete(listener);
|
|
707
|
+
if (group && group.size === 0) {
|
|
708
|
+
listeners.delete(appKey);
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
},
|
|
712
|
+
invalidate: (appKey) => {
|
|
713
|
+
if (appKey === void 0) {
|
|
714
|
+
const affected = Array.from(cache.keys());
|
|
715
|
+
cache.clear();
|
|
716
|
+
for (const key of affected) {
|
|
717
|
+
emit(key);
|
|
718
|
+
}
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
if (cache.delete(appKey)) {
|
|
722
|
+
emit(appKey);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
};
|
|
726
|
+
}
|
|
727
|
+
|
|
648
728
|
// src/services/config.ts
|
|
649
729
|
import { FEATURE_FLAGS } from "ptech-shell-sdk";
|
|
650
730
|
var DEFAULT_FLAGS = {
|
|
@@ -1530,6 +1610,37 @@ function createStandaloneSharedStateService() {
|
|
|
1530
1610
|
};
|
|
1531
1611
|
}
|
|
1532
1612
|
|
|
1613
|
+
// src/services/tenant.ts
|
|
1614
|
+
function createStandaloneTenantService(options = {}) {
|
|
1615
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1616
|
+
let snapshot = {
|
|
1617
|
+
tenantId: options.tenantId ?? "dev-tenant",
|
|
1618
|
+
tenantSlug: options.tenantSlug ?? "dev"
|
|
1619
|
+
};
|
|
1620
|
+
function emit() {
|
|
1621
|
+
for (const listener of listeners) {
|
|
1622
|
+
listener();
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
return {
|
|
1626
|
+
getSnapshot: () => ({ ...snapshot }),
|
|
1627
|
+
setTenant: (tenantId, tenantSlug) => {
|
|
1628
|
+
if (tenantId === snapshot.tenantId && tenantSlug === snapshot.tenantSlug) {
|
|
1629
|
+
return { ...snapshot };
|
|
1630
|
+
}
|
|
1631
|
+
snapshot = { tenantId, tenantSlug };
|
|
1632
|
+
emit();
|
|
1633
|
+
return { ...snapshot };
|
|
1634
|
+
},
|
|
1635
|
+
subscribe: (listener) => {
|
|
1636
|
+
listeners.add(listener);
|
|
1637
|
+
return () => {
|
|
1638
|
+
listeners.delete(listener);
|
|
1639
|
+
};
|
|
1640
|
+
}
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1533
1644
|
// src/services/user.ts
|
|
1534
1645
|
function createStandaloneUserService(seedUser) {
|
|
1535
1646
|
const listeners = /* @__PURE__ */ new Set();
|
|
@@ -1604,11 +1715,15 @@ function createTestServices(options = {}) {
|
|
|
1604
1715
|
realtime: realtimeOptions,
|
|
1605
1716
|
navigationPath = "/standalone",
|
|
1606
1717
|
featureFlags = {},
|
|
1607
|
-
runtimeConfig = {}
|
|
1718
|
+
runtimeConfig = {},
|
|
1719
|
+
tenant,
|
|
1720
|
+
appSettings
|
|
1608
1721
|
} = options;
|
|
1609
1722
|
const userService = createStandaloneUserService(user ?? null);
|
|
1610
1723
|
const notificationService = createStandaloneNotificationService();
|
|
1611
1724
|
const requestContext = createRequestContextService();
|
|
1725
|
+
const tenantService = createStandaloneTenantService(tenant);
|
|
1726
|
+
const appSettingsService = createStandaloneAppSettingsService(appSettings);
|
|
1612
1727
|
return {
|
|
1613
1728
|
i18n: createStandaloneI18nService(lang),
|
|
1614
1729
|
userService,
|
|
@@ -1616,7 +1731,8 @@ function createTestServices(options = {}) {
|
|
|
1616
1731
|
apiBase,
|
|
1617
1732
|
getUserService: () => getService(TOKENS.userService) ?? userService,
|
|
1618
1733
|
notificationService,
|
|
1619
|
-
requestContext
|
|
1734
|
+
requestContext,
|
|
1735
|
+
tenantService
|
|
1620
1736
|
}),
|
|
1621
1737
|
navigation: createStandaloneNavigationService(navigationPath),
|
|
1622
1738
|
configService: createStandaloneConfigService(
|
|
@@ -1636,7 +1752,9 @@ function createTestServices(options = {}) {
|
|
|
1636
1752
|
getTraceContext: () => requestContext.getSnapshot()
|
|
1637
1753
|
}),
|
|
1638
1754
|
notification: notificationService,
|
|
1639
|
-
analytics: createStandaloneAnalyticsService()
|
|
1755
|
+
analytics: createStandaloneAnalyticsService(),
|
|
1756
|
+
tenantService,
|
|
1757
|
+
appSettingsService
|
|
1640
1758
|
};
|
|
1641
1759
|
}
|
|
1642
1760
|
function initStandaloneServices(options = {}) {
|
|
@@ -1665,7 +1783,9 @@ function initStandaloneServices(options = {}) {
|
|
|
1665
1783
|
[TOKENS.realtime, services.realtime],
|
|
1666
1784
|
[TOKENS.observability, services.observability],
|
|
1667
1785
|
[TOKENS.notification, services.notification],
|
|
1668
|
-
[TOKENS.analytics, services.analytics]
|
|
1786
|
+
[TOKENS.analytics, services.analytics],
|
|
1787
|
+
[TOKENS.tenantService, services.tenantService],
|
|
1788
|
+
[TOKENS.appSettingsService, services.appSettingsService]
|
|
1669
1789
|
];
|
|
1670
1790
|
for (const [token, service] of tokenServiceMap) {
|
|
1671
1791
|
if (registerMode === "always" || !getService(token)) {
|
|
@@ -2167,8 +2287,10 @@ export {
|
|
|
2167
2287
|
createReactRouterNavigationAdapter,
|
|
2168
2288
|
createRequestContextService,
|
|
2169
2289
|
createStandaloneApiClient,
|
|
2290
|
+
createStandaloneAppSettingsService,
|
|
2170
2291
|
createStandaloneI18nService,
|
|
2171
2292
|
createStandaloneRealtimeService,
|
|
2293
|
+
createStandaloneTenantService,
|
|
2172
2294
|
createStandaloneUserService,
|
|
2173
2295
|
createTestServices,
|
|
2174
2296
|
initStandaloneServices,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ptech-shell-dev",
|
|
3
|
-
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Standalone/mock shell service implementations for Module Federation apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,17 +23,17 @@
|
|
|
23
23
|
"prepublishOnly": "npm run build"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"ptech-shell-sdk": "^1.
|
|
26
|
+
"ptech-shell-sdk": "^1.8.0"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/react": "^19.2.13",
|
|
33
|
+
"react": "^19.2.4",
|
|
34
|
+
"tsup": "^8.5.1",
|
|
35
|
+
"typescript": "^5.9.3"
|
|
27
36
|
},
|
|
28
|
-
"peerDependencies": {
|
|
29
|
-
"react": ">=18"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@types/react": "^19.2.13",
|
|
33
|
-
"react": "^19.2.4",
|
|
34
|
-
"tsup": "^8.5.1",
|
|
35
|
-
"typescript": "^5.9.3"
|
|
36
|
-
},
|
|
37
37
|
"keywords": [
|
|
38
38
|
"micro-frontend",
|
|
39
39
|
"module-federation",
|