@glubean/sdk 0.2.1 → 0.2.3

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 (119) hide show
  1. package/dist/bootstrap-registry.d.ts +38 -0
  2. package/dist/bootstrap-registry.d.ts.map +1 -0
  3. package/dist/bootstrap-registry.js +54 -0
  4. package/dist/bootstrap-registry.js.map +1 -0
  5. package/dist/configure/http.d.ts +25 -0
  6. package/dist/configure/http.d.ts.map +1 -0
  7. package/dist/configure/http.js +88 -0
  8. package/dist/configure/http.js.map +1 -0
  9. package/dist/configure/index.d.ts +78 -0
  10. package/dist/configure/index.d.ts.map +1 -0
  11. package/dist/configure/index.js +78 -0
  12. package/dist/configure/index.js.map +1 -0
  13. package/dist/configure/plugin.d.ts +23 -0
  14. package/dist/configure/plugin.d.ts.map +1 -0
  15. package/dist/configure/plugin.js +81 -0
  16. package/dist/configure/plugin.js.map +1 -0
  17. package/dist/configure/runtime.d.ts +24 -0
  18. package/dist/configure/runtime.d.ts.map +1 -0
  19. package/dist/configure/runtime.js +45 -0
  20. package/dist/configure/runtime.js.map +1 -0
  21. package/dist/configure/template.d.ts +22 -0
  22. package/dist/configure/template.d.ts.map +1 -0
  23. package/dist/configure/template.js +34 -0
  24. package/dist/configure/template.js.map +1 -0
  25. package/dist/configure/vars.d.ts +20 -0
  26. package/dist/configure/vars.d.ts.map +1 -0
  27. package/dist/configure/vars.js +48 -0
  28. package/dist/configure/vars.js.map +1 -0
  29. package/dist/configure.d.ts +2 -133
  30. package/dist/configure.d.ts.map +1 -1
  31. package/dist/configure.js +2 -436
  32. package/dist/configure.js.map +1 -1
  33. package/dist/contract-artifacts.d.ts +268 -0
  34. package/dist/contract-artifacts.d.ts.map +1 -0
  35. package/dist/contract-artifacts.js +402 -0
  36. package/dist/contract-artifacts.js.map +1 -0
  37. package/dist/contract-core.d.ts +43 -1
  38. package/dist/contract-core.d.ts.map +1 -1
  39. package/dist/contract-core.js +376 -5
  40. package/dist/contract-core.js.map +1 -1
  41. package/dist/contract-http/adapter.d.ts +1 -7
  42. package/dist/contract-http/adapter.d.ts.map +1 -1
  43. package/dist/contract-http/adapter.js +221 -199
  44. package/dist/contract-http/adapter.js.map +1 -1
  45. package/dist/contract-http/factory.d.ts.map +1 -1
  46. package/dist/contract-http/factory.js +13 -14
  47. package/dist/contract-http/factory.js.map +1 -1
  48. package/dist/contract-http/index.d.ts +1 -0
  49. package/dist/contract-http/index.d.ts.map +1 -1
  50. package/dist/contract-http/index.js +1 -0
  51. package/dist/contract-http/index.js.map +1 -1
  52. package/dist/contract-http/openapi.d.ts +56 -7
  53. package/dist/contract-http/openapi.d.ts.map +1 -1
  54. package/dist/contract-http/openapi.js +371 -21
  55. package/dist/contract-http/openapi.js.map +1 -1
  56. package/dist/contract-http/types.d.ts +72 -24
  57. package/dist/contract-http/types.d.ts.map +1 -1
  58. package/dist/contract-http/types.js +45 -1
  59. package/dist/contract-http/types.js.map +1 -1
  60. package/dist/contract-types.d.ts +270 -30
  61. package/dist/contract-types.d.ts.map +1 -1
  62. package/dist/expect.d.ts +13 -0
  63. package/dist/expect.d.ts.map +1 -1
  64. package/dist/expect.js +18 -0
  65. package/dist/expect.js.map +1 -1
  66. package/dist/index.d.ts +57 -10
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +15 -8
  69. package/dist/index.js.map +1 -1
  70. package/dist/install-plugin.d.ts +94 -0
  71. package/dist/install-plugin.d.ts.map +1 -0
  72. package/dist/install-plugin.js +222 -0
  73. package/dist/install-plugin.js.map +1 -0
  74. package/dist/internal.d.ts +2 -0
  75. package/dist/internal.d.ts.map +1 -1
  76. package/dist/internal.js +8 -0
  77. package/dist/internal.js.map +1 -1
  78. package/dist/plugin.d.ts +45 -34
  79. package/dist/plugin.d.ts.map +1 -1
  80. package/dist/plugin.js +47 -34
  81. package/dist/plugin.js.map +1 -1
  82. package/dist/runner-input-channel.d.ts +95 -0
  83. package/dist/runner-input-channel.d.ts.map +1 -0
  84. package/dist/runner-input-channel.js +110 -0
  85. package/dist/runner-input-channel.js.map +1 -0
  86. package/dist/{test-builder.d.ts → test/builder.d.ts} +2 -2
  87. package/dist/test/builder.d.ts.map +1 -0
  88. package/dist/{test-builder.js → test/builder.js} +3 -3
  89. package/dist/{test-builder.js.map → test/builder.js.map} +1 -1
  90. package/dist/{each-builder.d.ts → test/each-builder.d.ts} +1 -1
  91. package/dist/test/each-builder.d.ts.map +1 -0
  92. package/dist/{each-builder.js → test/each-builder.js} +3 -3
  93. package/dist/test/each-builder.js.map +1 -0
  94. package/dist/{test-extend.d.ts → test/extend.d.ts} +3 -3
  95. package/dist/test/extend.d.ts.map +1 -0
  96. package/dist/{test-extend.js → test/extend.js} +5 -5
  97. package/dist/test/extend.js.map +1 -0
  98. package/dist/{test-utils.d.ts → test/utils.d.ts} +2 -2
  99. package/dist/test/utils.d.ts.map +1 -0
  100. package/dist/{test-utils.js → test/utils.js} +1 -1
  101. package/dist/test/utils.js.map +1 -0
  102. package/dist/types.d.ts +78 -7
  103. package/dist/types.d.ts.map +1 -1
  104. package/package.json +1 -1
  105. package/dist/contract-http/flow-helpers.d.ts +0 -12
  106. package/dist/contract-http/flow-helpers.d.ts.map +0 -1
  107. package/dist/contract-http/flow-helpers.js +0 -34
  108. package/dist/contract-http/flow-helpers.js.map +0 -1
  109. package/dist/contract-http/markdown.d.ts +0 -10
  110. package/dist/contract-http/markdown.d.ts.map +0 -1
  111. package/dist/contract-http/markdown.js +0 -21
  112. package/dist/contract-http/markdown.js.map +0 -1
  113. package/dist/each-builder.d.ts.map +0 -1
  114. package/dist/each-builder.js.map +0 -1
  115. package/dist/test-builder.d.ts.map +0 -1
  116. package/dist/test-extend.d.ts.map +0 -1
  117. package/dist/test-extend.js.map +0 -1
  118. package/dist/test-utils.d.ts.map +0 -1
  119. package/dist/test-utils.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/configure/template.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iDAAiD;AACjD,MAAM,CAAC,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAgB,EAChB,IAA4B,EAC5B,OAA+B,EAC/B,OAAiC;IAEjC,OAAO,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,GAAW,EAAE,EAAE;QAC3D,MAAM,YAAY,GAAG,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,KAAK,GACT,CAAC,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;YAC7D,OAAO,CAAC,GAAG,CAAC;YACZ,IAAI,CAAC,GAAG,CAAC,CAAC;QACZ,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CACb,6CAA6C,GAAG,mCAAmC;gBACjF,WAAW,GAAG,sDAAsD,CACvE,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @module configure/vars
