@geekmidas/constructs 10.0.0-alpha.102 → 10.0.0-alpha.103

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.
Files changed (59) hide show
  1. package/dist/{HonoEndpointAdaptor-Cvhfj4gd.mjs → HonoEndpointAdaptor-RSvRnXSl.mjs} +17 -8
  2. package/dist/HonoEndpointAdaptor-RSvRnXSl.mjs.map +1 -0
  3. package/dist/{HonoEndpointAdaptor-C_FbrwlA.cjs → HonoEndpointAdaptor-eCKyEOl_.cjs} +19 -10
  4. package/dist/HonoEndpointAdaptor-eCKyEOl_.cjs.map +1 -0
  5. package/dist/adaptors/aws.cjs +31 -6
  6. package/dist/adaptors/aws.cjs.map +1 -1
  7. package/dist/adaptors/aws.d.cts +8 -0
  8. package/dist/adaptors/aws.d.cts.map +1 -1
  9. package/dist/adaptors/aws.d.mts +8 -0
  10. package/dist/adaptors/aws.d.mts.map +1 -1
  11. package/dist/adaptors/aws.mjs +29 -4
  12. package/dist/adaptors/aws.mjs.map +1 -1
  13. package/dist/adaptors/hono.cjs +1 -1
  14. package/dist/adaptors/hono.d.cts.map +1 -1
  15. package/dist/adaptors/hono.d.mts.map +1 -1
  16. package/dist/adaptors/hono.mjs +1 -1
  17. package/dist/adaptors/testing.cjs +15 -4
  18. package/dist/adaptors/testing.cjs.map +1 -1
  19. package/dist/adaptors/testing.d.cts +1 -1
  20. package/dist/adaptors/testing.d.cts.map +1 -1
  21. package/dist/adaptors/testing.d.mts +1 -1
  22. package/dist/adaptors/testing.d.mts.map +1 -1
  23. package/dist/adaptors/testing.mjs +14 -3
  24. package/dist/adaptors/testing.mjs.map +1 -1
  25. package/dist/credential-DYymbp_7.cjs +257 -0
  26. package/dist/credential-DYymbp_7.cjs.map +1 -0
  27. package/dist/credential-DfSAOOdY.mjs +222 -0
  28. package/dist/credential-DfSAOOdY.mjs.map +1 -0
  29. package/dist/credential.cjs +7 -155
  30. package/dist/credential.d.cts +2 -86
  31. package/dist/credential.d.mts +2 -86
  32. package/dist/credential.mjs +2 -152
  33. package/dist/external-api.cjs +3 -39
  34. package/dist/external-api.cjs.map +1 -1
  35. package/dist/external-api.d.cts +2 -2
  36. package/dist/external-api.d.mts +2 -2
  37. package/dist/external-api.mjs +1 -37
  38. package/dist/external-api.mjs.map +1 -1
  39. package/dist/fake-BcHTPz7N.d.mts +201 -0
  40. package/dist/fake-BcHTPz7N.d.mts.map +1 -0
  41. package/dist/fake-Dvion_Fh.d.cts +201 -0
  42. package/dist/fake-Dvion_Fh.d.cts.map +1 -0
  43. package/dist/{processAudits-DasOZjPl.cjs → rateLimit-BwHcMECR.cjs} +26 -5
  44. package/dist/rateLimit-BwHcMECR.cjs.map +1 -0
  45. package/dist/{processAudits-BRRVVHUB.mjs → rateLimit-DbOTsP01.mjs} +23 -2
  46. package/dist/rateLimit-DbOTsP01.mjs.map +1 -0
  47. package/package.json +31 -31
  48. package/dist/HonoEndpointAdaptor-C_FbrwlA.cjs.map +0 -1
  49. package/dist/HonoEndpointAdaptor-Cvhfj4gd.mjs.map +0 -1
  50. package/dist/credential.cjs.map +0 -1
  51. package/dist/credential.d.cts.map +0 -1
  52. package/dist/credential.d.mts.map +0 -1
  53. package/dist/credential.mjs.map +0 -1
  54. package/dist/external-api-MJ8id87V.d.mts +0 -105
  55. package/dist/external-api-MJ8id87V.d.mts.map +0 -1
  56. package/dist/external-api-O107yzZJ.d.cts +0 -105
  57. package/dist/external-api-O107yzZJ.d.cts.map +0 -1
  58. package/dist/processAudits-BRRVVHUB.mjs.map +0 -1
  59. package/dist/processAudits-DasOZjPl.cjs.map +0 -1
