@auto-engineer/component-implementor-react 1.95.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 (65) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-test.log +14 -0
  3. package/.turbo/turbo-type-check.log +4 -0
  4. package/CHANGELOG.md +109 -0
  5. package/LICENSE +10 -0
  6. package/dist/src/commands/implement-component.d.ts +45 -0
  7. package/dist/src/commands/implement-component.d.ts.map +1 -0
  8. package/dist/src/commands/implement-component.js +124 -0
  9. package/dist/src/commands/implement-component.js.map +1 -0
  10. package/dist/src/commands/implement-component.test.d.ts +2 -0
  11. package/dist/src/commands/implement-component.test.d.ts.map +1 -0
  12. package/dist/src/commands/implement-component.test.js +130 -0
  13. package/dist/src/commands/implement-component.test.js.map +1 -0
  14. package/dist/src/extract-code-block.d.ts +2 -0
  15. package/dist/src/extract-code-block.d.ts.map +1 -0
  16. package/dist/src/extract-code-block.js +7 -0
  17. package/dist/src/extract-code-block.js.map +1 -0
  18. package/dist/src/extract-code-block.test.d.ts +2 -0
  19. package/dist/src/extract-code-block.test.d.ts.map +1 -0
  20. package/dist/src/extract-code-block.test.js +28 -0
  21. package/dist/src/extract-code-block.test.js.map +1 -0
  22. package/dist/src/generate-component.d.ts +15 -0
  23. package/dist/src/generate-component.d.ts.map +1 -0
  24. package/dist/src/generate-component.js +39 -0
  25. package/dist/src/generate-component.js.map +1 -0
  26. package/dist/src/generate-component.test.d.ts +2 -0
  27. package/dist/src/generate-component.test.d.ts.map +1 -0
  28. package/dist/src/generate-component.test.js +77 -0
  29. package/dist/src/generate-component.test.js.map +1 -0
  30. package/dist/src/generate-story.d.ts +14 -0
  31. package/dist/src/generate-story.d.ts.map +1 -0
  32. package/dist/src/generate-story.js +35 -0
  33. package/dist/src/generate-story.js.map +1 -0
  34. package/dist/src/generate-story.test.d.ts +2 -0
  35. package/dist/src/generate-story.test.d.ts.map +1 -0
  36. package/dist/src/generate-story.test.js +62 -0
  37. package/dist/src/generate-story.test.js.map +1 -0
  38. package/dist/src/generate-test.d.ts +14 -0
  39. package/dist/src/generate-test.d.ts.map +1 -0
  40. package/dist/src/generate-test.js +38 -0
  41. package/dist/src/generate-test.js.map +1 -0
  42. package/dist/src/generate-test.test.d.ts +2 -0
  43. package/dist/src/generate-test.test.d.ts.map +1 -0
  44. package/dist/src/generate-test.test.js +66 -0
  45. package/dist/src/generate-test.test.js.map +1 -0
  46. package/dist/src/index.d.ts +12 -0
  47. package/dist/src/index.d.ts.map +1 -0
  48. package/dist/src/index.js +5 -0
  49. package/dist/src/index.js.map +1 -0
  50. package/dist/tsconfig.tsbuildinfo +1 -0
  51. package/ketchup-plan.md +13 -0
  52. package/package.json +25 -0
  53. package/src/commands/implement-component.test.ts +151 -0
  54. package/src/commands/implement-component.ts +190 -0
  55. package/src/extract-code-block.test.ts +33 -0
  56. package/src/extract-code-block.ts +6 -0
  57. package/src/generate-component.test.ts +93 -0
  58. package/src/generate-component.ts +57 -0
  59. package/src/generate-story.test.ts +75 -0
  60. package/src/generate-story.ts +51 -0
  61. package/src/generate-test.test.ts +78 -0
  62. package/src/generate-test.ts +55 -0
  63. package/src/index.ts +11 -0
  64. package/tsconfig.json +10 -0
  65. package/vitest.config.ts +14 -0
