@chemx/starter-kit 26.9.16-41 → 26.9.17-309
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/README.md +4 -0
- package/assets/chemx-starter-kit-logo.gif +0 -0
- package/blueprints/_view-template.scss +24 -0
- package/blueprints/atoms/a-button.vue +43 -0
- package/blueprints/molecule-capsule/_m-sample-card.scss +75 -0
- package/blueprints/molecule-capsule/index.ts +2 -0
- package/blueprints/molecule-capsule/m-chemx-badge/_m-chemx-badge.scss +76 -0
- package/blueprints/molecule-capsule/m-chemx-badge/index.ts +3 -0
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.spec.ts +74 -0
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.tsx +39 -0
- package/blueprints/molecule-capsule/m-chemx-badge/m-chemx-badge.vue +42 -0
- package/blueprints/molecule-capsule/m-chemx-badge/types.d.ts +12 -0
- package/blueprints/molecule-capsule/m-sample-card.spec.ts +74 -0
- package/blueprints/molecule-capsule/m-sample-card.tsx +72 -0
- package/blueprints/molecule-capsule/m-tab-button/_m-tab-button.scss +49 -0
- package/blueprints/molecule-capsule/m-tab-button/index.ts +3 -0
- package/blueprints/molecule-capsule/m-tab-button/m-tab-button.controller.ts +43 -0
- package/blueprints/molecule-capsule/m-tab-button/m-tab-button.spec.ts +40 -0
- package/blueprints/molecule-capsule/m-tab-button/m-tab-button.vue +38 -0
- package/blueprints/molecule-capsule/m-tab-button/types.d.ts +14 -0
- package/blueprints/molecule-capsule/types.d.ts +12 -0
- package/blueprints/shims-vue.d.ts +4 -0
- package/blueprints/view-template.tsx +20 -0
- package/blueprints/workflows/chemx-audit.yml +79 -0
- package/cli/audit/autofix.js +4 -5
- package/cli/audit/pattern-detector.js +90 -3
- package/cli/audit/pattern-detector.spec.js +36 -1
- package/cli/audit/prompts.js +10 -12
- package/cli/audit/roadmap.js +5 -20
- package/cli/audit/rules-predicates.js +3 -2
- package/cli/audit/rules.js +4 -0
- package/cli/audit-preflight-git.js +54 -0
- package/cli/audit-preflight-scope.js +87 -0
- package/cli/audit-preflight.d.ts +16 -0
- package/cli/audit-preflight.js +85 -0
- package/cli/audit-preflight.spec.js +115 -0
- package/cli/audit.js +47 -22
- package/cli/generator-templates/controller.js +36 -0
- package/cli/generator-templates/hooks.js +60 -0
- package/cli/generator-templates/naming.js +14 -0
- package/cli/generator-templates/react.js +63 -0
- package/cli/generator-templates/specs.js +38 -0
- package/cli/generator-templates/styles.js +64 -0
- package/cli/generator-templates/svelte.js +66 -0
- package/cli/generator-templates/types.js +29 -0
- package/cli/generator-templates/views.js +76 -0
- package/cli/generator-templates/vue.js +62 -0
- package/cli/generator-templates.d.ts +35 -0
- package/cli/generator-templates.js +28 -480
- package/cli/generator-templates.spec.js +108 -0
- package/cli/generator.js +2 -2
- package/cli/generator.spec.js +61 -1
- package/cli/help.js +9 -0
- package/cli/index.js +44 -7
- package/cli/installer-templates.js +67 -13
- package/cli/license.js +22 -1
- package/cli/mcp/installer.js +31 -21
- package/cli/mcp/resources.js +114 -7
- package/cli/mcp/server.spec.js +34 -0
- package/cli/mcp/tools.js +14 -4
- package/cli/postinstall.js +27 -0
- package/cli/project-detector.js +20 -2
- package/cli/project-detector.spec.js +19 -0
- package/cli/reader.js +18 -4
- package/cli/scaffold.js +19 -3
- package/cli/terminal.js +36 -1
- package/docs/CHANGELOG.md +10 -0
- package/package.json +8 -5
- package/scripts/postinstall.mjs +27 -0
- package/scripts/pre-commit.sh +135 -0
- package/scripts/publish-both.mjs +108 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export const buildReactView = (name, pascalName) => `import React from 'react';
|
|
2
|
+
import type { ${pascalName}ViewParams } from './types';
|
|
3
|
+
|
|
4
|
+
export const ${pascalName}View: React.FC<${pascalName}ViewParams> = ({
|
|
5
|
+
HeaderMolecule,
|
|
6
|
+
MainOrganism,
|
|
7
|
+
FooterMolecule
|
|
8
|
+
}) => (
|
|
9
|
+
<main className="${name}">
|
|
10
|
+
{HeaderMolecule}
|
|
11
|
+
{MainOrganism}
|
|
12
|
+
{FooterMolecule}
|
|
13
|
+
</main>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export default ${pascalName}View;
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
export const buildVueView = (name, pascalName) => `<script setup lang="ts">
|
|
20
|
+
import type { ${pascalName}ViewParams } from './types';
|
|
21
|
+
|
|
22
|
+
defineProps<${pascalName}ViewParams>();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<main class="${name}">
|
|
27
|
+
<component :is="HeaderMolecule" />
|
|
28
|
+
<component :is="MainOrganism" />
|
|
29
|
+
<component :is="FooterMolecule" />
|
|
30
|
+
</main>
|
|
31
|
+
</template>
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export const buildSvelteView = (name, pascalName) => `<script lang="ts">
|
|
35
|
+
import type { ${pascalName}ViewParams } from './types';
|
|
36
|
+
|
|
37
|
+
const {
|
|
38
|
+
HeaderMolecule,
|
|
39
|
+
MainOrganism,
|
|
40
|
+
FooterMolecule
|
|
41
|
+
}: ${pascalName}ViewParams = $props();
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<main class="${name}">
|
|
45
|
+
{@render HeaderMolecule?.()}
|
|
46
|
+
{@render MainOrganism?.()}
|
|
47
|
+
{@render FooterMolecule?.()}
|
|
48
|
+
</main>
|
|
49
|
+
`;
|
|
50
|
+
|
|
51
|
+
export const buildViewParamsType = (pascalName) => `export interface ${pascalName}ViewParams {
|
|
52
|
+
readonly HeaderMolecule?: unknown;
|
|
53
|
+
readonly MainOrganism?: unknown;
|
|
54
|
+
readonly FooterMolecule?: unknown;
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
export const buildViewIndex = (name, pascalName, ext) => {
|
|
59
|
+
const compExport = ext === 'vue' || ext === 'svelte'
|
|
60
|
+
? `export { default as ${pascalName}View } from './${name}.${ext}';`
|
|
61
|
+
: `export { ${pascalName}View } from './${name}';`;
|
|
62
|
+
|
|
63
|
+
return `${compExport}
|
|
64
|
+
export type * from './types';
|
|
65
|
+
`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const buildViewSpec = (name, pascalName) => `import { describe, it } from 'node:test';
|
|
69
|
+
import assert from 'node:assert/strict';
|
|
70
|
+
|
|
71
|
+
describe('${pascalName}View Table of Contents', () => {
|
|
72
|
+
it('defines pure declarative blueprint layout', () => {
|
|
73
|
+
assert.ok(true);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export const buildVueComponent = (name, pascalName, options = {}) => {
|
|
2
|
+
const atomsPackage = options.atomsPackage || null;
|
|
3
|
+
const hasController = options.hasController !== false;
|
|
4
|
+
const actionButton = atomsPackage
|
|
5
|
+
? ` <a-button
|
|
6
|
+
:disabled="!canProceed"
|
|
7
|
+
@click="handleAction"
|
|
8
|
+
>
|
|
9
|
+
{{ variant }}
|
|
10
|
+
</a-button>`
|
|
11
|
+
: ` <button
|
|
12
|
+
type="button"
|
|
13
|
+
class="${name}__action"
|
|
14
|
+
:disabled="!canProceed"
|
|
15
|
+
@click="handleAction"
|
|
16
|
+
>
|
|
17
|
+
{{ variant }}
|
|
18
|
+
</button>`;
|
|
19
|
+
|
|
20
|
+
const controllerImport = hasController
|
|
21
|
+
? `import { use${pascalName}Controller } from './${name}.controller';\n`
|
|
22
|
+
: '';
|
|
23
|
+
|
|
24
|
+
const controllerLogic = hasController
|
|
25
|
+
? `const { state, canProceed, descriptor, handleAction } = use${pascalName}Controller({
|
|
26
|
+
initialState: { status: 'idle' },
|
|
27
|
+
onAction: () => emit('action', props.title)
|
|
28
|
+
});`
|
|
29
|
+
: `const canProceed = true;
|
|
30
|
+
const descriptor = { text: 'Ready', className: '${name}__badge ${name}__badge--ready' };
|
|
31
|
+
const handleAction = () => emit('action', props.title);`;
|
|
32
|
+
|
|
33
|
+
return `<script setup lang="ts">
|
|
34
|
+
import type { ${pascalName}Props, ${pascalName}Emits } from './types';
|
|
35
|
+
${controllerImport}
|
|
36
|
+
const props = withDefaults(defineProps<${pascalName}Props>(), {
|
|
37
|
+
variant: 'standard'
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const emit = defineEmits<${pascalName}Emits>();
|
|
41
|
+
|
|
42
|
+
${controllerLogic}
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div class="${name}">
|
|
47
|
+
<div class="${name}__header">
|
|
48
|
+
<h3 class="${name}__title">{{ title }}</h3>
|
|
49
|
+
<p v-if="subtitle" class="${name}__subtitle">{{ subtitle }}</p>
|
|
50
|
+
<span :class="descriptor.className">{{ descriptor.text }}</span>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="${name}__body">
|
|
53
|
+
${actionButton}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<style lang="scss" scoped>
|
|
59
|
+
@use './_${name}.scss';
|
|
60
|
+
</style>
|
|
61
|
+
`;
|
|
62
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface TemplateOptions {
|
|
2
|
+
readonly atomsPackage?: string | null;
|
|
3
|
+
readonly hasController?: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export declare function toPascalCase(str: string): string;
|
|
7
|
+
export declare function toCamelCase(str: string): string;
|
|
8
|
+
|
|
9
|
+
export declare function buildReactComponent(name: string, pascalName: string, options?: TemplateOptions): string;
|
|
10
|
+
export declare function buildVueComponent(name: string, pascalName: string, options?: TemplateOptions): string;
|
|
11
|
+
export declare function buildSvelteComponent(name: string, pascalName: string, options?: TemplateOptions): string;
|
|
12
|
+
|
|
13
|
+
export declare function buildController(name: string, pascalName: string): string;
|
|
14
|
+
export declare function buildComponentSpec(name: string, pascalName: string, hasController?: boolean): string;
|
|
15
|
+
export declare function buildIndex(name: string, pascalName: string, ext: string, hasController?: boolean): string;
|
|
16
|
+
|
|
17
|
+
export declare function buildPropsType(name: string, pascalName: string): string;
|
|
18
|
+
export declare function buildStateType(name: string, pascalName: string): string;
|
|
19
|
+
export declare function buildTypesIndex(fileNames?: string[]): string;
|
|
20
|
+
export declare function buildTypes(name: string, pascalName: string): string;
|
|
21
|
+
|
|
22
|
+
export declare function buildScss(name: string): string;
|
|
23
|
+
|
|
24
|
+
export declare function buildHook(name: string, camelName: string, pascalName: string): string;
|
|
25
|
+
export declare function buildHookOptionsType(pascalName: string): string;
|
|
26
|
+
export declare function buildHookReturnType(pascalName: string): string;
|
|
27
|
+
export declare function buildHookIndex(name: string, camelName: string): string;
|
|
28
|
+
export declare function buildHookSpec(name: string, camelName: string): string;
|
|
29
|
+
|
|
30
|
+
export declare function buildReactView(name: string, pascalName: string): string;
|
|
31
|
+
export declare function buildVueView(name: string, pascalName: string): string;
|
|
32
|
+
export declare function buildSvelteView(name: string, pascalName: string): string;
|
|
33
|
+
export declare function buildViewParamsType(pascalName: string): string;
|
|
34
|
+
export declare function buildViewIndex(name: string, pascalName: string, ext: string): string;
|
|
35
|
+
export declare function buildViewSpec(name: string, pascalName: string): string;
|
|
@@ -1,480 +1,28 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
disabled={!canProceed}
|
|
30
|
-
onClick={handleAction}
|
|
31
|
-
>
|
|
32
|
-
{variant}
|
|
33
|
-
</button>`;
|
|
34
|
-
|
|
35
|
-
return `import React from 'react';
|
|
36
|
-
${atomImport}import type { ${pascalName}Props } from './types';
|
|
37
|
-
import { use${pascalName}Controller } from './${name}.controller';
|
|
38
|
-
|
|
39
|
-
export const ${pascalName}: React.FC<${pascalName}Props> = ({
|
|
40
|
-
title,
|
|
41
|
-
subtitle,
|
|
42
|
-
variant = 'standard',
|
|
43
|
-
onAction
|
|
44
|
-
}) => {
|
|
45
|
-
const { state, canProceed, descriptor, handleAction } = use${pascalName}Controller({
|
|
46
|
-
initialState: { status: 'idle' },
|
|
47
|
-
onAction
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
return (
|
|
51
|
-
<div className="${name}">
|
|
52
|
-
<div className="${name}__header">
|
|
53
|
-
<h3 className="${name}__title">{title}</h3>
|
|
54
|
-
{subtitle && <p className="${name}__subtitle">{subtitle}</p>}
|
|
55
|
-
<span className={descriptor.className}>{descriptor.text}</span>
|
|
56
|
-
</div>
|
|
57
|
-
<div className="${name}__body">
|
|
58
|
-
${actionButton}
|
|
59
|
-
</div>
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export default ${pascalName};
|
|
65
|
-
`;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
export const buildVueComponent = (name, pascalName, options = {}) => {
|
|
69
|
-
const atomsPackage = options.atomsPackage || null;
|
|
70
|
-
const actionButton = atomsPackage
|
|
71
|
-
? ` <a-button
|
|
72
|
-
:disabled="!canProceed"
|
|
73
|
-
@click="handleAction"
|
|
74
|
-
>
|
|
75
|
-
{{ variant }}
|
|
76
|
-
</a-button>`
|
|
77
|
-
: ` <button
|
|
78
|
-
type="button"
|
|
79
|
-
class="${name}__action"
|
|
80
|
-
:disabled="!canProceed"
|
|
81
|
-
@click="handleAction"
|
|
82
|
-
>
|
|
83
|
-
{{ variant }}
|
|
84
|
-
</button>`;
|
|
85
|
-
|
|
86
|
-
return `<script setup lang="ts">
|
|
87
|
-
import type { ${pascalName}Props, ${pascalName}Emits } from './types';
|
|
88
|
-
import { use${pascalName}Controller } from './${name}.controller';
|
|
89
|
-
|
|
90
|
-
const props = withDefaults(defineProps<${pascalName}Props>(), {
|
|
91
|
-
variant: 'standard'
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
const emit = defineEmits<${pascalName}Emits>();
|
|
95
|
-
|
|
96
|
-
const { state, canProceed, descriptor, handleAction } = use${pascalName}Controller({
|
|
97
|
-
initialState: { status: 'idle' },
|
|
98
|
-
onAction: () => emit('action', props.title)
|
|
99
|
-
});
|
|
100
|
-
</script>
|
|
101
|
-
|
|
102
|
-
<template>
|
|
103
|
-
<div class="${name}">
|
|
104
|
-
<div class="${name}__header">
|
|
105
|
-
<h3 class="${name}__title">{{ title }}</h3>
|
|
106
|
-
<p v-if="subtitle" class="${name}__subtitle">{{ subtitle }}</p>
|
|
107
|
-
<span :class="descriptor.className">{{ descriptor.text }}</span>
|
|
108
|
-
</div>
|
|
109
|
-
<div class="${name}__body">
|
|
110
|
-
${actionButton}
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</template>
|
|
114
|
-
|
|
115
|
-
<style lang="scss" scoped>
|
|
116
|
-
@use './_${name}.scss';
|
|
117
|
-
</style>
|
|
118
|
-
`;
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export const buildSvelteComponent = (name, pascalName, options = {}) => {
|
|
122
|
-
const atomsPackage = options.atomsPackage || null;
|
|
123
|
-
const atomImport = atomsPackage ? `import { AtomButton } from '${atomsPackage}';\n` : '';
|
|
124
|
-
const actionButton = atomsPackage
|
|
125
|
-
? ` <AtomButton
|
|
126
|
-
disabled={!controller.canProceed}
|
|
127
|
-
onclick={controller.handleAction}
|
|
128
|
-
>
|
|
129
|
-
{variant}
|
|
130
|
-
</AtomButton>`
|
|
131
|
-
: ` <button
|
|
132
|
-
type="button"
|
|
133
|
-
class="${name}__action"
|
|
134
|
-
disabled={!controller.canProceed}
|
|
135
|
-
onclick={controller.handleAction}
|
|
136
|
-
>
|
|
137
|
-
{variant}
|
|
138
|
-
</button>`;
|
|
139
|
-
|
|
140
|
-
return `<script lang="ts">
|
|
141
|
-
import type { ${pascalName}Props } from './types';
|
|
142
|
-
${atomImport}import { create${pascalName}Controller } from './${name}.controller';
|
|
143
|
-
|
|
144
|
-
const {
|
|
145
|
-
title,
|
|
146
|
-
subtitle = '',
|
|
147
|
-
variant = 'standard',
|
|
148
|
-
onAction
|
|
149
|
-
}: ${pascalName}Props = $props();
|
|
150
|
-
|
|
151
|
-
const controller = create${pascalName}Controller({
|
|
152
|
-
initialState: { status: 'idle' },
|
|
153
|
-
onAction
|
|
154
|
-
});
|
|
155
|
-
</script>
|
|
156
|
-
|
|
157
|
-
<div class="${name}">
|
|
158
|
-
<div class="${name}__header">
|
|
159
|
-
<h3 class="${name}__title">{title}</h3>
|
|
160
|
-
{#if subtitle}
|
|
161
|
-
<p class="${name}__subtitle">{subtitle}</p>
|
|
162
|
-
{/if}
|
|
163
|
-
<span class={controller.descriptor.className}>{controller.descriptor.text}</span>
|
|
164
|
-
</div>
|
|
165
|
-
<div class="${name}__body">
|
|
166
|
-
${actionButton}
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
<style lang="scss">
|
|
171
|
-
@use './_${name}.scss';
|
|
172
|
-
</style>
|
|
173
|
-
`;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
export const buildController = (name, pascalName) => `import { useState, useMemo } from 'react';
|
|
177
|
-
import type { ${pascalName}State, ${pascalName}Descriptor } from './types';
|
|
178
|
-
|
|
179
|
-
interface ControllerOptions {
|
|
180
|
-
readonly initialState?: ${pascalName}State;
|
|
181
|
-
readonly onAction?: () => void;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export const use${pascalName}Controller = (options: ControllerOptions = {}) => {
|
|
185
|
-
const [state, setState] = useState<${pascalName}State>(
|
|
186
|
-
options.initialState || { status: 'idle' }
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
const isIdle = state.status === 'idle';
|
|
190
|
-
const isPending = state.status === 'loading';
|
|
191
|
-
const canProceed = isIdle && !isPending;
|
|
192
|
-
|
|
193
|
-
const descriptor: ${pascalName}Descriptor = useMemo(() => {
|
|
194
|
-
if (state.status === 'loading') {
|
|
195
|
-
return { text: 'Loading...', className: '${name}__badge ${name}__badge--pending' };
|
|
196
|
-
}
|
|
197
|
-
if (state.status === 'active') {
|
|
198
|
-
return { text: 'Active', className: '${name}__badge ${name}__badge--active' };
|
|
199
|
-
}
|
|
200
|
-
return { text: 'Ready', className: '${name}__badge ${name}__badge--ready' };
|
|
201
|
-
}, [state.status]);
|
|
202
|
-
|
|
203
|
-
const handleAction = () => {
|
|
204
|
-
if (!canProceed) return;
|
|
205
|
-
setState({ status: 'active', activeId: 'item-1' });
|
|
206
|
-
options.onAction?.();
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
return { state, canProceed, descriptor, handleAction };
|
|
210
|
-
};
|
|
211
|
-
`;
|
|
212
|
-
|
|
213
|
-
export const buildPropsType = (name, pascalName) => `export interface ${pascalName}Props {
|
|
214
|
-
readonly title: string;
|
|
215
|
-
readonly subtitle?: string;
|
|
216
|
-
readonly variant?: 'standard' | 'highlight';
|
|
217
|
-
readonly onAction?: () => void;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export interface ${pascalName}Emits {
|
|
221
|
-
(e: 'action', title: string): void;
|
|
222
|
-
}
|
|
223
|
-
`;
|
|
224
|
-
|
|
225
|
-
export const buildStateType = (name, pascalName) => `export type ${pascalName}State =
|
|
226
|
-
| { readonly status: 'idle' }
|
|
227
|
-
| { readonly status: 'loading'; readonly progress: number }
|
|
228
|
-
| { readonly status: 'active'; readonly activeId: string }
|
|
229
|
-
| { readonly status: 'fault'; readonly faultMessage: string };
|
|
230
|
-
|
|
231
|
-
export interface ${pascalName}Descriptor {
|
|
232
|
-
readonly text: string;
|
|
233
|
-
readonly className: string;
|
|
234
|
-
}
|
|
235
|
-
`;
|
|
236
|
-
|
|
237
|
-
export const buildTypesIndex = (fileNames = ['props', 'state']) =>
|
|
238
|
-
fileNames.map((f) => `export type * from './${f}.d.ts';`).join('\n') + '\n';
|
|
239
|
-
|
|
240
|
-
export const buildTypes = (name, pascalName) => `${buildStateType(name, pascalName)}
|
|
241
|
-
${buildPropsType(name, pascalName)}`;
|
|
242
|
-
|
|
243
|
-
export const buildComponentSpec = (name, pascalName, hasController = true) => {
|
|
244
|
-
if (hasController) {
|
|
245
|
-
return `import { describe, it } from 'node:test';
|
|
246
|
-
import assert from 'node:assert/strict';
|
|
247
|
-
import { use${pascalName}Controller } from './${name}.controller.ts';
|
|
248
|
-
|
|
249
|
-
describe('${pascalName} Capsule Controller', () => {
|
|
250
|
-
it('exports pure controller hook', () => {
|
|
251
|
-
assert.equal(typeof use${pascalName}Controller, 'function');
|
|
252
|
-
});
|
|
253
|
-
});
|
|
254
|
-
`;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
return `import { describe, it } from 'node:test';
|
|
258
|
-
import assert from 'node:assert/strict';
|
|
259
|
-
|
|
260
|
-
describe('${pascalName} Atom Foundation', () => {
|
|
261
|
-
it('defines foundational UI atom contract', () => {
|
|
262
|
-
assert.ok(true);
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
`;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
export const buildScss = (name) => `.${name} {
|
|
269
|
-
display: flex;
|
|
270
|
-
flex-direction: column;
|
|
271
|
-
padding: 16px;
|
|
272
|
-
background: rgba(19, 30, 58, 0.7);
|
|
273
|
-
backdrop-filter: blur(12px);
|
|
274
|
-
border: 1px solid rgba(98, 201, 255, 0.15);
|
|
275
|
-
border-radius: 8px;
|
|
276
|
-
|
|
277
|
-
&__header {
|
|
278
|
-
display: flex;
|
|
279
|
-
justify-content: space-between;
|
|
280
|
-
align-items: center;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
&__title {
|
|
284
|
-
margin: 0;
|
|
285
|
-
font-size: 16px;
|
|
286
|
-
color: #ffffff;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
&__subtitle {
|
|
290
|
-
margin: 4px 0 0;
|
|
291
|
-
font-size: 12px;
|
|
292
|
-
color: #94a3b8;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
&__badge {
|
|
296
|
-
font-size: 11px;
|
|
297
|
-
padding: 2px 8px;
|
|
298
|
-
border-radius: 4px;
|
|
299
|
-
background: #0b1329;
|
|
300
|
-
|
|
301
|
-
&--ready { color: #62c9ff; }
|
|
302
|
-
&--active { color: #4ade80; }
|
|
303
|
-
&--pending { color: #facc15; }
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
&__body {
|
|
307
|
-
margin-top: 14px;
|
|
308
|
-
display: flex;
|
|
309
|
-
justify-content: flex-end;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
&__action {
|
|
313
|
-
padding: 6px 14px;
|
|
314
|
-
border-radius: 4px;
|
|
315
|
-
background: #1e293b;
|
|
316
|
-
border: 1px solid #334155;
|
|
317
|
-
color: #ffffff;
|
|
318
|
-
cursor: pointer;
|
|
319
|
-
|
|
320
|
-
&:hover:not(:disabled) {
|
|
321
|
-
background: #334155;
|
|
322
|
-
border-color: #62c9ff;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
&:disabled {
|
|
326
|
-
opacity: 0.5;
|
|
327
|
-
cursor: not-allowed;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
`;
|
|
332
|
-
|
|
333
|
-
export const buildIndex = (name, pascalName, ext) => {
|
|
334
|
-
const compExport = ext === 'vue' || ext === 'svelte'
|
|
335
|
-
? `export { default as ${pascalName} } from './${name}.${ext}';`
|
|
336
|
-
: `export { ${pascalName} } from './${name}';`;
|
|
337
|
-
|
|
338
|
-
return `${compExport}
|
|
339
|
-
export { use${pascalName}Controller } from './${name}.controller';
|
|
340
|
-
export type * from './types';
|
|
341
|
-
`;
|
|
342
|
-
};
|
|
343
|
-
|
|
344
|
-
export const buildHook = (name, camelName, pascalName) => `import { useState, useCallback, useEffect } from 'react';
|
|
345
|
-
import type { ${pascalName}HookOptions, ${pascalName}HookReturn } from './types';
|
|
346
|
-
|
|
347
|
-
export const ${camelName} = (options: ${pascalName}HookOptions = {}): ${pascalName}HookReturn => {
|
|
348
|
-
const [data, setData] = useState<string | null>(null);
|
|
349
|
-
const [isLoading, setIsLoading] = useState<boolean>(false);
|
|
350
|
-
const [error, setError] = useState<string | null>(null);
|
|
351
|
-
|
|
352
|
-
const execute = useCallback(async () => {
|
|
353
|
-
setIsLoading(true);
|
|
354
|
-
setError(null);
|
|
355
|
-
try {
|
|
356
|
-
setData('ready');
|
|
357
|
-
options.onSuccess?.();
|
|
358
|
-
} catch (err) {
|
|
359
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
360
|
-
setError(message);
|
|
361
|
-
} finally {
|
|
362
|
-
setIsLoading(false);
|
|
363
|
-
}
|
|
364
|
-
}, [options]);
|
|
365
|
-
|
|
366
|
-
useEffect(() => {
|
|
367
|
-
if (options.immediate) {
|
|
368
|
-
execute();
|
|
369
|
-
}
|
|
370
|
-
}, [options.immediate, execute]);
|
|
371
|
-
|
|
372
|
-
return { data, isLoading, error, execute };
|
|
373
|
-
};
|
|
374
|
-
`;
|
|
375
|
-
|
|
376
|
-
export const buildHookOptionsType = (pascalName) => `export interface ${pascalName}HookOptions {
|
|
377
|
-
readonly immediate?: boolean;
|
|
378
|
-
readonly onSuccess?: () => void;
|
|
379
|
-
}
|
|
380
|
-
`;
|
|
381
|
-
|
|
382
|
-
export const buildHookReturnType = (pascalName) => `export interface ${pascalName}HookReturn {
|
|
383
|
-
readonly data: string | null;
|
|
384
|
-
readonly isLoading: boolean;
|
|
385
|
-
readonly error: string | null;
|
|
386
|
-
readonly execute: () => Promise<void>;
|
|
387
|
-
}
|
|
388
|
-
`;
|
|
389
|
-
|
|
390
|
-
export const buildHookIndex = (name, camelName) => `export { ${camelName} } from './${name}';
|
|
391
|
-
export type * from './types';
|
|
392
|
-
`;
|
|
393
|
-
|
|
394
|
-
export const buildHookSpec = (name, camelName) => `import { describe, it } from 'node:test';
|
|
395
|
-
import assert from 'node:assert/strict';
|
|
396
|
-
import { ${camelName} } from './${name}.ts';
|
|
397
|
-
|
|
398
|
-
describe('${camelName} Hook Composable', () => {
|
|
399
|
-
it('exports pure hook function', () => {
|
|
400
|
-
assert.equal(typeof ${camelName}, 'function');
|
|
401
|
-
});
|
|
402
|
-
});
|
|
403
|
-
`;
|
|
404
|
-
|
|
405
|
-
export const buildReactView = (name, pascalName) => `import React from 'react';
|
|
406
|
-
import type { ${pascalName}ViewParams } from './types';
|
|
407
|
-
|
|
408
|
-
export const ${pascalName}View: React.FC<${pascalName}ViewParams> = ({
|
|
409
|
-
HeaderMolecule,
|
|
410
|
-
MainOrganism,
|
|
411
|
-
FooterMolecule
|
|
412
|
-
}) => (
|
|
413
|
-
<main className="${name}">
|
|
414
|
-
{HeaderMolecule}
|
|
415
|
-
{MainOrganism}
|
|
416
|
-
{FooterMolecule}
|
|
417
|
-
</main>
|
|
418
|
-
);
|
|
419
|
-
|
|
420
|
-
export default ${pascalName}View;
|
|
421
|
-
`;
|
|
422
|
-
|
|
423
|
-
export const buildVueView = (name, pascalName) => `<script setup lang="ts">
|
|
424
|
-
import type { ${pascalName}ViewParams } from './types';
|
|
425
|
-
|
|
426
|
-
defineProps<${pascalName}ViewParams>();
|
|
427
|
-
</script>
|
|
428
|
-
|
|
429
|
-
<template>
|
|
430
|
-
<main class="${name}">
|
|
431
|
-
<component :is="HeaderMolecule" />
|
|
432
|
-
<component :is="MainOrganism" />
|
|
433
|
-
<component :is="FooterMolecule" />
|
|
434
|
-
</main>
|
|
435
|
-
</template>
|
|
436
|
-
`;
|
|
437
|
-
|
|
438
|
-
export const buildSvelteView = (name, pascalName) => `<script lang="ts">
|
|
439
|
-
import type { ${pascalName}ViewParams } from './types';
|
|
440
|
-
|
|
441
|
-
const {
|
|
442
|
-
HeaderMolecule,
|
|
443
|
-
MainOrganism,
|
|
444
|
-
FooterMolecule
|
|
445
|
-
}: ${pascalName}ViewParams = $props();
|
|
446
|
-
</script>
|
|
447
|
-
|
|
448
|
-
<main class="${name}">
|
|
449
|
-
{@render HeaderMolecule?.()}
|
|
450
|
-
{@render MainOrganism?.()}
|
|
451
|
-
{@render FooterMolecule?.()}
|
|
452
|
-
</main>
|
|
453
|
-
`;
|
|
454
|
-
|
|
455
|
-
export const buildViewParamsType = (pascalName) => `export interface ${pascalName}ViewParams {
|
|
456
|
-
readonly HeaderMolecule?: unknown;
|
|
457
|
-
readonly MainOrganism?: unknown;
|
|
458
|
-
readonly FooterMolecule?: unknown;
|
|
459
|
-
}
|
|
460
|
-
`;
|
|
461
|
-
|
|
462
|
-
export const buildViewIndex = (name, pascalName, ext) => {
|
|
463
|
-
const compExport = ext === 'vue' || ext === 'svelte'
|
|
464
|
-
? `export { default as ${pascalName}View } from './${name}.${ext}';`
|
|
465
|
-
: `export { ${pascalName}View } from './${name}';`;
|
|
466
|
-
|
|
467
|
-
return `${compExport}
|
|
468
|
-
export type * from './types';
|
|
469
|
-
`;
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
export const buildViewSpec = (name, pascalName) => `import { describe, it } from 'node:test';
|
|
473
|
-
import assert from 'node:assert/strict';
|
|
474
|
-
|
|
475
|
-
describe('${pascalName}View Table of Contents', () => {
|
|
476
|
-
it('defines pure declarative blueprint layout', () => {
|
|
477
|
-
assert.ok(true);
|
|
478
|
-
});
|
|
479
|
-
});
|
|
480
|
-
`;
|
|
1
|
+
export { toPascalCase, toCamelCase } from './generator-templates/naming.js';
|
|
2
|
+
export { buildReactComponent } from './generator-templates/react.js';
|
|
3
|
+
export { buildVueComponent } from './generator-templates/vue.js';
|
|
4
|
+
export { buildSvelteComponent } from './generator-templates/svelte.js';
|
|
5
|
+
export { buildController } from './generator-templates/controller.js';
|
|
6
|
+
export { buildComponentSpec, buildIndex } from './generator-templates/specs.js';
|
|
7
|
+
export {
|
|
8
|
+
buildPropsType,
|
|
9
|
+
buildStateType,
|
|
10
|
+
buildTypesIndex,
|
|
11
|
+
buildTypes
|
|
12
|
+
} from './generator-templates/types.js';
|
|
13
|
+
export { buildScss } from './generator-templates/styles.js';
|
|
14
|
+
export {
|
|
15
|
+
buildHook,
|
|
16
|
+
buildHookOptionsType,
|
|
17
|
+
buildHookReturnType,
|
|
18
|
+
buildHookIndex,
|
|
19
|
+
buildHookSpec
|
|
20
|
+
} from './generator-templates/hooks.js';
|
|
21
|
+
export {
|
|
22
|
+
buildReactView,
|
|
23
|
+
buildVueView,
|
|
24
|
+
buildSvelteView,
|
|
25
|
+
buildViewParamsType,
|
|
26
|
+
buildViewIndex,
|
|
27
|
+
buildViewSpec
|
|
28
|
+
} from './generator-templates/views.js';
|