@@ -1,156 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- let _geekmidas_manifest = require("@geekmidas/manifest");
3
- let _geekmidas_schema_parser = require("@geekmidas/schema/parser");
4
- //#region src/credential.ts
5
- /**
6
- * `Credential` — a third-party credential with a shape.
7
- *
8
- * The answer to the design's first open question, "where does `Secret` sit?".
9
- * It sits beside a secret rather than replacing it, because the two differ by
10
- * *lifecycle* and that is the only difference worth two kinds for: a secret is
11
- * generated and rotated by the platform and is one opaque string, while a
12
- * credential is issued by someone else, arrives with several fields, and is
13
- * worth validating on the way in.
14
- *
15
- * ```ts
16
- * export const stripe = new Credential('Stripe', {
17
- * schema: z.object({ secretKey: z.string(), webhookSecret: z.string() }),
18
- * });
19
- *
20
- * // in a handler — no await, already parsed and validated
21
- * services.stripe.secretKey
22
- * ```
23
- *
24
- * **Nothing about it is async at the call site**, which is the part that looks
25
- * like it should be hard and is not. `Service.register()` may return a promise
26
- * and `ServiceDiscovery` awaits every one before a handler runs, so fetching a
27
- * value and validating it — including when a StandardSchema's `~standard.validate`
28
- * returns a promise of its own — both happen inside that existing seam.
29
- *
30
- * **One key holding JSON, not one key per field.** That is the shape a secret
31
- * manager stores, and it is the only shape that works with an arbitrary
32
- * StandardSchema: the spec has no introspection API, so enumerating a schema's
33
- * fields means reaching into one library's internals (`.shape`) and being wrong
34
- * for every other.
35
- */
36
- var Credential = class {
37
- options;
38
- id;
39
- service;
40
- /**
41
- * Declared once and read by both `declare()` and `connect()`, so the key the
42
- * target publishes and the key the client reads cannot drift.
43
- */
44
- keys;
45
- /**
46
- * The resolved value, held as the *promise* rather than the value.
47
- *
48
- * Caching the promise is what makes two concurrent registrations share one
49
- * resolution: caching the value would let both start before either finished,
50
- * which is a duplicated fetch every cold start rather than never.
51
- */
52
- resolved;
53
- constructor(id, options) {
54
- this.options = options;
55
- const canonical = (0, _geekmidas_manifest.canonicalId)(id);
56
- this.id = canonical;
57
- this.keys = { credentials: (0, _geekmidas_manifest.provideKey)(canonical, "credentials") };
58
- this.service = {
59
- serviceName: (0, _geekmidas_manifest.serviceKey)(canonical),
60
- register: (registerOptions) => this.connect(registerOptions)
61
- };
62
- }
63
- /**
64
- * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value
65
- * is validated against where it is read. Public so a tool setting the value
66
- * (`gkm secrets:add`) can check it, and describe its fields, before it is
67
- * stored rather than at the first request.
68
- */
69
- get credentialsSchema() {
70
- return this.options.schema;
71
- }
72
- declare() {
73
- return [{
74
- kind: "credential",
75
- id: this.id,
76
- provides: [this.keys.credentials]
77
- }];
78
- }
79
- connect(options) {
80
- if (this.options.refresh) return this.resolve(options);
81
- this.resolved ??= this.resolve(options);
82
- return this.resolved;
83
- }
84
- resolve(options) {
85
- return readCredentials(this.id, this.keys.credentials, this.options.schema, options.envParser);
86
- }
87
- };
88
- /**
89
- * A credentials key, read and validated against its schema.
90
- *
91
- * Shared with every construct that holds a third party's credentials — an
92
- * `ExternalApi` reads its own the same way — so the shape a stage stores and
93
- * the error a bad value raises are the same everywhere.
94
- *
95
- * @throws {MalformedCredential} when the value is not what the schema says.
96
- */
97
- async function readCredentials(id, key, schema, envParser) {
98
- const { raw } = envParser.create((get) => ({ raw: get(key).string() })).parse();
99
- try {
100
- return await (0, _geekmidas_schema_parser.parseSchema)(schema, decodeCredentials(raw));
101
- } catch (issues) {
102
- throw new MalformedCredential(id, key, issues);
103
- }
104
- }
105
- /**
106
- * The raw environment value as the thing the schema should see.
107
- *
108
- * JSON when it is JSON, and the string itself when it is not — a credential
109
- * with a single opaque field is ordinary, and requiring `"…"` around it would
110
- * be ceremony that every operator setting one by hand would get wrong once.
111
- *
112
- * Exported so a tool checking a value before it is stored reads it exactly as
113
- * the process that uses it will.
114
- */
115
- function decodeCredentials(raw) {
116
- const value = raw.startsWith(JSON_SCHEME) ? raw.slice(JSON_SCHEME.length) : raw;
117
- try {
118
- return JSON.parse(value);
119
- } catch {
120
- return value;
121
- }
122
- }
123
- /**
124
- * The explicit form, for the case a credential legitimately *is* a JSON string
125
- * and must not be parsed into an object. Rare, and cheaper to support than to
126
- * explain.
127
- */
128
- const JSON_SCHEME = "json:";
129
- /** A credential was set, and is not what its schema says it should be. */
130
- var MalformedCredential = class extends Error {
131
- id;
132
- key;
133
- issues;
134
- constructor(id, key, issues) {
135
- super(`${key} is not a valid ${id} credential. It is validated where it is read, so this is the value that is set rather than the code that uses it: ${describe(issues)}`);
136
- this.id = id;
137
- this.key = key;
138
- this.issues = issues;
139
- this.name = "MalformedCredential";
140
- }
141
- };
142
- /** StandardSchema issues as one line. */
143
- function describe(issues) {
144
- if (!Array.isArray(issues)) return String(issues);
145
- return issues.map((issue) => {
146
- const path = issue.path?.map((segment) => typeof segment === "object" ? String(segment.key) : String(segment)).join(".");
147
- return path ? `${path}: ${issue.message}` : issue.message;
148
- }).join("; ");
149
- }
150
- //#endregion
151
- exports.Credential = Credential;
152
- exports.MalformedCredential = MalformedCredential;
153
- exports.decodeCredentials = decodeCredentials;
154
- exports.readCredentials = readCredentials;
155
-
156
- //# sourceMappingURL=credential.cjs.map
2
+ const require_credential = require("./credential-DYymbp_7.cjs");
3
+ exports.Credential = require_credential.Credential;
4
+ exports.MalformedCredential = require_credential.MalformedCredential;
5
+ exports.decodeCredentials = require_credential.decodeCredentials;
6
+ exports.fake = require_credential.fake;
7
+ exports.isFake = require_credential.isFake;
8
+ exports.readCredentials = require_credential.readCredentials;
@@ -1,86 +1,2 @@
1
- import { t as StandardSchemaV1 } from "./index-CeEtxDmK.cjs";
2
- import { r as Consumable } from "./construct-interface-B1AfqRl4.cjs";
3
- import { Service, ServiceRegisterOptions } from "@geekmidas/services";
4
- import { ConstructName, Declaration } from "@geekmidas/manifest";
5
- //#region src/credential.d.ts
6
- /** What a credential's schema yields. */
7
- type Value<TSchema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<TSchema>;
8
- export interface CredentialOptions<TSchema extends StandardSchemaV1> {
9
- /**
10
- * What the credential must look like.
11
- *
12
- * Validated at registration, so a malformed or half-set credential fails
13
- * when the process starts rather than on the first request that needs the
14
- * one field somebody forgot.
15
- */
16
- schema: TSchema;
17
- /**
18
- * Re-resolve on every registration instead of once per process.
19
- *
20
- * Off by default: a credential is resolved once and reused, because the
21
- * alternative is a fetch on every request. The cost of that default is that
22
- * a rotated credential needs a restart, which is the right trade for a value
23
- * that changes a few times a year — and this is the escape hatch for when it
24
- * is not.
25
- */
26
- refresh?: boolean;
27
- }
28
- export declare class Credential<TName extends string = string, TSchema extends StandardSchemaV1 = StandardSchemaV1> implements Consumable<TName, Value<TSchema>> {
29
- private readonly options;
30
- readonly id: TName;
31
- readonly service: Service<Uncapitalize<TName>, Value<TSchema>>;
32
- /**
33
- * Declared once and read by both `declare()` and `connect()`, so the key the
34
- * target publishes and the key the client reads cannot drift.
35
- */
36
- private readonly keys;
37
- /**
38
- * The resolved value, held as the *promise* rather than the value.
39
- *
40
- * Caching the promise is what makes two concurrent registrations share one
41
- * resolution: caching the value would let both start before either finished,
42
- * which is a duplicated fetch every cold start rather than never.
43
- */
44
- private resolved?;
45
- constructor(id: ConstructName<TName>, options: CredentialOptions<TSchema>);
46
- /**
47
- * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value
48
- * is validated against where it is read. Public so a tool setting the value
49
- * (`gkm secrets:add`) can check it, and describe its fields, before it is
50
- * stored rather than at the first request.
51
- */
52
- get credentialsSchema(): TSchema;
53
- declare(): Declaration[];
54
- private connect;
55
- private resolve;
56
- }
57
- /**
58
- * A credentials key, read and validated against its schema.
59
- *
60
- * Shared with every construct that holds a third party's credentials — an
61
- * `ExternalApi` reads its own the same way — so the shape a stage stores and
62
- * the error a bad value raises are the same everywhere.
63
- *
64
- * @throws {MalformedCredential} when the value is not what the schema says.
65
- */
66
- export declare function readCredentials<TSchema extends StandardSchemaV1>(id: string, key: string, schema: TSchema, envParser: ServiceRegisterOptions['envParser']): Promise<Value<TSchema>>;
67
- /**
68
- * The raw environment value as the thing the schema should see.
69
- *
70
- * JSON when it is JSON, and the string itself when it is not — a credential
71
- * with a single opaque field is ordinary, and requiring `"…"` around it would
72
- * be ceremony that every operator setting one by hand would get wrong once.
73
- *
74
- * Exported so a tool checking a value before it is stored reads it exactly as
75
- * the process that uses it will.
76
- */
77
- export declare function decodeCredentials(raw: string): unknown;
78
- /** A credential was set, and is not what its schema says it should be. */
79
- export declare class MalformedCredential extends Error {
80
- readonly id: string;
81
- readonly key: string;
82
- readonly issues: unknown;
83
- constructor(id: string, key: string, issues: unknown);
84
- }
85
- //#endregion
86
- //# sourceMappingURL=credential.d.cts.map
1
+ import { c as Credential, d as decodeCredentials, f as readCredentials, i as isFake, l as CredentialOptions, r as fake, t as Fake, u as MalformedCredential } from "./fake-Dvion_Fh.cjs";
2
+ export { Credential, CredentialOptions, type Fake, MalformedCredential, decodeCredentials, fake, isFake, readCredentials };
@@ -1,86 +1,2 @@
1
- import { t as StandardSchemaV1 } from "./index-CeEtxDmK.mjs";
2
- import { r as Consumable } from "./construct-interface-DluK3_da.mjs";
3
- import { ConstructName, Declaration } from "@geekmidas/manifest";
4
- import { Service, ServiceRegisterOptions } from "@geekmidas/services";
5
- //#region src/credential.d.ts
6
- /** What a credential's schema yields. */
7
- type Value<TSchema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<TSchema>;
8
- export interface CredentialOptions<TSchema extends StandardSchemaV1> {
9
- /**
10
- * What the credential must look like.
11
- *
12
- * Validated at registration, so a malformed or half-set credential fails
13
- * when the process starts rather than on the first request that needs the
14
- * one field somebody forgot.
15
- */
16
- schema: TSchema;
17
- /**
18
- * Re-resolve on every registration instead of once per process.
19
- *
20
- * Off by default: a credential is resolved once and reused, because the
21
- * alternative is a fetch on every request. The cost of that default is that
22
- * a rotated credential needs a restart, which is the right trade for a value
23
- * that changes a few times a year — and this is the escape hatch for when it
24
- * is not.
25
- */
26
- refresh?: boolean;
27
- }
28
- export declare class Credential<TName extends string = string, TSchema extends StandardSchemaV1 = StandardSchemaV1> implements Consumable<TName, Value<TSchema>> {
29
- private readonly options;
30
- readonly id: TName;
31
- readonly service: Service<Uncapitalize<TName>, Value<TSchema>>;
32
- /**
33
- * Declared once and read by both `declare()` and `connect()`, so the key the
34
- * target publishes and the key the client reads cannot drift.
35
- */
36
- private readonly keys;
37
- /**
38
- * The resolved value, held as the *promise* rather than the value.
39
- *
40
- * Caching the promise is what makes two concurrent registrations share one
41
- * resolution: caching the value would let both start before either finished,
42
- * which is a duplicated fetch every cold start rather than never.
43
- */
44
- private resolved?;
45
- constructor(id: ConstructName<TName>, options: CredentialOptions<TSchema>);
46
- /**
47
- * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value
48
- * is validated against where it is read. Public so a tool setting the value
49
- * (`gkm secrets:add`) can check it, and describe its fields, before it is
50
- * stored rather than at the first request.
51
- */
52
- get credentialsSchema(): TSchema;
53
- declare(): Declaration[];
54
- private connect;
55
- private resolve;
56
- }
57
- /**
58
- * A credentials key, read and validated against its schema.
59
- *
60
- * Shared with every construct that holds a third party's credentials — an
61
- * `ExternalApi` reads its own the same way — so the shape a stage stores and
62
- * the error a bad value raises are the same everywhere.
63
- *
64
- * @throws {MalformedCredential} when the value is not what the schema says.
65
- */
66
- export declare function readCredentials<TSchema extends StandardSchemaV1>(id: string, key: string, schema: TSchema, envParser: ServiceRegisterOptions['envParser']): Promise<Value<TSchema>>;
67
- /**
68
- * The raw environment value as the thing the schema should see.
69
- *
70
- * JSON when it is JSON, and the string itself when it is not — a credential
71
- * with a single opaque field is ordinary, and requiring `"…"` around it would
72
- * be ceremony that every operator setting one by hand would get wrong once.
73
- *
74
- * Exported so a tool checking a value before it is stored reads it exactly as
75
- * the process that uses it will.
76
- */
77
- export declare function decodeCredentials(raw: string): unknown;
78
- /** A credential was set, and is not what its schema says it should be. */
79
- export declare class MalformedCredential extends Error {
80
- readonly id: string;
81
- readonly key: string;
82
- readonly issues: unknown;
83
- constructor(id: string, key: string, issues: unknown);
84
- }
85
- //#endregion
86
- //# sourceMappingURL=credential.d.mts.map
1
+ import { c as Credential, d as decodeCredentials, f as readCredentials, i as isFake, l as CredentialOptions, r as fake, t as Fake, u as MalformedCredential } from "./fake-BcHTPz7N.mjs";
2
+ export { Credential, CredentialOptions, type Fake, MalformedCredential, decodeCredentials, fake, isFake, readCredentials };
@@ -1,152 +1,2 @@
1
- import { canonicalId, provideKey, serviceKey } from "@geekmidas/manifest";
2
- import { parseSchema } from "@geekmidas/schema/parser";
3
- //#region src/credential.ts
4
- /**
5
- * `Credential` — a third-party credential with a shape.
6
- *
7
- * The answer to the design's first open question, "where does `Secret` sit?".
8
- * It sits beside a secret rather than replacing it, because the two differ by
9
- * *lifecycle* and that is the only difference worth two kinds for: a secret is
10
- * generated and rotated by the platform and is one opaque string, while a
11
- * credential is issued by someone else, arrives with several fields, and is
12
- * worth validating on the way in.
13
- *
14
- * ```ts
15
- * export const stripe = new Credential('Stripe', {
16
- * schema: z.object({ secretKey: z.string(), webhookSecret: z.string() }),
17
- * });
18
- *
19
- * // in a handler — no await, already parsed and validated
20
- * services.stripe.secretKey
21
- * ```
22
- *
23
- * **Nothing about it is async at the call site**, which is the part that looks
24
- * like it should be hard and is not. `Service.register()` may return a promise
25
- * and `ServiceDiscovery` awaits every one before a handler runs, so fetching a
26
- * value and validating it — including when a StandardSchema's `~standard.validate`
27
- * returns a promise of its own — both happen inside that existing seam.
28
- *
29
- * **One key holding JSON, not one key per field.** That is the shape a secret
30
- * manager stores, and it is the only shape that works with an arbitrary
31
- * StandardSchema: the spec has no introspection API, so enumerating a schema's
32
- * fields means reaching into one library's internals (`.shape`) and being wrong
33
- * for every other.
34
- */
35
- var Credential = class {
36
- options;
37
- id;
38
- service;
39
- /**
40
- * Declared once and read by both `declare()` and `connect()`, so the key the
41
- * target publishes and the key the client reads cannot drift.
42
- */
43
- keys;
44
- /**
45
- * The resolved value, held as the *promise* rather than the value.
46
- *
47
- * Caching the promise is what makes two concurrent registrations share one
48
- * resolution: caching the value would let both start before either finished,
49
- * which is a duplicated fetch every cold start rather than never.
50
- */
51
- resolved;
52
- constructor(id, options) {
53
- this.options = options;
54
- const canonical = canonicalId(id);
55
- this.id = canonical;
56
- this.keys = { credentials: provideKey(canonical, "credentials") };
57
- this.service = {
58
- serviceName: serviceKey(canonical),
59
- register: (registerOptions) => this.connect(registerOptions)
60
- };
61
- }
62
- /**
63
- * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value
64
- * is validated against where it is read. Public so a tool setting the value
65
- * (`gkm secrets:add`) can check it, and describe its fields, before it is
66
- * stored rather than at the first request.
67
- */
68
- get credentialsSchema() {
69
- return this.options.schema;
70
- }
71
- declare() {
72
- return [{
73
- kind: "credential",
74
- id: this.id,
75
- provides: [this.keys.credentials]
76
- }];
77
- }
78
- connect(options) {
79
- if (this.options.refresh) return this.resolve(options);
80
- this.resolved ??= this.resolve(options);
81
- return this.resolved;
82
- }
83
- resolve(options) {
84
- return readCredentials(this.id, this.keys.credentials, this.options.schema, options.envParser);
85
- }
86
- };
87
- /**
88
- * A credentials key, read and validated against its schema.
89
- *
90
- * Shared with every construct that holds a third party's credentials — an
91
- * `ExternalApi` reads its own the same way — so the shape a stage stores and
92
- * the error a bad value raises are the same everywhere.
93
- *
94
- * @throws {MalformedCredential} when the value is not what the schema says.
95
- */
96
- async function readCredentials(id, key, schema, envParser) {
97
- const { raw } = envParser.create((get) => ({ raw: get(key).string() })).parse();
98
- try {
99
- return await parseSchema(schema, decodeCredentials(raw));
100
- } catch (issues) {
101
- throw new MalformedCredential(id, key, issues);
102
- }
103
- }
104
- /**
105
- * The raw environment value as the thing the schema should see.
106
- *
107
- * JSON when it is JSON, and the string itself when it is not — a credential
108
- * with a single opaque field is ordinary, and requiring `"…"` around it would
109
- * be ceremony that every operator setting one by hand would get wrong once.
110
- *
111
- * Exported so a tool checking a value before it is stored reads it exactly as
112
- * the process that uses it will.
113
- */
114
- function decodeCredentials(raw) {
115
- const value = raw.startsWith(JSON_SCHEME) ? raw.slice(JSON_SCHEME.length) : raw;
116
- try {
117
- return JSON.parse(value);
118
- } catch {
119
- return value;
120
- }
121
- }
122
- /**
123
- * The explicit form, for the case a credential legitimately *is* a JSON string
124
- * and must not be parsed into an object. Rare, and cheaper to support than to
125
- * explain.
126
- */
127
- const JSON_SCHEME = "json:";
128
- /** A credential was set, and is not what its schema says it should be. */
129
- var MalformedCredential = class extends Error {
130
- id;
131
- key;
132
- issues;
133
- constructor(id, key, issues) {
134
- super(`${key} is not a valid ${id} credential. It is validated where it is read, so this is the value that is set rather than the code that uses it: ${describe(issues)}`);
135
- this.id = id;
136
- this.key = key;
137
- this.issues = issues;
138
- this.name = "MalformedCredential";
139
- }
140
- };
141
- /** StandardSchema issues as one line. */
142
- function describe(issues) {
143
- if (!Array.isArray(issues)) return String(issues);
144
- return issues.map((issue) => {
145
- const path = issue.path?.map((segment) => typeof segment === "object" ? String(segment.key) : String(segment)).join(".");
146
- return path ? `${path}: ${issue.message}` : issue.message;
147
- }).join("; ");
148
- }
149
- //#endregion
150
- export { Credential, MalformedCredential, decodeCredentials, readCredentials };
151
-
152
- //# sourceMappingURL=credential.mjs.map
1
+ import { a as fake, i as readCredentials, n as MalformedCredential, o as isFake, r as decodeCredentials, t as Credential } from "./credential-DfSAOOdY.mjs";
2
+ export { Credential, MalformedCredential, decodeCredentials, fake, isFake, readCredentials };
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_credential = require("./credential.cjs");
2
+ const require_credential = require("./credential-DYymbp_7.cjs");
3
3
  const require_tracing = require("./tracing-DPMidF_r.cjs");