@@ -0,0 +1,5 @@
1
+
2
+ > @auto-engineer/component-implementor-react@1.95.0 build /home/runner/work/auto-engineer/auto-engineer/packages/component-implementor-react
3
+ > tsc && tsx ../../scripts/fix-esm-imports.ts
4
+
5
+ Fixed ESM imports in dist/
@@ -0,0 +1,14 @@
1
+
2
+ > @auto-engineer/component-implementor-react@1.94.0 test /home/runner/work/auto-engineer/auto-engineer/packages/component-implementor-react
3
+ > vitest run --reporter=dot
4
+
5
+
6
+  RUN  v3.2.4 /home/runner/work/auto-engineer/auto-engineer/packages/component-implementor-react
7
+
8
+ ····················
9
+
10
+  Test Files  5 passed (5)
11
+  Tests  20 passed (20)
12
+  Start at  16:17:02
13
+  Duration  2.95s (transform 1.36s, setup 0ms, collect 2.34s, tests 151ms, environment 1ms, prepare 1.99s)
14
+
@@ -0,0 +1,4 @@
1
+
2
+ > @auto-engineer/component-implementor-react@1.94.0 type-check /home/runner/work/auto-engineer/auto-engineer/packages/component-implementor-react
3
+ > tsc --noEmit
4
+
package/CHANGELOG.md ADDED
@@ -0,0 +1,109 @@
1
+ # @auto-engineer/component-implementor-react
2
+
3
+ ## 1.95.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`d641d0e`](https://github.com/BeOnAuto/auto-engineer/commit/d641d0e6ded1c6e136a2d33e380c204b730abeb1) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **server-generator-apollo-emmett**: add null-document guidance to projection template
8
+ - **server-generator-apollo-emmett**: add discriminated union guidance to evolve template
9
+ - **server-generator-apollo-emmett**: fill missing inline object fields with type defaults
10
+ - **server-implementer**: add discriminated union narrowing guidance to prompts
11
+ - **server-implementer**: load full shared directory into implementer context
12
+
13
+ ### Patch Changes
14
+
15
+ - [`d49324c`](https://github.com/BeOnAuto/auto-engineer/commit/d49324cec0f25f601f8beec216898da05cce22f9) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **component-implementor-react**: add missing publishConfig for public npm access
16
+
17
+ - Updated dependencies [[`d641d0e`](https://github.com/BeOnAuto/auto-engineer/commit/d641d0e6ded1c6e136a2d33e380c204b730abeb1), [`d49324c`](https://github.com/BeOnAuto/auto-engineer/commit/d49324cec0f25f601f8beec216898da05cce22f9)]:
18
+ - @auto-engineer/message-bus@1.95.0
19
+ - @auto-engineer/model-factory@1.95.0
20
+
21
+ ## 1.94.0
22
+
23
+ ### Minor Changes
24
+
25
+ - [`5c22022`](https://github.com/BeOnAuto/auto-engineer/commit/5c220229c406fe300930f21530bea288cfe709ee) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **server-generator-apollo-emmett**: add null-document guidance to projection template
26
+ - **server-generator-apollo-emmett**: add discriminated union guidance to evolve template
27
+ - **server-generator-apollo-emmett**: fill missing inline object fields with type defaults
28
+ - **server-implementer**: add discriminated union narrowing guidance to prompts
29
+ - **server-implementer**: load full shared directory into implementer context
30
+
31
+ ### Patch Changes
32
+
33
+ - [`e016efa`](https://github.com/BeOnAuto/auto-engineer/commit/e016efa10d937a630e7be631f1c11722e8aed024) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **global**: extract inline object helpers to narrative, migrate all consumers
34
+
35
+ - Updated dependencies [[`5c22022`](https://github.com/BeOnAuto/auto-engineer/commit/5c220229c406fe300930f21530bea288cfe709ee), [`e016efa`](https://github.com/BeOnAuto/auto-engineer/commit/e016efa10d937a630e7be631f1c11722e8aed024)]:
36
+ - @auto-engineer/message-bus@1.94.0
37
+ - @auto-engineer/model-factory@1.94.0
38
+
39
+ ## 1.93.0
40
+
41
+ ### Minor Changes
42
+
43
+ - [`b39bfd1`](https://github.com/BeOnAuto/auto-engineer/commit/b39bfd1b15a6ba83bf70c1045f0f99ca01af9e6d) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **server-generator-apollo-emmett**: fill missing inline object fields with type defaults
44
+ - **server-implementer**: add discriminated union narrowing guidance to prompts
45
+ - **global**: mark all bursts done in ketchup plans
46
+
47
+ - [`0d1d200`](https://github.com/BeOnAuto/auto-engineer/commit/0d1d200744a6cbf8d1383ca3189ff3c3056d1baf) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **server-generator-apollo-emmett**: add null-document guidance to projection template
48
+
49
+ - [`5779ee2`](https://github.com/BeOnAuto/auto-engineer/commit/5779ee2adec80576a3885e11268310cfaf487be3) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **root**: add .auto-configure.json to .gitignore
50
+ - **generate-react-client**: send X-Org-Id header in components upload
51
+ - **cli**: persist /configure data to .auto-configure.json
52
+ - **cli**: /configure defaults COMPONENTS_UPLOAD_URL for local dev
53
+ - **cli**: /configure sets ORG_ID and PROJECT_ID env vars
54
+
55
+ - [`7abc038`](https://github.com/BeOnAuto/auto-engineer/commit/7abc038ca3ddd6b71e94523b26be23ed62acc06b) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **server-generator-apollo-emmett**: add discriminated union guidance to evolve template
56
+
57
+ ### Patch Changes
58
+
59
+ - [`36446e8`](https://github.com/BeOnAuto/auto-engineer/commit/36446e80626f019fef6409d3c8b2b0c0eee74b32) Thanks [@rami-hatoum](https://github.com/rami-hatoum)! - - **server-generator-apollo-emmett**: mark bursts 20-22 done in ketchup plan
60
+
61
+ - Updated dependencies [[`b39bfd1`](https://github.com/BeOnAuto/auto-engineer/commit/b39bfd1b15a6ba83bf70c1045f0f99ca01af9e6d), [`0d1d200`](https://github.com/BeOnAuto/auto-engineer/commit/0d1d200744a6cbf8d1383ca3189ff3c3056d1baf), [`21a0840`](https://github.com/BeOnAuto/auto-engineer/commit/21a084062e0132a146c31b5ed395051f8423dbed), [`c8b5ced`](https://github.com/BeOnAuto/auto-engineer/commit/c8b5ced06aec8f03fd81270da37b70ed0c5ee1a4), [`36446e8`](https://github.com/BeOnAuto/auto-engineer/commit/36446e80626f019fef6409d3c8b2b0c0eee74b32), [`a306579`](https://github.com/BeOnAuto/auto-engineer/commit/a3065799dd4f2c60cacf895d4af93af456d93447), [`5779ee2`](https://github.com/BeOnAuto/auto-engineer/commit/5779ee2adec80576a3885e11268310cfaf487be3), [`ef365c4`](https://github.com/BeOnAuto/auto-engineer/commit/ef365c4f58a41736871db4c70b817375984a638e), [`7abc038`](https://github.com/BeOnAuto/auto-engineer/commit/7abc038ca3ddd6b71e94523b26be23ed62acc06b), [`8c21b52`](https://github.com/BeOnAuto/auto-engineer/commit/8c21b529e4f0a83f00bdaa0fe10562b12a19d349)]:
62
+ - @auto-engineer/message-bus@1.93.0
63
+ - @auto-engineer/model-factory@1.93.0
64
+
65
+ ## 1.92.0
66
+
67
+ ### Minor Changes
68
+
69
+ - [`5475f60`](https://github.com/BeOnAuto/auto-engineer/commit/5475f6079c6591e8b5fa8dd22825a9d933d0aeb8) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - Added .auto-configure.json to .gitignore to prevent local configuration from being committed to version control
70
+
71
+ - [`5c5b8bc`](https://github.com/BeOnAuto/auto-engineer/commit/5c5b8bc401fdc3234ae4fdca1fdf13770eeb0935) Thanks [@github-actions[bot]](https://github.com/github-actions%5Bbot%5D)! - - **component-implementor-react**: add index.ts with COMMANDS export
72
+ - **component-implementor-react**: add implement-component command handler
73
+ - **component-implementor-react**: add generate-story module
74
+ - **component-implementor-react**: add generate-component module
75
+ - **component-implementor-react**: add generate-test module
76
+
77
+ ### Patch Changes
78
+
79
+ - Updated dependencies [[`b984faa`](https://github.com/BeOnAuto/auto-engineer/commit/b984faa03a182560b49182129bfd183768c27890), [`b4b422c`](https://github.com/BeOnAuto/auto-engineer/commit/b4b422c00c0e2a59bf7d9bc35c5d9f29e86bea0d), [`5475f60`](https://github.com/BeOnAuto/auto-engineer/commit/5475f6079c6591e8b5fa8dd22825a9d933d0aeb8), [`5c5b8bc`](https://github.com/BeOnAuto/auto-engineer/commit/5c5b8bc401fdc3234ae4fdca1fdf13770eeb0935), [`17713c7`](https://github.com/BeOnAuto/auto-engineer/commit/17713c757e3f340b68709152563a3e8ac69c32a2), [`bc5e46b`](https://github.com/BeOnAuto/auto-engineer/commit/bc5e46b5c5b65f488e18a87fa252ab35b20ce79b), [`903f609`](https://github.com/BeOnAuto/auto-engineer/commit/903f6099b898803b6cbf42ce0c9aa59f2675da2c), [`bd8c82c`](https://github.com/BeOnAuto/auto-engineer/commit/bd8c82cb031101598d0a85d45d0c43c2deca579e)]:
80
+ - @auto-engineer/message-bus@1.92.0
81
+ - @auto-engineer/model-factory@1.92.0
82
+
83
+ ## 1.91.0
84
+
85
+ ### Minor Changes
86
+
87
+ - [`ca28476`](https://github.com/BeOnAuto/auto-engineer/commit/ca2847643354c281b82b3427bb45be1caf023370) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add generate-test module
88
+
89
+ - [`c272077`](https://github.com/BeOnAuto/auto-engineer/commit/c272077c9934a7ed44e2a8eeec800dd7de41eb2a) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add extract-code-block utility
90
+
91
+ - [`2263623`](https://github.com/BeOnAuto/auto-engineer/commit/2263623af310170130aaa99dbd41919378c397ab) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add generate-component module
92
+
93
+ - [`ceaa70d`](https://github.com/BeOnAuto/auto-engineer/commit/ceaa70df7f8374f8426f3a876a516b2433f28da1) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add generate-story module
94
+
95
+ - [`a54bd95`](https://github.com/BeOnAuto/auto-engineer/commit/a54bd9562f9bed95bb1d78e627028d27761b1624) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add index.ts with COMMANDS export
96
+
97
+ - [`150fcb0`](https://github.com/BeOnAuto/auto-engineer/commit/150fcb020d147a5563c3b7a3712e7fcd25febd9e) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add implement-component command handler
98
+
99
+ ### Patch Changes
100
+
101
+ - [`8d0ef1f`](https://github.com/BeOnAuto/auto-engineer/commit/8d0ef1f12d0bccb0825c7e70e64c92c5325aaad3) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: add package infrastructure
102
+
103
+ - [`aa6f3ec`](https://github.com/BeOnAuto/auto-engineer/commit/aa6f3ec7c976b1acebaafa22f29385e0757ab807) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - Updated project dependency lockfile
104
+
105
+ - [`7a132d1`](https://github.com/BeOnAuto/auto-engineer/commit/7a132d126238ea715dcbd13ee2261ce2def70428) Thanks [@SamHatoum](https://github.com/SamHatoum)! - - **component-implementor-react**: mark all bursts done in plan
106
+
107
+ - Updated dependencies [[`39d380d`](https://github.com/BeOnAuto/auto-engineer/commit/39d380d87fcd9507a24e0848b1934246f7ab7ee0), [`ca28476`](https://github.com/BeOnAuto/auto-engineer/commit/ca2847643354c281b82b3427bb45be1caf023370), [`8d0ef1f`](https://github.com/BeOnAuto/auto-engineer/commit/8d0ef1f12d0bccb0825c7e70e64c92c5325aaad3), [`aa6f3ec`](https://github.com/BeOnAuto/auto-engineer/commit/aa6f3ec7c976b1acebaafa22f29385e0757ab807), [`c272077`](https://github.com/BeOnAuto/auto-engineer/commit/c272077c9934a7ed44e2a8eeec800dd7de41eb2a), [`2263623`](https://github.com/BeOnAuto/auto-engineer/commit/2263623af310170130aaa99dbd41919378c397ab), [`7a132d1`](https://github.com/BeOnAuto/auto-engineer/commit/7a132d126238ea715dcbd13ee2261ce2def70428), [`ceaa70d`](https://github.com/BeOnAuto/auto-engineer/commit/ceaa70df7f8374f8426f3a876a516b2433f28da1), [`a54bd95`](https://github.com/BeOnAuto/auto-engineer/commit/a54bd9562f9bed95bb1d78e627028d27761b1624), [`150fcb0`](https://github.com/BeOnAuto/auto-engineer/commit/150fcb020d147a5563c3b7a3712e7fcd25febd9e), [`f5ccb56`](https://github.com/BeOnAuto/auto-engineer/commit/f5ccb566483a3350298d92cd6ca3d3632f636bd3)]:
108
+ - @auto-engineer/message-bus@1.91.0
109
+ - @auto-engineer/model-factory@1.91.0
package/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ Elastic License 2.0
2
+
3
+ Copyright 2024 Sam Hatoum
4
+
5
+ This software and associated documentation files (the "Software") are licensed under the Elastic License 2.0 (the "License"). You may not use this file except in compliance with the License.
6
+
7
+ You may obtain a copy of the License at:
8
+ https://www.elastic.co/licensing/elastic-license
9
+
10
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
@@ -0,0 +1,45 @@
1
+ import { type Command, type Event } from '@auto-engineer/message-bus';
2
+ type ComponentJobPayload = {
3
+ componentId: string;
4
+ structure: string[];
5
+ rendering: string[];
6
+ interaction: string[];
7
+ styling: string[];
8
+ storybookPath: string;
9
+ files: {
10
+ create?: string[];
11
+ modify?: string[];
12
+ };
13
+ };
14
+ type ComponentJob = {
15
+ id: string;
16
+ dependsOn: string[];
17
+ target: 'ImplementComponent';
18
+ payload: ComponentJobPayload;
19
+ };
20
+ export type ImplementComponentCommand = Command<'ImplementComponent', {
21
+ targetDir: string;
22
+ job: ComponentJob;
23
+ }>;
24
+ export type ComponentImplementedEvent = Event<'ComponentImplemented', {
25
+ name: string;
26
+ componentPath: string;
27
+ testPath: string;
28
+ storyPath: string;
29
+ filesCreated: string[];
30
+ }>;
31
+ export type ComponentImplementationFailedEvent = Event<'ComponentImplementationFailed', {
32
+ error: string;
33
+ name: string;
34
+ }>;
35
+ export type ImplementComponentEvents = ComponentImplementedEvent | ComponentImplementationFailedEvent;
36
+ export declare function handleImplementComponent(command: ImplementComponentCommand): Promise<ComponentImplementedEvent | ComponentImplementationFailedEvent>;
37
+ export declare const commandHandler: import("@auto-engineer/message-bus").UnifiedCommandHandler<Readonly<{
38
+ type: string;
39
+ data: Readonly<Record<string, unknown>>;
40
+ timestamp?: Date;
41
+ requestId?: string;
42
+ correlationId?: string;
43
+ }>>;
44
+ export default commandHandler;
45
+ //# sourceMappingURL=implement-component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implement-component.d.ts","sourceRoot":"","sources":["../../../src/commands/implement-component.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,OAAO,EAAwB,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAQ5F,KAAK,mBAAmB,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACjD,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAC7C,oBAAoB,EACpB;IACE,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;CACnB,CACF,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,KAAK,CAC3C,sBAAsB,EACtB;IACE,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CACF,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG,KAAK,CACpD,+BAA+B,EAC/B;IACE,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CACF,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,yBAAyB,GAAG,kCAAkC,CAAC;AAuBtG,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,yBAAyB,GAAG,kCAAkC,CAAC,CA8EzE;AAED,eAAO,MAAM,cAAc;;;;;;GA2BzB,CAAC;AAEH,eAAe,cAAc,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { defineCommandHandler } from '@auto-engineer/message-bus';
5
+ import createDebug from 'debug';
6
+ import { generateComponentFile } from '../generate-component.js';
7
+ import { generateStoryFile } from '../generate-story.js';
8
+ import { generateTestFile } from '../generate-test.js';
9
+ const debug = createDebug('auto:component-implementor-react:command');
10
+ function pascalCase(id) {
11
+ return id
12
+ .split('-')
13
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
14
+ .join('');
15
+ }
16
+ function deriveFilePaths(targetDir, payload) {
17
+ const rawPath = payload.files.modify?.[0] ?? payload.files.create?.[0] ?? '';
18
+ const componentPath = path.resolve(targetDir, rawPath);
19
+ const dir = path.dirname(componentPath);
20
+ const componentName = pascalCase(payload.componentId);
21
+ const testPath = path.join(dir, `${componentName}.test.tsx`);
22
+ const storyPath = path.resolve(targetDir, payload.storybookPath);
23
+ return { componentPath, testPath, storyPath, componentName };
24
+ }
25
+ export async function handleImplementComponent(command) {
26
+ const { targetDir, job } = command.data;
27
+ const { payload } = job;
28
+ const { componentPath, testPath, storyPath, componentName } = deriveFilePaths(targetDir, payload);
29
+ const isModify = (payload.files.modify?.length ?? 0) > 0;
30
+ debug('Implementing component: %s', componentName);
31
+ try {
32
+ let existingComponent;
33
+ if (isModify && existsSync(componentPath)) {
34
+ existingComponent = await readFile(componentPath, 'utf-8');
35
+ debug('Read existing component: %d chars', existingComponent.length);
36
+ }
37
+ const specDeltas = {
38
+ structure: payload.structure,
39
+ rendering: payload.rendering,
40
+ interaction: payload.interaction,
41
+ styling: payload.styling,
42
+ };
43
+ debug('Generating test file...');
44
+ const testCode = await generateTestFile({
45
+ componentName,
46
+ specDeltas,
47
+ existingComponent,
48
+ });
49
+ debug('Generating component file...');
50
+ const componentCode = await generateComponentFile({
51
+ componentName,
52
+ specDeltas,
53
+ testCode,
54
+ existingComponent,
55
+ });
56
+ debug('Generating story file...');
57
+ const storyCode = await generateStoryFile({
58
+ componentName,
59
+ specDeltas,
60
+ componentCode,
61
+ });
62
+ await mkdir(path.dirname(testPath), { recursive: true });
63
+ await Promise.all([
64
+ writeFile(testPath, testCode, 'utf-8'),
65
+ writeFile(componentPath, componentCode, 'utf-8'),
66
+ writeFile(storyPath, storyCode, 'utf-8'),
67
+ ]);
68
+ debug('Wrote 3 files for %s', componentName);
69
+ return {
70
+ type: 'ComponentImplemented',
71
+ data: {
72
+ name: componentName,
73
+ componentPath,
74
+ testPath,
75
+ storyPath,
76
+ filesCreated: [testPath, componentPath, storyPath],
77
+ },
78
+ timestamp: new Date(),
79
+ requestId: command.requestId,
80
+ correlationId: command.correlationId,
81
+ };
82
+ }
83
+ catch (error) {
84
+ const errorMessage = error instanceof Error ? error.message : String(error);
85
+ debug('Implementation failed: %s', errorMessage);
86
+ return {
87
+ type: 'ComponentImplementationFailed',
88
+ data: { error: errorMessage, name: componentName },
89
+ timestamp: new Date(),
90
+ requestId: command.requestId,
91
+ correlationId: command.correlationId,
92
+ };
93
+ }
94
+ }
95
+ export const commandHandler = defineCommandHandler({
96
+ name: 'ImplementComponent',
97
+ displayName: 'Implement Component',
98
+ alias: 'implement:component',
99
+ description: 'Generate a React component with test and Storybook story from structured spec deltas',
100
+ category: 'implement',
101
+ icon: 'component',
102
+ fields: {
103
+ targetDir: {
104
+ description: 'The client project root directory',
105
+ required: true,
106
+ },
107
+ job: {
108
+ description: 'ComponentJob with structured spec delta payload',
109
+ required: true,
110
+ },
111
+ },
112
+ examples: [
113
+ '$ auto implement:component --target-dir=./client --job=\'{"id":"job_1","dependsOn":[],"target":"ImplementComponent","payload":{...}}\'',
114
+ ],
115
+ events: [
116
+ { name: 'ComponentImplemented', displayName: 'Component Implemented' },
117
+ { name: 'ComponentImplementationFailed', displayName: 'Component Implementation Failed' },
118
+ ],
119
+ handle: async (command) => {
120
+ return handleImplementComponent(command);
121
+ },
122
+ });
123
+ export default commandHandler;
124
+ //# sourceMappingURL=implement-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implement-component.js","sourceRoot":"","sources":["../../../src/commands/implement-component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=implement-component.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implement-component.test.d.ts","sourceRoot":"","sources":["../../../src/commands/implement-component.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,130 @@
1
+ import { afterEach, describe, expect, it, vi } from 'vitest';
2
+ vi.mock('ai', () => ({
3
+ generateText: vi.fn(),
4
+ }));
5
+ vi.mock('@auto-engineer/model-factory', () => ({
6
+ createModelFromEnv: vi.fn(() => 'mock-model'),
7
+ }));
8
+ vi.mock('node:fs/promises', () => ({
9
+ readFile: vi.fn(),
10
+ writeFile: vi.fn(),
11
+ mkdir: vi.fn(),
12
+ }));
13
+ vi.mock('node:fs', () => ({
14
+ existsSync: vi.fn(),
15
+ }));
16
+ import { existsSync } from 'node:fs';
17
+ import { readFile, writeFile } from 'node:fs/promises';
18
+ import { generateText } from 'ai';
19
+ import { commandHandler, handleImplementComponent } from './implement-component.js';
20
+ function makeCommand(overrides = {}) {
21
+ return {
22
+ type: 'ImplementComponent',
23
+ data: {
24
+ targetDir: '/project/client',
25
+ job: {
26
+ id: 'job_1',
27
+ dependsOn: [],
28
+ target: 'ImplementComponent',
29
+ payload: {
30
+ componentId: 'my-button',
31
+ structure: ['renders a button element'],
32
+ rendering: ['shows spinner when loading'],
33
+ interaction: ['calls onClick handler'],
34
+ styling: ['uses primary class'],
35
+ storybookPath: 'src/components/ui/MyButton.stories.tsx',
36
+ files: { create: ['src/components/ui/MyButton.tsx'] },
37
+ },
38
+ },
39
+ ...overrides,
40
+ },
41
+ requestId: 'req-1',
42
+ correlationId: 'cor-1',
43
+ };
44
+ }
45
+ describe('implement-component', () => {
46
+ afterEach(() => {
47
+ vi.clearAllMocks();
48
+ });
49
+ describe('handleImplementComponent', () => {
50
+ it('generates 3 files and returns ComponentImplemented on success', async () => {
51
+ const mockGenerateText = vi.mocked(generateText);
52
+ mockGenerateText
53
+ .mockResolvedValueOnce({ text: 'test file code' })
54
+ .mockResolvedValueOnce({ text: 'component file code' })
55
+ .mockResolvedValueOnce({ text: 'story file code' });
56
+ vi.mocked(existsSync).mockReturnValue(false);
57
+ vi.mocked(writeFile).mockResolvedValue(undefined);
58
+ const result = await handleImplementComponent(makeCommand());
59
+ expect(result).toEqual({
60
+ type: 'ComponentImplemented',
61
+ data: {
62
+ name: 'MyButton',
63
+ componentPath: '/project/client/src/components/ui/MyButton.tsx',
64
+ testPath: '/project/client/src/components/ui/MyButton.test.tsx',
65
+ storyPath: '/project/client/src/components/ui/MyButton.stories.tsx',
66
+ filesCreated: [
67
+ '/project/client/src/components/ui/MyButton.test.tsx',
68
+ '/project/client/src/components/ui/MyButton.tsx',
69
+ '/project/client/src/components/ui/MyButton.stories.tsx',
70
+ ],
71
+ },
72
+ timestamp: expect.any(Date),
73
+ requestId: 'req-1',
74
+ correlationId: 'cor-1',
75
+ });
76
+ expect(writeFile).toHaveBeenCalledTimes(3);
77
+ });
78
+ it('reads existing component when modifying', async () => {
79
+ const mockGenerateText = vi.mocked(generateText);
80
+ mockGenerateText
81
+ .mockResolvedValueOnce({ text: 'test code' })
82
+ .mockResolvedValueOnce({ text: 'component code' })
83
+ .mockResolvedValueOnce({ text: 'story code' });
84
+ vi.mocked(existsSync).mockReturnValue(true);
85
+ vi.mocked(readFile).mockResolvedValue('existing component code');
86
+ vi.mocked(writeFile).mockResolvedValue(undefined);
87
+ const command = makeCommand({
88
+ job: {
89
+ id: 'job_2',
90
+ dependsOn: [],
91
+ target: 'ImplementComponent',
92
+ payload: {
93
+ componentId: 'my-button',
94
+ structure: ['renders a button'],
95
+ rendering: [],
96
+ interaction: [],
97
+ styling: [],
98
+ storybookPath: 'src/components/ui/MyButton.stories.tsx',
99
+ files: { modify: ['src/components/ui/MyButton.tsx'] },
100
+ },
101
+ },
102
+ });
103
+ await handleImplementComponent(command);
104
+ expect(readFile).toHaveBeenCalledWith('/project/client/src/components/ui/MyButton.tsx', 'utf-8');
105
+ });
106
+ it('returns ComponentImplementationFailed on error', async () => {
107
+ const mockGenerateText = vi.mocked(generateText);
108
+ mockGenerateText.mockRejectedValue(new Error('AI service down'));
109
+ vi.mocked(existsSync).mockReturnValue(false);
110
+ const result = await handleImplementComponent(makeCommand());
111
+ expect(result).toEqual({
112
+ type: 'ComponentImplementationFailed',
113
+ data: {
114
+ error: 'AI service down',
115
+ name: 'MyButton',
116
+ },
117
+ timestamp: expect.any(Date),
118
+ requestId: 'req-1',
119
+ correlationId: 'cor-1',
120
+ });
121
+ });
122
+ });
123
+ describe('commandHandler', () => {
124
+ it('has correct metadata', () => {
125
+ expect(commandHandler.name).toBe('ImplementComponent');
126
+ expect(commandHandler.alias).toBe('implement:component');
127
+ });
128
+ });
129
+ });
130
+ //# sourceMappingURL=implement-component.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"implement-component.test.js","sourceRoot":"","sources":["../../../src/commands/implement-component.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function extractCodeBlock(text: string): string;
2
+ //# sourceMappingURL=extract-code-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-code-block.d.ts","sourceRoot":"","sources":["../../src/extract-code-block.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKrD"}
@@ -0,0 +1,7 @@
1
+ export function extractCodeBlock(text) {
2
+ return text
3
+ .replace(/```(?:tsx?|typescript)?/g, '')
4
+ .replace(/```/g, '')
5
+ .trim();
6
+ }
7
+ //# sourceMappingURL=extract-code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-code-block.js","sourceRoot":"","sources":["../../src/extract-code-block.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI;SACR,OAAO,CAAC,0BAA0B,EAAE,EAAE,CAAC;SACvC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;SACnB,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=extract-code-block.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-code-block.test.d.ts","sourceRoot":"","sources":["../../src/extract-code-block.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { extractCodeBlock } from './extract-code-block.js';
3
+ describe('extractCodeBlock', () => {
4
+ it('returns plain text unchanged', () => {
5
+ expect(extractCodeBlock('const x = 1;')).toBe('const x = 1;');
6
+ });
7
+ it('strips tsx fenced code block', () => {
8
+ const input = '```tsx\nconst x = 1;\n```';
9
+ expect(extractCodeBlock(input)).toBe('const x = 1;');
10
+ });
11
+ it('strips typescript fenced code block', () => {
12
+ const input = '```typescript\nconst x = 1;\n```';
13
+ expect(extractCodeBlock(input)).toBe('const x = 1;');
14
+ });
15
+ it('strips ts fenced code block', () => {
16
+ const input = '```ts\nconst x = 1;\n```';
17
+ expect(extractCodeBlock(input)).toBe('const x = 1;');
18
+ });
19
+ it('strips bare fenced code block', () => {
20
+ const input = '```\nconst x = 1;\n```';
21
+ expect(extractCodeBlock(input)).toBe('const x = 1;');
22
+ });
23
+ it('trims surrounding whitespace', () => {
24
+ const input = ' ```tsx\n const x = 1;\n ``` ';
25
+ expect(extractCodeBlock(input)).toBe('const x = 1;');
26
+ });
27
+ });
28
+ //# sourceMappingURL=extract-code-block.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-code-block.test.js","sourceRoot":"","sources":["../../src/extract-code-block.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,KAAK,GAAG,2BAA2B,CAAC;QAC1C,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,KAAK,GAAG,kCAAkC,CAAC;QACjD,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QACrC,MAAM,KAAK,GAAG,0BAA0B,CAAC;QACzC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QACvC,MAAM,KAAK,GAAG,wBAAwB,CAAC;QACvC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,KAAK,GAAG,mCAAmC,CAAC;QAClD,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ type SpecDeltas = {
2
+ structure: string[];
3
+ rendering: string[];
4
+ interaction: string[];
5
+ styling: string[];
6
+ };
7
+ type GenerateComponentInput = {
8
+ componentName: string;
9
+ specDeltas: SpecDeltas;
10
+ testCode: string;
11
+ existingComponent?: string;
12
+ };
13
+ export declare function generateComponentFile(input: GenerateComponentInput): Promise<string>;
14
+ export {};
15
+ //# sourceMappingURL=generate-component.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-component.d.ts","sourceRoot":"","sources":["../../src/generate-component.ts"],"names":[],"mappings":"AAIA,KAAK,UAAU,GAAG;IAChB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAiCF,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,CAO1F"}
@@ -0,0 +1,39 @@
1
+ import { createModelFromEnv } from '@auto-engineer/model-factory';
2
+ import { generateText } from 'ai';
3
+ import { extractCodeBlock } from './extract-code-block.js';
4
+ function buildSpecSection(heading, items) {
5
+ if (items.length === 0)
6
+ return '';
7
+ return `## ${heading}\n${items.map((i) => `- ${i}`).join('\n')}`;
8
+ }
9
+ function buildPrompt(input) {
10
+ const sections = [
11
+ buildSpecSection('Structure', input.specDeltas.structure),
12
+ buildSpecSection('Rendering', input.specDeltas.rendering),
13
+ buildSpecSection('Interaction', input.specDeltas.interaction),
14
+ buildSpecSection('Styling', input.specDeltas.styling),
15
+ ]
16
+ .filter(Boolean)
17
+ .join('\n\n');
18
+ const existingContext = input.existingComponent
19
+ ? `\n\n## Existing Component\n\`\`\`tsx\n${input.existingComponent}\n\`\`\``
20
+ : '';
21
+ return `Component: ${input.componentName}\n\n${sections}${existingContext}\n\n## Test File\n\`\`\`tsx\n${input.testCode}\n\`\`\``;
22
+ }
23
+ const SYSTEM_PROMPT = `You are a React component expert. Write a React component (.tsx) that satisfies the spec and passes the provided test.
24
+
25
+ Rules:
26
+ - Use functional components with TypeScript
27
+ - Export the component as a named export
28
+ - Use Tailwind CSS classes for styling
29
+ - The component must pass the provided test
30
+ - Return ONLY the component file code, no commentary`;
31
+ export async function generateComponentFile(input) {
32
+ const { text } = await generateText({
33
+ model: createModelFromEnv(),
34
+ system: SYSTEM_PROMPT,
35
+ prompt: buildPrompt(input),
36
+ });
37
+ return extractCodeBlock(text);
38
+ }
39
+ //# sourceMappingURL=generate-component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-component.js","sourceRoot":"","sources":["../../src/generate-component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgBxD,SAAS,gBAAgB,CAAC,OAAe,EAAE,KAAe;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO,MAAM,OAAO,KAAK,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,KAA6B;IAChD,MAAM,QAAQ,GAAG;QACf,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QACzD,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QACzD,gBAAgB,CAAC,aAAa,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;QAC7D,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;KACtD;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;IAEhB,MAAM,eAAe,GAAG,KAAK,CAAC,iBAAiB;QAC7C,CAAC,CAAC,yCAAyC,KAAK,CAAC,iBAAiB,UAAU;QAC5E,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,cAAc,KAAK,CAAC,aAAa,OAAO,QAAQ,GAAG,eAAe,gCAAgC,KAAK,CAAC,QAAQ,UAAU,CAAC;AACpI,CAAC;AAED,MAAM,aAAa,GAAG;;;;;;;qDAO+B,CAAC;AAEtD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAA6B;IACvE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,YAAY,CAAC;QAClC,KAAK,EAAE,kBAAkB,EAAE;QAC3B,MAAM,EAAE,aAAa;QACrB,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC;KAC3B,CAAC,CAAC;IACH,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=generate-component.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-component.test.d.ts","sourceRoot":"","sources":["../../src/generate-component.test.ts"],"names":[],"mappings":""}