@specverse/engines 4.1.30 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/examples/manifests/frontend-only.yaml +3 -6
- package/assets/examples/manifests/fullstack-app.yaml +5 -7
- package/assets/examples/manifests/fullstack-monorepo.yaml +3 -6
- package/assets/templates/default/specs/main.specly +65 -0
- package/dist/inference/comprehensive-engine.d.ts.map +1 -1
- package/dist/inference/comprehensive-engine.js +3 -19
- package/dist/inference/comprehensive-engine.js.map +1 -1
- package/dist/inference/core/rule-engine.d.ts +31 -0
- package/dist/inference/core/rule-engine.d.ts.map +1 -1
- package/dist/inference/core/rule-engine.js +117 -33
- package/dist/inference/core/rule-engine.js.map +1 -1
- package/dist/inference/core/rule-file-types.d.ts +0 -2
- package/dist/inference/core/rule-file-types.d.ts.map +1 -1
- package/dist/inference/core/rule-file-types.js +3 -6
- package/dist/inference/core/rule-file-types.js.map +1 -1
- package/dist/inference/core/rule-loader.d.ts +5 -15
- package/dist/inference/core/rule-loader.d.ts.map +1 -1
- package/dist/inference/core/rule-loader.js +43 -132
- package/dist/inference/core/rule-loader.js.map +1 -1
- package/dist/inference/core/types.d.ts +0 -6
- package/dist/inference/core/types.d.ts.map +1 -1
- package/dist/inference/core/types.js +0 -4
- package/dist/inference/core/types.js.map +1 -1
- package/dist/inference/logical/generators/component-type-resolver.d.ts +0 -26
- package/dist/inference/logical/generators/component-type-resolver.d.ts.map +1 -1
- package/dist/inference/logical/generators/component-type-resolver.js +0 -19
- package/dist/inference/logical/generators/component-type-resolver.js.map +1 -1
- package/dist/inference/logical/generators/specialist-view-expander.d.ts +1 -17
- package/dist/inference/logical/generators/specialist-view-expander.d.ts.map +1 -1
- package/dist/inference/logical/generators/specialist-view-expander.js +0 -15
- package/dist/inference/logical/generators/specialist-view-expander.js.map +1 -1
- package/dist/inference/logical/generators/view-generator.d.ts +4 -14
- package/dist/inference/logical/generators/view-generator.d.ts.map +1 -1
- package/dist/inference/logical/generators/view-generator.js +6 -26
- package/dist/inference/logical/generators/view-generator.js.map +1 -1
- package/dist/inference/logical/index.d.ts +2 -2
- package/dist/inference/logical/index.d.ts.map +1 -1
- package/dist/inference/logical/logical-engine.d.ts.map +1 -1
- package/dist/inference/logical/logical-engine.js +17 -80
- package/dist/inference/logical/logical-engine.js.map +1 -1
- package/dist/inference/quint-transpiler.d.ts +5 -3
- package/dist/inference/quint-transpiler.d.ts.map +1 -1
- package/dist/inference/quint-transpiler.js +11 -6
- package/dist/inference/quint-transpiler.js.map +1 -1
- package/dist/libs/instance-factories/CURVED-INTERFACE.md +278 -0
- package/dist/libs/instance-factories/README.md +73 -0
- package/dist/libs/instance-factories/applications/README.md +51 -0
- package/dist/libs/instance-factories/applications/generic-app.yaml +52 -0
- package/{libs/instance-factories/applications/react-app.yaml → dist/libs/instance-factories/applications/react-app-runtime.yaml} +30 -77
- package/dist/libs/instance-factories/applications/react-app-starter.yaml +143 -0
- package/dist/libs/instance-factories/applications/templates/react/env-example-generator.js +24 -2
- package/dist/libs/instance-factories/applications/templates/react/vite-config-generator.js +54 -33
- package/dist/libs/instance-factories/applications/templates/react-starter/README.md +211 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/api-types-starter-generator.js +69 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/app-tsx-generator.js +110 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/belongs-to.js +40 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/dashboard-body-composer.js +129 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/detail-body-composer.js +80 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/form-body-composer.js +217 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/helpers-emitter.js +51 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/html-to-jsx.js +192 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/list-body-composer.js +56 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/orchestrator.js +41 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/package-json-generator.js +38 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/regen-safety.js +89 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/skeletons/dashboard.tsx.template +49 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/skeletons/detail.tsx.template +96 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/skeletons/form.tsx.template +116 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/skeletons/list.tsx.template +74 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/use-api-hooks-starter-generator.js +95 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/view-emitter.js +81 -0
- package/dist/libs/instance-factories/applications/templates/react-starter/views-generator.js +66 -0
- package/dist/libs/instance-factories/archived/fastify-prisma.yaml +104 -0
- package/dist/libs/instance-factories/cli/README.md +43 -0
- package/dist/libs/instance-factories/cli/commander-js.yaml +55 -0
- package/dist/libs/instance-factories/cli/templates/commander/command-generator.js +63 -12
- package/dist/libs/instance-factories/communication/README.md +47 -0
- package/dist/libs/instance-factories/communication/event-emitter.yaml +60 -0
- package/dist/libs/instance-factories/communication/rabbitmq-events.yaml +87 -0
- package/dist/libs/instance-factories/controllers/README.md +42 -0
- package/dist/libs/instance-factories/controllers/fastify.yaml +139 -0
- package/dist/libs/instance-factories/controllers/templates/fastify/server-generator.js +29 -2
- package/dist/libs/instance-factories/infrastructure/README.md +29 -0
- package/dist/libs/instance-factories/infrastructure/docker-k8s.yaml +61 -0
- package/dist/libs/instance-factories/orms/README.md +54 -0
- package/dist/libs/instance-factories/orms/prisma.yaml +89 -0
- package/dist/libs/instance-factories/orms/templates/prisma/schema-generator.js +2 -2
- package/dist/libs/instance-factories/scaffolding/README.md +49 -0
- package/dist/libs/instance-factories/scaffolding/generic-scaffold.yaml +65 -0
- package/dist/libs/instance-factories/sdks/README.md +28 -0
- package/dist/libs/instance-factories/sdks/python-sdk.yaml +66 -0
- package/dist/libs/instance-factories/sdks/typescript-sdk.yaml +59 -0
- package/dist/libs/instance-factories/services/README.md +55 -0
- package/dist/libs/instance-factories/services/prisma-services.yaml +71 -0
- package/dist/libs/instance-factories/storage/README.md +34 -0
- package/dist/libs/instance-factories/storage/mongodb.yaml +79 -0
- package/dist/libs/instance-factories/storage/postgresql.yaml +75 -0
- package/dist/libs/instance-factories/storage/redis.yaml +79 -0
- package/dist/libs/instance-factories/testing/README.md +40 -0
- package/dist/libs/instance-factories/testing/vitest-tests.yaml +63 -0
- package/dist/libs/instance-factories/tools/README.md +70 -0
- package/dist/libs/instance-factories/tools/mcp.yaml +36 -0
- package/dist/libs/instance-factories/tools/vscode.yaml +35 -0
- package/dist/libs/instance-factories/validation/README.md +38 -0
- package/dist/libs/instance-factories/validation/zod.yaml +56 -0
- package/dist/realize/engines/code-generator.d.ts.map +1 -1
- package/dist/realize/engines/code-generator.js +3 -0
- package/dist/realize/engines/code-generator.js.map +1 -1
- package/dist/realize/index.d.ts.map +1 -1
- package/dist/realize/index.js +15 -22
- package/dist/realize/index.js.map +1 -1
- package/dist/registry/utils/manifest-adapter.d.ts +8 -1
- package/dist/registry/utils/manifest-adapter.d.ts.map +1 -1
- package/dist/registry/utils/manifest-adapter.js +8 -1
- package/dist/registry/utils/manifest-adapter.js.map +1 -1
- package/libs/instance-factories/applications/react-app-starter.yaml +143 -0
- package/libs/instance-factories/applications/templates/react/env-example-generator.ts +24 -2
- package/libs/instance-factories/applications/templates/react/vite-config-generator.ts +54 -33
- package/libs/instance-factories/applications/templates/react-starter/README.md +211 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/dashboard-body-composer.test.ts +153 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/detail-body-composer.test.ts +146 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/form-body-composer.test.ts +188 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/helpers-emitter.test.ts +55 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/html-to-jsx.test.ts +140 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/list-body-composer.test.ts +146 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/orchestrator.test.ts +184 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/parity-p2-factory-imports.test.ts +116 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/parity-p3-rendered-output.test.ts +183 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/regen-safety.test.ts +144 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/starter-generators.test.ts +114 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/view-emitter.test.ts +107 -0
- package/libs/instance-factories/applications/templates/react-starter/__tests__/views-generator.test.ts +139 -0
- package/libs/instance-factories/applications/templates/react-starter/api-types-starter-generator.ts +98 -0
- package/libs/instance-factories/applications/templates/react-starter/app-tsx-generator.ts +141 -0
- package/libs/instance-factories/applications/templates/react-starter/belongs-to.ts +82 -0
- package/libs/instance-factories/applications/templates/react-starter/dashboard-body-composer.ts +189 -0
- package/libs/instance-factories/applications/templates/react-starter/detail-body-composer.ts +135 -0
- package/libs/instance-factories/applications/templates/react-starter/form-body-composer.ts +383 -0
- package/libs/instance-factories/applications/templates/react-starter/helpers-emitter.ts +66 -0
- package/libs/instance-factories/applications/templates/react-starter/html-to-jsx.ts +334 -0
- package/libs/instance-factories/applications/templates/react-starter/list-body-composer.ts +146 -0
- package/libs/instance-factories/applications/templates/react-starter/orchestrator.ts +95 -0
- package/libs/instance-factories/applications/templates/react-starter/package-json-generator.ts +57 -0
- package/libs/instance-factories/applications/templates/react-starter/regen-safety.ts +157 -0
- package/libs/instance-factories/applications/templates/react-starter/skeletons/dashboard.tsx.template +49 -0
- package/libs/instance-factories/applications/templates/react-starter/skeletons/detail.tsx.template +96 -0
- package/libs/instance-factories/applications/templates/react-starter/skeletons/form.tsx.template +116 -0
- package/libs/instance-factories/applications/templates/react-starter/skeletons/list.tsx.template +74 -0
- package/libs/instance-factories/applications/templates/react-starter/use-api-hooks-starter-generator.ts +124 -0
- package/libs/instance-factories/applications/templates/react-starter/view-emitter.ts +209 -0
- package/libs/instance-factories/applications/templates/react-starter/views-generator.ts +137 -0
- package/libs/instance-factories/cli/templates/commander/command-generator.ts +63 -12
- package/libs/instance-factories/controllers/fastify.yaml +7 -0
- package/libs/instance-factories/controllers/templates/fastify/server-generator.ts +36 -2
- package/libs/instance-factories/orms/templates/prisma/schema-generator.ts +11 -4
- package/package.json +3 -3
- package/dist/libs/instance-factories/applications/templates/react/_view-components-source.js +0 -530
- package/dist/libs/instance-factories/applications/templates/react/app-tsx-generator.js +0 -73
- package/dist/libs/instance-factories/applications/templates/react/field-helpers-generator.js +0 -99
- package/dist/libs/instance-factories/applications/templates/react/package-json-generator.js +0 -49
- package/dist/libs/instance-factories/applications/templates/react/pattern-adapter-generator.js +0 -156
- package/dist/libs/instance-factories/applications/templates/react/react-pattern-adapter.js +0 -935
- package/dist/libs/instance-factories/applications/templates/react/relationship-field-generator.js +0 -143
- package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-generator.js +0 -646
- package/dist/libs/instance-factories/applications/templates/react/tailwind-adapter-wrapper-generator.js +0 -65
- package/dist/libs/instance-factories/applications/templates/react/view-dashboard-generator.js +0 -143
- package/dist/libs/instance-factories/applications/templates/react/view-detail-generator.js +0 -143
- package/dist/libs/instance-factories/applications/templates/react/view-form-generator.js +0 -355
- package/dist/libs/instance-factories/applications/templates/react/view-list-generator.js +0 -91
- package/dist/libs/instance-factories/applications/templates/react/view-router-generator.js +0 -79
- package/dist/libs/instance-factories/views/index.js +0 -48
- package/dist/libs/instance-factories/views/templates/react/adapters/antd-adapter.js +0 -742
- package/dist/libs/instance-factories/views/templates/react/adapters/mui-adapter.js +0 -824
- package/dist/libs/instance-factories/views/templates/react/adapters/shadcn-adapter.js +0 -719
- package/dist/libs/instance-factories/views/templates/react/app-generator.js +0 -45
- package/dist/libs/instance-factories/views/templates/react/components-generator.js +0 -820
- package/dist/libs/instance-factories/views/templates/react/forms-generator.js +0 -275
- package/dist/libs/instance-factories/views/templates/react/frontend-package-json-generator.js +0 -46
- package/dist/libs/instance-factories/views/templates/react/hooks-generator.js +0 -81
- package/dist/libs/instance-factories/views/templates/react/index-css-generator.js +0 -9
- package/dist/libs/instance-factories/views/templates/react/index-html-generator.js +0 -23
- package/dist/libs/instance-factories/views/templates/react/main-tsx-generator.js +0 -21
- package/dist/libs/instance-factories/views/templates/react/react-component-generator.js +0 -299
- package/dist/libs/instance-factories/views/templates/react/router-generator.js +0 -136
- package/dist/libs/instance-factories/views/templates/react/router-generic-generator.js +0 -107
- package/dist/libs/instance-factories/views/templates/react/shared-utils-generator.js +0 -187
- package/dist/libs/instance-factories/views/templates/react/spec-json-generator.js +0 -7
- package/dist/libs/instance-factories/views/templates/react/types-generator.js +0 -56
- package/dist/libs/instance-factories/views/templates/react/views-metadata-generator.js +0 -27
- package/dist/libs/instance-factories/views/templates/react/vite-config-generator.js +0 -29
- package/dist/libs/instance-factories/views/templates/runtime/runtime-view-renderer.js +0 -261
- package/dist/libs/instance-factories/views/templates/shared/adapter-types.js +0 -34
- package/dist/libs/instance-factories/views/templates/shared/atomic-components-registry.js +0 -800
- package/dist/libs/instance-factories/views/templates/shared/base-generator.js +0 -305
- package/dist/libs/instance-factories/views/templates/shared/component-metadata.js +0 -517
- package/dist/libs/instance-factories/views/templates/shared/composite-pattern-types.js +0 -0
- package/dist/libs/instance-factories/views/templates/shared/composite-patterns.js +0 -445
- package/dist/libs/instance-factories/views/templates/shared/index.js +0 -80
- package/dist/libs/instance-factories/views/templates/shared/pattern-validator.js +0 -210
- package/dist/libs/instance-factories/views/templates/shared/property-mapper.js +0 -492
- package/dist/libs/instance-factories/views/templates/shared/syntax-mapper.js +0 -321
- package/dist/realize/index.js.bak +0 -758
- package/libs/instance-factories/applications/templates/react/_view-components-source.ts +0 -555
- package/libs/instance-factories/applications/templates/react/app-tsx-generator.ts +0 -94
- package/libs/instance-factories/applications/templates/react/field-helpers-generator.ts +0 -106
- package/libs/instance-factories/applications/templates/react/package-json-generator.ts +0 -57
- package/libs/instance-factories/applications/templates/react/pattern-adapter-generator.ts +0 -179
- package/libs/instance-factories/applications/templates/react/react-pattern-adapter.tsx +0 -1347
- package/libs/instance-factories/applications/templates/react/relationship-field-generator.ts +0 -150
- package/libs/instance-factories/applications/templates/react/tailwind-adapter-generator.ts +0 -704
- package/libs/instance-factories/applications/templates/react/tailwind-adapter-wrapper-generator.ts +0 -84
- package/libs/instance-factories/applications/templates/react/view-dashboard-generator.ts +0 -150
- package/libs/instance-factories/applications/templates/react/view-detail-generator.ts +0 -150
- package/libs/instance-factories/applications/templates/react/view-form-generator.ts +0 -362
- package/libs/instance-factories/applications/templates/react/view-list-generator.ts +0 -98
- package/libs/instance-factories/applications/templates/react/view-router-generator.ts +0 -89
- package/libs/instance-factories/views/README.md +0 -62
- package/libs/instance-factories/views/index.d.ts +0 -13
- package/libs/instance-factories/views/index.d.ts.map +0 -1
- package/libs/instance-factories/views/index.js +0 -18
- package/libs/instance-factories/views/index.js.map +0 -1
- package/libs/instance-factories/views/index.ts +0 -45
- package/libs/instance-factories/views/react-components.yaml +0 -129
- package/libs/instance-factories/views/templates/ARCHITECTURE.md +0 -198
- package/libs/instance-factories/views/templates/react/adapters/antd-adapter.ts +0 -869
- package/libs/instance-factories/views/templates/react/adapters/mui-adapter.ts +0 -953
- package/libs/instance-factories/views/templates/react/adapters/shadcn-adapter.ts +0 -806
- package/libs/instance-factories/views/templates/react/app-generator.ts +0 -55
- package/libs/instance-factories/views/templates/react/components-generator.ts +0 -938
- package/libs/instance-factories/views/templates/react/forms-generator.ts +0 -325
- package/libs/instance-factories/views/templates/react/frontend-package-json-generator.ts +0 -57
- package/libs/instance-factories/views/templates/react/hooks-generator.ts +0 -106
- package/libs/instance-factories/views/templates/react/index-css-generator.ts +0 -14
- package/libs/instance-factories/views/templates/react/index-html-generator.ts +0 -34
- package/libs/instance-factories/views/templates/react/main-tsx-generator.ts +0 -29
- package/libs/instance-factories/views/templates/react/react-component-generator.d.ts +0 -152
- package/libs/instance-factories/views/templates/react/react-component-generator.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/react/react-component-generator.js +0 -398
- package/libs/instance-factories/views/templates/react/react-component-generator.js.map +0 -1
- package/libs/instance-factories/views/templates/react/react-component-generator.ts +0 -533
- package/libs/instance-factories/views/templates/react/router-generator.ts +0 -197
- package/libs/instance-factories/views/templates/react/router-generic-generator.ts +0 -132
- package/libs/instance-factories/views/templates/react/shared-utils-generator.ts +0 -196
- package/libs/instance-factories/views/templates/react/spec-json-generator.ts +0 -17
- package/libs/instance-factories/views/templates/react/types-generator.ts +0 -76
- package/libs/instance-factories/views/templates/react/views-metadata-generator.ts +0 -42
- package/libs/instance-factories/views/templates/react/vite-config-generator.ts +0 -38
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.js.map +0 -1
- package/libs/instance-factories/views/templates/runtime/runtime-view-renderer.ts +0 -474
- package/libs/instance-factories/views/templates/shared/__tests__/composite-patterns.test.ts +0 -242
- package/libs/instance-factories/views/templates/shared/adapter-types.d.ts +0 -77
- package/libs/instance-factories/views/templates/shared/adapter-types.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/adapter-types.js +0 -47
- package/libs/instance-factories/views/templates/shared/adapter-types.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/adapter-types.ts +0 -142
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.d.ts +0 -63
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.js +0 -822
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/atomic-components-registry.ts +0 -908
- package/libs/instance-factories/views/templates/shared/base-generator.d.ts +0 -247
- package/libs/instance-factories/views/templates/shared/base-generator.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/base-generator.js +0 -363
- package/libs/instance-factories/views/templates/shared/base-generator.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/base-generator.ts +0 -608
- package/libs/instance-factories/views/templates/shared/component-metadata.d.ts +0 -254
- package/libs/instance-factories/views/templates/shared/component-metadata.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/component-metadata.js +0 -602
- package/libs/instance-factories/views/templates/shared/component-metadata.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/component-metadata.ts +0 -803
- package/libs/instance-factories/views/templates/shared/composite-pattern-types.ts +0 -250
- package/libs/instance-factories/views/templates/shared/composite-patterns.ts +0 -535
- package/libs/instance-factories/views/templates/shared/index.ts +0 -68
- package/libs/instance-factories/views/templates/shared/pattern-validator.ts +0 -279
- package/libs/instance-factories/views/templates/shared/property-mapper.d.ts +0 -149
- package/libs/instance-factories/views/templates/shared/property-mapper.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/property-mapper.js +0 -580
- package/libs/instance-factories/views/templates/shared/property-mapper.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/property-mapper.ts +0 -700
- package/libs/instance-factories/views/templates/shared/syntax-mapper.d.ts +0 -143
- package/libs/instance-factories/views/templates/shared/syntax-mapper.d.ts.map +0 -1
- package/libs/instance-factories/views/templates/shared/syntax-mapper.js +0 -420
- package/libs/instance-factories/views/templates/shared/syntax-mapper.js.map +0 -1
- package/libs/instance-factories/views/templates/shared/syntax-mapper.ts +0 -539
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React Forms Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates React forms with react-hook-form and Zod validation
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { TemplateContext } from '@specverse/types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate React form component for a model
|
|
11
|
-
*/
|
|
12
|
-
export default function generateReactForm(context: TemplateContext): string {
|
|
13
|
-
const { model, spec } = context;
|
|
14
|
-
|
|
15
|
-
if (!model) {
|
|
16
|
-
throw new Error('Model is required in template context');
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const modelName = model.name;
|
|
20
|
-
const formName = `${modelName}Form`;
|
|
21
|
-
|
|
22
|
-
return `/**
|
|
23
|
-
* ${formName}
|
|
24
|
-
* Form component for creating/editing ${modelName}
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { useForm } from 'react-hook-form';
|
|
28
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
29
|
-
import { z } from 'zod';
|
|
30
|
-
import { useEffect } from 'react';
|
|
31
|
-
import type { ${modelName} } from '../../types/${modelName}';
|
|
32
|
-
|
|
33
|
-
// Zod schema for form validation
|
|
34
|
-
const ${modelName.toLowerCase()}Schema = z.object({
|
|
35
|
-
${generateSchemaFields(model)}
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
type ${modelName}FormData = z.infer<typeof ${modelName.toLowerCase()}Schema>;
|
|
39
|
-
|
|
40
|
-
interface ${formName}Props {
|
|
41
|
-
${modelName.toLowerCase()}?: ${modelName};
|
|
42
|
-
onSubmit: (data: ${modelName}FormData) => void;
|
|
43
|
-
onValidate?: (data: ${modelName}FormData) => void;
|
|
44
|
-
onDelete?: () => void;
|
|
45
|
-
onCancel?: () => void;
|
|
46
|
-
isDeleting?: boolean;
|
|
47
|
-
isValidating?: boolean;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* ${formName} Component
|
|
52
|
-
*/
|
|
53
|
-
export function ${formName}({ ${modelName.toLowerCase()}, onSubmit, onValidate, onDelete, onCancel, isDeleting, isValidating }: ${formName}Props) {
|
|
54
|
-
const {
|
|
55
|
-
register,
|
|
56
|
-
handleSubmit,
|
|
57
|
-
getValues,
|
|
58
|
-
reset,
|
|
59
|
-
formState: { errors, isSubmitting },
|
|
60
|
-
} = useForm<${modelName}FormData>({
|
|
61
|
-
resolver: zodResolver(${modelName.toLowerCase()}Schema),
|
|
62
|
-
defaultValues: ${modelName.toLowerCase()} || {},
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Reset form when ${modelName.toLowerCase()} changes
|
|
66
|
-
useEffect(() => {
|
|
67
|
-
if (${modelName.toLowerCase()}) {
|
|
68
|
-
reset(${modelName.toLowerCase()});
|
|
69
|
-
} else {
|
|
70
|
-
reset({});
|
|
71
|
-
}
|
|
72
|
-
}, [${modelName.toLowerCase()}, reset]);
|
|
73
|
-
|
|
74
|
-
const handleValidateClick = () => {
|
|
75
|
-
if (onValidate) {
|
|
76
|
-
const data = getValues();
|
|
77
|
-
onValidate(data);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<form onSubmit={handleSubmit(onSubmit)} className="${modelName.toLowerCase()}-form space-y-4" autoComplete="off" data-lpignore="true" data-form-type="other">
|
|
83
|
-
{/* Hidden fake fields to trick password managers */}
|
|
84
|
-
<input type="text" name="fake-username" style={{ display: 'none' }} tabIndex={-1} autoComplete="off" aria-hidden="true" />
|
|
85
|
-
<input type="password" name="fake-password" style={{ display: 'none' }} tabIndex={-1} autoComplete="new-password" aria-hidden="true" />
|
|
86
|
-
|
|
87
|
-
${generateFormFields(model)}
|
|
88
|
-
|
|
89
|
-
<div className="form-actions flex flex-wrap gap-2 pt-4">
|
|
90
|
-
<button
|
|
91
|
-
type="submit"
|
|
92
|
-
disabled={isSubmitting}
|
|
93
|
-
className="px-6 py-2 bg-blue-600 text-white font-medium rounded hover:bg-blue-700 disabled:bg-slate-600 disabled:cursor-not-allowed transition-colors"
|
|
94
|
-
>
|
|
95
|
-
{isSubmitting ? 'Saving...' : 'Save'}
|
|
96
|
-
</button>
|
|
97
|
-
|
|
98
|
-
{onValidate && (
|
|
99
|
-
<button
|
|
100
|
-
type="button"
|
|
101
|
-
onClick={handleValidateClick}
|
|
102
|
-
disabled={isValidating}
|
|
103
|
-
className="px-6 py-2 bg-green-600 text-white font-medium rounded hover:bg-green-700 disabled:bg-slate-600 disabled:cursor-not-allowed transition-colors"
|
|
104
|
-
>
|
|
105
|
-
{isValidating ? 'Validating...' : 'Validate'}
|
|
106
|
-
</button>
|
|
107
|
-
)}
|
|
108
|
-
|
|
109
|
-
{onDelete && (
|
|
110
|
-
<button
|
|
111
|
-
type="button"
|
|
112
|
-
onClick={onDelete}
|
|
113
|
-
disabled={isDeleting}
|
|
114
|
-
className="px-6 py-2 bg-red-600 text-white font-medium rounded hover:bg-red-700 disabled:bg-slate-600 disabled:cursor-not-allowed transition-colors"
|
|
115
|
-
>
|
|
116
|
-
{isDeleting ? 'Deleting...' : 'Delete'}
|
|
117
|
-
</button>
|
|
118
|
-
)}
|
|
119
|
-
|
|
120
|
-
{onCancel && (
|
|
121
|
-
<button
|
|
122
|
-
type="button"
|
|
123
|
-
onClick={onCancel}
|
|
124
|
-
className="px-6 py-2 bg-slate-600 text-gray-200 font-medium rounded hover:bg-slate-500 transition-colors"
|
|
125
|
-
>
|
|
126
|
-
Cancel
|
|
127
|
-
</button>
|
|
128
|
-
)}
|
|
129
|
-
</div>
|
|
130
|
-
</form>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Generate Zod schema fields from model attributes
|
|
138
|
-
*/
|
|
139
|
-
function generateSchemaFields(model: any): string {
|
|
140
|
-
let attributes = model.attributes || {};
|
|
141
|
-
|
|
142
|
-
// If attributes is an array (from Object.entries), convert back to object
|
|
143
|
-
if (Array.isArray(attributes)) {
|
|
144
|
-
const obj: Record<string, any> = {};
|
|
145
|
-
attributes.forEach((attr: any, index: number) => {
|
|
146
|
-
if (attr && typeof attr === 'object' && attr.name) {
|
|
147
|
-
obj[attr.name] = attr;
|
|
148
|
-
} else if (Array.isArray(attr) && attr.length >= 2) {
|
|
149
|
-
// Handle [name, config] tuple format
|
|
150
|
-
obj[attr[0]] = attr[1];
|
|
151
|
-
} else {
|
|
152
|
-
obj[index.toString()] = attr;
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
attributes = obj;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const fields: string[] = [];
|
|
159
|
-
|
|
160
|
-
for (const [name, config] of Object.entries(attributes)) {
|
|
161
|
-
const attr: any = config;
|
|
162
|
-
|
|
163
|
-
// Skip metadata fields (category set at parse time)
|
|
164
|
-
if (attr.category === 'metadata') continue;
|
|
165
|
-
|
|
166
|
-
const type = attr.type || 'String';
|
|
167
|
-
let zodType = 'z.string()';
|
|
168
|
-
|
|
169
|
-
// Map SpecVerse types to Zod types
|
|
170
|
-
if (type === 'Integer' || type === 'Number') zodType = 'z.number()';
|
|
171
|
-
if (type === 'Boolean') zodType = 'z.boolean()';
|
|
172
|
-
if (type === 'Email') zodType = 'z.string().email()';
|
|
173
|
-
if (type === 'DateTime') zodType = 'z.string()'; // datetime-local input gives string, not ISO datetime
|
|
174
|
-
if (type === 'UUID') zodType = 'z.string().uuid()';
|
|
175
|
-
|
|
176
|
-
// Add constraints
|
|
177
|
-
if (attr.required) {
|
|
178
|
-
// Already required by default
|
|
179
|
-
} else {
|
|
180
|
-
zodType += '.optional()';
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (attr.min && type === 'String') {
|
|
184
|
-
zodType = zodType.replace(')', `.min(${attr.min})`);
|
|
185
|
-
}
|
|
186
|
-
if (attr.max && type === 'String') {
|
|
187
|
-
zodType = zodType.replace(')', `.max(${attr.max})`);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
fields.push(` ${name}: ${zodType},`);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return fields.join('\n');
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Generate form fields from model attributes
|
|
198
|
-
*/
|
|
199
|
-
function generateFormFields(model: any): string {
|
|
200
|
-
let attributes = model.attributes || {};
|
|
201
|
-
|
|
202
|
-
// If attributes is an array (from Object.entries), convert back to object
|
|
203
|
-
if (Array.isArray(attributes)) {
|
|
204
|
-
const obj: Record<string, any> = {};
|
|
205
|
-
attributes.forEach((attr: any, index: number) => {
|
|
206
|
-
if (attr && typeof attr === 'object' && attr.name) {
|
|
207
|
-
obj[attr.name] = attr;
|
|
208
|
-
} else if (Array.isArray(attr) && attr.length >= 2) {
|
|
209
|
-
// Handle [name, config] tuple format
|
|
210
|
-
obj[attr[0]] = attr[1];
|
|
211
|
-
} else {
|
|
212
|
-
obj[index.toString()] = attr;
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
attributes = obj;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const fields: string[] = [];
|
|
219
|
-
const regularFields: string[] = [];
|
|
220
|
-
const textAreaFields: string[] = [];
|
|
221
|
-
|
|
222
|
-
for (const [name, config] of Object.entries(attributes)) {
|
|
223
|
-
const attr: any = config;
|
|
224
|
-
|
|
225
|
-
// Skip metadata fields (category set at parse time)
|
|
226
|
-
if (attr.category === 'metadata') continue;
|
|
227
|
-
|
|
228
|
-
const type = attr.type || 'String';
|
|
229
|
-
const label = name.charAt(0).toUpperCase() + name.slice(1);
|
|
230
|
-
const isRequired = attr.required;
|
|
231
|
-
|
|
232
|
-
let inputType = 'text';
|
|
233
|
-
if (type === 'Email') inputType = 'email';
|
|
234
|
-
if (type === 'Number' || type === 'Integer') inputType = 'number';
|
|
235
|
-
if (type === 'Boolean') inputType = 'checkbox';
|
|
236
|
-
if (type === 'DateTime') inputType = 'datetime-local';
|
|
237
|
-
if (type === 'Text') inputType = 'textarea';
|
|
238
|
-
|
|
239
|
-
const field = inputType === 'textarea' ? ` <div className="form-field">
|
|
240
|
-
<label htmlFor="${name}" className="block text-sm font-medium text-gray-300 mb-1">
|
|
241
|
-
${name}${isRequired ? ' <span className="text-red-400">*</span>' : ''}
|
|
242
|
-
</label>
|
|
243
|
-
<textarea
|
|
244
|
-
id="${name}"
|
|
245
|
-
{...register('${name}')}
|
|
246
|
-
rows={2}
|
|
247
|
-
className={\`w-full px-3 py-2 rounded bg-slate-700 border transition-colors text-gray-200
|
|
248
|
-
\${errors['${name}']
|
|
249
|
-
? 'border-red-500 focus:border-red-400'
|
|
250
|
-
: 'border-slate-600 focus:border-blue-500'
|
|
251
|
-
} focus:outline-none focus:ring-0 resize-none\`}
|
|
252
|
-
placeholder="Enter ${name}"
|
|
253
|
-
autoComplete="off"
|
|
254
|
-
data-lpignore="true"
|
|
255
|
-
data-form-type="other"
|
|
256
|
-
readOnly
|
|
257
|
-
onFocus={(e) => e.target.removeAttribute('readonly')}
|
|
258
|
-
/>
|
|
259
|
-
{errors['${name}'] && (
|
|
260
|
-
<p className="mt-1 text-xs text-red-400">{errors['${name}']?.message}</p>
|
|
261
|
-
)}
|
|
262
|
-
</div>` : inputType === 'checkbox' ? ` <div className="form-field">
|
|
263
|
-
<label htmlFor="${name}" className="flex items-center text-sm font-medium text-gray-300">
|
|
264
|
-
<input
|
|
265
|
-
id="${name}"
|
|
266
|
-
type="checkbox"
|
|
267
|
-
{...register('${name}')}
|
|
268
|
-
className="mr-2"
|
|
269
|
-
autoComplete="off"
|
|
270
|
-
data-lpignore="true"
|
|
271
|
-
/>
|
|
272
|
-
${name}${isRequired ? ' <span className="ml-1 text-red-400">*</span>' : ''}
|
|
273
|
-
</label>
|
|
274
|
-
{errors['${name}'] && (
|
|
275
|
-
<p className="mt-1 text-xs text-red-400">{errors['${name}']?.message}</p>
|
|
276
|
-
)}
|
|
277
|
-
</div>` : ` <div className="form-field">
|
|
278
|
-
<label htmlFor="${name}" className="block text-sm font-medium text-gray-300 mb-1">
|
|
279
|
-
${name}${isRequired ? ' <span className="text-red-400">*</span>' : ''}
|
|
280
|
-
</label>
|
|
281
|
-
<input
|
|
282
|
-
id="${name}"
|
|
283
|
-
type="${inputType}"
|
|
284
|
-
{...register('${name}')}
|
|
285
|
-
className={\`w-full px-3 py-2 rounded bg-slate-700 border transition-colors text-gray-200
|
|
286
|
-
\${errors['${name}']
|
|
287
|
-
? 'border-red-500 focus:border-red-400'
|
|
288
|
-
: 'border-slate-600 focus:border-blue-500'
|
|
289
|
-
} focus:outline-none focus:ring-0\`}
|
|
290
|
-
placeholder="Enter ${name}"
|
|
291
|
-
autoComplete="off"
|
|
292
|
-
data-lpignore="true"
|
|
293
|
-
data-form-type="other"
|
|
294
|
-
readOnly
|
|
295
|
-
onFocus={(e) => e.target.removeAttribute('readonly')}
|
|
296
|
-
/>
|
|
297
|
-
{errors['${name}'] && (
|
|
298
|
-
<p className="mt-1 text-xs text-red-400">{errors['${name}']?.message}</p>
|
|
299
|
-
)}
|
|
300
|
-
</div>`;
|
|
301
|
-
|
|
302
|
-
// Separate textarea fields from regular fields
|
|
303
|
-
if (inputType === 'textarea') {
|
|
304
|
-
textAreaFields.push(field);
|
|
305
|
-
} else {
|
|
306
|
-
regularFields.push(field);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Build final output with grid layout for regular fields
|
|
311
|
-
let output = '';
|
|
312
|
-
|
|
313
|
-
if (regularFields.length > 0) {
|
|
314
|
-
output += ` <div className="grid grid-cols-1 md:grid-cols-2 gap-4">\n`;
|
|
315
|
-
output += regularFields.join('\n\n');
|
|
316
|
-
output += `\n </div>`;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
if (textAreaFields.length > 0) {
|
|
320
|
-
if (output) output += '\n\n';
|
|
321
|
-
output += textAreaFields.join('\n\n');
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
return output;
|
|
325
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Frontend Package JSON Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates package.json for the frontend workspace with React dependencies
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { TemplateContext } from '@specverse/types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate frontend workspace package.json
|
|
11
|
-
*/
|
|
12
|
-
export default function generateFrontendPackageJson(context: TemplateContext): string {
|
|
13
|
-
const { spec } = context;
|
|
14
|
-
|
|
15
|
-
const componentName = spec?.name || 'app';
|
|
16
|
-
const packageName = `${componentName.toLowerCase()}-frontend`;
|
|
17
|
-
|
|
18
|
-
const packageJson = {
|
|
19
|
-
name: packageName,
|
|
20
|
-
version: '1.0.0',
|
|
21
|
-
description: `Frontend for ${spec?.description || componentName}`,
|
|
22
|
-
private: true,
|
|
23
|
-
type: 'module',
|
|
24
|
-
scripts: {
|
|
25
|
-
dev: 'vite',
|
|
26
|
-
build: 'tsc && vite build',
|
|
27
|
-
preview: 'vite preview',
|
|
28
|
-
lint: 'eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0',
|
|
29
|
-
'type-check': 'tsc --noEmit'
|
|
30
|
-
},
|
|
31
|
-
dependencies: {
|
|
32
|
-
'react': '^18.3.1',
|
|
33
|
-
'react-dom': '^18.3.1',
|
|
34
|
-
'react-router-dom': '^6.26.2',
|
|
35
|
-
'@tanstack/react-query': '^5.56.2',
|
|
36
|
-
'zustand': '^4.5.5',
|
|
37
|
-
'axios': '^1.7.7'
|
|
38
|
-
},
|
|
39
|
-
devDependencies: {
|
|
40
|
-
'@types/react': '^18.3.9',
|
|
41
|
-
'@types/react-dom': '^18.3.0',
|
|
42
|
-
'@typescript-eslint/eslint-plugin': '^8.7.0',
|
|
43
|
-
'@typescript-eslint/parser': '^8.7.0',
|
|
44
|
-
'@vitejs/plugin-react': '^4.3.1',
|
|
45
|
-
'autoprefixer': '^10.4.20',
|
|
46
|
-
'eslint': '^9.11.1',
|
|
47
|
-
'eslint-plugin-react-hooks': '^5.1.0-rc.0',
|
|
48
|
-
'eslint-plugin-react-refresh': '^0.4.12',
|
|
49
|
-
'postcss': '^8.4.47',
|
|
50
|
-
'tailwindcss': '^3.4.13',
|
|
51
|
-
'typescript': '^5.6.2',
|
|
52
|
-
'vite': '^5.4.8'
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
return JSON.stringify(packageJson, null, 2);
|
|
57
|
-
}
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React Hooks Generator — per-model convenience hook.
|
|
3
|
-
*
|
|
4
|
-
* Emits `use${Model}()` which is a thin delegator over the canonical
|
|
5
|
-
* hooks in `hooks/useApi.ts`. Historically this generator produced
|
|
6
|
-
* its own `useQuery(...)` + `useMutation(...)` blocks with private
|
|
7
|
-
* query keys (`['poll', id]`, `['polls', filters]`), which meant:
|
|
8
|
-
*
|
|
9
|
-
* 1. WebSocket events invalidating `['entities', modelName]` never
|
|
10
|
-
* reached views that consumed this hook.
|
|
11
|
-
* 2. The conformance check `no-bare-usequery-in-views` lit up for
|
|
12
|
-
* every per-model hook file.
|
|
13
|
-
*
|
|
14
|
-
* v2: delegate everything to `useEntitiesQuery` and
|
|
15
|
-
* `useExecuteOperationMutation` so there's exactly one cache key
|
|
16
|
-
* per model and one mutation pipeline across the whole frontend.
|
|
17
|
-
*
|
|
18
|
-
* The public API of `use${Model}()` is preserved for callers that
|
|
19
|
-
* depend on it: { [model], [models], isLoading, error, refetch,
|
|
20
|
-
* create, update, delete, isCreating, isUpdating, isDeleting }.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import type { TemplateContext } from '@specverse/types';
|
|
24
|
-
|
|
25
|
-
export default function generateReactHook(context: TemplateContext): string {
|
|
26
|
-
const { model } = context;
|
|
27
|
-
|
|
28
|
-
if (!model) {
|
|
29
|
-
throw new Error('Model is required in template context');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const modelName = model.name;
|
|
33
|
-
const hookName = `use${modelName}`;
|
|
34
|
-
const controllerName = `${modelName}Controller`;
|
|
35
|
-
const singular = modelName.charAt(0).toLowerCase() + modelName.slice(1);
|
|
36
|
-
const plural = singular + 's';
|
|
37
|
-
|
|
38
|
-
return `/**
|
|
39
|
-
* ${hookName}
|
|
40
|
-
*
|
|
41
|
-
* Thin delegator over the canonical useApi hooks. All state flows
|
|
42
|
-
* through \`['entities', '${modelName}']\` so WebSocket invalidation
|
|
43
|
-
* reaches every view consuming this hook.
|
|
44
|
-
*/
|
|
45
|
-
|
|
46
|
-
import { useMemo } from 'react';
|
|
47
|
-
import {
|
|
48
|
-
useEntitiesQuery,
|
|
49
|
-
useExecuteOperationMutation,
|
|
50
|
-
} from './useApi';
|
|
51
|
-
import type { ${modelName} } from '../types/${modelName}';
|
|
52
|
-
|
|
53
|
-
interface ${capitalize(hookName)}Options {
|
|
54
|
-
id?: string;
|
|
55
|
-
list?: boolean;
|
|
56
|
-
filters?: Record<string, any>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function ${hookName}(opts: ${capitalize(hookName)}Options = {}) {
|
|
60
|
-
const { id, filters: _filters } = opts;
|
|
61
|
-
|
|
62
|
-
// Canonical list query — one cache key per model. The list flag
|
|
63
|
-
// is preserved for backwards compatibility but the query always
|
|
64
|
-
// runs; React Query dedupes across consumers automatically.
|
|
65
|
-
const query = useEntitiesQuery('${controllerName}', '${modelName}');
|
|
66
|
-
const ${plural} = (query.data as ${modelName}[] | undefined) || [];
|
|
67
|
-
|
|
68
|
-
// Single-entity lookup is client-side against the canonical list
|
|
69
|
-
// so both the detail view and the list view share one source of
|
|
70
|
-
// truth. If the caller needs server-side hydration for a single
|
|
71
|
-
// entity, they should call useEntitiesQuery directly with a
|
|
72
|
-
// filtered controller endpoint.
|
|
73
|
-
const ${singular} = useMemo<${modelName} | null>(() => {
|
|
74
|
-
if (!id) return null;
|
|
75
|
-
for (const entity of ${plural}) {
|
|
76
|
-
const entityId = (entity as any)?.id || (entity as any)?.data?.id;
|
|
77
|
-
if (entityId === id) return entity;
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
}, [id, ${plural}]);
|
|
81
|
-
|
|
82
|
-
const mutation = useExecuteOperationMutation();
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
${singular},
|
|
86
|
-
${plural},
|
|
87
|
-
isLoading: query.isLoading,
|
|
88
|
-
error: query.error,
|
|
89
|
-
refetch: () => { /* handled by useEntitiesQuery refetchInterval + WS invalidation */ },
|
|
90
|
-
create: (data: Partial<${modelName}>) =>
|
|
91
|
-
mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'create', data: data as Record<string, unknown> }),
|
|
92
|
-
update: (args: { id: string; data: Partial<${modelName}> }) =>
|
|
93
|
-
mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'update', entityId: args.id, data: args.data as Record<string, unknown> }),
|
|
94
|
-
delete: (entityId: string) =>
|
|
95
|
-
mutation.mutateAsync({ controllerName: '${controllerName}', operationName: 'delete', entityId, data: {} }),
|
|
96
|
-
isCreating: mutation.isPending,
|
|
97
|
-
isUpdating: mutation.isPending,
|
|
98
|
-
isDeleting: mutation.isPending,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
`;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function capitalize(s: string): string {
|
|
105
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
106
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React index.css Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates Tailwind CSS entry point
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { TemplateContext } from '@specverse/types';
|
|
8
|
-
|
|
9
|
-
export default function generateIndexCss(context: TemplateContext): string {
|
|
10
|
-
return `@tailwind base;
|
|
11
|
-
@tailwind components;
|
|
12
|
-
@tailwind utilities;
|
|
13
|
-
`;
|
|
14
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React index.html Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates the HTML entry point for a React application
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { TemplateContext } from '@specverse/types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate index.html for React application
|
|
11
|
-
*/
|
|
12
|
-
export default function generateIndexHtml(context: TemplateContext): string {
|
|
13
|
-
const { spec } = context;
|
|
14
|
-
|
|
15
|
-
// Extract component name from spec metadata
|
|
16
|
-
const componentName = spec?.metadata?.component || spec?.component?.name || 'App';
|
|
17
|
-
const description = spec?.metadata?.description || spec?.component?.description || 'Generated by SpecVerse';
|
|
18
|
-
|
|
19
|
-
return `<!DOCTYPE html>
|
|
20
|
-
<html lang="en">
|
|
21
|
-
<head>
|
|
22
|
-
<meta charset="UTF-8" />
|
|
23
|
-
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
24
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
25
|
-
<meta name="description" content="${description}" />
|
|
26
|
-
<title>${componentName}</title>
|
|
27
|
-
</head>
|
|
28
|
-
<body>
|
|
29
|
-
<div id="root"></div>
|
|
30
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
31
|
-
</body>
|
|
32
|
-
</html>
|
|
33
|
-
`;
|
|
34
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React main.tsx Entry Point Generator
|
|
3
|
-
*
|
|
4
|
-
* Generates the main.tsx entry point for React application
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { TemplateContext } from '@specverse/types';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Generate main.tsx React entry point
|
|
11
|
-
*/
|
|
12
|
-
export default function generateMainTsx(context: TemplateContext): string {
|
|
13
|
-
return `/**
|
|
14
|
-
* React Application Entry Point
|
|
15
|
-
* Auto-generated by SpecVerse
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import React from 'react';
|
|
19
|
-
import ReactDOM from 'react-dom/client';
|
|
20
|
-
import App from './App';
|
|
21
|
-
import './index.css';
|
|
22
|
-
|
|
23
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
24
|
-
<React.StrictMode>
|
|
25
|
-
<App />
|
|
26
|
-
</React.StrictMode>
|
|
27
|
-
);
|
|
28
|
-
`;
|
|
29
|
-
}
|