@vc-shell/create-vc-app 1.1.99-alpha.2 → 1.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.
Files changed (86) hide show
  1. package/README.md +26 -552
  2. package/dist/index.js +530 -1901
  3. package/dist/templates/base/_package.json +6 -7
  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/_husky/commit-msg +0 -4
  49. package/dist/templates/base/_husky/pre-commit +0 -4
  50. package/dist/templates/base/ai-guides/.cursorrules-vc-shell +0 -529
  51. package/dist/templates/base/ai-guides/README.md +0 -360
  52. package/dist/templates/base/ai-guides/guides/AI_GUIDE.md +0 -195
  53. package/dist/templates/base/ai-guides/guides/blade-patterns.md +0 -384
  54. package/dist/templates/base/ai-guides/guides/complete-workflow.md +0 -781
  55. package/dist/templates/base/ai-guides/guides/composables-reference.md +0 -338
  56. package/dist/templates/base/ai-guides/guides/troubleshooting.md +0 -529
  57. package/dist/templates/base/ai-guides/guides/ui-components-reference.md +0 -903
  58. package/dist/templates/base/ai-guides/prompts/adapt-existing-module.md +0 -1026
  59. package/dist/templates/base/ai-guides/prompts/advanced-scenarios.md +0 -852
  60. package/dist/templates/base/ai-guides/prompts/api-client-generation.md +0 -877
  61. package/dist/templates/base/ai-guides/prompts/cli-usage.md +0 -640
  62. package/dist/templates/base/ai-guides/prompts/quick-start-scenarios.md +0 -773
  63. package/dist/templates/base/ai-guides/prompts/simple-modifications.md +0 -987
  64. package/dist/templates/base/scripts/release.ts +0 -5
  65. package/dist/templates/blades/details/blade.vue +0 -175
  66. package/dist/templates/blades/grid/blade.vue +0 -340
  67. package/dist/templates/composables/details-composable.ts +0 -101
  68. package/dist/templates/composables/grid-composable.ts +0 -244
  69. package/dist/templates/module/components/index.ts +0 -2
  70. package/dist/templates/module/components/widgets/index.ts +0 -2
  71. package/dist/templates/module/composables/index.ts +0 -3
  72. package/dist/templates/module/index.ts +0 -13
  73. package/dist/templates/module/locales/en.json +0 -65
  74. package/dist/templates/module/locales/index.ts +0 -4
  75. package/dist/templates/module/pages/index.ts +0 -3
  76. package/dist/templates/widgets/widget.vue +0 -113
  77. package/dist/utils/form-builder.d.ts +0 -69
  78. package/dist/utils/form-builder.d.ts.map +0 -1
  79. package/dist/utils/format.d.ts +0 -24
  80. package/dist/utils/format.d.ts.map +0 -1
  81. package/dist/utils/naming.d.ts +0 -44
  82. package/dist/utils/naming.d.ts.map +0 -1
  83. package/dist/utils/register-module.d.ts +0 -21
  84. package/dist/utils/register-module.d.ts.map +0 -1
  85. package/dist/workflows/create-app.d.ts +0 -14
  86. 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'