@ahmedrowaihi/k6-toolkit 0.2.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.
Files changed (50) hide show
  1. package/LICENSE.md +21 -0
  2. package/dist/ast-imports.d.ts +15 -0
  3. package/dist/ast-imports.d.ts.map +1 -0
  4. package/dist/ast-imports.js +12 -0
  5. package/dist/ast-imports.js.map +1 -0
  6. package/dist/bundle.d.ts +25 -0
  7. package/dist/bundle.d.ts.map +1 -0
  8. package/dist/bundle.js +59 -0
  9. package/dist/bundle.js.map +1 -0
  10. package/dist/index.d.ts +7 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +6 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/init.d.ts +50 -0
  15. package/dist/init.d.ts.map +1 -0
  16. package/dist/init.js +73 -0
  17. package/dist/init.js.map +1 -0
  18. package/dist/loadtest-scaffold.d.ts +32 -0
  19. package/dist/loadtest-scaffold.d.ts.map +1 -0
  20. package/dist/loadtest-scaffold.js +130 -0
  21. package/dist/loadtest-scaffold.js.map +1 -0
  22. package/dist/operation-map.d.ts +6 -0
  23. package/dist/operation-map.d.ts.map +1 -0
  24. package/dist/operation-map.js +27 -0
  25. package/dist/operation-map.js.map +1 -0
  26. package/dist/print.d.ts +4 -0
  27. package/dist/print.d.ts.map +1 -0
  28. package/dist/print.js +14 -0
  29. package/dist/print.js.map +1 -0
  30. package/dist/rename-report.d.ts +26 -0
  31. package/dist/rename-report.d.ts.map +1 -0
  32. package/dist/rename-report.js +30 -0
  33. package/dist/rename-report.js.map +1 -0
  34. package/dist/run.d.ts +27 -0
  35. package/dist/run.d.ts.map +1 -0
  36. package/dist/run.js +30 -0
  37. package/dist/run.js.map +1 -0
  38. package/dist/snapshot.d.ts +6 -0
  39. package/dist/snapshot.d.ts.map +1 -0
  40. package/dist/snapshot.js +35 -0
  41. package/dist/snapshot.js.map +1 -0
  42. package/dist/spawn-k6.d.ts +30 -0
  43. package/dist/spawn-k6.d.ts.map +1 -0
  44. package/dist/spawn-k6.js +46 -0
  45. package/dist/spawn-k6.js.map +1 -0
  46. package/dist/sync.d.ts +23 -0
  47. package/dist/sync.d.ts.map +1 -0
  48. package/dist/sync.js +37 -0
  49. package/dist/sync.js.map +1 -0
  50. package/package.json +67 -0
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ahmed Rowaihi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,15 @@
1
+ import ts from "typescript";
2
+ export interface NamedImportSpec {
3
+ name: string;
4
+ alias?: string;
5
+ typeOnly?: boolean;
6
+ }
7
+ /** `import { a, b as c } from "mod";` */
8
+ export declare function namedImport(specs: ReadonlyArray<NamedImportSpec>, moduleSpecifier: string, options?: {
9
+ typeOnly?: boolean;
10
+ }): ts.ImportDeclaration;
11
+ /** `import * as name from "mod";` (`typeOnly: true` for `import type * as name`). */
12
+ export declare function namespaceImport(name: string, moduleSpecifier: string, options?: {
13
+ typeOnly?: boolean;
14
+ }): ts.ImportDeclaration;
15
+ //# sourceMappingURL=ast-imports.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-imports.d.ts","sourceRoot":"","sources":["../src/ast-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAI5B,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CACzB,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,EACrC,eAAe,EAAE,MAAM,EACvB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,EAAE,CAAC,iBAAiB,CAiBtB;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,MAAM,EACvB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,EAAE,CAAC,iBAAiB,CAUtB"}
@@ -0,0 +1,12 @@
1
+ import ts from "typescript";
2
+ const f = ts.factory;
3
+ /** `import { a, b as c } from "mod";` */
4
+ export function namedImport(specs, moduleSpecifier, options = {}) {
5
+ const elements = specs.map((s) => f.createImportSpecifier(s.typeOnly ?? false, s.alias ? f.createIdentifier(s.name) : undefined, f.createIdentifier(s.alias ?? s.name)));
6
+ return f.createImportDeclaration(undefined, f.createImportClause(options.typeOnly ?? false, undefined, f.createNamedImports(elements)), f.createStringLiteral(moduleSpecifier));
7
+ }
8
+ /** `import * as name from "mod";` (`typeOnly: true` for `import type * as name`). */
9
+ export function namespaceImport(name, moduleSpecifier, options = {}) {
10
+ return f.createImportDeclaration(undefined, f.createImportClause(options.typeOnly ?? false, undefined, f.createNamespaceImport(f.createIdentifier(name))), f.createStringLiteral(moduleSpecifier));
11
+ }
12
+ //# sourceMappingURL=ast-imports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast-imports.js","sourceRoot":"","sources":["../src/ast-imports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;AAQrB,yCAAyC;AACzC,MAAM,UAAU,WAAW,CACzB,KAAqC,EACrC,eAAuB,EACvB,UAAkC,EAAE;IAEpC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/B,CAAC,CAAC,qBAAqB,CACrB,CAAC,CAAC,QAAQ,IAAI,KAAK,EACnB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAChD,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,CACtC,CACF,CAAC;IACF,OAAO,CAAC,CAAC,uBAAuB,CAC9B,SAAS,EACT,CAAC,CAAC,kBAAkB,CAClB,OAAO,CAAC,QAAQ,IAAI,KAAK,EACzB,SAAS,EACT,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAC/B,EACD,CAAC,CAAC,mBAAmB,CAAC,eAAe,CAAC,CACvC,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAC7B,IAAY,EACZ,eAAuB,EACvB,UAAkC,EAAE;IAEpC,OAAO,CAAC,CAAC,uBAAuB,CAC9B,SAAS,EACT,CAAC,CAAC,kBAAkB,CAClB,OAAO,CAAC,QAAQ,IAAI,KAAK,EACzB,SAAS,EACT,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAClD,EACD,CAAC,CAAC,mBAAmB,CAAC,eAAe,CAAC,CACvC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { type UserConfig } from "tsdown";
2
+ /**
3
+ * Anything tsdown's `build()` accepts. Consumers can pass plugins,
4
+ * watch, dts, target — full Rolldown surface. `entry` is required.
5
+ */
6
+ export type BundleOpts = UserConfig & {
7
+ entry: NonNullable<UserConfig["entry"]>;
8
+ };
9
+ export interface BundleResult {
10
+ /** Absolute path to the entry chunk — feed straight into `k6 run`. */
11
+ outfile: string;
12
+ /** Every chunk emitted (debug / multi-entry use cases). */
13
+ chunks: ReadonlyArray<{
14
+ fileName: string;
15
+ isEntry: boolean;
16
+ }>;
17
+ }
18
+ /**
19
+ * Bundle a k6 loadtest entry into a single ESM file the k6 binary can
20
+ * load. Defaults target k6's VM (es2022 + neutral platform + external
21
+ * `k6` / `k6/*`). All tsdown options pass through; arrays/strings in
22
+ * `external` are concatenated with the k6 defaults.
23
+ */
24
+ export declare function bundle(opts: BundleOpts): Promise<BundleResult>;
25
+ //# sourceMappingURL=bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAEA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEhD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG;IACpC,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,2DAA2D;IAC3D,MAAM,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CAC/D;AAaD;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBpE"}
package/dist/bundle.js ADDED
@@ -0,0 +1,59 @@
1
+ import { resolve } from "node:path";
2
+ import { build } from "tsdown";
3
+ const K6_EXTERNAL_DEFAULTS = ["k6", /^k6\//];
4
+ const DEFAULTS = {
5
+ format: "esm",
6
+ target: "es2022",
7
+ platform: "neutral",
8
+ external: [...K6_EXTERNAL_DEFAULTS],
9
+ logLevel: "error",
10
+ dts: false,
11
+ };
12
+ /**
13
+ * Bundle a k6 loadtest entry into a single ESM file the k6 binary can
14
+ * load. Defaults target k6's VM (es2022 + neutral platform + external
15
+ * `k6` / `k6/*`). All tsdown options pass through; arrays/strings in
16
+ * `external` are concatenated with the k6 defaults.
17
+ */
18
+ export async function bundle(opts) {
19
+ const merged = {
20
+ ...DEFAULTS,
21
+ ...opts,
22
+ external: mergeExternal(opts.external),
23
+ };
24
+ const [bundle] = await build(merged);
25
+ if (!bundle)
26
+ throw new Error("tsdown produced no bundle");
27
+ const entryChunk = bundle.chunks.find(isEntryChunk);
28
+ if (!entryChunk) {
29
+ throw new Error("tsdown produced no entry chunk — check your entry config");
30
+ }
31
+ const outDir = bundle.config.outDir ?? "dist";
32
+ return {
33
+ outfile: resolve(outDir, entryChunk.fileName),
34
+ chunks: bundle.chunks.map((c) => ({
35
+ fileName: c.fileName,
36
+ isEntry: isEntryChunk(c),
37
+ })),
38
+ };
39
+ }
40
+ function isEntryChunk(chunk) {
41
+ return chunk.type === "chunk" && chunk.isEntry === true;
42
+ }
43
+ function mergeExternal(user) {
44
+ if (user === undefined)
45
+ return [...K6_EXTERNAL_DEFAULTS];
46
+ if (typeof user === "function") {
47
+ return (id, parentId, isResolved) => {
48
+ for (const marker of K6_EXTERNAL_DEFAULTS) {
49
+ if (marker instanceof RegExp ? marker.test(id) : marker === id) {
50
+ return true;
51
+ }
52
+ }
53
+ return user(id, parentId, isResolved);
54
+ };
55
+ }
56
+ const userArr = Array.isArray(user) ? user : [user];
57
+ return [...K6_EXTERNAL_DEFAULTS, ...userArr];
58
+ }
59
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAmB,MAAM,QAAQ,CAAC;AAiBhD,MAAM,oBAAoB,GAAmC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAE7E,MAAM,QAAQ,GAAe;IAC3B,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,CAAC,GAAG,oBAAoB,CAAC;IACnC,QAAQ,EAAE,OAAO;IACjB,GAAG,EAAE,KAAK;CACX,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB;IAC3C,MAAM,MAAM,GAAe;QACzB,GAAG,QAAQ;QACX,GAAG,IAAI;QACP,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC;KACvC,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC;IAC9C,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC;QAC7C,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;SACzB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,KAGrB;IACC,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC;AAC1D,CAAC;AAED,SAAS,aAAa,CAAC,IAA4B;IACjD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,oBAAoB,CAAC,CAAC;IACzD,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE;YAClC,KAAK,MAAM,MAAM,IAAI,oBAAoB,EAAE,CAAC;gBAC1C,IAAI,MAAM,YAAY,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;oBAC/D,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxC,CAAC,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,oBAAoB,EAAE,GAAG,OAAO,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { type GenerateOptions, type GenerateResult, generate, type ScaffoldOptions, } from "@ahmedrowaihi/k6-gen";
2
+ export { type BundleOpts, type BundleResult, bundle } from "./bundle.js";
3
+ export { type AuthFlavor, type InitFile, type InitOptions, type InitResult, init, } from "./init.js";
4
+ export type { OperationDiff, RenameEntry } from "./rename-report.js";
5
+ export { type RunK6Options, type RunK6Result, runK6 } from "./run.js";
6
+ export { type SyncOptions, type SyncResult, sync } from "./sync.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,QAAQ,EACR,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EACL,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { generate, } from "@ahmedrowaihi/k6-gen";
2
+ export { bundle } from "./bundle.js";
3
+ export { init, } from "./init.js";
4
+ export { runK6 } from "./run.js";
5
+ export { sync } from "./sync.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,QAAQ,GAET,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAsC,MAAM,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAKL,IAAI,GACL,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAuC,KAAK,EAAE,MAAM,UAAU,CAAC;AACtE,OAAO,EAAqC,IAAI,EAAE,MAAM,WAAW,CAAC"}
package/dist/init.d.ts ADDED
@@ -0,0 +1,50 @@
1
+ import type { GenerateOptions, GenerateResult } from "@ahmedrowaihi/k6-gen";
2
+ import { type AuthFlavor, type ScaffoldLoadtestOpts } from "./loadtest-scaffold.js";
3
+ export type { AuthFlavor } from "./loadtest-scaffold.js";
4
+ export interface InitOptions extends Pick<GenerateOptions, "input" | "normalize" | "defaultBaseUrl" | "scaffold"> {
5
+ /** Project root. Default: `process.cwd()`. */
6
+ cwd?: string;
7
+ /** Output directory for the generated client. Default: `./src/gen`. */
8
+ output?: string;
9
+ /** Where the loadtest scaffold lands. Default: `./loadtest.ts`. */
10
+ loadtestPath?: string;
11
+ /** Auth recipe wired into the scaffold. Default: `"none"`. */
12
+ auth?: AuthFlavor;
13
+ /** Env var holding the bearer token (only used when `auth === "bearer"`). */
14
+ bearerEnv?: string;
15
+ /** Header name for the API key (only used when `auth === "apiKey"`). */
16
+ apiKeyHeader?: string;
17
+ /** Env var holding the API key (only used when `auth === "apiKey"`). */
18
+ apiKeyEnv?: string;
19
+ /** Pace preset baked into the scaffold. Default: `"smoke"`. */
20
+ pace?: ScaffoldLoadtestOpts["pace"];
21
+ /** Scaffold pace duration string. Default: `"30s"`. */
22
+ duration?: string;
23
+ /**
24
+ * When set, emit `scenarios: { … }` with one entry per name instead of
25
+ * the single-pace shape. Each scenario gets its own pace + flow.
26
+ */
27
+ scenarios?: ReadonlyArray<string>;
28
+ /** Refuse to overwrite an existing loadtest file. Default: `true`. */
29
+ noOverwrite?: boolean;
30
+ /** Don't touch disk — return what would have been written. */
31
+ dryRun?: boolean;
32
+ }
33
+ export interface InitFile {
34
+ path: string;
35
+ content: string;
36
+ /** `false` when `dryRun` set or `noOverwrite` skipped the write. */
37
+ written: boolean;
38
+ }
39
+ export interface InitResult {
40
+ files: InitFile[];
41
+ generated: GenerateResult;
42
+ }
43
+ /**
44
+ * Scaffold a fresh k6 project: generate the typed client and emit a
45
+ * starter `loadtest.ts` parameterized on `auth` / `pace` / `scenarios`.
46
+ * The first param-less GET operation seeds the flow step so the file
47
+ * runs out of the box.
48
+ */
49
+ export declare function init(opts: InitOptions): Promise<InitResult>;
50
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG5E,OAAO,EACL,KAAK,UAAU,EACf,KAAK,oBAAoB,EAE1B,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,WAAW,WACf,SAAQ,IAAI,CACV,eAAe,EACf,OAAO,GAAG,WAAW,GAAG,gBAAgB,GAAG,UAAU,CACtD;IACD,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACpC,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,EAAE,cAAc,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA0CjE"}
package/dist/init.js ADDED
@@ -0,0 +1,73 @@
1
+ import { existsSync } from "node:fs";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname, relative, resolve } from "node:path";
4
+ import { scaffoldLoadtest, } from "./loadtest-scaffold.js";
5
+ import { sync } from "./sync.js";
6
+ /**
7
+ * Scaffold a fresh k6 project: generate the typed client and emit a
8
+ * starter `loadtest.ts` parameterized on `auth` / `pace` / `scenarios`.
9
+ * The first param-less GET operation seeds the flow step so the file
10
+ * runs out of the box.
11
+ */
12
+ export async function init(opts) {
13
+ const cwd = opts.cwd ?? process.cwd();
14
+ const output = resolve(cwd, opts.output ?? "./src/gen");
15
+ const loadtestPath = resolve(cwd, opts.loadtestPath ?? "./loadtest.ts");
16
+ const auth = opts.auth ?? "none";
17
+ const generated = await sync({
18
+ input: opts.input,
19
+ output,
20
+ cwd,
21
+ normalize: opts.normalize ?? true,
22
+ defaultBaseUrl: opts.defaultBaseUrl,
23
+ scaffold: opts.scaffold,
24
+ dryRun: opts.dryRun,
25
+ });
26
+ const content = scaffoldLoadtest({
27
+ clientImportPath: relativeClientImport(loadtestPath, output),
28
+ auth,
29
+ bearerEnv: opts.bearerEnv,
30
+ apiKeyHeader: opts.apiKeyHeader,
31
+ apiKeyEnv: opts.apiKeyEnv,
32
+ pace: opts.pace,
33
+ duration: opts.duration,
34
+ scenarios: opts.scenarios,
35
+ seedOperation: pickSeedOperation(generated.ir),
36
+ });
37
+ const exists = existsSync(loadtestPath);
38
+ const shouldSkip = exists && (opts.noOverwrite ?? true);
39
+ let written = false;
40
+ if (!opts.dryRun && !shouldSkip) {
41
+ await mkdir(dirname(loadtestPath), { recursive: true });
42
+ await writeFile(loadtestPath, content);
43
+ written = true;
44
+ }
45
+ return {
46
+ files: [{ path: loadtestPath, content, written }],
47
+ generated,
48
+ };
49
+ }
50
+ function relativeClientImport(loadtestPath, outputDir) {
51
+ const rel = relative(dirname(loadtestPath), outputDir).replaceAll("\\", "/");
52
+ return `./${rel || "."}/index.js`;
53
+ }
54
+ /** First GET op with no required path params + no required body. */
55
+ function pickSeedOperation(ir) {
56
+ const paths = ir
57
+ .paths;
58
+ if (!paths)
59
+ return undefined;
60
+ for (const pathItem of Object.values(paths)) {
61
+ const op = pathItem?.get;
62
+ if (!op?.id)
63
+ continue;
64
+ const requiredPathParams = Object.values(op.parameters?.path ?? {}).filter((p) => p.required);
65
+ if (requiredPathParams.length > 0)
66
+ continue;
67
+ if (op.body?.required)
68
+ continue;
69
+ return op.id;
70
+ }
71
+ return undefined;
72
+ }
73
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ export type AuthFlavor = "none" | "bearer" | "basic" | "apiKey" | "session";
2
+ export interface ScaffoldLoadtestOpts {
3
+ /** Relative import path for the generated client. */
4
+ clientImportPath: string;
5
+ /** Auth recipe wired into `use: [...]`. */
6
+ auth: AuthFlavor;
7
+ /** Env var holding the bearer token (only for `auth === "bearer"`). */
8
+ bearerEnv?: string;
9
+ /** Header name for the API key (only for `auth === "apiKey"`). */
10
+ apiKeyHeader?: string;
11
+ /** Env var holding the API key (only for `auth === "apiKey"`). */
12
+ apiKeyEnv?: string;
13
+ /** k6 pace preset. Default: `"smoke"`. */
14
+ pace?: "smoke" | "load" | "stress" | "spike" | "soak";
15
+ /** Duration string passed to the pace preset. Default: `"30s"`. */
16
+ duration?: string;
17
+ /**
18
+ * Names for the `scenarios: { … }` block. When non-empty, the
19
+ * scaffold uses the multi-scenario shape (each gets its own pace +
20
+ * flow). When omitted/empty, falls back to the single-pace shape.
21
+ */
22
+ scenarios?: ReadonlyArray<string>;
23
+ /**
24
+ * Operation to seed the first flow step with. When set, the scaffold
25
+ * emits `api.<name>()` instead of an empty placeholder so new devs
26
+ * see a real call out of the box.
27
+ */
28
+ seedOperation?: string;
29
+ }
30
+ /** Render a starter `loadtest.ts` via `ts.factory` — no template strings. */
31
+ export declare function scaffoldLoadtest(opts: ScaffoldLoadtestOpts): string;
32
+ //# sourceMappingURL=loadtest-scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadtest-scaffold.d.ts","sourceRoot":"","sources":["../src/loadtest-scaffold.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,qDAAqD;IACrD,gBAAgB,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,IAAI,EAAE,UAAU,CAAC;IACjB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACtD,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAID,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAcnE"}
@@ -0,0 +1,130 @@
1
+ import ts from "typescript";
2
+ import { namedImport, namespaceImport } from "./ast-imports.js";
3
+ import { printStatements } from "./print.js";
4
+ const f = ts.factory;
5
+ /** Render a starter `loadtest.ts` via `ts.factory` — no template strings. */
6
+ export function scaffoldLoadtest(opts) {
7
+ const pace = opts.pace ?? "smoke";
8
+ const stmts = [
9
+ k6FrameworkImport(opts.auth, pace),
10
+ namespaceImport("api", opts.clientImportPath),
11
+ ];
12
+ if (opts.auth !== "none")
13
+ stmts.push(authDecl(opts));
14
+ stmts.push(loadtestDecl(opts, pace));
15
+ stmts.push(reExportConst("options", "lt", "options"));
16
+ stmts.push(defaultExportProp("lt", "default"));
17
+ return printStatements(stmts);
18
+ }
19
+ function k6FrameworkImport(auth, pace) {
20
+ const names = new Set(["defineLoadTest", "flow", pace]);
21
+ if (auth !== "none")
22
+ names.add("useAuth");
23
+ return namedImport([...names].map((name) => ({ name })), "@ahmedrowaihi/k6");
24
+ }
25
+ function authDecl(opts) {
26
+ return varConst("auth", authCallExpr(opts));
27
+ }
28
+ function authCallExpr(opts) {
29
+ const useAuth = f.createIdentifier("useAuth");
30
+ switch (opts.auth) {
31
+ case "bearer":
32
+ return useAuthCall(useAuth, "bearer", [
33
+ objLit({ env: f.createStringLiteral(opts.bearerEnv ?? "API_TOKEN") }),
34
+ ]);
35
+ case "basic":
36
+ return useAuthCall(useAuth, "basic", [
37
+ objLit({
38
+ user: objLit({ env: f.createStringLiteral("API_USER") }),
39
+ pass: objLit({ env: f.createStringLiteral("API_PASS") }),
40
+ }),
41
+ ]);
42
+ case "apiKey":
43
+ return useAuthCall(useAuth, "apiKey", [
44
+ objLit({
45
+ name: f.createStringLiteral(opts.apiKeyHeader ?? "X-API-Key"),
46
+ env: f.createStringLiteral(opts.apiKeyEnv ?? "API_KEY"),
47
+ }),
48
+ ]);
49
+ case "session":
50
+ return useAuthCall(useAuth, "session", [
51
+ objLit({
52
+ signIn: f.createArrowFunction(undefined, undefined, [], undefined, f.createToken(ts.SyntaxKind.EqualsGreaterThanToken), f.createBlock([
53
+ f.createReturnStatement(f.createStringLiteral("/* obtain session cookie */")),
54
+ ], true)),
55
+ }),
56
+ ]);
57
+ default:
58
+ throw new Error(`Unknown auth flavor: ${opts.auth}`);
59
+ }
60
+ }
61
+ function useAuthCall(useAuth, fn, args) {
62
+ return f.createCallExpression(f.createPropertyAccessExpression(useAuth, f.createIdentifier(fn)), undefined, args);
63
+ }
64
+ function loadtestDecl(opts, pace) {
65
+ const duration = opts.duration ?? "30s";
66
+ const props = [];
67
+ if (opts.auth !== "none")
68
+ props.push(useEntry());
69
+ if (opts.scenarios && opts.scenarios.length > 0) {
70
+ props.push(scenariosEntry(opts.scenarios, pace, duration, opts.seedOperation));
71
+ }
72
+ else {
73
+ props.push(paceEntry(pace, duration), budgetsEntry(), flowEntry(opts.seedOperation));
74
+ }
75
+ return varConst("lt", f.createCallExpression(f.createIdentifier("defineLoadTest"), undefined, [
76
+ f.createObjectLiteralExpression(props, true),
77
+ ]));
78
+ }
79
+ function useEntry() {
80
+ return f.createPropertyAssignment("use", f.createArrayLiteralExpression([f.createIdentifier("auth")], false));
81
+ }
82
+ function paceEntry(pace, duration) {
83
+ return f.createPropertyAssignment("pace", f.createCallExpression(f.createIdentifier(pace), undefined, [
84
+ objLit({ duration: f.createStringLiteral(duration) }),
85
+ ]));
86
+ }
87
+ function budgetsEntry() {
88
+ return f.createPropertyAssignment("budgets", objLit({
89
+ p95: f.createStringLiteral("500ms"),
90
+ errors: f.createStringLiteral("1%"),
91
+ },
92
+ /* multiline */ true));
93
+ }
94
+ function flowEntry(seedOp) {
95
+ return f.createPropertyAssignment("flow", flowExpr(seedOp));
96
+ }
97
+ function flowExpr(seedOp) {
98
+ const stepLabel = seedOp ?? "health";
99
+ return f.createCallExpression(f.createPropertyAccessExpression(f.createCallExpression(f.createIdentifier("flow"), undefined, []), f.createIdentifier("step")), undefined, [
100
+ f.createStringLiteral(stepLabel),
101
+ f.createArrowFunction(undefined, undefined, [], undefined, f.createToken(ts.SyntaxKind.EqualsGreaterThanToken), f.createBlock(seedOp ? [seededCallStatement(seedOp)] : [], true)),
102
+ ]);
103
+ }
104
+ function seededCallStatement(opName) {
105
+ return f.createExpressionStatement(f.createCallExpression(f.createPropertyAccessExpression(f.createIdentifier("api"), f.createIdentifier(opName)), undefined, []));
106
+ }
107
+ function scenariosEntry(names, pace, duration, seedOp) {
108
+ const scenarioObj = f.createObjectLiteralExpression(names.map((name) => f.createPropertyAssignment(name, objLit({
109
+ pace: f.createCallExpression(f.createIdentifier(pace), undefined, [
110
+ objLit({ duration: f.createStringLiteral(duration) }),
111
+ ]),
112
+ flow: flowExpr(seedOp),
113
+ }, true))), true);
114
+ return f.createPropertyAssignment("scenarios", scenarioObj);
115
+ }
116
+ function objLit(props, multiline = false) {
117
+ return f.createObjectLiteralExpression(Object.entries(props).map(([k, v]) => f.createPropertyAssignment(k, v)), multiline);
118
+ }
119
+ function varConst(name, init) {
120
+ return f.createVariableStatement(undefined, f.createVariableDeclarationList([f.createVariableDeclaration(name, undefined, undefined, init)], ts.NodeFlags.Const));
121
+ }
122
+ function reExportConst(localName, sourceVar, sourceProp) {
123
+ return f.createVariableStatement([f.createModifier(ts.SyntaxKind.ExportKeyword)], f.createVariableDeclarationList([
124
+ f.createVariableDeclaration(localName, undefined, undefined, f.createPropertyAccessExpression(f.createIdentifier(sourceVar), f.createIdentifier(sourceProp))),
125
+ ], ts.NodeFlags.Const));
126
+ }
127
+ function defaultExportProp(sourceVar, sourceProp) {
128
+ return f.createExportAssignment(undefined, false, f.createPropertyAccessExpression(f.createIdentifier(sourceVar), f.createIdentifier(sourceProp)));
129
+ }
130
+ //# sourceMappingURL=loadtest-scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadtest-scaffold.js","sourceRoot":"","sources":["../src/loadtest-scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { IR } from "@ahmedrowaihi/openapi-tools";
2
+ /** `"GET /pets/{id}" → "getPetById"`. */
3
+ export type OperationMap = Map<string, string>;
4
+ /** Build the op-id map for rename detection. Drops missing/blank operationIds. */
5
+ export declare function extractOperationMap(ir: IR.Model): OperationMap;
6
+ //# sourceMappingURL=operation-map.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-map.d.ts","sourceRoot":"","sources":["../src/operation-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAYtD,yCAAyC;AACzC,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/C,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,GAAG,YAAY,CAc9D"}
@@ -0,0 +1,27 @@
1
+ const HTTP_METHODS = [
2
+ "get",
3
+ "put",
4
+ "post",
5
+ "delete",
6
+ "options",
7
+ "head",
8
+ "patch",
9
+ ];
10
+ /** Build the op-id map for rename detection. Drops missing/blank operationIds. */
11
+ export function extractOperationMap(ir) {
12
+ const out = new Map();
13
+ const paths = ir.paths ?? {};
14
+ for (const [path, pathItem] of Object.entries(paths)) {
15
+ if (!pathItem)
16
+ continue;
17
+ for (const method of HTTP_METHODS) {
18
+ const op = pathItem[method];
19
+ const id = op?.operationId?.trim();
20
+ if (!id)
21
+ continue;
22
+ out.set(`${method.toUpperCase()} ${path}`, id);
23
+ }
24
+ }
25
+ return out;
26
+ }
27
+ //# sourceMappingURL=operation-map.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-map.js","sourceRoot":"","sources":["../src/operation-map.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG;IACnB,KAAK;IACL,KAAK;IACL,MAAM;IACN,QAAQ;IACR,SAAS;IACT,MAAM;IACN,OAAO;CACC,CAAC;AAKX,kFAAkF;AAClF,MAAM,UAAU,mBAAmB,CAAC,EAAY;IAC9C,MAAM,GAAG,GAAiB,IAAI,GAAG,EAAE,CAAC;IACpC,MAAM,KAAK,GACR,EAA0D,CAAC,KAAK,IAAI,EAAE,CAAC;IAC1E,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAyC,CAAC;YACpE,MAAM,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,EAAE;gBAAE,SAAS;YAClB,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,4 @@
1
+ import ts from "typescript";
2
+ /** Render TS AST statements into a source-file string. */
3
+ export declare function printStatements(statements: ReadonlyArray<ts.Statement>, header?: string): string;
4
+ //# sourceMappingURL=print.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.d.ts","sourceRoot":"","sources":["../src/print.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAO5B,0DAA0D;AAC1D,wBAAgB,eAAe,CAC7B,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,EACvC,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAYR"}
package/dist/print.js ADDED
@@ -0,0 +1,14 @@
1
+ import ts from "typescript";
2
+ const printer = ts.createPrinter({
3
+ newLine: ts.NewLineKind.LineFeed,
4
+ removeComments: false,
5
+ });
6
+ /** Render TS AST statements into a source-file string. */
7
+ export function printStatements(statements, header) {
8
+ const source = ts.createSourceFile("out.ts", "", ts.ScriptTarget.ES2022, false, ts.ScriptKind.TS);
9
+ const body = statements
10
+ .map((stmt) => printer.printNode(ts.EmitHint.Unspecified, stmt, source))
11
+ .join("\n\n");
12
+ return header ? `${header}\n\n${body}\n` : `${body}\n`;
13
+ }
14
+ //# sourceMappingURL=print.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print.js","sourceRoot":"","sources":["../src/print.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC;IAC/B,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ;IAChC,cAAc,EAAE,KAAK;CACtB,CAAC,CAAC;AAEH,0DAA0D;AAC1D,MAAM,UAAU,eAAe,CAC7B,UAAuC,EACvC,MAAe;IAEf,MAAM,MAAM,GAAG,EAAE,CAAC,gBAAgB,CAChC,QAAQ,EACR,EAAE,EACF,EAAE,CAAC,YAAY,CAAC,MAAM,EACtB,KAAK,EACL,EAAE,CAAC,UAAU,CAAC,EAAE,CACjB,CAAC;IACF,MAAM,IAAI,GAAG,UAAU;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;SACvE,IAAI,CAAC,MAAM,CAAC,CAAC;IAChB,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC;AACzD,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { OperationMap } from "./operation-map.js";
2
+ export interface RenameEntry {
3
+ method: string;
4
+ path: string;
5
+ from: string;
6
+ to: string;
7
+ }
8
+ export interface OperationDiff {
9
+ /** Same (method, path) — operationId changed. */
10
+ renamed: RenameEntry[];
11
+ /** Endpoints that existed before but no longer do. */
12
+ removed: Array<{
13
+ method: string;
14
+ path: string;
15
+ operationId: string;
16
+ }>;
17
+ /** Endpoints that didn't exist before. */
18
+ added: Array<{
19
+ method: string;
20
+ path: string;
21
+ operationId: string;
22
+ }>;
23
+ }
24
+ /** Diff two op-id maps. Rename = same (method, path), different operationId. */
25
+ export declare function diffOperationIds(prev: OperationMap, next: OperationMap): OperationDiff;
26
+ //# sourceMappingURL=rename-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-report.d.ts","sourceRoot":"","sources":["../src/rename-report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B,iDAAiD;IACjD,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,sDAAsD;IACtD,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtE,0CAA0C;IAC1C,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrE;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,YAAY,EAClB,IAAI,EAAE,YAAY,GACjB,aAAa,CAwBf"}
@@ -0,0 +1,30 @@
1
+ /** Diff two op-id maps. Rename = same (method, path), different operationId. */
2
+ export function diffOperationIds(prev, next) {
3
+ const renamed = [];
4
+ const removed = [];
5
+ const added = [];
6
+ for (const [key, prevId] of prev) {
7
+ const nextId = next.get(key);
8
+ if (!nextId) {
9
+ const [method, path] = splitKey(key);
10
+ removed.push({ method, path, operationId: prevId });
11
+ continue;
12
+ }
13
+ if (nextId !== prevId) {
14
+ const [method, path] = splitKey(key);
15
+ renamed.push({ method, path, from: prevId, to: nextId });
16
+ }
17
+ }
18
+ for (const [key, nextId] of next) {
19
+ if (prev.has(key))
20
+ continue;
21
+ const [method, path] = splitKey(key);
22
+ added.push({ method, path, operationId: nextId });
23
+ }
24
+ return { renamed, removed, added };
25
+ }
26
+ function splitKey(key) {
27
+ const i = key.indexOf(" ");
28
+ return [key.slice(0, i), key.slice(i + 1)];
29
+ }
30
+ //# sourceMappingURL=rename-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-report.js","sourceRoot":"","sources":["../src/rename-report.ts"],"names":[],"mappings":"AAkBA,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAC9B,IAAkB,EAClB,IAAkB;IAElB,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,OAAO,GAA6B,EAAE,CAAC;IAC7C,MAAM,KAAK,GAA2B,EAAE,CAAC;IAEzC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC"}
package/dist/run.d.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { type BundleOpts } from "./bundle.js";
2
+ import { type K6FlagArgs, type SpawnK6Opts } from "./spawn-k6.js";
3
+ export interface RunK6Options extends K6FlagArgs {
4
+ /** Source entry to bundle. Required. */
5
+ entry: string;
6
+ /** Extra bundler options forwarded to tsdown. `entry` from here is ignored. */
7
+ bundle?: Omit<BundleOpts, "entry">;
8
+ /** Where to spawn from. Default: process.cwd(). */
9
+ cwd?: string;
10
+ /** Path/name of the k6 binary. Default: "k6". */
11
+ binary?: string;
12
+ /** Inherit/pipe k6 stdio. Default: "inherit". */
13
+ stdio?: SpawnK6Opts["stdio"];
14
+ }
15
+ export interface RunK6Result {
16
+ /** Exit code; signal-killed processes resolve to `128 + signum`. */
17
+ exitCode: number;
18
+ /** Where the bundle was written. */
19
+ outfile: string;
20
+ }
21
+ /**
22
+ * Bundle a k6 loadtest with tsdown, then spawn the k6 binary against
23
+ * the resulting file. One call covers what `k6-tools run` does at the
24
+ * CLI level.
25
+ */
26
+ export declare function runK6(opts: RunK6Options): Promise<RunK6Result>;
27
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAU,MAAM,aAAa,CAAC;AACtD,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,WAAW,EAEjB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,YAAa,SAAQ,UAAU;IAC9C,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,MAAM,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACnC,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAuBpE"}
package/dist/run.js ADDED
@@ -0,0 +1,30 @@
1
+ import { resolve } from "node:path";
2
+ import { bundle } from "./bundle.js";
3
+ import { buildK6Args, spawnK6, } from "./spawn-k6.js";
4
+ /**
5
+ * Bundle a k6 loadtest with tsdown, then spawn the k6 binary against
6
+ * the resulting file. One call covers what `k6-tools run` does at the
7
+ * CLI level.
8
+ */
9
+ export async function runK6(opts) {
10
+ const cwd = opts.cwd ?? process.cwd();
11
+ const { outfile } = await bundle({
12
+ ...(opts.bundle ?? {}),
13
+ entry: resolve(cwd, opts.entry),
14
+ });
15
+ const k6Args = buildK6Args(outfile, {
16
+ baseUrl: opts.baseUrl,
17
+ vus: opts.vus,
18
+ duration: opts.duration,
19
+ out: opts.out,
20
+ summary: opts.summary,
21
+ extraArgs: opts.extraArgs,
22
+ });
23
+ const exitCode = await spawnK6(k6Args, {
24
+ binary: opts.binary,
25
+ cwd,
26
+ stdio: opts.stdio,
27
+ });
28
+ return { exitCode, outfile };
29
+ }
30
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAmB,MAAM,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,WAAW,EAGX,OAAO,GACR,MAAM,eAAe,CAAC;AAsBvB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAkB;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC;QACtB,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,WAAW,CAAC,OAAO,EAAE;QAClC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,SAAS,EAAE,IAAI,CAAC,SAAS;KAC1B,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE;QACrC,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,GAAG;QACH,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;IAEH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { OperationMap } from "./operation-map.js";
2
+ export declare const SNAPSHOT_FILENAME = ".k6-spec-snapshot.json";
3
+ export declare function loadSnapshotOps(path: string): Promise<OperationMap | null>;
4
+ /** Persist the current op map for the next sync to diff against. */
5
+ export declare function writeSnapshotOps(path: string, ops: OperationMap): Promise<void>;
6
+ //# sourceMappingURL=snapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,eAAO,MAAM,iBAAiB,2BAA2B,CAAC;AAO1D,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA0B9B;AAED,oEAAoE;AACpE,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CAOf"}
@@ -0,0 +1,35 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
+ export const SNAPSHOT_FILENAME = ".k6-spec-snapshot.json";
4
+ export async function loadSnapshotOps(path) {
5
+ let raw;
6
+ try {
7
+ raw = await readFile(path, "utf8");
8
+ }
9
+ catch (err) {
10
+ if (err.code === "ENOENT")
11
+ return null;
12
+ throw new Error(`Failed to read snapshot at ${path}: ${err.message}`);
13
+ }
14
+ let data;
15
+ try {
16
+ data = JSON.parse(raw);
17
+ }
18
+ catch (err) {
19
+ throw new Error(`Malformed snapshot at ${path}: ${err.message}. Delete the file to regenerate.`);
20
+ }
21
+ if (data?.v !== 1 || !data.operations) {
22
+ throw new Error(`Unrecognized snapshot schema at ${path} (expected v=1). Delete the file to regenerate.`);
23
+ }
24
+ return new Map(Object.entries(data.operations));
25
+ }
26
+ /** Persist the current op map for the next sync to diff against. */
27
+ export async function writeSnapshotOps(path, ops) {
28
+ await mkdir(dirname(path), { recursive: true });
29
+ const payload = {
30
+ v: 1,
31
+ operations: Object.fromEntries(ops),
32
+ };
33
+ await writeFile(path, JSON.stringify(payload, null, 2));
34
+ }
35
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AAO1D,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY;IAEZ,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAClE,MAAM,IAAI,KAAK,CACb,8BAA8B,IAAI,KAAM,GAAa,CAAC,OAAO,EAAE,CAChE,CAAC;IACJ,CAAC;IAED,IAAI,IAAmB,CAAC;IACxB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,yBAAyB,IAAI,KAAM,GAAa,CAAC,OAAO,kCAAkC,CAC3F,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,mCAAmC,IAAI,iDAAiD,CACzF,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,GAAiB;IAEjB,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,OAAO,GAAkB;QAC7B,CAAC,EAAE,CAAC;QACJ,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC;KACpC,CAAC;IACF,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { type StdioOptions } from "node:child_process";
2
+ export interface K6FlagArgs {
3
+ baseUrl?: string;
4
+ vus?: string;
5
+ duration?: string;
6
+ /** k6 `--out` sinks. Each entry is a separate `--out` flag. */
7
+ out?: ReadonlyArray<string>;
8
+ /** k6 `--summary-export=<path>`. */
9
+ summary?: string;
10
+ /** Extra args appended verbatim after the synthesized flags. */
11
+ extraArgs?: ReadonlyArray<string>;
12
+ }
13
+ /** Build the `k6 run …` argv for one bundle. */
14
+ export declare function buildK6Args(outfile: string, args?: K6FlagArgs): string[];
15
+ export interface SpawnK6Opts {
16
+ /** Where to inherit/pipe k6's stdio. Default: "inherit". */
17
+ stdio?: StdioOptions;
18
+ /** Path/name of the k6 binary. Default: "k6". */
19
+ binary?: string;
20
+ /** Working directory. */
21
+ cwd?: string;
22
+ }
23
+ /**
24
+ * Spawn k6 with the given argv. Resolves to the exit code; for
25
+ * signal-terminated processes returns `128 + signum` per POSIX so
26
+ * callers can fail-fast on Ctrl-C / SIGKILL without manual signal
27
+ * decoding.
28
+ */
29
+ export declare function spawnK6(k6Args: ReadonlyArray<string>, opts?: SpawnK6Opts): Promise<number>;
30
+ //# sourceMappingURL=spawn-k6.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-k6.d.ts","sourceRoot":"","sources":["../src/spawn-k6.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAG9D,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACnC;AAED,gDAAgD;AAChD,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,EAAE,CAU5E;AAED,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAC7B,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,MAAM,CAAC,CAajB"}
@@ -0,0 +1,46 @@
1
+ import { spawn } from "node:child_process";
2
+ import { constants as osConstants } from "node:os";
3
+ /** Build the `k6 run …` argv for one bundle. */
4
+ export function buildK6Args(outfile, args = {}) {
5
+ const out = ["run"];
6
+ if (args.baseUrl)
7
+ out.push("-e", `BASE_URL=${args.baseUrl}`);
8
+ if (args.vus)
9
+ out.push("--vus", args.vus);
10
+ if (args.duration)
11
+ out.push("--duration", args.duration);
12
+ for (const sink of args.out ?? [])
13
+ out.push("--out", sink);
14
+ if (args.summary)
15
+ out.push(`--summary-export=${args.summary}`);
16
+ out.push(...(args.extraArgs ?? []));
17
+ out.push(outfile);
18
+ return out;
19
+ }
20
+ /**
21
+ * Spawn k6 with the given argv. Resolves to the exit code; for
22
+ * signal-terminated processes returns `128 + signum` per POSIX so
23
+ * callers can fail-fast on Ctrl-C / SIGKILL without manual signal
24
+ * decoding.
25
+ */
26
+ export function spawnK6(k6Args, opts = {}) {
27
+ const child = spawn(opts.binary ?? "k6", [...k6Args], {
28
+ stdio: opts.stdio ?? "inherit",
29
+ cwd: opts.cwd,
30
+ });
31
+ return new Promise((resolve, reject) => {
32
+ child.on("exit", (code, signal) => {
33
+ if (code !== null)
34
+ return resolve(code);
35
+ if (signal)
36
+ return resolve(128 + (signalNumber(signal) ?? 1));
37
+ resolve(1);
38
+ });
39
+ child.on("error", reject);
40
+ });
41
+ }
42
+ /** Look up the platform-correct signum from Node's os.constants. */
43
+ function signalNumber(signal) {
44
+ return osConstants.signals[signal];
45
+ }
46
+ //# sourceMappingURL=spawn-k6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-k6.js","sourceRoot":"","sources":["../src/spawn-k6.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC;AAcnD,gDAAgD;AAChD,MAAM,UAAU,WAAW,CAAC,OAAe,EAAE,OAAmB,EAAE;IAChE,MAAM,GAAG,GAAa,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,IAAI,CAAC,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7D,IAAI,IAAI,CAAC,GAAG;QAAE,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,QAAQ;QAAE,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,GAAG,IAAI,EAAE;QAAE,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC3D,IAAI,IAAI,CAAC,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC;IACpC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClB,OAAO,GAAG,CAAC;AACb,CAAC;AAWD;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,MAA6B,EAC7B,OAAoB,EAAE;IAEtB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE;QACpD,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,SAAS;QAC9B,GAAG,EAAE,IAAI,CAAC,GAAG;KACd,CAAC,CAAC;IACH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YAChC,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,MAAM;gBAAE,OAAO,OAAO,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,oEAAoE;AACpE,SAAS,YAAY,CAAC,MAAsB;IAC1C,OAAQ,WAAW,CAAC,OAA8C,CAAC,MAAM,CAAC,CAAC;AAC7E,CAAC"}
package/dist/sync.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { type GenerateOptions, type GenerateResult } from "@ahmedrowaihi/k6-gen";
2
+ import { type OperationDiff } from "./rename-report.js";
3
+ export interface SyncOptions extends Pick<GenerateOptions, "input" | "normalize" | "defaultBaseUrl" | "scaffold" | "dryRun"> {
4
+ /** Output directory for the generated client. */
5
+ output: string;
6
+ /** Working directory used to resolve relative `input` / `output`. Default: `process.cwd()`. */
7
+ cwd?: string;
8
+ /** Diff operationIds against the prior sync's snapshot. */
9
+ reportRenames?: boolean;
10
+ /** Persist a fresh snapshot after generate. Default: `true`. */
11
+ writeSnapshot?: boolean;
12
+ }
13
+ export interface SyncResult extends GenerateResult {
14
+ /** Drift summary; populated only when `reportRenames` is true. */
15
+ diff?: OperationDiff;
16
+ }
17
+ /**
18
+ * Drive {@link generate} from a spec to an output directory, plus the
19
+ * snapshot bookkeeping that powers `--report-renames`. Returns the full
20
+ * `GenerateResult` (files + ir) so callers can chain.
21
+ */
22
+ export declare function sync(opts: SyncOptions): Promise<SyncResult>;
23
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EAEpB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EAAoB,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAO1E,MAAM,WAAW,WACf,SAAQ,IAAI,CACV,eAAe,EACf,OAAO,GAAG,WAAW,GAAG,gBAAgB,GAAG,UAAU,GAAG,QAAQ,CACjE;IACD,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAW,SAAQ,cAAc;IAChD,kEAAkE;IAClE,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BjE"}
package/dist/sync.js ADDED
@@ -0,0 +1,37 @@
1
+ import { join, resolve } from "node:path";
2
+ import { generate, } from "@ahmedrowaihi/k6-gen";
3
+ import { resolveSpecInput } from "@ahmedrowaihi/openapi-tools";
4
+ import { extractOperationMap } from "./operation-map.js";
5
+ import { diffOperationIds } from "./rename-report.js";
6
+ import { loadSnapshotOps, SNAPSHOT_FILENAME, writeSnapshotOps, } from "./snapshot.js";
7
+ /**
8
+ * Drive {@link generate} from a spec to an output directory, plus the
9
+ * snapshot bookkeeping that powers `--report-renames`. Returns the full
10
+ * `GenerateResult` (files + ir) so callers can chain.
11
+ */
12
+ export async function sync(opts) {
13
+ const cwd = opts.cwd ?? process.cwd();
14
+ const output = resolve(cwd, opts.output);
15
+ const input = resolveSpecInput(opts.input, cwd);
16
+ const snapshotPath = join(output, SNAPSHOT_FILENAME);
17
+ const prevOps = opts.reportRenames
18
+ ? await loadSnapshotOps(snapshotPath)
19
+ : null;
20
+ const result = await generate({
21
+ input,
22
+ output,
23
+ normalize: opts.normalize,
24
+ defaultBaseUrl: opts.defaultBaseUrl,
25
+ scaffold: opts.scaffold,
26
+ dryRun: opts.dryRun,
27
+ });
28
+ const nextOps = extractOperationMap(result.ir);
29
+ if (!opts.dryRun && opts.writeSnapshot !== false) {
30
+ await writeSnapshotOps(snapshotPath, nextOps);
31
+ }
32
+ const diff = opts.reportRenames
33
+ ? diffOperationIds(prevOps ?? new Map(), nextOps)
34
+ : undefined;
35
+ return { ...result, diff };
36
+ }
37
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAGL,QAAQ,GACT,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAsB,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAsBvB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAiB;IAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAErD,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa;QAChC,CAAC,CAAC,MAAM,eAAe,CAAC,YAAY,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC;QAC5B,KAAK;QACL,MAAM;QACN,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK,EAAE,CAAC;QACjD,MAAM,gBAAgB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa;QAC7B,CAAC,CAAC,gBAAgB,CAAC,OAAO,IAAI,IAAI,GAAG,EAAE,EAAE,OAAO,CAAC;QACjD,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@ahmedrowaihi/k6-toolkit",
3
+ "version": "0.2.0",
4
+ "description": "Programmatic toolkit for k6 workflows. Bundle loadtests (tsdown passthrough), spawn the k6 binary, sync the typed client from OpenAPI specs. One library covering the bundle → run → sync flow.",
5
+ "keywords": [
6
+ "k6",
7
+ "load-testing",
8
+ "openapi",
9
+ "codegen",
10
+ "bundler",
11
+ "tsdown"
12
+ ],
13
+ "homepage": "https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/k6/toolkit",
14
+ "bugs": {
15
+ "url": "https://github.com/ahmedrowaihi/contract-kit/issues"
16
+ },
17
+ "license": "MIT",
18
+ "author": {
19
+ "name": "Ahmed Rowaihi",
20
+ "email": "ahmedrowaihi@gmail.com"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/ahmedrowaihi/contract-kit.git",
25
+ "directory": "packages/k6/toolkit"
26
+ },
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "main": "./dist/index.js",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.js"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
38
+ "files": [
39
+ "dist",
40
+ "README.md",
41
+ "LICENSE.md"
42
+ ],
43
+ "publishConfig": {
44
+ "access": "public",
45
+ "provenance": true
46
+ },
47
+ "dependencies": {
48
+ "tinyglobby": "^0.2.10",
49
+ "tsdown": "^0.22.0",
50
+ "@ahmedrowaihi/k6-gen": "0.2.2",
51
+ "@ahmedrowaihi/openapi-tools": "1.4.0"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^22",
55
+ "vitest": "^4.0.0",
56
+ "@ahmedrowaihi/tsconfig": "0.0.0"
57
+ },
58
+ "engines": {
59
+ "node": ">=20.19.0"
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.build.json",
63
+ "dev": "tsc -p tsconfig.build.json --watch",
64
+ "typecheck": "tsc --noEmit",
65
+ "test": "vitest run --passWithNoTests"
66
+ }
67
+ }