3
+ *
4
+ * Lazy vars and secrets accessor builders for configure().
5
+ *
6
+ * Each property is an Object.defineProperty getter that resolves at access time.
7
+ * Values support `{{key}}` template syntax or literal strings.
8
+ * Not cached — re-reads runtime on every access so session updates are visible.
9
+ */
10
+ /**
11
+ * Build a lazy vars accessor. Each property resolves via resolveTemplate on access.
12
+ * @internal
13
+ */
14
+ export declare function buildLazyVars<V extends Record<string, string>>(mapping: Record<string, string>): Readonly<V>;
15
+ /**
16
+ * Build a lazy secrets accessor. Each property resolves via resolveTemplate on access.
17
+ * @internal
18
+ */
19
+ export declare function buildLazySecrets<S extends Record<string, string>>(mapping: Record<string, string>): Readonly<S>;
20
+ //# sourceMappingURL=vars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vars.d.ts","sourceRoot":"","sources":["../../src/configure/vars.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,QAAQ,CAAC,CAAC,CAAC,CAab;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/D,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,QAAQ,CAAC,CAAC,CAAC,CAab"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @module configure/vars
3
+ *
4
+ * Lazy vars and secrets accessor builders for configure().
5
+ *
6
+ * Each property is an Object.defineProperty getter that resolves at access time.
7
+ * Values support `{{key}}` template syntax or literal strings.
8
+ * Not cached — re-reads runtime on every access so session updates are visible.
9
+ */
10
+ import { getRuntime } from "./runtime.js";
11
+ import { resolveTemplate } from "./template.js";
12
+ /**
13
+ * Build a lazy vars accessor. Each property resolves via resolveTemplate on access.
14
+ * @internal
15
+ */
16
+ export function buildLazyVars(mapping) {
17
+ const obj = {};
18
+ for (const [prop, value] of Object.entries(mapping)) {
19
+ Object.defineProperty(obj, prop, {
20
+ get() {
21
+ const runtime = getRuntime();
22
+ return resolveTemplate(value, runtime.vars, runtime.secrets, runtime.session);
23
+ },
24
+ enumerable: true,
25
+ configurable: false,
26
+ });
27
+ }
28
+ return obj;
29
+ }
30
+ /**
31
+ * Build a lazy secrets accessor. Each property resolves via resolveTemplate on access.
32
+ * @internal
33
+ */
34
+ export function buildLazySecrets(mapping) {
35
+ const obj = {};
36
+ for (const [prop, value] of Object.entries(mapping)) {
37
+ Object.defineProperty(obj, prop, {
38
+ get() {
39
+ const runtime = getRuntime();
40
+ return resolveTemplate(value, runtime.vars, runtime.secrets, runtime.session);
41
+ },
42
+ enumerable: true,
43
+ configurable: false,
44
+ });
45
+ }
46
+ return obj;
47
+ }
48
+ //# sourceMappingURL=vars.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vars.js","sourceRoot":"","sources":["../../src/configure/vars.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,OAA+B;IAE/B,MAAM,GAAG,GAAG,EAA4B,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE;YAC/B,GAAG;gBACD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;gBAC7B,OAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAChF,CAAC;YACD,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAA6B,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAA+B;IAE/B,MAAM,GAAG,GAAG,EAA4B,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE;YAC/B,GAAG;gBACD,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;gBAC7B,OAAO,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAChF,CAAC;YACD,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAA6B,CAAC;AACvC,CAAC"}
@@ -1,134 +1,3 @@
1
- /**
2
- * File-level configuration for Glubean tests.
3
- *
4
- * `configure()` lets you declare shared dependencies (vars, secrets, HTTP config)
5
- * once at the top of a test file (or in a shared `configure.ts`), eliminating
6
- * repetitive `ctx.vars.require()` / `ctx.secrets.require()` calls in every test.
7
- *
8
- * All returned values are **lazy** — they are not resolved until a test function
9
- * actually accesses them at runtime. This means:
10
- * - Safe to call at module top-level (scanner won't trigger resolution)
11
- * - Safe to share across files via re-exports
12
- * - Each test execution gets the correct runtime values
13
- *
14
- * @example Single file usage
15
- * ```ts
16
- * import { test, configure } from "@glubean/sdk";
17
- *
18
- * const { vars, secrets, http } = configure({
19
- * vars: { baseUrl: "BASE_URL" },
20
- * secrets: { apiKey: "API_KEY" },
21
- * http: {
22
- * prefixUrl: "BASE_URL",
23
- * headers: { Authorization: "Bearer {{API_KEY}}" },
24
- * },
25
- * });
26
- *
27
- * export const listUsers = test("list-users", async (ctx) => {
28
- * const res = await http.get("users").json();
29
- * ctx.assert(res.length > 0, "has users");
30
- * });
31
- * ```
32
- *
33
- * @example Shared across files (tests/configure.ts)
34
- * ```ts
35
- * // tests/configure.ts
36
- * import { configure } from "@glubean/sdk";
37
- * export const { vars, secrets, http } = configure({
38
- * vars: { baseUrl: "BASE_URL" },
39
- * http: { prefixUrl: "BASE_URL" },
40
- * });
41
- *
42
- * // tests/users.test.ts
43
- * import { test } from "@glubean/sdk";
44
- * import { http } from "./configure.js";
45
- *
46
- * export const listUsers = test("list-users", async (ctx) => {
47
- * const res = await http.get("users").json();
48
- * });
49
- * ```
50
- *
51
- * @module configure
52
- */
53
- import type { ConfigureOptions, ConfigureResult, PluginFactory, ReservedConfigureKeys, ResolvePlugins } from "./types.js";
54
- import { type InternalRuntime } from "./runtime-carrier.js";
55
- export type { InternalRuntime };
56
- /**
57
- * Resolve `{{key}}` template placeholders in a string.
58
- *
59
- * Resolution priority (first non-empty wins):
60
- * 1. Session — dynamic values set during session setup (e.g., auth tokens)
61
- * 2. Secrets — from `.env.secrets`
62
- * 3. Vars — from `.env`
63
- *
64
- * Session values must be strings to resolve in templates. Non-string session
65
- * values are silently skipped (they're still accessible via `ctx.session.get()`).
66
- *
67
- * This is used internally by `buildLazyHttp()` and exposed to plugin authors
68
- * via `GlubeanRuntime.resolveTemplate()`.
69
- */
70
- export declare function resolveTemplate(template: string, vars: Record<string, string>, secrets: Record<string, string>, session?: Record<string, unknown>): string;
71
- /**
72
- * Declare file-level dependencies on vars, secrets, and HTTP configuration.
73
- *
74
- * Returns lazy accessors that resolve at test runtime, not at import time.
75
- * All declared vars and secrets are **required** — missing values cause the test
76
- * to fail immediately with a clear error message.
77
- *
78
- * The returned objects can be shared across files via re-exports.
79
- *
80
- * @param options Configuration declaring vars, secrets, and HTTP defaults
81
- * @returns Lazy accessors for vars, secrets, and a pre-configured HTTP client
82
- *
83
- * @example Basic usage
84
- * ```ts
85
- * import { test, configure } from "@glubean/sdk";
86
- *
87
- * const { vars, http } = configure({
88
- * vars: { baseUrl: "base_url" },
89
- * http: { prefixUrl: "base_url" },
90
- * });
91
- *
92
- * export const listUsers = test("list-users", async (ctx) => {
93
- * const res = await http.get("users").json();
94
- * ctx.log(`Base URL: ${vars.baseUrl}`);
95
- * });
96
- * ```
97
- *
98
- * @example Full configuration with secrets
99
- * ```ts
100
- * const { vars, secrets, http } = configure({
101
- * vars: { baseUrl: "base_url", orgId: "org_id" },
102
- * secrets: { apiKey: "api_key" },
103
- * http: {
104
- * prefixUrl: "base_url",
105
- * headers: { Authorization: "Bearer {{api_key}}" },
106
- * },
107
- * });
108
- * ```
109
- *
110
- * @example Shared across test files
111
- * ```ts
112
- * // tests/configure.ts
113
- * export const { vars, secrets, http } = configure({ ... });
114
- *
115
- * // tests/users.test.ts
116
- * import { http, vars } from "./configure.js";
117
- * ```
118
- */
119
- export declare function configure<V extends Record<string, string> = Record<string, string>, S extends Record<string, string> = Record<string, string>, P extends Record<string, PluginFactory<any>> = Record<string, never>>(options: ConfigureOptions & {
120
- vars?: {
121
- [K in keyof V]: string;
122
- };
123
- secrets?: {
124
- [K in keyof S]: string;
125
- };
126
- plugins?: P & {
127
- [K in ReservedConfigureKeys]?: never;
128
- };
129
- }): ConfigureResult<{
130
- [K in keyof V]: string;
131
- }, {
132
- [K in keyof S]: string;
133
- }> & ResolvePlugins<P>;
1
+ export { configure, resolveTemplate } from "./configure/index.js";
2
+ export type { InternalRuntime } from "./configure/index.js";
134
3
  //# sourceMappingURL=configure.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,EAEV,gBAAgB,EAChB,eAAe,EAGf,aAAa,EACb,qBAAqB,EACrB,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EAAE,eAAe,EAAE,CAAC;AA8GhC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC,MAAM,CAgBR;AAyOD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,SAAS,CACvB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACzD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAEzD,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAEpE,OAAO,EAAE,gBAAgB,GAAG;IAC1B,IAAI,CAAC,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;KAAE,CAAC;IAClC,OAAO,CAAC,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;KAAE,CAAC;IACrC,OAAO,CAAC,EAAE,CAAC,GAAG;SAAG,CAAC,IAAI,qBAAqB,CAAC,CAAC,EAAE,KAAK;KAAE,CAAC;CACxD,GAEC,eAAe,CACf;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;CAAE,EAC1B;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;CAAE,CAC3B,GACC,cAAc,CAAC,CAAC,CAAC,CAuBpB"}
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/configure.js CHANGED
@@ -1,437 +1,3 @@
1
- /**
2
- * File-level configuration for Glubean tests.
3
- *
4
- * `configure()` lets you declare shared dependencies (vars, secrets, HTTP config)
5
- * once at the top of a test file (or in a shared `configure.ts`), eliminating
6
- * repetitive `ctx.vars.require()` / `ctx.secrets.require()` calls in every test.
7
- *
8
- * All returned values are **lazy** — they are not resolved until a test function
9
- * actually accesses them at runtime. This means:
10
- * - Safe to call at module top-level (scanner won't trigger resolution)
11
- * - Safe to share across files via re-exports
12
- * - Each test execution gets the correct runtime values
13
- *
14
- * @example Single file usage
15
- * ```ts
16
- * import { test, configure } from "@glubean/sdk";
17
- *
18
- * const { vars, secrets, http } = configure({
19
- * vars: { baseUrl: "BASE_URL" },
20
- * secrets: { apiKey: "API_KEY" },
21
- * http: {
22
- * prefixUrl: "BASE_URL",
23
- * headers: { Authorization: "Bearer {{API_KEY}}" },
24
- * },
25
- * });
26
- *
27
- * export const listUsers = test("list-users", async (ctx) => {
28
- * const res = await http.get("users").json();
29
- * ctx.assert(res.length > 0, "has users");
30
- * });
31
- * ```
32
- *
33
- * @example Shared across files (tests/configure.ts)
34
- * ```ts
35
- * // tests/configure.ts
36
- * import { configure } from "@glubean/sdk";
37
- * export const { vars, secrets, http } = configure({
38
- * vars: { baseUrl: "BASE_URL" },
39
- * http: { prefixUrl: "BASE_URL" },
40
- * });
41
- *
42
- * // tests/users.test.ts
43
- * import { test } from "@glubean/sdk";
44
- * import { http } from "./configure.js";
45
- *
46
- * export const listUsers = test("list-users", async (ctx) => {
47
- * const res = await http.get("users").json();
48
- * });
49
- * ```
50
- *
51
- * @module configure
52
- */
53
- import { getRuntime as getCarrierRuntime, } from "./runtime-carrier.js";
54
- // =============================================================================
55
- // Runtime accessor
56
- // =============================================================================
57
- /**
58
- * Get the current runtime context, throwing if accessed outside test execution.
59
- * Thin wrapper over the carrier's optional `getRuntime()` that preserves the
60
- * legacy throw-on-missing contract.
61
- *
62
- * @internal
63
- */
64
- function getRuntime() {
65
- const runtime = getCarrierRuntime();
66
- if (!runtime) {
67
- throw new Error("configure() values can only be accessed during test execution. " +
68
- "Did you try to read a var or secret at module load time? " +
69
- "Move the access inside a test function.");
70
- }
71
- return runtime;
72
- }
73
- /**
74
- * Require a var from the runtime context.
75
- * Throws if the var is missing or empty.
76
- *
77
- * @internal
78
- */
79
- function requireVar(key) {
80
- const runtime = getRuntime();
81
- const value = runtime.vars[key];
82
- if (value === undefined || value === null || value === "") {
83
- throw new Error(`Missing required var: ${key}`);
84
- }
85
- return value;
86
- }
87
- /**
88
- * Require a secret from the runtime context.
89
- * Throws if the secret is missing or empty.
90
- *
91
- * @internal
92
- */
93
- function requireSecret(key) {
94
- const runtime = getRuntime();
95
- const value = runtime.secrets[key];
96
- if (value === undefined || value === null || value === "") {
97
- throw new Error(`Missing required secret: ${key}`);
98
- }
99
- return value;
100
- }
101
- // =============================================================================
102
- // Lazy proxy builders
103
- // =============================================================================
104
- /**
105
- * Regex for `{{key}}` template placeholders in header values.
106
- */
107
- const TEMPLATE_RE = /\{\{([\w-]+)\}\}/g;
108
- /**
109
- * Build a lazy vars accessor object.
110
- * Each property is a getter that calls `requireVar()` on access.
111
- *
112
- * @internal
113
- */
114
- function buildLazyVars(mapping) {
115
- const obj = {};
116
- for (const [prop, value] of Object.entries(mapping)) {
117
- Object.defineProperty(obj, prop, {
118
- get() {
119
- const runtime = getRuntime();
120
- return resolveTemplate(value, runtime.vars, runtime.secrets, runtime.session);
121
- },
122
- enumerable: true,
123
- configurable: false,
124
- });
125
- }
126
- return obj;
127
- }
128
- /**
129
- * Build a lazy secrets accessor object.
130
- * Each property is a getter that calls `requireSecret()` on access.
131
- *
132
- * @internal
133
- */
134
- function buildLazySecrets(mapping) {
135
- const obj = {};
136
- for (const [prop, value] of Object.entries(mapping)) {
137
- Object.defineProperty(obj, prop, {
138
- get() {
139
- const runtime = getRuntime();
140
- return resolveTemplate(value, runtime.vars, runtime.secrets, runtime.session);
141
- },
142
- enumerable: true,
143
- configurable: false,
144
- });
145
- }
146
- return obj;
147
- }
148
- /**
149
- * Resolve `{{key}}` template placeholders in a string.
150
- *
151
- * Resolution priority (first non-empty wins):
152
- * 1. Session — dynamic values set during session setup (e.g., auth tokens)
153
- * 2. Secrets — from `.env.secrets`
154
- * 3. Vars — from `.env`
155
- *
156
- * Session values must be strings to resolve in templates. Non-string session
157
- * values are silently skipped (they're still accessible via `ctx.session.get()`).
158
- *
159
- * This is used internally by `buildLazyHttp()` and exposed to plugin authors
160
- * via `GlubeanRuntime.resolveTemplate()`.
161
- */
162
- export function resolveTemplate(template, vars, secrets, session) {
163
- return template.replace(TEMPLATE_RE, (_match, key) => {
164
- // Session first (dynamic, from setup hooks), then secrets, then vars
165
- const sessionValue = session?.[key];
166
- const value = (typeof sessionValue === "string" ? sessionValue : undefined) ??
167
- secrets[key] ??
168
- vars[key];
169
- if (value === undefined || value === null || value === "") {
170
- throw new Error(`Missing value for template placeholder "{{${key}}}" in configure() http headers. ` +
171
- `Ensure "${key}" is available in session, as a secret, or as a var.`);
172
- }
173
- return value;
174
- });
175
- }
176
- /**
177
- * Build a lazy HTTP client proxy.
178
- * On first method call, resolves the config and creates an extended client.
179
- *
180
- * @internal
181
- */
182
- function buildLazyHttp(httpOptions) {
183
- // Cache the resolved client per runtime identity to avoid re-extending on every call.
184
- // Since each test runs in its own subprocess, a WeakMap keyed on runtime object
185
- // ensures we get one extended client per test execution.
186
- const cache = new WeakMap();
187
- function getClient() {
188
- const runtime = getRuntime();
189
- let client = cache.get(runtime);
190
- if (client)
191
- return client;
192
- // Build ky-compatible options from the configure http config
193
- const extendOptions = {};
194
- if (httpOptions.prefixUrl) {
195
- extendOptions.prefixUrl = resolveTemplate(httpOptions.prefixUrl, runtime.vars, runtime.secrets, runtime.session);
196
- }
197
- if (httpOptions.headers) {
198
- const resolvedHeaders = {};
199
- for (const [name, template] of Object.entries(httpOptions.headers)) {
200
- resolvedHeaders[name] = resolveTemplate(template, runtime.vars, runtime.secrets, runtime.session);
201
- }
202
- extendOptions.headers = resolvedHeaders;
203
- }
204
- if (httpOptions.searchParams) {
205
- const resolvedParams = {};
206
- for (const [name, template] of Object.entries(httpOptions.searchParams)) {
207
- resolvedParams[name] = resolveTemplate(template, runtime.vars, runtime.secrets, runtime.session);
208
- }
209
- extendOptions.searchParams = resolvedParams;
210
- }
211
- if (httpOptions.timeout !== undefined) {
212
- extendOptions.timeout = httpOptions.timeout;
213
- }
214
- if (httpOptions.retry !== undefined) {
215
- extendOptions.retry = httpOptions.retry;
216
- }
217
- if (httpOptions.throwHttpErrors !== undefined) {
218
- extendOptions.throwHttpErrors = httpOptions.throwHttpErrors;
219
- }
220
- if (httpOptions.hooks) {
221
- extendOptions.hooks = httpOptions.hooks;
222
- }
223
- if (httpOptions.redirect !== undefined) {
224
- extendOptions.redirect = httpOptions.redirect;
225
- }
226
- if (typeof process !== "undefined" && process.env?.["GLUBEAN_DEBUG"]) {
227
- process.stderr.write(`[glubean:debug] configure.getClient extendOptions=${JSON.stringify({ ...extendOptions, headers: "..." })}\n`);
228
- }
229
- client = runtime.http.extend(extendOptions);
230
- cache.set(runtime, client);
231
- return client;
232
- }
233
- // Create a callable proxy that delegates all method calls to the lazily-resolved client.
234
- const HTTP_METHODS = [
235
- "get",
236
- "post",
237
- "put",
238
- "patch",
239
- "delete",
240
- "head",
241
- ];
242
- // The callable function (for `http(url, options)` shorthand)
243
- const proxy = function (url, options) {
244
- return getClient()(url, options);
245
- };
246
- // Method shortcuts
247
- for (const method of HTTP_METHODS) {
248
- proxy[method] = (url, options) => getClient()[method](url, options);
249
- }
250
- // extend() — returns a new HttpClient that merges options with the resolved base
251
- proxy.extend = (options) => getClient().extend(options);
252
- // Expose configured timeout for error reporting (e.g. contract timeout errors)
253
- proxy._configuredTimeout = httpOptions.timeout;
254
- return proxy;
255
- }
256
- // =============================================================================
257
- // Lazy plugin builder
258
- // =============================================================================
259
- /**
260
- * Build lazy property descriptors for plugin factories.
261
- * Each plugin is instantiated on first property access with a WeakMap cache
262
- * keyed by the internal runtime identity.
263
- *
264
- * Returns PropertyDescriptorMap (not a ready object) so the caller can use
265
- * Object.defineProperties() without triggering getters via spread.
266
- *
267
- * @internal
268
- */
269
- /** Reserved keys that plugins cannot shadow. */
270
- const RESERVED_KEYS = new Set(["vars", "secrets", "http"]);
271
- /**
272
- * Resolve (or retrieve cached) the real plugin instance for the current runtime.
273
- *
274
- * @internal
275
- */
276
- function resolvePlugin(factory, cache) {
277
- const runtime = getRuntime();
278
- if (cache.has(runtime))
279
- return cache.get(runtime);
280
- // Build the augmented runtime that plugins see
281
- const noop = () => { };
282
- const augmented = {
283
- vars: runtime.vars,
284
- secrets: runtime.secrets,
285
- http: runtime.http,
286
- test: runtime.test,
287
- requireVar,
288
- requireSecret,
289
- resolveTemplate: (template) => resolveTemplate(template, runtime.vars, runtime.secrets, runtime.session),
290
- trace: runtime.trace?.bind(runtime) ?? noop,
291
- action: runtime.action?.bind(runtime) ?? noop,
292
- event: runtime.event?.bind(runtime) ?? noop,
293
- log: runtime.log?.bind(runtime) ?? noop,
294
- };
295
- const instance = factory.create(augmented);
296
- cache.set(runtime, instance);
297
- return instance;
298
- }
299
- /**
300
- * Build a Proxy that defers plugin creation until the plugin is actually used.
301
- *
302
- * This allows `const { chrome } = configure(...)` to work at module top-level —
303
- * the destructured value is a transparent Proxy, not the real plugin instance.
304
- * The real instance is created lazily on first property access / method call
305
- * during test execution.
306
- *
307
- * @internal
308
- */
309
- function buildLazyPlugin(factory) {
310
- const cache = new WeakMap();
311
- return new Proxy(Object.create(null), {
312
- get(_target, prop, receiver) {
313
- const instance = resolvePlugin(factory, cache);
314
- const value = Reflect.get(instance, prop, receiver);
315
- return typeof value === "function"
316
- ? value.bind(instance)
317
- : value;
318
- },
319
- set(_target, prop, value) {
320
- const instance = resolvePlugin(factory, cache);
321
- return Reflect.set(instance, prop, value);
322
- },
323
- has(_target, prop) {
324
- const instance = resolvePlugin(factory, cache);
325
- return Reflect.has(instance, prop);
326
- },
327
- ownKeys() {
328
- const instance = resolvePlugin(factory, cache);
329
- return Reflect.ownKeys(instance);
330
- },
331
- getOwnPropertyDescriptor(_target, prop) {
332
- const instance = resolvePlugin(factory, cache);
333
- return Object.getOwnPropertyDescriptor(instance, prop);
334
- },
335
- });
336
- }
337
- function buildLazyPlugins(plugins) {
338
- const result = {};
339
- for (const [name, factory] of Object.entries(plugins)) {
340
- if (RESERVED_KEYS.has(name)) {
341
- throw new Error(`Plugin name "${name}" conflicts with a reserved configure() field. ` +
342
- `Choose a different key (reserved: ${[...RESERVED_KEYS].join(", ")}).`);
343
- }
344
- result[name] = buildLazyPlugin(factory);
345
- }
346
- return result;
347
- }
348
- // =============================================================================
349
- // Public API
350
- // =============================================================================
351
- /**
352
- * Declare file-level dependencies on vars, secrets, and HTTP configuration.
353
- *
354
- * Returns lazy accessors that resolve at test runtime, not at import time.
355
- * All declared vars and secrets are **required** — missing values cause the test
356
- * to fail immediately with a clear error message.
357
- *
358
- * The returned objects can be shared across files via re-exports.
359
- *
360
- * @param options Configuration declaring vars, secrets, and HTTP defaults
361
- * @returns Lazy accessors for vars, secrets, and a pre-configured HTTP client
362
- *
363
- * @example Basic usage
364
- * ```ts
365
- * import { test, configure } from "@glubean/sdk";
366
- *
367
- * const { vars, http } = configure({
368
- * vars: { baseUrl: "base_url" },
369
- * http: { prefixUrl: "base_url" },
370
- * });
371
- *
372
- * export const listUsers = test("list-users", async (ctx) => {
373
- * const res = await http.get("users").json();
374
- * ctx.log(`Base URL: ${vars.baseUrl}`);
375
- * });
376
- * ```
377
- *
378
- * @example Full configuration with secrets
379
- * ```ts
380
- * const { vars, secrets, http } = configure({
381
- * vars: { baseUrl: "base_url", orgId: "org_id" },
382
- * secrets: { apiKey: "api_key" },
383
- * http: {
384
- * prefixUrl: "base_url",
385
- * headers: { Authorization: "Bearer {{api_key}}" },
386
- * },
387
- * });
388
- * ```
389
- *
390
- * @example Shared across test files
391
- * ```ts
392
- * // tests/configure.ts
393
- * export const { vars, secrets, http } = configure({ ... });
394
- *
395
- * // tests/users.test.ts
396
- * import { http, vars } from "./configure.js";
397
- * ```
398
- */
399
- export function configure(options) {
400
- const vars = options.vars
401
- ? buildLazyVars(options.vars)
402
- : {};
403
- const secrets = options.secrets
404
- ? buildLazySecrets(options.secrets)
405
- : {};
406
- const http = options.http ? buildLazyHttp(options.http) : buildPassthroughHttp();
407
- const base = { vars, secrets, http };
408
- if (options.plugins) {
409
- Object.assign(base, buildLazyPlugins(options.plugins));
410
- }
411
- return base;
412
- }
413
- /**
414
- * Build a passthrough HTTP client that simply delegates to ctx.http.
415
- * Used when `configure()` is called without `http` options.
416
- *
417
- * @internal
418
- */
419
- function buildPassthroughHttp() {
420
- const HTTP_METHODS = [
421
- "get",
422
- "post",
423
- "put",
424
- "patch",
425
- "delete",
426
- "head",
427
- ];
428
- const proxy = function (url, options) {
429
- return getRuntime().http(url, options);
430
- };
431
- for (const method of HTTP_METHODS) {
432
- proxy[method] = (url, options) => getRuntime().http[method](url, options);
433
- }
434
- proxy.extend = (options) => getRuntime().http.extend(options);
435
- return proxy;
436
- }
1
+ // Back-compat re-export. Implementation has moved to ./configure/index.ts
2
+ export { configure, resolveTemplate } from "./configure/index.js";
437
3
  //# sourceMappingURL=configure.js.map