@vc-shell/create-vc-app 1.1.99-alpha.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +26 -552
  2. package/dist/index.js +530 -1900
  3. package/dist/templates/base/_package.json +5 -5
  4. package/dist/templates/base/src/main.ts +4 -0
  5. package/dist/templates/mocks/sample-data/constants.ts +89 -0
  6. package/dist/templates/mocks/sample-data/index.ts +2 -0
  7. package/dist/templates/mocks/sample-data/methods.ts +65 -0
  8. package/dist/templates/modules/classic-module/composables/index.ts +2 -0
  9. package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}Details/index.ts +24 -0
  10. package/dist/templates/modules/classic-module/composables/use{{ModuleNamePascalCase}}List/index.ts +47 -0
  11. package/dist/templates/modules/classic-module/index.ts +8 -0
  12. package/dist/templates/modules/classic-module/locales/en.json +37 -0
  13. package/dist/templates/modules/classic-module/locales/index.ts +2 -0
  14. package/dist/templates/modules/classic-module/pages/details.vue +87 -0
  15. package/dist/templates/modules/classic-module/pages/index.ts +2 -0
  16. package/dist/templates/modules/classic-module/pages/list.vue +257 -0
  17. package/dist/templates/sample/classic-module/composables/index.ts +2 -0
  18. package/dist/templates/sample/classic-module/composables/useDetails/index.ts +54 -0
  19. package/dist/templates/sample/classic-module/composables/useList/index.ts +62 -0
  20. package/dist/templates/sample/classic-module/index.ts +8 -0
  21. package/dist/templates/sample/classic-module/locales/en.json +67 -0
  22. package/dist/templates/sample/classic-module/locales/index.ts +2 -0
  23. package/dist/templates/sample/classic-module/pages/details.vue +238 -0
  24. package/dist/templates/sample/classic-module/pages/index.ts +2 -0
  25. package/dist/templates/sample/classic-module/pages/list.vue +300 -0
  26. package/dist/templates/sample/overrides/main.ts +52 -0
  27. package/package.json +7 -12
  28. package/dist/cli/argv.d.ts +0 -4
  29. package/dist/cli/argv.d.ts.map +0 -1
  30. package/dist/cli/constants.d.ts +0 -4
  31. package/dist/cli/constants.d.ts.map +0 -1
  32. package/dist/cli/errors.d.ts +0 -12
  33. package/dist/cli/errors.d.ts.map +0 -1
  34. package/dist/cli/help.d.ts +0 -3
  35. package/dist/cli/help.d.ts.map +0 -1
  36. package/dist/cli/run.d.ts +0 -2
  37. package/dist/cli/run.d.ts.map +0 -1
  38. package/dist/cli/runtime.d.ts +0 -7
  39. package/dist/cli/runtime.d.ts.map +0 -1
  40. package/dist/cli/types.d.ts +0 -30
  41. package/dist/cli/types.d.ts.map +0 -1
  42. package/dist/cli/utils.d.ts +0 -4
  43. package/dist/cli/utils.d.ts.map +0 -1
  44. package/dist/cli/validation.d.ts +0 -5
  45. package/dist/cli/validation.d.ts.map +0 -1
  46. package/dist/commands/generate-blade.d.ts +0 -16
  47. package/dist/commands/generate-blade.d.ts.map +0 -1
  48. package/dist/templates/base/ai-guides/.cursorrules-vc-shell +0 -529
  49. package/dist/templates/base/ai-guides/README.md +0 -360
  50. package/dist/templates/base/ai-guides/guides/AI_GUIDE.md +0 -195
  51. package/dist/templates/base/ai-guides/guides/blade-patterns.md +0 -384
  52. package/dist/templates/base/ai-guides/guides/complete-workflow.md +0 -781
  53. package/dist/templates/base/ai-guides/guides/composables-reference.md +0 -338
  54. package/dist/templates/base/ai-guides/guides/troubleshooting.md +0 -529
  55. package/dist/templates/base/ai-guides/guides/ui-components-reference.md +0 -903
  56. package/dist/templates/base/ai-guides/prompts/adapt-existing-module.md +0 -1026
  57. package/dist/templates/base/ai-guides/prompts/advanced-scenarios.md +0 -852
  58. package/dist/templates/base/ai-guides/prompts/api-client-generation.md +0 -877
  59. package/dist/templates/base/ai-guides/prompts/cli-usage.md +0 -640
  60. package/dist/templates/base/ai-guides/prompts/quick-start-scenarios.md +0 -773
  61. package/dist/templates/base/ai-guides/prompts/simple-modifications.md +0 -987
  62. package/dist/templates/blades/details/blade.vue +0 -175
  63. package/dist/templates/blades/grid/blade.vue +0 -340
  64. package/dist/templates/composables/details-composable.ts +0 -101
  65. package/dist/templates/composables/grid-composable.ts +0 -244
  66. package/dist/templates/module/components/index.ts +0 -2
  67. package/dist/templates/module/components/widgets/index.ts +0 -2
  68. package/dist/templates/module/composables/index.ts +0 -3
  69. package/dist/templates/module/index.ts +0 -13
  70. package/dist/templates/module/locales/en.json +0 -65
  71. package/dist/templates/module/locales/index.ts +0 -4
  72. package/dist/templates/module/pages/index.ts +0 -3
  73. package/dist/templates/widgets/widget.vue +0 -113
  74. package/dist/utils/form-builder.d.ts +0 -69
  75. package/dist/utils/form-builder.d.ts.map +0 -1
  76. package/dist/utils/format.d.ts +0 -24
  77. package/dist/utils/format.d.ts.map +0 -1
  78. package/dist/utils/naming.d.ts +0 -44
  79. package/dist/utils/naming.d.ts.map +0 -1
  80. package/dist/utils/register-module.d.ts +0 -21
  81. package/dist/utils/register-module.d.ts.map +0 -1
  82. package/dist/workflows/create-app.d.ts +0 -14
  83. package/dist/workflows/create-app.d.ts.map +0 -1