4
4
  let _geekmidas_manifest = require("@geekmidas/manifest");
5
5
  //#region src/external-api.ts
@@ -98,45 +98,9 @@ function hostOf(url) {
98
98
  return url;
99
99
  }
100
100
  }
101
- /**
102
- * Marks a fake. A registered symbol, so a fake built by a second copy of this
103
- * package — a linked workspace, two versions in a lockfile — is still one.
104
- */
105
- const FAKE = Symbol.for("@geekmidas/constructs/fake");
106
- /**
107
- * Build the fake `test/fakes/<id>.ts` default-exports.
108
- *
109
- * Pass the API's type to have the credentials checked against its schema —
110
- * `fake.app<typeof polar>(…)`.
111
- */
112
- const fake = {
113
- /** A working implementation of the API, kept beside the tests that use it. */
114
- app(handler, options) {
115
- return {
116
- [FAKE]: true,
117
- kind: "app",
118
- handler,
119
- credentials: options.credentials
120
- };
121
- },
122
- /** A local server the provider publishes — `stripe/stripe-mock`. */
123
- image(image, options) {
124
- return {
125
- [FAKE]: true,
126
- kind: "image",
127
- image,
128
- port: options.port,
129
- credentials: options.credentials
130
- };
131
- }
132
- };
133
- /** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
134
- function isFake(value) {
135
- return typeof value === "object" && value !== null && value[FAKE] === true;
136
- }
137
101
  //#endregion
138
102
  exports.ExternalApi = ExternalApi;
139
- exports.fake = fake;
140
- exports.isFake = isFake;
103
+ exports.fake = require_credential.fake;
104
+ exports.isFake = require_credential.isFake;
141
105
 
142
106
  //# sourceMappingURL=external-api.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"external-api.cjs","names":["canonicalId","provideKey","serviceKey","readCredentials","traceClient"],"sources":["../src/external-api.ts"],"sourcesContent":["/**\n * `ExternalApi` — an HTTP API somebody else runs.\n *\n * Polar, Stripe, a payment gateway: nothing to provision, but an address that\n * changes by stage and credentials the provider issued for each one. Without a\n * construct every integration writes that switching by hand — an optional\n * `POLAR_URL`, a fake started somewhere, a client built in a service — and the\n * target cannot see any of it.\n *\n * ```ts\n * // constructs/polar.ts\n * export const polar = new ExternalApi('Polar', {\n * url: 'https://www.polaraccesslink.com',\n * credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),\n * client: ({ url, credentials }) => new PolarClient(url, credentials),\n * });\n *\n * // test/fakes/polar.ts\n * export default fake.app(new Hono().post('/v3/oauth2/token', …), {\n * credentials: { clientId: 'fake', clientSecret: 'fake' },\n * });\n *\n * // in a handler — the real API deployed, the fake locally and in tests\n * .dependsOn([polar])\n * .handle(({ services }) => services.polar.exchangeCode(code))\n * ```\n *\n * Deployed, the URL is `url` — one for every stage, or one per stage name with\n * a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one\n * JSON value read the way a `Credential`'s is. Locally and in tests both come\n * from the fake.\n *\n * **The construct never names its fake.** It is found by convention, at\n * `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —\n * so a fake, and the recorded responses it answers from, cannot end up in a\n * deployed bundle however the bundler follows imports.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Consumable } from './construct-interface';\nimport { readCredentials } from './credential';\nimport type { DeployedStage, LocalStage } from './stages';\nimport { traceClient } from './tracing';\n\n/** What a credentials schema yields. */\ntype Value<TSchema extends StandardSchemaV1> =\n\tStandardSchemaV1.InferOutput<TSchema>;\n\n/**\n * Where an external API answers: one URL for every stage, or one per stage\n * name with `default` for any stage not listed.\n *\n * Keyed by the stages `gkm.config.ts` declares once `.gkm/stages.d.ts` exists,\n * so a key that names no stage — `prodution` — is a type error rather than a\n * URL nothing reads. Without the file any key goes, as before.\n */\nexport type ExternalApiUrl =\n\t| string\n\t| (string extends LocalStage | DeployedStage\n\t\t\t? Readonly<Record<string, string>>\n\t\t\t: { readonly [S in LocalStage | DeployedStage]?: string } & {\n\t\t\t\t\treadonly default?: string;\n\t\t\t\t});\n\nexport interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {\n\t/**\n\t * Where it answers deployed: one URL for every stage, or one per stage\n\t * name, with `default` for any stage not listed.\n\t */\n\turl: ExternalApiUrl;\n\t/** What the stage's `<ID>_CREDENTIALS` must look like. */\n\tcredentials: TSchema;\n\t/** What a handler is handed, built from where it answers and the credentials. */\n\tclient: (connection: {\n\t\turl: string;\n\t\tcredentials: Value<TSchema>;\n\t}) => TClient | Promise<TClient>;\n}\n\nexport class ExternalApi<\n\tTName extends string = string,\n\tTSchema extends StandardSchemaV1 = StandardSchemaV1,\n\tTClient = unknown,\n> implements Consumable<TName, TClient>\n{\n\t// `Consumable` for the reason `Credential` gives: a client generic in\n\t// `TClient` cannot satisfy `Construct`'s conditional service type.\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, TClient>;\n\n\t/** Read by both `declare()` and `connect()`, so the two cannot drift. */\n\tprivate readonly keys: { url: string; credentials: string };\n\n\t/** The promise, so concurrent registrations share one client. */\n\tprivate connected?: Promise<TClient>;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: ExternalApiOptions<TSchema, TClient>,\n\t) {\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.keys = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\tcredentials: provideKey(canonical, 'credentials'),\n\t\t};\n\n\t\t// A field, not a getter: consumers cache services by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\tregister: (registerOptions) => {\n\t\t\t\tthis.connected ??= this.connect(registerOptions);\n\t\t\t\treturn this.connected;\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value\n\t * is validated against where it is read. Public so a tool setting the value\n\t * (`gkm secrets:add`) can check it, and describe its fields, before it is\n\t * stored rather than at the first request.\n\t */\n\tget credentialsSchema(): TSchema {\n\t\treturn this.options.credentials;\n\t}\n\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'external-api',\n\t\t\t\tid: this.id,\n\t\t\t\t// The stage-keyed map is a record of URLs to the manifest, which\n\t\t\t\t// reads it by whatever stage it is resolving.\n\t\t\t\turl: this.options.url as Readonly<Record<string, string>> | string,\n\t\t\t\tprovides: [this.keys.url, this.keys.credentials],\n\t\t\t},\n\t\t];\n\t}\n\n\tprivate async connect(options: ServiceRegisterOptions): Promise<TClient> {\n\t\tconst { url } = options.envParser\n\t\t\t.create((get) => ({ url: get(this.keys.url).string() }))\n\t\t\t.parse();\n\t\tconst credentials = await readCredentials(\n\t\t\tthis.id,\n\t\t\tthis.keys.credentials,\n\t\t\tthis.options.credentials,\n\t\t\toptions.envParser,\n\t\t);\n\n\t\tconst client = await this.options.client({ url, credentials });\n\t\t// Each call a span carrying this API's name — the parent of the fetch\n\t\t// it makes, which is traced already.\n\t\treturn traceClient(this.id, client, {\n\t\t\t'server.address': hostOf(url),\n\t\t});\n\t}\n}\n\nfunction hostOf(url: string): string {\n\ttry {\n\t\treturn new URL(url).host;\n\t} catch {\n\t\treturn url;\n\t}\n}\n\n/** Anything that answers a request — a Hono app, or a bare `{ fetch }`. */\nexport interface FetchHandler {\n\tfetch(request: Request): Response | Promise<Response>;\n}\n\n/**\n * Marks a fake. A registered symbol, so a fake built by a second copy of this\n * package — a linked workspace, two versions in a lockfile — is still one.\n */\nconst FAKE = Symbol.for('@geekmidas/constructs/fake');\n\n/** What an external API's credentials look like going in, for a fake to supply. */\ntype CredentialsOf<TApi> =\n\tTApi extends ExternalApi<string, infer TSchema, unknown>\n\t\t? StandardSchemaV1.InferInput<TSchema>\n\t\t: unknown;\n\n/**\n * An external API's stand-in, as `test/fakes/<id>.ts` default-exports it.\n *\n * `credentials` are what the fake accepts, and what a local or test stage is\n * handed as `<ID>_CREDENTIALS` in place of the stage's own.\n */\nexport type Fake = {\n\treadonly [FAKE]: true;\n\treadonly credentials: unknown;\n} & (\n\t| {\n\t\t\treadonly kind: 'app';\n\t\t\t/** Served by gkm: in-process in a test, on its own port in `gkm dev`. */\n\t\t\treadonly handler: FetchHandler;\n\t }\n\t| {\n\t\t\treadonly kind: 'image';\n\t\t\t/** The provider's own local server, run as a container. */\n\t\t\treadonly image: string;\n\t\t\t/** The port it listens on inside the container. */\n\t\t\treadonly port: number;\n\t }\n);\n\n/**\n * Build the fake `test/fakes/<id>.ts` default-exports.\n *\n * Pass the API's type to have the credentials checked against its schema —\n * `fake.app<typeof polar>(…)`.\n */\nexport const fake = {\n\t/** A working implementation of the API, kept beside the tests that use it. */\n\tapp<TApi = unknown>(\n\t\thandler: FetchHandler,\n\t\toptions: { credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'app',\n\t\t\thandler,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n\n\t/** A local server the provider publishes — `stripe/stripe-mock`. */\n\timage<TApi = unknown>(\n\t\timage: string,\n\t\toptions: { port: number; credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'image',\n\t\t\timage,\n\t\t\tport: options.port,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n};\n\n/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */\nexport function isFake(value: unknown): value is Fake {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { [FAKE]?: unknown })[FAKE] === true\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,IAAa,cAAb,MAKA;CAcmB;CAXlB;CACA;;CAGA;;CAGA;CAEA,YACC,IACA,SACC;EADgB,KAAA,UAAA;EAEjB,MAAM,aAAA,GAAYA,oBAAAA,YAAAA,CAAY,EAAY;EAE1C,KAAK,KAAK;EACV,KAAK,OAAO;GACX,MAAA,GAAKC,oBAAAA,WAAAA,CAAW,WAAW,KAAK;GAChC,cAAA,GAAaA,oBAAAA,WAAAA,CAAW,WAAW,aAAa;EACjD;EAGA,KAAK,UAAU;GACd,cAAA,GAAaC,oBAAAA,WAAAA,CAAW,SAAS;GACjC,WAAW,oBAAoB;IAC9B,KAAK,cAAc,KAAK,QAAQ,eAAe;IAC/C,OAAO,KAAK;GACb;EACD;CACD;;;;;;;CAQA,IAAI,oBAA6B;EAChC,OAAO,KAAK,QAAQ;CACrB;CAEA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GAGT,KAAK,KAAK,QAAQ;GAClB,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW;EAChD,CACD;CACD;CAEA,MAAc,QAAQ,SAAmD;EACxE,MAAM,EAAE,QAAQ,QAAQ,UACtB,QAAQ,SAAS,EAAE,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvD,MAAM;EACR,MAAM,cAAc,MAAMC,mBAAAA,gBACzB,KAAK,IACL,KAAK,KAAK,aACV,KAAK,QAAQ,aACb,QAAQ,SACT;EAEA,MAAM,SAAS,MAAM,KAAK,QAAQ,OAAO;GAAE;GAAK;EAAY,CAAC;EAG7D,OAAOC,gBAAAA,YAAY,KAAK,IAAI,QAAQ,EACnC,kBAAkB,OAAO,GAAG,EAC7B,CAAC;CACF;AACD;AAEA,SAAS,OAAO,KAAqB;CACpC,IAAI;EACH,OAAO,IAAI,IAAI,GAAG,CAAC,CAAC;CACrB,QAAQ;EACP,OAAO;CACR;AACD;;;;;AAWA,MAAM,OAAO,OAAO,IAAI,4BAA4B;;;;;;;AAsCpD,MAAa,OAAO;;CAEnB,IACC,SACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,aAAa,QAAQ;EACtB;CACD;;CAGA,MACC,OACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,MAAM,QAAQ;GACd,aAAa,QAAQ;EACtB;CACD;AACD;;AAGA,SAAgB,OAAO,OAA+B;CACrD,OACC,OAAO,UAAU,YACjB,UAAU,QACT,MAA+B,UAAU;AAE5C"}
1
+ {"version":3,"file":"external-api.cjs","names":["canonicalId","provideKey","serviceKey","readCredentials","traceClient"],"sources":["../src/external-api.ts"],"sourcesContent":["/**\n * `ExternalApi` — an HTTP API somebody else runs.\n *\n * Polar, Stripe, a payment gateway: nothing to provision, but an address that\n * changes by stage and credentials the provider issued for each one. Without a\n * construct every integration writes that switching by hand — an optional\n * `POLAR_URL`, a fake started somewhere, a client built in a service — and the\n * target cannot see any of it.\n *\n * ```ts\n * // constructs/polar.ts\n * export const polar = new ExternalApi('Polar', {\n * url: 'https://www.polaraccesslink.com',\n * credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),\n * client: ({ url, credentials }) => new PolarClient(url, credentials),\n * });\n *\n * // test/fakes/polar.ts\n * export default fake.app(new Hono().post('/v3/oauth2/token', …), {\n * credentials: { clientId: 'fake', clientSecret: 'fake' },\n * });\n *\n * // in a handler — the real API deployed, the fake locally and in tests\n * .dependsOn([polar])\n * .handle(({ services }) => services.polar.exchangeCode(code))\n * ```\n *\n * Deployed, the URL is `url` — one for every stage, or one per stage name with\n * a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one\n * JSON value read the way a `Credential`'s is. Locally and in tests both come\n * from the fake.\n *\n * **The construct never names its fake.** It is found by convention, at\n * `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —\n * so a fake, and the recorded responses it answers from, cannot end up in a\n * deployed bundle however the bundler follows imports.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Consumable } from './construct-interface';\nimport { readCredentials } from './credential';\nimport type { DeployedStage, LocalStage } from './stages';\nimport { traceClient } from './tracing';\n\n/** What a credentials schema yields. */\ntype Value<TSchema extends StandardSchemaV1> =\n\tStandardSchemaV1.InferOutput<TSchema>;\n\n/**\n * Where an external API answers: one URL for every stage, or one per stage\n * name with `default` for any stage not listed.\n *\n * Keyed by the stages `gkm.config.ts` declares once `.gkm/stages.d.ts` exists,\n * so a key that names no stage — `prodution` — is a type error rather than a\n * URL nothing reads. Without the file any key goes, as before.\n */\nexport type ExternalApiUrl =\n\t| string\n\t| (string extends LocalStage | DeployedStage\n\t\t\t? Readonly<Record<string, string>>\n\t\t\t: { readonly [S in LocalStage | DeployedStage]?: string } & {\n\t\t\t\t\treadonly default?: string;\n\t\t\t\t});\n\nexport interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {\n\t/**\n\t * Where it answers deployed: one URL for every stage, or one per stage\n\t * name, with `default` for any stage not listed.\n\t */\n\turl: ExternalApiUrl;\n\t/** What the stage's `<ID>_CREDENTIALS` must look like. */\n\tcredentials: TSchema;\n\t/** What a handler is handed, built from where it answers and the credentials. */\n\tclient: (connection: {\n\t\turl: string;\n\t\tcredentials: Value<TSchema>;\n\t}) => TClient | Promise<TClient>;\n}\n\nexport class ExternalApi<\n\tTName extends string = string,\n\tTSchema extends StandardSchemaV1 = StandardSchemaV1,\n\tTClient = unknown,\n> implements Consumable<TName, TClient>\n{\n\t// `Consumable` for the reason `Credential` gives: a client generic in\n\t// `TClient` cannot satisfy `Construct`'s conditional service type.\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, TClient>;\n\n\t/** Read by both `declare()` and `connect()`, so the two cannot drift. */\n\tprivate readonly keys: { url: string; credentials: string };\n\n\t/** The promise, so concurrent registrations share one client. */\n\tprivate connected?: Promise<TClient>;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: ExternalApiOptions<TSchema, TClient>,\n\t) {\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.keys = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\tcredentials: provideKey(canonical, 'credentials'),\n\t\t};\n\n\t\t// A field, not a getter: consumers cache services by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\tregister: (registerOptions) => {\n\t\t\t\tthis.connected ??= this.connect(registerOptions);\n\t\t\t\treturn this.connected;\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * What the stage's `<ID>_CREDENTIALS` must look like — the schema the value\n\t * is validated against where it is read. Public so a tool setting the value\n\t * (`gkm secrets:add`) can check it, and describe its fields, before it is\n\t * stored rather than at the first request.\n\t */\n\tget credentialsSchema(): TSchema {\n\t\treturn this.options.credentials;\n\t}\n\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'external-api',\n\t\t\t\tid: this.id,\n\t\t\t\t// The stage-keyed map is a record of URLs to the manifest, which\n\t\t\t\t// reads it by whatever stage it is resolving.\n\t\t\t\turl: this.options.url as Readonly<Record<string, string>> | string,\n\t\t\t\tprovides: [this.keys.url, this.keys.credentials],\n\t\t\t},\n\t\t];\n\t}\n\n\tprivate async connect(options: ServiceRegisterOptions): Promise<TClient> {\n\t\tconst { url } = options.envParser\n\t\t\t.create((get) => ({ url: get(this.keys.url).string() }))\n\t\t\t.parse();\n\t\tconst credentials = await readCredentials(\n\t\t\tthis.id,\n\t\t\tthis.keys.credentials,\n\t\t\tthis.options.credentials,\n\t\t\toptions.envParser,\n\t\t);\n\n\t\tconst client = await this.options.client({ url, credentials });\n\t\t// Each call a span carrying this API's name — the parent of the fetch\n\t\t// it makes, which is traced already.\n\t\treturn traceClient(this.id, client, {\n\t\t\t'server.address': hostOf(url),\n\t\t});\n\t}\n}\n\nfunction hostOf(url: string): string {\n\ttry {\n\t\treturn new URL(url).host;\n\t} catch {\n\t\treturn url;\n\t}\n}\n\nexport {\n\ttype Fake,\n\ttype FetchHandler,\n\tfake,\n\tisFake,\n} from './fake';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuFA,IAAa,cAAb,MAKA;CAcmB;CAXlB;CACA;;CAGA;;CAGA;CAEA,YACC,IACA,SACC;EADgB,KAAA,UAAA;EAEjB,MAAM,aAAA,GAAYA,oBAAAA,YAAAA,CAAY,EAAY;EAE1C,KAAK,KAAK;EACV,KAAK,OAAO;GACX,MAAA,GAAKC,oBAAAA,WAAAA,CAAW,WAAW,KAAK;GAChC,cAAA,GAAaA,oBAAAA,WAAAA,CAAW,WAAW,aAAa;EACjD;EAGA,KAAK,UAAU;GACd,cAAA,GAAaC,oBAAAA,WAAAA,CAAW,SAAS;GACjC,WAAW,oBAAoB;IAC9B,KAAK,cAAc,KAAK,QAAQ,eAAe;IAC/C,OAAO,KAAK;GACb;EACD;CACD;;;;;;;CAQA,IAAI,oBAA6B;EAChC,OAAO,KAAK,QAAQ;CACrB;CAEA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GAGT,KAAK,KAAK,QAAQ;GAClB,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW;EAChD,CACD;CACD;CAEA,MAAc,QAAQ,SAAmD;EACxE,MAAM,EAAE,QAAQ,QAAQ,UACtB,QAAQ,SAAS,EAAE,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvD,MAAM;EACR,MAAM,cAAc,MAAMC,mBAAAA,gBACzB,KAAK,IACL,KAAK,KAAK,aACV,KAAK,QAAQ,aACb,QAAQ,SACT;EAEA,MAAM,SAAS,MAAM,KAAK,QAAQ,OAAO;GAAE;GAAK;EAAY,CAAC;EAG7D,OAAOC,gBAAAA,YAAY,KAAK,IAAI,QAAQ,EACnC,kBAAkB,OAAO,GAAG,EAC7B,CAAC;CACF;AACD;AAEA,SAAS,OAAO,KAAqB;CACpC,IAAI;EACH,OAAO,IAAI,IAAI,GAAG,CAAC,CAAC;CACrB,QAAQ;EACP,OAAO;CACR;AACD"}
@@ -1,2 +1,2 @@
1
- import { a as FetchHandler, i as Fake, n as ExternalApiOptions, o as fake, r as ExternalApiUrl, s as isFake, t as ExternalApi } from "./external-api-O107yzZJ.cjs";
2
- export { ExternalApi, ExternalApiOptions, ExternalApiUrl, Fake, FetchHandler, fake, isFake };
1
+ import { a as ExternalApi, i as isFake, n as FetchHandler, o as ExternalApiOptions, r as fake, s as ExternalApiUrl, t as Fake } from "./fake-Dvion_Fh.cjs";
2
+ export { ExternalApi, ExternalApiOptions, ExternalApiUrl, type Fake, type FetchHandler, fake, isFake };
@@ -1,2 +1,2 @@
1
- import { a as FetchHandler, i as Fake, n as ExternalApiOptions, o as fake, r as ExternalApiUrl, s as isFake, t as ExternalApi } from "./external-api-MJ8id87V.mjs";
2
- export { ExternalApi, ExternalApiOptions, ExternalApiUrl, Fake, FetchHandler, fake, isFake };
1
+ import { a as ExternalApi, i as isFake, n as FetchHandler, o as ExternalApiOptions, r as fake, s as ExternalApiUrl, t as Fake } from "./fake-BcHTPz7N.mjs";
2
+ export { ExternalApi, ExternalApiOptions, ExternalApiUrl, type Fake, type FetchHandler, fake, isFake };
@@ -1,4 +1,4 @@
1
- import { readCredentials } from "./credential.mjs";
1
+ import { a as fake, i as readCredentials, o as isFake } from "./credential-DfSAOOdY.mjs";
2
2
  import { r as traceClient } from "./tracing-CxaZ98IB.mjs";
3
3
  import { canonicalId, provideKey, serviceKey } from "@geekmidas/manifest";
4
4
  //#region src/external-api.ts
@@ -97,42 +97,6 @@ function hostOf(url) {
97
97
  return url;
98
98
  }
99
99
  }
100
- /**
101
- * Marks a fake. A registered symbol, so a fake built by a second copy of this
102
- * package — a linked workspace, two versions in a lockfile — is still one.
103
- */
104
- const FAKE = Symbol.for("@geekmidas/constructs/fake");
105
- /**
106
- * Build the fake `test/fakes/<id>.ts` default-exports.
107
- *
108
- * Pass the API's type to have the credentials checked against its schema —
109
- * `fake.app<typeof polar>(…)`.
110
- */
111
- const fake = {
112
- /** A working implementation of the API, kept beside the tests that use it. */
113
- app(handler, options) {
114
- return {
115
- [FAKE]: true,
116
- kind: "app",
117
- handler,
118
- credentials: options.credentials
119
- };
120
- },
121
- /** A local server the provider publishes — `stripe/stripe-mock`. */
122
- image(image, options) {
123
- return {
124
- [FAKE]: true,
125
- kind: "image",
126
- image,
127
- port: options.port,
128
- credentials: options.credentials
129
- };
130
- }
131
- };
132
- /** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
133
- function isFake(value) {
134
- return typeof value === "object" && value !== null && value[FAKE] === true;
135
- }
136
100
  //#endregion
137
101
  export { ExternalApi, fake, isFake };
138
102