@conduit-client/service-provisioner 3.7.1 → 3.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/types/v1/index.d.ts +50 -0
- package/dist/v1/index.js +99 -29
- package/dist/v1/index.js.map +1 -1
- package/package.json +3 -3
package/dist/types/v1/index.d.ts
CHANGED
|
@@ -33,6 +33,22 @@ export type RequestedService<R extends ServiceRequest<any>> = R extends Optional
|
|
|
33
33
|
export type RequestedServices<R extends ServicesRequest<any>> = {
|
|
34
34
|
[k in keyof R]: RequestedService<R[k]>;
|
|
35
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* A function that attempts to resolve a set of requested services. A runtime
|
|
38
|
+
* environment must provide a ServiceResolver to enable service consumers to
|
|
39
|
+
* request services. buildStaticServiceResolver() and buildDynamicServiceResolver()
|
|
40
|
+
* can be used to create resolvers for scenarios where the full set of services is
|
|
41
|
+
* known ahead of time.
|
|
42
|
+
*/
|
|
43
|
+
export type ServiceResolver<R extends ServicesRequest<any>> = (requested: R) => PromiseLike<[resolved: RequestedServices<R>, unresolved: Array<keyof R>]>;
|
|
44
|
+
/**
|
|
45
|
+
* Indicates if a published service satisfies a given service request.
|
|
46
|
+
*
|
|
47
|
+
* @param service published service
|
|
48
|
+
* @param request requested service
|
|
49
|
+
* @returns true if the published service satisfies the request; false otherwise
|
|
50
|
+
*/
|
|
51
|
+
export declare function serviceSatisfies(service: PublishedService, request: ServiceRequest<ServiceDescriptor<unknown>>): boolean;
|
|
36
52
|
/**
|
|
37
53
|
* Attempts to resolve a set of requested services against a set of published services.
|
|
38
54
|
* Returns a map of the requested services if the published services satisfy the request;
|
|
@@ -42,6 +58,9 @@ export type RequestedServices<R extends ServicesRequest<any>> = {
|
|
|
42
58
|
* override the default getServices() implementation below. Service consumers should only
|
|
43
59
|
* use the default export to request the services they need.
|
|
44
60
|
*
|
|
61
|
+
* This function is provided for legacy use only. New code should use resolvers and/or
|
|
62
|
+
* serviceSatisfies() instead.
|
|
63
|
+
*
|
|
45
64
|
* @param published published services
|
|
46
65
|
* @param requested requested services
|
|
47
66
|
* @returns service map if published satisfies requests; undefined if not
|
|
@@ -76,3 +95,34 @@ export default function getServices<R extends ServicesRequest<any>>(request: R,
|
|
|
76
95
|
* @param services services to be used to satisfy future getServices() requests
|
|
77
96
|
*/
|
|
78
97
|
export declare function setServices(services: PublishedService[]): void;
|
|
98
|
+
/**
|
|
99
|
+
* Sets the service resolver that will be used to satisfy calls to getServices().
|
|
100
|
+
* Any previously registered service resolver is replaced with the resolver provided.
|
|
101
|
+
* Note overwriting resolvers should be done with great care as previous callers
|
|
102
|
+
* of getServices() will not be aware of the new resolver.
|
|
103
|
+
*
|
|
104
|
+
* @param resolver service resolver
|
|
105
|
+
*/
|
|
106
|
+
export declare function setServiceResolver(resolver: ServiceResolver<any>): void;
|
|
107
|
+
/**
|
|
108
|
+
* Builds a service resolver that will resolve against the supplied static set of services.
|
|
109
|
+
*
|
|
110
|
+
* Note that the returned resolver is functionally equivalent to one returned by
|
|
111
|
+
* buildDynamicServiceResolver() when only static services are supplied. This function
|
|
112
|
+
* is preferred when all services are statically created and bootstrap size is a concern.
|
|
113
|
+
*
|
|
114
|
+
* @param services statically-defined services
|
|
115
|
+
* @returns a ServiceResolver that resolves against the supplied services
|
|
116
|
+
*/
|
|
117
|
+
export declare function buildStaticServiceResolver<R extends ServicesRequest<ServiceDescriptor<unknown>>>(services: PublishedService[]): ServiceResolver<R>;
|
|
118
|
+
/**
|
|
119
|
+
* Builds a service resolver that will resolve against the supplied set of satic & dynamic
|
|
120
|
+
* services.
|
|
121
|
+
*
|
|
122
|
+
* @param services set of statically-defined services, or builder functions for dynamically-
|
|
123
|
+
* defined services
|
|
124
|
+
* @returns a ServiceResolver that resolves against the supplied services
|
|
125
|
+
*/
|
|
126
|
+
export declare function buildDynamicServiceResolver<R extends ServicesRequest<ServiceDescriptor<unknown>>>(services: Array<PublishedService | (Omit<PublishedService, 'service'> & {
|
|
127
|
+
builder: (request: ServiceRequest<ServiceDescriptor<unknown>>) => PromiseLike<PublishedService>;
|
|
128
|
+
})>): ServiceResolver<R>;
|
package/dist/v1/index.js
CHANGED
|
@@ -4,40 +4,45 @@
|
|
|
4
4
|
* For full license text, see the LICENSE.txt file
|
|
5
5
|
*/
|
|
6
6
|
import { racesync, satisfies, resolvedPromiseLike } from "@conduit-client/utils";
|
|
7
|
+
function serviceSatisfies(service, request) {
|
|
8
|
+
return (
|
|
9
|
+
// service types must match
|
|
10
|
+
service.type === request.type && // version of the service must satisfy the requested version
|
|
11
|
+
satisfies(service.version, request.version) && // no tags requested, or the service matches every requested tag value
|
|
12
|
+
(request.tags === void 0 || Object.keys(request.tags).every((tag) => {
|
|
13
|
+
var _a;
|
|
14
|
+
return ((_a = service.tags) == null ? void 0 : _a[tag]) === request.tags[tag];
|
|
15
|
+
}))
|
|
16
|
+
);
|
|
17
|
+
}
|
|
7
18
|
function resolve(published, requested) {
|
|
8
|
-
const
|
|
9
|
-
for (const [name,
|
|
10
|
-
const matchingService = published.find(
|
|
11
|
-
(s) => (
|
|
12
|
-
// service types must match
|
|
13
|
-
s.type === request.type && // version of the service must satisfy the requested version
|
|
14
|
-
satisfies(s.version, request.version) && // no tags requested, or the service matches every requested tag value
|
|
15
|
-
(request.tags === void 0 || Object.keys(request.tags).every((tag) => {
|
|
16
|
-
var _a;
|
|
17
|
-
return ((_a = s.tags) == null ? void 0 : _a[tag]) === request.tags[tag];
|
|
18
|
-
}))
|
|
19
|
-
)
|
|
20
|
-
);
|
|
19
|
+
const resolved = {};
|
|
20
|
+
for (const [name, req] of Object.entries(requested)) {
|
|
21
|
+
const matchingService = published.find((s) => serviceSatisfies(s, req));
|
|
21
22
|
if (matchingService) {
|
|
22
|
-
|
|
23
|
-
} else if (!("optional" in
|
|
24
|
-
return;
|
|
23
|
+
resolved[name] = matchingService.service;
|
|
24
|
+
} else if (!("optional" in req && req.optional)) {
|
|
25
|
+
return void 0;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
return
|
|
28
|
+
return resolved;
|
|
28
29
|
}
|
|
29
|
-
let
|
|
30
|
-
let
|
|
31
|
-
(resolve2) =>
|
|
30
|
+
let resolverAvailable;
|
|
31
|
+
let waitForResolver = new Promise(
|
|
32
|
+
(resolve2) => resolverAvailable = resolve2
|
|
32
33
|
);
|
|
33
34
|
function getServices(request, timeout = 3e4) {
|
|
34
|
-
const servicesPromise =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
const servicesPromise = waitForResolver.then(
|
|
36
|
+
(resolver) => (
|
|
37
|
+
// try to resolve the requested services against our services
|
|
38
|
+
resolver(request).then(([resolved, unresolved]) => {
|
|
39
|
+
if (unresolved.length === 0) {
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
throw new Error("no matches found for one or more requested services");
|
|
43
|
+
})
|
|
44
|
+
)
|
|
45
|
+
);
|
|
41
46
|
let timeoutId;
|
|
42
47
|
let timeoutPromise = new Promise((_, reject) => {
|
|
43
48
|
timeoutId = setTimeout(() => reject(new Error("OneStore services unavailable")), timeout);
|
|
@@ -55,12 +60,77 @@ function getServices(request, timeout = 3e4) {
|
|
|
55
60
|
);
|
|
56
61
|
}
|
|
57
62
|
function setServices(services) {
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
setServiceResolver(buildStaticServiceResolver(services));
|
|
64
|
+
}
|
|
65
|
+
function setServiceResolver(resolver) {
|
|
66
|
+
waitForResolver = resolvedPromiseLike(resolver);
|
|
67
|
+
resolverAvailable(resolver);
|
|
68
|
+
}
|
|
69
|
+
function buildStaticServiceResolver(services) {
|
|
70
|
+
return (requested) => {
|
|
71
|
+
const resolved = {};
|
|
72
|
+
const unresolved = [];
|
|
73
|
+
for (const [name, req] of Object.entries(requested)) {
|
|
74
|
+
const matchingService = services.find((s) => serviceSatisfies(s, req));
|
|
75
|
+
if (matchingService) {
|
|
76
|
+
resolved[name] = matchingService.service;
|
|
77
|
+
} else if (!("optional" in req && req.optional)) {
|
|
78
|
+
unresolved.push(name);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return resolvedPromiseLike([resolved, unresolved]);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
function buildDynamicServiceResolver(services) {
|
|
85
|
+
const currentServices = services.map((svc) => Object.assign({ service: void 0 }, svc));
|
|
86
|
+
return (requested) => {
|
|
87
|
+
const resolved = {};
|
|
88
|
+
const pending = [];
|
|
89
|
+
const unresolved = [];
|
|
90
|
+
Object.entries(requested).forEach(([name, req]) => {
|
|
91
|
+
const matchingService = currentServices.find((s) => serviceSatisfies(s, req));
|
|
92
|
+
if (matchingService == null ? void 0 : matchingService.service) {
|
|
93
|
+
resolved[name] = matchingService.service;
|
|
94
|
+
} else if (matchingService == null ? void 0 : matchingService.promise) {
|
|
95
|
+
pending.push(
|
|
96
|
+
matchingService.promise.then((builtService) => {
|
|
97
|
+
resolved[name] = builtService.service;
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
} else if (matchingService == null ? void 0 : matchingService.builder) {
|
|
101
|
+
matchingService.promise = matchingService.builder(req);
|
|
102
|
+
pending.push(
|
|
103
|
+
matchingService.promise.then(
|
|
104
|
+
(builtService) => {
|
|
105
|
+
resolved[name] = matchingService.service = builtService.service;
|
|
106
|
+
matchingService.promise = void 0;
|
|
107
|
+
},
|
|
108
|
+
(error) => {
|
|
109
|
+
console.error(
|
|
110
|
+
`failed to build service ${matchingService.type}/${matchingService.version}: ${error}`
|
|
111
|
+
);
|
|
112
|
+
matchingService.promise = void 0;
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
} else if (!("optional" in req && req.optional)) {
|
|
118
|
+
unresolved.push(name);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
if (pending.length > 0) {
|
|
122
|
+
return Promise.all(pending).then(() => [resolved, unresolved]);
|
|
123
|
+
}
|
|
124
|
+
return resolvedPromiseLike([resolved, unresolved]);
|
|
125
|
+
};
|
|
60
126
|
}
|
|
61
127
|
export {
|
|
128
|
+
buildDynamicServiceResolver,
|
|
129
|
+
buildStaticServiceResolver,
|
|
62
130
|
getServices as default,
|
|
63
131
|
resolve,
|
|
132
|
+
serviceSatisfies,
|
|
133
|
+
setServiceResolver,
|
|
64
134
|
setServices
|
|
65
135
|
};
|
|
66
136
|
//# sourceMappingURL=index.js.map
|
package/dist/v1/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/v1/index.ts"],"sourcesContent":["import {\n resolvedPromiseLike,\n racesync,\n satisfies,\n type ServiceDescriptor,\n} from '@conduit-client/utils';\n\n/**\n * When a service instance is registered it can have additional tags associated with it.\n * Service consumers can use these tags to discriminate among otherwise equivalent\n * instances of the service.\n */\nexport type PublishedService = ServiceDescriptor<unknown> & {\n tags?: Record<string, string>;\n};\n\n/**\n * A request for a required single service.\n */\nexport type ServiceRequest<D extends ServiceDescriptor<unknown>> = Omit<D, 'service'> & {\n tags?: Record<string, string>;\n};\n\n/**\n * A request for an optional single service.\n */\nexport type OptionalServiceRequest<D extends ServiceDescriptor<unknown>> = ServiceRequest<D> & {\n optional: true;\n};\n\n/**\n * A request for a set of services.\n */\nexport type ServicesRequest<\n D extends ServiceDescriptor<unknown>,\n Name extends string = D['type'],\n> = Record<Name, ServiceRequest<D> | OptionalServiceRequest<D>>;\n\n/**\n * Utility type to extract the service implementation type from a ServiceRequest.\n */\nexport type RequestedService<R extends ServiceRequest<any>> =\n R extends OptionalServiceRequest<ServiceDescriptor<infer S>>\n ? S | undefined\n : R extends ServiceRequest<ServiceDescriptor<infer S>>\n ? S\n : never;\n\n/**\n * A map of services that matches a given ServicesRequest.\n */\nexport type RequestedServices<R extends ServicesRequest<any>> = {\n [k in keyof R]: RequestedService<R[k]>;\n};\n\n/**\n * Attempts to resolve a set of requested services against a set of published services.\n * Returns a map of the requested services if the published services satisfy the request;\n * undefined if published services are missing one or more of the requested services.\n *\n * Note that this function is exported ONLY for use by runtime environments that need to\n * override the default getServices() implementation below. Service consumers should only\n * use the default export to request the services they need.\n *\n * @param published published services\n * @param requested requested services\n * @returns service map if published satisfies requests; undefined if not\n */\nexport function resolve<R extends ServicesRequest<ServiceDescriptor<unknown>>>(\n published: PublishedService[],\n requested: R\n): RequestedServices<R> | undefined {\n const result: RequestedServices<R> = {} as any;\n\n for (const [name, request] of Object.entries(requested)) {\n const matchingService = published.find(\n (s) =>\n // service types must match\n s.type === request.type &&\n // version of the service must satisfy the requested version\n satisfies(s.version, request.version) &&\n // no tags requested, or the service matches every requested tag value\n (request.tags === undefined ||\n Object.keys(request.tags).every((tag) => s.tags?.[tag] === request.tags![tag]))\n );\n\n if (matchingService) {\n (result as any)[name] = matchingService.service;\n } else if (!('optional' in request && request.optional)) {\n return;\n }\n }\n\n return result;\n}\n\n/**\n * Most-recently set of published services.\n */\nlet servicesAvailable: (services: PublishedService[]) => void;\nlet waitForServices: PromiseLike<PublishedService[]> = new Promise<PublishedService[]>(\n (resolve) => (servicesAvailable = resolve)\n);\n\n/**\n * Requests a given set of services from the runtime environment.\n *\n * The default implementation of this function guarantees that the return\n * PromiseLike will be resolved synchronously. That is, one of the functions\n * supplied to its .then() will be invoked before .then() returns. Overrides\n * of this function SHOULD preserve this behavior whenever possible, as\n * some service consumer initialization patterns cannot support asynchronous\n * initialization of services.\n *\n * @param request requested services\n * @returns PromiseLike for the requested services; rejects if the requested\n * services are not available\n */\nexport default function getServices<R extends ServicesRequest<any>>(\n request: R,\n timeout: number = 30000\n): PromiseLike<RequestedServices<R>> {\n const servicesPromise = waitForServices.then((services) => {\n // try to resolve the requested services against our services\n const result = resolve(services, request);\n\n // resolve/reject based on whether we have all the requested services\n if (result) {\n return result;\n }\n\n throw new Error('no matches found for one or more requested services');\n });\n\n let timeoutId: ReturnType<typeof setTimeout>;\n let timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error('OneStore services unavailable')), timeout);\n });\n\n return racesync([servicesPromise, timeoutPromise]).then(\n (value) => {\n clearTimeout(timeoutId);\n return value;\n },\n (reason) => {\n clearTimeout(timeoutId);\n // eslint-disable-next-line\n console.error(reason);\n throw reason;\n }\n );\n}\n\n/**\n * Sets the services that will be used to satisfy calls to getServices().\n * Any previously registered services are replaced with the services provided.\n * Note overwriting services should be done with great care as previous callers\n * of getServices() will not be aware of the new services.\n * \n * The default implementation provided by this module only supports a single\n * set of active services. Runtime environments that require multiple sets of\n * active services will need to override this module with their own\n * implementation.\n \n * @param services services to be used to satisfy future getServices() requests\n */\nexport function setServices(services: PublishedService[]) {\n waitForServices = resolvedPromiseLike(services);\n servicesAvailable(services);\n}\n"],"names":["resolve"],"mappings":";;;;;;AAoEO,SAAS,QACZ,WACA,WACgC;AAChC,QAAM,SAA+B,CAAA;AAErC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,UAAM,kBAAkB,UAAU;AAAA,MAC9B,CAAC;AAAA;AAAA,QAEG,EAAE,SAAS,QAAQ;AAAA,QAEnB,UAAU,EAAE,SAAS,QAAQ,OAAO;AAAA,SAEnC,QAAQ,SAAS,UACd,OAAO,KAAK,QAAQ,IAAI,EAAE,MAAM,CAAC,QAAA;;AAAQ,0BAAE,SAAF,mBAAS,UAAS,QAAQ,KAAM,GAAG;AAAA,SAAC;AAAA;AAAA,IAAA;AAGzF,QAAI,iBAAiB;AAChB,aAAe,IAAI,IAAI,gBAAgB;AAAA,IAC5C,WAAW,EAAE,cAAc,WAAW,QAAQ,WAAW;AACrD;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;AAKA,IAAI;AACJ,IAAI,kBAAmD,IAAI;AAAA,EACvD,CAACA,aAAa,oBAAoBA;AACtC;AAgBA,SAAwB,YACpB,SACA,UAAkB,KACe;AACjC,QAAM,kBAAkB,gBAAgB,KAAK,CAAC,aAAa;AAEvD,UAAM,SAAS,QAAQ,UAAU,OAAO;AAGxC,QAAI,QAAQ;AACR,aAAO;AAAA,IACX;AAEA,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACzE,CAAC;AAED,MAAI;AACJ,MAAI,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACnD,gBAAY,WAAW,MAAM,OAAO,IAAI,MAAM,+BAA+B,CAAC,GAAG,OAAO;AAAA,EAC5F,CAAC;AAED,SAAO,SAAS,CAAC,iBAAiB,cAAc,CAAC,EAAE;AAAA,IAC/C,CAAC,UAAU;AACP,mBAAa,SAAS;AACtB,aAAO;AAAA,IACX;AAAA,IACA,CAAC,WAAW;AACR,mBAAa,SAAS;AAEtB,cAAQ,MAAM,MAAM;AACpB,YAAM;AAAA,IACV;AAAA,EAAA;AAER;AAeO,SAAS,YAAY,UAA8B;AACtD,oBAAkB,oBAAoB,QAAQ;AAC9C,oBAAkB,QAAQ;AAC9B;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/v1/index.ts"],"sourcesContent":["import {\n resolvedPromiseLike,\n racesync,\n satisfies,\n type ServiceDescriptor,\n} from '@conduit-client/utils';\n\n/**\n * When a service instance is registered it can have additional tags associated with it.\n * Service consumers can use these tags to discriminate among otherwise equivalent\n * instances of the service.\n */\nexport type PublishedService = ServiceDescriptor<unknown> & {\n tags?: Record<string, string>;\n};\n\n/**\n * A request for a required single service.\n */\nexport type ServiceRequest<D extends ServiceDescriptor<unknown>> = Omit<D, 'service'> & {\n tags?: Record<string, string>;\n};\n\n/**\n * A request for an optional single service.\n */\nexport type OptionalServiceRequest<D extends ServiceDescriptor<unknown>> = ServiceRequest<D> & {\n optional: true;\n};\n\n/**\n * A request for a set of services.\n */\nexport type ServicesRequest<\n D extends ServiceDescriptor<unknown>,\n Name extends string = D['type'],\n> = Record<Name, ServiceRequest<D> | OptionalServiceRequest<D>>;\n\n/**\n * Utility type to extract the service implementation type from a ServiceRequest.\n */\nexport type RequestedService<R extends ServiceRequest<any>> =\n R extends OptionalServiceRequest<ServiceDescriptor<infer S>>\n ? S | undefined\n : R extends ServiceRequest<ServiceDescriptor<infer S>>\n ? S\n : never;\n\n/**\n * A map of services that matches a given ServicesRequest.\n */\nexport type RequestedServices<R extends ServicesRequest<any>> = {\n [k in keyof R]: RequestedService<R[k]>;\n};\n\n/**\n * A function that attempts to resolve a set of requested services. A runtime\n * environment must provide a ServiceResolver to enable service consumers to\n * request services. buildStaticServiceResolver() and buildDynamicServiceResolver()\n * can be used to create resolvers for scenarios where the full set of services is\n * known ahead of time.\n */\nexport type ServiceResolver<R extends ServicesRequest<any>> = (\n requested: R\n) => PromiseLike<[resolved: RequestedServices<R>, unresolved: Array<keyof R>]>;\n\n/**\n * Indicates if a published service satisfies a given service request.\n *\n * @param service published service\n * @param request requested service\n * @returns true if the published service satisfies the request; false otherwise\n */\nexport function serviceSatisfies(\n service: PublishedService,\n request: ServiceRequest<ServiceDescriptor<unknown>>\n): boolean {\n return (\n // service types must match\n service.type === request.type &&\n // version of the service must satisfy the requested version\n satisfies(service.version, request.version) &&\n // no tags requested, or the service matches every requested tag value\n (request.tags === undefined ||\n Object.keys(request.tags).every((tag) => service.tags?.[tag] === request.tags![tag]))\n );\n}\n\n/**\n * Attempts to resolve a set of requested services against a set of published services.\n * Returns a map of the requested services if the published services satisfy the request;\n * undefined if published services are missing one or more of the requested services.\n *\n * Note that this function is exported ONLY for use by runtime environments that need to\n * override the default getServices() implementation below. Service consumers should only\n * use the default export to request the services they need.\n *\n * This function is provided for legacy use only. New code should use resolvers and/or\n * serviceSatisfies() instead.\n *\n * @param published published services\n * @param requested requested services\n * @returns service map if published satisfies requests; undefined if not\n */\nexport function resolve<R extends ServicesRequest<ServiceDescriptor<unknown>>>(\n published: PublishedService[],\n requested: R\n): RequestedServices<R> | undefined {\n const resolved: RequestedServices<R> = {} as any;\n const unresolved: Array<keyof R> = [];\n\n for (const [name, req] of Object.entries(requested)) {\n const matchingService = published.find((s) => serviceSatisfies(s, req));\n\n if (matchingService) {\n (resolved as any)[name] = matchingService.service;\n } else if (!('optional' in req && req.optional)) {\n return undefined;\n }\n }\n\n return resolved;\n}\n\n/**\n * Most-recently set resolver.\n */\nlet resolverAvailable: (resolver: ServiceResolver<any>) => void;\nlet waitForResolver: PromiseLike<ServiceResolver<any>> = new Promise<ServiceResolver<any>>(\n (resolve) => (resolverAvailable = resolve)\n);\n\n/**\n * Requests a given set of services from the runtime environment.\n *\n * The default implementation of this function guarantees that the return\n * PromiseLike will be resolved synchronously. That is, one of the functions\n * supplied to its .then() will be invoked before .then() returns. Overrides\n * of this function SHOULD preserve this behavior whenever possible, as\n * some service consumer initialization patterns cannot support asynchronous\n * initialization of services.\n *\n * @param request requested services\n * @returns PromiseLike for the requested services; rejects if the requested\n * services are not available\n */\nexport default function getServices<R extends ServicesRequest<any>>(\n request: R,\n timeout: number = 30000\n): PromiseLike<RequestedServices<R>> {\n const servicesPromise = waitForResolver.then((resolver) =>\n // try to resolve the requested services against our services\n resolver(request).then(([resolved, unresolved]) => {\n if (unresolved.length === 0) {\n return resolved;\n }\n\n throw new Error('no matches found for one or more requested services');\n })\n );\n\n let timeoutId: ReturnType<typeof setTimeout>;\n let timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new Error('OneStore services unavailable')), timeout);\n });\n\n return racesync([servicesPromise, timeoutPromise]).then(\n (value) => {\n clearTimeout(timeoutId);\n return value;\n },\n (reason) => {\n clearTimeout(timeoutId);\n // eslint-disable-next-line\n console.error(reason);\n throw reason;\n }\n );\n}\n\n/**\n * Sets the services that will be used to satisfy calls to getServices().\n * Any previously registered services are replaced with the services provided.\n * Note overwriting services should be done with great care as previous callers\n * of getServices() will not be aware of the new services.\n * \n * The default implementation provided by this module only supports a single\n * set of active services. Runtime environments that require multiple sets of\n * active services will need to override this module with their own\n * implementation.\n \n * @param services services to be used to satisfy future getServices() requests\n */\nexport function setServices(services: PublishedService[]) {\n setServiceResolver(buildStaticServiceResolver(services));\n}\n\n/**\n * Sets the service resolver that will be used to satisfy calls to getServices().\n * Any previously registered service resolver is replaced with the resolver provided.\n * Note overwriting resolvers should be done with great care as previous callers\n * of getServices() will not be aware of the new resolver.\n *\n * @param resolver service resolver\n */\nexport function setServiceResolver(resolver: ServiceResolver<any>) {\n waitForResolver = resolvedPromiseLike(resolver);\n resolverAvailable(resolver);\n}\n\n/**\n * Builds a service resolver that will resolve against the supplied static set of services.\n *\n * Note that the returned resolver is functionally equivalent to one returned by\n * buildDynamicServiceResolver() when only static services are supplied. This function\n * is preferred when all services are statically created and bootstrap size is a concern.\n *\n * @param services statically-defined services\n * @returns a ServiceResolver that resolves against the supplied services\n */\nexport function buildStaticServiceResolver<R extends ServicesRequest<ServiceDescriptor<unknown>>>(\n services: PublishedService[]\n): ServiceResolver<R> {\n return (requested: R) => {\n const resolved: RequestedServices<R> = {} as any;\n const unresolved: Array<keyof R> = [];\n\n for (const [name, req] of Object.entries(requested)) {\n const matchingService = services.find((s) => serviceSatisfies(s, req));\n\n if (matchingService) {\n (resolved as any)[name] = matchingService.service;\n } else if (!('optional' in req && req.optional)) {\n unresolved.push(name);\n }\n }\n\n return resolvedPromiseLike([resolved, unresolved]);\n };\n}\n\n/**\n * Builds a service resolver that will resolve against the supplied set of satic & dynamic\n * services.\n *\n * @param services set of statically-defined services, or builder functions for dynamically-\n * defined services\n * @returns a ServiceResolver that resolves against the supplied services\n */\nexport function buildDynamicServiceResolver<R extends ServicesRequest<ServiceDescriptor<unknown>>>(\n services: Array<\n | PublishedService\n | (Omit<PublishedService, 'service'> & {\n builder: (\n request: ServiceRequest<ServiceDescriptor<unknown>>\n ) => PromiseLike<PublishedService>;\n })\n >\n): ServiceResolver<R> {\n // Used to track the current set of services. Each service is in one of the following\n // states:\n //\n // - service !== undefined\n // the service has been built and is available\n // - service === undefined && promise !== undefined\n // the service is being built, the promise will resolve to the service when available\n // - service === undefined && promise === undefined && builder !== undefined\n // the service needs to be built\n const currentServices: Array<\n PublishedService & {\n builder?: (\n request: ServiceRequest<ServiceDescriptor<unknown>>\n ) => PromiseLike<PublishedService>;\n promise?: PromiseLike<PublishedService>;\n }\n > = services.map((svc) => Object.assign({ service: undefined }, svc));\n\n return (requested: R) => {\n const resolved: RequestedServices<R> = {} as any;\n const pending: PromiseLike<void>[] = [];\n const unresolved: Array<keyof R> = [];\n\n Object.entries(requested).forEach(([name, req]) => {\n const matchingService = currentServices.find((s) => serviceSatisfies(s, req));\n\n // service is already built\n if (matchingService?.service) {\n (resolved as any)[name] = matchingService.service;\n }\n // service is being built\n else if (matchingService?.promise) {\n pending.push(\n matchingService.promise.then((builtService) => {\n (resolved as any)[name] = builtService.service;\n })\n );\n }\n // service needs to be built\n else if (matchingService?.builder) {\n matchingService.promise = matchingService.builder(req);\n pending.push(\n matchingService.promise.then(\n (builtService) => {\n (resolved as any)[name] = matchingService.service =\n builtService.service;\n matchingService.promise = undefined;\n },\n (error) => {\n // eslint-disable-next-line\n console.error(\n `failed to build service ${matchingService.type}/${matchingService.version}: ${error}`\n );\n // clear the promise so future requests will retry building the service\n matchingService.promise = undefined;\n throw error;\n }\n )\n );\n }\n // service is not available; note that this logic prioritizes building an\n // optional service over reporting it as unresolved\n else if (!('optional' in req && req.optional)) {\n unresolved.push(name);\n }\n });\n\n if (pending.length > 0) {\n return Promise.all(pending).then(() => [resolved, unresolved]);\n }\n\n return resolvedPromiseLike([resolved, unresolved]);\n };\n}\n"],"names":["resolve"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduit-client/service-provisioner",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Luvio Service Provisioner",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"watch": "npm run build --watch"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@conduit-client/utils": "3.
|
|
34
|
+
"@conduit-client/utils": "3.8.0"
|
|
35
35
|
},
|
|
36
36
|
"volta": {
|
|
37
37
|
"extends": "../../../package.json"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"size-limit": [
|
|
40
40
|
{
|
|
41
41
|
"path": "./dist/v1/index.js",
|
|
42
|
-
"limit": "
|
|
42
|
+
"limit": "1.2 kB"
|
|
43
43
|
}
|
|
44
44
|
]
|
|
45
45
|
}
|