@@ -0,0 +1,54 @@
1
+ import { Ref, computed, ref } from "vue";
2
+ import { useAsync, useLoading, useModificationTracker } from "@vc-shell/framework";
3
+ import {
4
+ MockedItem,
5
+ addNewMockItem,
6
+ currencyOptions,
7
+ loadMockItem,
8
+ removeMockItem,
9
+ updateMockItem,
10
+ } from "../../sample-data";
11
+
12
+ export default () => {
13
+ const item = ref({}) as Ref<MockedItem>;
14
+
15
+ const { isModified, currentValue, resetModificationState } = useModificationTracker(item);
16
+
17
+ const { loading: itemLoading, action: getItem } = useAsync<{ id: string }>(async (payload) => {
18
+ item.value = await loadMockItem(payload);
19
+ });
20
+
21
+ const { loading: saveLoading, action: saveItem } = useAsync<MockedItem, MockedItem | void>(async (payload) => {
22
+ if (payload) {
23
+ if (payload.id) {
24
+ const _res = await updateMockItem(payload)
25
+
26
+ resetModificationState(_res);
27
+ return _res;
28
+ } else {
29
+ const _res = await addNewMockItem(payload);
30
+
31
+ resetModificationState(_res);
32
+ return _res;
33
+ }
34
+ }
35
+ });
36
+
37
+ const { loading: removeLoading, action: removeItem } = useAsync<{ id: string }>(async (payload) => {
38
+ if (payload) {
39
+ return await removeMockItem(payload);
40
+ }
41
+ });
42
+
43
+ const loading = useLoading(itemLoading, saveLoading, removeLoading);
44
+
45
+ return {
46
+ item: currentValue,
47
+ loading: computed(() => loading.value),
48
+ currencyOptions: computed(() => currencyOptions),
49
+ isModified,
50
+ getItem,
51
+ saveItem,
52
+ removeItem,
53
+ };
54
+ };
@@ -0,0 +1,62 @@
1
+ import { ComputedRef, Ref, computed, ref } from "vue";
2
+ import { useAsync, useLoading } from "@vc-shell/framework";
3
+ import { MockedItem, MockedQuery, loadMockItemsList, removeMockItem } from "../../sample-data";
4
+
5
+ export interface useClassicAppList {
6
+ data: ComputedRef<MockedItem[] | undefined>;
7
+ loading: Ref<boolean>;
8
+ totalCount: Ref<number>;
9
+ pages: Ref<number>;
10
+ searchQuery: Ref<SearchQuery>;
11
+ currentPage: ComputedRef<number>;
12
+ getItems: (query: MockedQuery) => Promise<void>;
13
+ removeItems: (args: { ids: string[] }) => void;
14
+ }
15
+ interface SearchQuery {
16
+ take?: number;
17
+ skip?: number;
18
+ sort?: string;
19
+ keyword?: string;
20
+ }
21
+ interface SearchResult {
22
+ results: MockedItem[];
23
+ totalCount: number;
24
+ }
25
+
26
+ export type { MockedItem };
27
+
28
+ export default (options?: { pageSize?: number, sort?: string }): useClassicAppList => {
29
+ const pageSize = options?.pageSize || 20;
30
+ const searchResult = ref<SearchResult>();
31
+ const searchQuery = ref<SearchQuery>({
32
+ take: pageSize,
33
+ skip: 0,
34
+ sort: options?.sort || "createdDate:DESC",
35
+ });
36
+
37
+ const { loading: itemLoading, action: getItems } = useAsync<MockedQuery>(async (query) => {
38
+ searchQuery.value = { ...searchQuery.value, ...query };
39
+ if (query) searchResult.value = await loadMockItemsList(searchQuery.value);
40
+ });
41
+
42
+ const { loading: removeLoading, action: removeItems } = useAsync<{ ids: string[] }>(async (args) => {
43
+ if (args) {
44
+ for (const id of args.ids) {
45
+ await removeMockItem({ id });
46
+ }
47
+ }
48
+ });
49
+
50
+ const loading = useLoading(itemLoading, removeLoading);
51
+
52
+ return {
53
+ data: computed(() => searchResult.value?.results),
54
+ loading: computed(() => loading.value),
55
+ totalCount: computed(() => searchResult.value?.totalCount || 0),
56
+ pages: computed(() => Math.ceil((searchResult.value?.totalCount || 1) / pageSize)),
57
+ currentPage: computed(() => Math.ceil((searchQuery.value?.skip || 0) / Math.max(1, pageSize) + 1)),
58
+ searchQuery,
59
+ getItems,
60
+ removeItems,
61
+ };
62
+ };
@@ -0,0 +1,8 @@
1
+ import * as pages from "./pages";
2
+ import * as locales from "./locales";
3
+ import { createAppModule } from "@vc-shell/framework";
4
+
5
+ export default createAppModule(pages, locales);
6
+
7
+ export * from "./pages";
8
+ export * from "./composables";
@@ -0,0 +1,67 @@
1
+ {
2
+ "SAMPLE_APP": {
3
+ "MENU": {
4
+ "TITLE": "Sample"
5
+ },
6
+ "PAGES": {
7
+ "LIST": {
8
+ "TITLE": "Sample list",
9
+ "TOOLBAR": {
10
+ "REFRESH": "Refresh",
11
+ "REMOVE": "Remove"
12
+ },
13
+ "SEARCH": {
14
+ "PLACEHOLDER": "Search keywords"
15
+ },
16
+ "TABLE": {
17
+ "TOTALS": "Count:",
18
+ "HEADER": {
19
+ "IMAGE": "Img",
20
+ "PRODUCT_NAME": "Product name",
21
+ "DESCRIPTION": "Description",
22
+ "PRICE": "Price",
23
+ "SALE_PRICE": "Sale price",
24
+ "CURRENCY": "Currency"
25
+ },
26
+ "ACTIONS": {
27
+ "DELETE": "Delete"
28
+ }
29
+ },
30
+ "EMPTY": {
31
+ "NO_ITEMS": "No items found",
32
+ "ADD": "Add item"
33
+ },
34
+ "NOT_FOUND": {
35
+ "EMPTY": "No items found",
36
+ "RESET": "Reset"
37
+ }
38
+ },
39
+ "DETAILS": {
40
+ "TITLE": {
41
+ "DETAILS": " details",
42
+ "LOADING": "Loading..."
43
+ },
44
+ "TOOLBAR": {
45
+ "SAVE": "Save",
46
+ "DELETE": "Delete"
47
+ },
48
+ "FIELDS": {
49
+ "NAME": "Name",
50
+ "CONTENT": "Content",
51
+ "GUID": "GUID",
52
+ "DESCRIPTION": "Description",
53
+ "PRICE": "Price",
54
+ "SALE_PRICE": "Sale price"
55
+ }
56
+ },
57
+ "ALERTS": {
58
+ "CLOSE_CONFIRMATION": "You have unsaved changes. Close anyway?",
59
+ "DELETE": "Are you sure you want to delete this item?",
60
+ "DELETE_SELECTED_CONFIRMATION": {
61
+ "MESSAGE": "Are you sure you want to delete {count} selected items?",
62
+ "ALL": "all {totalCount}"
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,2 @@
1
+ import * as en from "./en.json";
2
+ export { en };
@@ -0,0 +1,238 @@
1
+ <template>
2
+ <VcBlade
3
+ v-loading="loading"
4
+ :title="title"
5
+ :expanded="expanded"
6
+ :closable="closable"
7
+ width="70%"
8
+ :toolbar-items="bladeToolbar"
9
+ @close="$emit('close:blade')"
10
+ @expand="$emit('expand:blade')"
11
+ @collapse="$emit('collapse:blade')"
12
+ >
13
+ <VcContainer class="tw-p-2">
14
+ <VcForm class="tw-space-y-4">
15
+ <Field
16
+ v-slot="{ errorMessage, handleChange, errors }"
17
+ name="name"
18
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.NAME')"
19
+ rules="required"
20
+ :model-value="item.name"
21
+ >
22
+ <VcInput
23
+ v-model="item.name"
24
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.NAME')"
25
+ required
26
+ :error="!!errors.length"
27
+ :error-message="errorMessage"
28
+ @update:model-value="handleChange"
29
+ ></VcInput>
30
+ </Field>
31
+ <VcCard header="Content">
32
+ <div class="tw-p-4 tw-space-y-4">
33
+ <Field
34
+ v-slot="{ errorMessage, handleChange, errors }"
35
+ name="guid"
36
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.GUID')"
37
+ :rules="{
38
+ required: true,
39
+ regex: /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/,
40
+ }"
41
+ :model-value="item.guid"
42
+ >
43
+ <VcInput
44
+ v-model="item.guid"
45
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.GUID')"
46
+ required
47
+ :error="!!errors.length"
48
+ :error-message="errorMessage"
49
+ @update:model-value="handleChange"
50
+ ></VcInput>
51
+ </Field>
52
+ <Field
53
+ v-slot="{ errorMessage, handleChange, errors }"
54
+ name="description"
55
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.DESCRIPTION')"
56
+ :rules="{
57
+ required: true,
58
+ }"
59
+ :model-value="item.description"
60
+ >
61
+ <VcTextarea
62
+ v-model="item.description"
63
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.DESCRIPTION')"
64
+ required
65
+ :error="!!errors.length"
66
+ :error-message="errorMessage"
67
+ @update:model-value="handleChange"
68
+ ></VcTextarea>
69
+ </Field>
70
+ </div>
71
+ </VcCard>
72
+ <VcCard
73
+ v-if="item.currency"
74
+ header="Prices"
75
+ >
76
+ <VcRow class="tw-p-4 tw-gap-4">
77
+ <VcCol :size="2">
78
+ <Field
79
+ v-slot="{ errorMessage, handleChange, errors }"
80
+ name="price"
81
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.PRICE')"
82
+ :rules="{
83
+ required: true,
84
+ }"
85
+ :model-value="item.price"
86
+ >
87
+ <VcInputCurrency
88
+ v-model="item.price"
89
+ v-model:option="item.currency"
90
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.PRICE')"
91
+ required
92
+ option-value="value"
93
+ option-label="label"
94
+ :error="!!errors.length"
95
+ :error-message="errorMessage"
96
+ :options="currencyOptions"
97
+ @update:model-value="handleChange"
98
+ ></VcInputCurrency>
99
+ </Field>
100
+ </VcCol>
101
+ <VcCol :size="2">
102
+ <Field
103
+ v-slot="{ errorMessage, handleChange, errors }"
104
+ name="salePrice"
105
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.SALE_PRICE')"
106
+ :rules="{
107
+ required: true,
108
+ }"
109
+ :model-value="item.salePrice"
110
+ >
111
+ <VcInputCurrency
112
+ v-model="item.salePrice"
113
+ v-model:option="item.currency"
114
+ :label="$t('SAMPLE_APP.PAGES.DETAILS.FIELDS.SALE_PRICE')"
115
+ required
116
+ option-value="value"
117
+ option-label="label"
118
+ :error="!!errors.length"
119
+ :error-message="errorMessage"
120
+ :options="currencyOptions"
121
+ @update:model-value="handleChange"
122
+ ></VcInputCurrency>
123
+ </Field>
124
+ </VcCol>
125
+ </VcRow>
126
+ </VcCard>
127
+ </VcForm>
128
+ </VcContainer>
129
+ </VcBlade>
130
+ </template>
131
+
132
+ <script lang="ts" setup>
133
+ import { IBladeToolbar, IParentCallArgs, useBeforeUnload, useBladeNavigation, usePopup } from "@vc-shell/framework";
134
+ import { useDetails } from "./../composables";
135
+ import { computed, onMounted, ref } from "vue";
136
+ import { Field, useForm } from "vee-validate";
137
+ import { useI18n } from "vue-i18n";
138
+ import * as _ from "lodash-es";
139
+
140
+ export interface Props {
141
+ expanded?: boolean;
142
+ closable?: boolean;
143
+ param?: string;
144
+ }
145
+
146
+ export interface Emits {
147
+ (event: "parent:call", args: IParentCallArgs): void;
148
+ (event: "collapse:blade"): void;
149
+ (event: "expand:blade"): void;
150
+ (event: "close:blade"): void;
151
+ }
152
+
153
+ defineOptions({
154
+ url: "/sample-details",
155
+ name: "SampleDetails",
156
+ });
157
+
158
+ const props = withDefaults(defineProps<Props>(), {
159
+ expanded: true,
160
+ closable: true,
161
+ param: undefined,
162
+ });
163
+
164
+ const emit = defineEmits<Emits>();
165
+
166
+ const { loading, getItem, saveItem, removeItem, item, currencyOptions, isModified } = useDetails();
167
+ const { showConfirmation } = usePopup();
168
+ const { onBeforeClose } = useBladeNavigation();
169
+ const { t } = useI18n({ useScope: "global" });
170
+
171
+ const { meta } = useForm({
172
+ validateOnMount: false,
173
+ });
174
+
175
+ const isDisabled = computed(() => {
176
+ return !meta.value.dirty || !meta.value.valid;
177
+ });
178
+
179
+ const title = computed(() => {
180
+ return props.param
181
+ ? item.value?.name
182
+ ? item.value?.name + t("SAMPLE_APP.PAGES.DETAILS.TITLE.DETAILS")
183
+ : t("SAMPLE_APP.PAGES.DETAILS.TITLE.LOADING")
184
+ : "Test App" + t("SAMPLE_APP.PAGES.DETAILS.TITLE.DETAILS");
185
+ });
186
+
187
+ const bladeToolbar = ref<IBladeToolbar[]>([
188
+ {
189
+ id: "save",
190
+ icon: "material-save",
191
+ title: "Save",
192
+ async clickHandler() {
193
+ await saveItem(item.value);
194
+
195
+ emit("parent:call", {
196
+ method: "reload",
197
+ });
198
+ emit("close:blade");
199
+ },
200
+ disabled: computed(() => !(isModified.value && !isDisabled.value)),
201
+ },
202
+ {
203
+ id: "delete",
204
+ icon: "material-delete",
205
+ title: "Delete",
206
+ async clickHandler() {
207
+ if (await showConfirmation(t(`SAMPLE_APP.PAGES.ALERTS.DELETE`))) {
208
+ if (props.param) {
209
+ await removeItem({ id: props.param });
210
+ emit("parent:call", {
211
+ method: "reload",
212
+ });
213
+
214
+ emit("close:blade");
215
+ }
216
+ }
217
+ },
218
+ },
219
+ ]);
220
+
221
+ onMounted(async () => {
222
+ if (props.param) {
223
+ await getItem({ id: props.param });
224
+ }
225
+ });
226
+
227
+ onBeforeClose(async () => {
228
+ if (!isDisabled.value && isModified.value) {
229
+ return await showConfirmation(t("SAMPLE_APP.PAGES.ALERTS.CLOSE_CONFIRMATION"));
230
+ }
231
+ });
232
+
233
+ useBeforeUnload(computed(() => !isDisabled.value && isModified.value));
234
+
235
+ defineExpose({
236
+ title,
237
+ });
238
+ </script>
@@ -0,0 +1,2 @@
1
+ export { default as List } from "./list.vue";
2
+ export {default as Details } from './details.vue'