@simitgroup/simpleapp-generator 1.6.7-b-alpha → 1.6.7-c-alpha

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/ReleaseNote.md CHANGED
@@ -1,3 +1,7 @@
1
+ [1.6.7c-alpha]
2
+
3
+ 1. Add Require Plan For Mini App
4
+
1
5
  [1.6.7b-alpha]
2
6
 
3
7
  1. Fix Missing Import
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simitgroup/simpleapp-generator",
3
- "version": "1.6.7b-alpha",
3
+ "version": "1.6.7c-alpha",
4
4
  "description": "frontend nuxtjs and backend nests code generator using jsonschema",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -4,7 +4,7 @@
4
4
  * last change 2025-06-09
5
5
  */
6
6
 
7
- import _ from "lodash";
7
+ import _, { min } from "lodash";
8
8
  import {
9
9
  Miniapp,
10
10
  MiniAppDetail,
@@ -15,6 +15,7 @@ import {
15
15
  import {
16
16
  MiniAppFormWithMiniAppCode,
17
17
  MiniAppFrameworkCompatibility,
18
+ MiniAppPermissionResult,
18
19
  } from "~/simpleapp/generate/features/miniApp/app/types/miniApp";
19
20
 
20
21
  export default defineNuxtPlugin(async () => {
@@ -41,6 +42,17 @@ export default defineNuxtPlugin(async () => {
41
42
 
42
43
  const MINI_APP_BUILT_IN_SETTING_NAME = "mini-app-setting";
43
44
 
45
+ const _ERROR = {
46
+ MISSING_REQUIRED_PLAN: "missingRequiredPlan",
47
+ INSUFFICIENT_ACCESS_PERMISSION: "insufficientAccessPermission",
48
+ INSUFFICIENT_INSTALL_PERMISSION: "insufficientInstallPermission",
49
+ INSUFFICIENT_UNINSTALL_PERMISSION: "insufficientUninstallPermission",
50
+ INSUFFICIENT_CHANGE_SETTING_PERMISSION:
51
+ "insufficientChangeSettingPermission",
52
+ NO_MINI_APP_FEATURE: "packageTypeRestricted",
53
+ NOT_YET_INSTALL: "notYetInstall",
54
+ };
55
+
44
56
  const useMiniAppStore = defineStore("mini-app", {
45
57
  state: () => ({
46
58
  actionAccess: {} as MiniAppDetailActionAccess,
@@ -99,7 +111,10 @@ export default defineNuxtPlugin(async () => {
99
111
  getMenuItems() {
100
112
  return this.installedMiniApps.flatMap((miniApp) => {
101
113
  const pages = miniApp.integration.pages.filter((page) => {
102
- return this.checkIsAllowAccessMiniAppPage(miniApp.code, page.code) && this.isRequiredToShowOnMenu(page);
114
+ return (
115
+ this.isAllowAccessMiniAppPage(miniApp.code, page.code) &&
116
+ this.isRequiredToShowOnMenu(page)
117
+ );
103
118
  });
104
119
 
105
120
  if (this.isCanUpdateSetting) {
@@ -138,7 +153,7 @@ export default defineNuxtPlugin(async () => {
138
153
  });
139
154
  },
140
155
 
141
- isRequiredToShowOnMenu(page: MiniappIntegrationPages){
156
+ isRequiredToShowOnMenu(page: MiniappIntegrationPages) {
142
157
  return page.isHideOnMenu !== true;
143
158
  },
144
159
 
@@ -185,34 +200,81 @@ export default defineNuxtPlugin(async () => {
185
200
 
186
201
  // ================================ Permission ===============================
187
202
 
188
- getActionAccess(
189
- type: "install" | "uninstall" | "updateSetting" | "plan",
190
- ) {
191
- switch (type) {
192
- case "install":
193
- return {
194
- isAllow: this.isCanInstall,
195
- reason: "insufficientInstallPermission",
196
- };
197
-
198
- case "uninstall":
199
- return {
200
- isAllow: this.isCanUninstall,
201
- reason: "insufficientUninstallPermission",
202
- };
203
-
204
- case "updateSetting":
205
- return {
206
- isAllow: this.isCanUpdateSetting,
207
- reason: "insufficientChangeSettingPermission",
208
- };
209
-
210
- case "plan":
211
- return {
212
- isAllow: this.isHasMiniAppFeature,
213
- reason: "packageTypeRestricted",
214
- };
203
+ hasRequiredPlan(miniApp: Miniapp) {
204
+ const currentPlan = getUserProfile().package ?? "";
205
+ const requiredPlans = miniApp.requiredPlans ?? [];
206
+ if (_.isEmpty(requiredPlans)) return true;
207
+
208
+ return requiredPlans.includes(currentPlan);
209
+ },
210
+
211
+ checkHasFeature() {
212
+ return this._check([
213
+ [() => this.isHasMiniAppFeature, _ERROR.NO_MINI_APP_FEATURE],
214
+ ]);
215
+ },
216
+
217
+ checkHasRequiredPlan(miniApp: Miniapp) {
218
+ return this._check([
219
+ [() => this.hasRequiredPlan(miniApp), _ERROR.MISSING_REQUIRED_PLAN],
220
+ ]);
221
+ },
222
+
223
+ checkIsInstalled(miniAppCode: string) {
224
+ return this._check([
225
+ [() => this.isMiniAppInstalled(miniAppCode), _ERROR.NOT_YET_INSTALL],
226
+ ]);
227
+ },
228
+
229
+ checkCanAccess(miniAppCode: string, pageCode: string) {
230
+ if (pageCode === MINI_APP_BUILT_IN_SETTING_NAME) {
231
+ return this._check([
232
+ [
233
+ () => this.isCanUpdateSetting,
234
+ _ERROR.INSUFFICIENT_ACCESS_PERMISSION,
235
+ ],
236
+ ]);
215
237
  }
238
+
239
+ return this._check([
240
+ [
241
+ () => this.isAllowAccessMiniAppPage(miniAppCode, pageCode),
242
+ _ERROR.INSUFFICIENT_ACCESS_PERMISSION,
243
+ ],
244
+ ]);
245
+ },
246
+
247
+ checkCanInstall(miniApp: Miniapp) {
248
+ return this._check([
249
+ [() => this.hasRequiredPlan(miniApp), _ERROR.MISSING_REQUIRED_PLAN],
250
+ [() => this.isCanInstall, _ERROR.INSUFFICIENT_INSTALL_PERMISSION],
251
+ ]);
252
+ },
253
+
254
+ checkCanUninstall(miniApp: Miniapp) {
255
+ return this._check([
256
+ [() => this.isCanUninstall, _ERROR.INSUFFICIENT_UNINSTALL_PERMISSION],
257
+ ]);
258
+ },
259
+
260
+ checkCanUpdateSetting(miniApp: Miniapp) {
261
+ return this._check([
262
+ [() => this.hasRequiredPlan(miniApp), _ERROR.MISSING_REQUIRED_PLAN],
263
+ [
264
+ () => this.isCanUpdateSetting,
265
+ _ERROR.INSUFFICIENT_CHANGE_SETTING_PERMISSION,
266
+ ],
267
+ ]);
268
+ },
269
+
270
+ _check(checks: [() => boolean, string][]): MiniAppPermissionResult {
271
+ for (const [checkFn, reason] of checks) {
272
+ if (!checkFn()) {
273
+ return { status: false, reason };
274
+ }
275
+ }
276
+
277
+ return { status: true };
216
278
  },
217
279
 
218
280
  // ============================ Path & Navigation ============================
@@ -254,7 +316,7 @@ export default defineNuxtPlugin(async () => {
254
316
 
255
317
  // ============================ Validation ============================
256
318
 
257
- checkIsMiniAppInstalled(miniAppCode: string) {
319
+ isMiniAppInstalled(miniAppCode: string) {
258
320
  const miniApp = this.installedMiniApps.find(
259
321
  (item) => item.code === miniAppCode,
260
322
  );
@@ -262,7 +324,7 @@ export default defineNuxtPlugin(async () => {
262
324
  return miniApp ? true : false;
263
325
  },
264
326
 
265
- checkIsAllowAccessMiniAppPage(miniAppCode: string, pageCode: string) {
327
+ isAllowAccessMiniAppPage(miniAppCode: string, pageCode: string) {
266
328
  const miniApp = this.installedMiniApps.find(
267
329
  (item) => item.code === miniAppCode,
268
330
  );
@@ -1,19 +1,17 @@
1
1
  <template>
2
2
  <MiniAppRestrictedWarning
3
- v-if="!actionAccess.isAllow"
4
- :reason="actionAccess.reason"
3
+ v-if="!permission.status"
4
+ :reason="permission.reason ?? ''"
5
5
  class="flex items-center justify-center mt-10"
6
6
  />
7
7
  <slot v-else />
8
8
  </template>
9
9
 
10
10
  <script setup lang="ts">
11
+ import { MiniAppPermissionResult } from "../types/miniApp";
11
12
  import MiniAppRestrictedWarning from "./MiniAppRestrictedWarning.vue";
12
13
 
13
14
  defineProps<{
14
- actionAccess: {
15
- isAllow: boolean;
16
- reason: string;
17
- };
15
+ permission: MiniAppPermissionResult;
18
16
  }>();
19
17
  </script>
@@ -12,7 +12,8 @@
12
12
  </div>
13
13
 
14
14
  <MiniAppPermissionWrapper
15
- :actionAccess="$miniAppStore.getActionAccess('updateSetting')"
15
+ v-if="miniApp"
16
+ :permission="$miniAppStore.checkCanUpdateSetting(miniApp)"
16
17
  >
17
18
  <slot />
18
19
  </MiniAppPermissionWrapper>
@@ -20,10 +21,18 @@
20
21
  </template>
21
22
 
22
23
  <script setup lang="ts">
23
- import MiniAppPermissionWrapper from './MiniAppPermissionWrapper.vue';
24
+ import MiniAppPermissionWrapper from "./MiniAppPermissionWrapper.vue";
24
25
 
25
- defineProps<{
26
+ const props = defineProps<{
26
27
  isFetching: boolean;
28
+ miniAppCode: string;
27
29
  miniAppTitle: string;
28
30
  }>();
31
+
32
+ const { $miniAppStore } = useNuxtApp();
33
+ const miniApp = computed(() => {
34
+ return $miniAppStore.installedMiniApps.find(
35
+ (item) => item.code === props.miniAppCode,
36
+ );
37
+ });
29
38
  </script>
@@ -6,10 +6,14 @@
6
6
  :data="data"
7
7
  #default="o"
8
8
  >
9
- <MiniAppSettingLayout :isFetching="isFetching" :miniAppTitle="miniAppTitle">
9
+ <MiniAppSettingLayout
10
+ :isFetching="isFetching"
11
+ :miniAppCode="_miniAppCode"
12
+ :miniAppTitle="miniAppTitle"
13
+ >
10
14
  <template #action>
11
15
  <Button class="btn-primary" @click="o.validate(validateCallBack)">
12
- {{ t('miniAppLang.saveSetting') }}
16
+ {{ t("miniAppLang.saveSetting") }}
13
17
  </Button>
14
18
  </template>
15
19
 
@@ -20,8 +24,8 @@
20
24
  class="text-sm text-gray-600 whitespace-pre-line"
21
25
  >
22
26
  {{
23
- t('miniAppLang.miniAppSettingNote', {
24
- miniAppNote: miniApp.integration.settings.note ?? ''
27
+ t("miniAppLang.miniAppSettingNote", {
28
+ miniAppNote: miniApp.integration.settings.note ?? "",
25
29
  })
26
30
  }}
27
31
  </p>
@@ -42,15 +46,15 @@
42
46
  </template>
43
47
 
44
48
  <script setup lang="ts" generic="T">
45
- import _ from 'lodash';
46
- import MiniAppSettingLayout from './MiniAppSettingLayout.vue';
47
- import CustomFieldFormField from '../../../customField/components/CustomFieldFormField.vue';
49
+ import _ from "lodash";
50
+ import MiniAppSettingLayout from "./MiniAppSettingLayout.vue";
51
+ import CustomFieldFormField from "../../../customField/components/CustomFieldFormField.vue";
48
52
 
49
53
  const props = defineProps<{
50
54
  miniAppCode?: string;
51
55
  }>();
52
56
 
53
- const _miniAppCode = props.miniAppCode ?? getPathPara('miniAppCode');
57
+ const _miniAppCode = props.miniAppCode ?? getPathPara("miniAppCode");
54
58
 
55
59
  const {
56
60
  isFetching,
@@ -60,7 +64,7 @@ const {
60
64
  settingSchema,
61
65
  data,
62
66
  loadMiniAppDetail,
63
- validateCallBack
67
+ validateCallBack,
64
68
  } = useMiniAppSetting(_miniAppCode);
65
69
 
66
70
  onMounted(async () => {
@@ -3,37 +3,47 @@
3
3
 
4
4
  <MiniAppPermissionWrapper
5
5
  v-if="!$miniAppStore.isFetchingInstalledMiniApps"
6
- :actionAccess="$miniAppStore.getActionAccess('plan')"
6
+ :permission="permission"
7
7
  >
8
- <MiniAppPermissionWrapper
9
- :actionAccess="{
10
- isAllow: $miniAppStore.checkIsMiniAppInstalled(miniAppCode),
11
- reason: 'notYetInstall'
12
- }"
13
- >
14
- <MiniAppPermissionWrapper
15
- v-if="pageCode !== ''"
16
- :actionAccess="{
17
- isAllow: $miniAppStore.checkIsAllowAccessMiniAppPage(
18
- miniAppCode,
19
- pageCode
20
- ),
21
- reason: 'insufficientAccessPermission'
22
- }"
23
- >
24
- <slot />
25
- </MiniAppPermissionWrapper>
26
-
27
- <slot v-else />
28
- </MiniAppPermissionWrapper>
8
+ <slot />
29
9
  </MiniAppPermissionWrapper>
30
10
  </template>
31
11
 
32
12
  <script setup lang="ts">
33
- import MiniAppPermissionWrapper from './MiniAppPermissionWrapper.vue';
13
+ import MiniAppPermissionWrapper from "./MiniAppPermissionWrapper.vue";
34
14
 
35
- defineProps<{
15
+ const props = defineProps<{
36
16
  miniAppCode: string;
37
17
  pageCode: string;
38
18
  }>();
19
+
20
+ const { $miniAppStore } = useNuxtApp();
21
+
22
+ const miniApp = computed(() => {
23
+ return $miniAppStore.installedMiniApps.find(
24
+ (item) => item.code === props.miniAppCode,
25
+ );
26
+ });
27
+
28
+ const permission = computed(() => {
29
+ const checkHasFeature = $miniAppStore.checkHasFeature();
30
+ if (!checkHasFeature.status) return checkHasFeature;
31
+
32
+ const checkIsInstalled = $miniAppStore.checkIsInstalled(props.miniAppCode);
33
+ if (!checkIsInstalled.status) return checkIsInstalled;
34
+
35
+ if (!miniApp.value) {
36
+ return {
37
+ status: false,
38
+ reason: "unknownMiniApp",
39
+ };
40
+ }
41
+
42
+ const checkHasRequiredPlan = $miniAppStore.checkHasRequiredPlan(
43
+ miniApp.value,
44
+ );
45
+ if (!checkHasRequiredPlan.status) return checkHasRequiredPlan;
46
+
47
+ return $miniAppStore.checkCanAccess(props.miniAppCode, props.pageCode);
48
+ });
39
49
  </script>
@@ -7,7 +7,7 @@
7
7
  }"
8
8
  @click="handleMiniAppClick(item)"
9
9
  >
10
- <div class="absolute top-2 right-2 flex space-x-1">
10
+ <div class="absolute top-1 right-1 flex space-x-1">
11
11
  <MiniAppIntegrationItemBadge :item="item" />
12
12
  </div>
13
13
 
@@ -1,12 +1,32 @@
1
1
  <template>
2
2
  <span
3
- class="text-white text-xs px-2 font-bold py-0.5 rounded-md shadow uppercase"
3
+ v-if="badgeType !== 'notAvailable' && badgeType !== 'noFeature'"
4
+ class="text-white text-[0.65rem] px-2 font-bold py-0.5 rounded-md shadow uppercase"
4
5
  :class="{
5
- 'bg-emerald-500': badgeType === 'free',
6
+ 'bg-emerald-500': badgeType === 'available',
6
7
  'bg-yellow-400': badgeType === 'comingSoon',
7
8
  }"
8
9
  >
9
- {{ t(badgeType) }}
10
+ {{ t(`miniAppLang.${badgeType}`) }}
11
+ </span>
12
+ <span
13
+ v-else
14
+ class="bg-slate-200/50 text-surface-500 text-[0.65rem] px-2 font-bold py-0.5 rounded-md uppercase"
15
+ >
16
+ <template v-if="badgeType === 'notAvailable'">
17
+ {{
18
+ t(`miniAppLang.requiredPlansOnly`, {
19
+ requiredPlans: item.requiredPlans.join(" | "),
20
+ })
21
+ }}
22
+ </template>
23
+ <template v-else>
24
+ {{
25
+ t("miniAppLang.requiredPlansOnly", {
26
+ requiredPlans: ["lite", "pro", "enterprise"].join(" | "),
27
+ })
28
+ }}
29
+ </template>
10
30
  </span>
11
31
  </template>
12
32
 
@@ -17,15 +37,21 @@ const props = defineProps<{
17
37
  item: Miniapp;
18
38
  }>();
19
39
 
20
- const badgeType = computed(() => {
21
- if (props.item.status === "published" && props.item.pricing === 0) {
22
- return "free";
23
- }
40
+ const { $miniAppStore } = useNuxtApp();
24
41
 
42
+ const badgeType = computed(() => {
25
43
  if (props.item.status === "upcoming") {
26
44
  return "comingSoon";
27
45
  }
28
46
 
29
- return "";
47
+ if ($miniAppStore.hasRequiredPlan(props.item)) {
48
+ if (!$miniAppStore.isHasMiniAppFeature) {
49
+ return "noFeature";
50
+ }
51
+
52
+ return "available";
53
+ }
54
+
55
+ return "notAvailable";
30
56
  });
31
57
  </script>
@@ -18,17 +18,17 @@
18
18
  </div>
19
19
  </template>
20
20
  <script setup lang="ts">
21
- import UndrawNodata from '~/components/icon/UndrawNodata.vue';
22
- import { Miniapp } from '~/simpleapp/generate/openapi';
23
- import MiniAppIntegrationItem from './MiniAppIntegrationItem.vue';
21
+ import UndrawNodata from "~/components/icon/UndrawNodata.vue";
22
+ import { Miniapp } from "~/simpleapp/generate/openapi";
23
+ import MiniAppIntegrationItem from "./MiniAppIntegrationItem.vue";
24
24
 
25
25
  defineProps<{ items: Miniapp[] | undefined }>();
26
26
 
27
27
  const emits = defineEmits<{
28
- (event: 'miniAppClick', item: Miniapp): void;
28
+ (event: "miniAppClick", item: Miniapp): void;
29
29
  }>();
30
30
 
31
31
  function handleMiniAppClick(item: Miniapp) {
32
- emits('miniAppClick', item);
32
+ emits("miniAppClick", item);
33
33
  }
34
34
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <title>{{ miniApp?.name }} - {{ t('miniAppLang.miniApp') }}</title>
2
+ <title>{{ miniApp?.name }} - {{ t("miniAppLang.miniApp") }}</title>
3
3
  <LoadingLine :loading="isFetching" />
4
4
 
5
5
  <div
@@ -18,6 +18,28 @@
18
18
  </div>
19
19
  <span>|</span>
20
20
  <div>v {{ miniApp.version }}</div>
21
+
22
+ <div
23
+ v-if="!_.isEmpty(miniApp.requiredPlans)"
24
+ class="flex items-center gap-2"
25
+ >
26
+ <span>|</span>
27
+ <span
28
+ v-for="permission in miniApp.requiredPlans ?? []"
29
+ class="px-3 py-0.5 bg-slate-100 text-surface-500 font-semibold text-xs rounded uppercase"
30
+ >
31
+ {{ permission }}
32
+ </span>
33
+ </div>
34
+ <div v-else class="flex items-center gap-2">
35
+ <span>|</span>
36
+ <span
37
+ v-for="permission in ['lite', 'pro', 'enterprise']"
38
+ class="px-3 py-0.5 bg-slate-100 text-surface-500 font-semibold text-xs rounded uppercase"
39
+ >
40
+ {{ permission }}
41
+ </span>
42
+ </div>
21
43
  </div>
22
44
  <p class="text-gray-600">{{ miniApp.intro.description }}</p>
23
45
  </div>
@@ -31,13 +53,14 @@
31
53
  </template>
32
54
  <MiniAppPermissionWrapper
33
55
  v-else
34
- :actionAccess="$miniAppStore.getActionAccess('plan')"
56
+ :permission="$miniAppStore.checkHasFeature()"
35
57
  >
36
- <div class="flex space-x-2">
37
- <template v-if="$miniAppStore.checkIsMiniAppInstalled(miniApp.code)">
58
+ <div class="flex items-center space-x-2">
59
+ <template v-if="$miniAppStore.isMiniAppInstalled(miniApp.code)">
38
60
  <!-- Installed -->
39
61
  <MiniAppPermissionWrapper
40
- :actionAccess="$miniAppStore.getActionAccess('uninstall')"
62
+ :permission="$miniAppStore.checkCanUninstall(miniApp)"
63
+ class="!mt-0"
41
64
  >
42
65
  <ButtonDefault
43
66
  :label="t('miniAppLang.uninstallApp')"
@@ -52,7 +75,8 @@
52
75
  miniApp.integration.settings &&
53
76
  !_.isEmpty(miniApp.integration.settings)
54
77
  "
55
- :actionAccess="$miniAppStore.getActionAccess('updateSetting')"
78
+ :permission="$miniAppStore.checkCanUpdateSetting(miniApp)"
79
+ class="!mt-0"
56
80
  >
57
81
  <ButtonSecondary
58
82
  :label="t('miniAppLang.openSetting')"
@@ -65,7 +89,8 @@
65
89
  <template v-else>
66
90
  <!-- Not yet install -->
67
91
  <MiniAppPermissionWrapper
68
- :actionAccess="$miniAppStore.getActionAccess('install')"
92
+ :permission="$miniAppStore.checkCanInstall(miniApp)"
93
+ class="!mt-0"
69
94
  >
70
95
  <ButtonPrimary
71
96
  :label="t('miniAppLang.installApp')"
@@ -125,9 +150,9 @@
125
150
  </template>
126
151
 
127
152
  <script setup lang="ts">
128
- import _ from 'lodash';
129
- import { MiniAppDetail } from '~/simpleapp/generate/openapi';
130
- import MiniAppPermissionWrapper from '../MiniAppPermissionWrapper.vue';
153
+ import _ from "lodash";
154
+ import { MiniAppDetail } from "~/simpleapp/generate/openapi";
155
+ import MiniAppPermissionWrapper from "../MiniAppPermissionWrapper.vue";
131
156
 
132
157
  defineProps<{
133
158
  miniApp?: MiniAppDetail;
@@ -136,21 +161,21 @@ defineProps<{
136
161
  }>();
137
162
 
138
163
  const emits = defineEmits<{
139
- (e: 'installApp'): void;
140
- (e: 'uninstallApp'): void;
141
- (e: 'openSetting'): void;
142
- (e: 'upgradePlan'): void;
164
+ (e: "installApp"): void;
165
+ (e: "uninstallApp"): void;
166
+ (e: "openSetting"): void;
167
+ (e: "upgradePlan"): void;
143
168
  }>();
144
169
 
145
170
  function handleInstallApp() {
146
- emits('installApp');
171
+ emits("installApp");
147
172
  }
148
173
 
149
174
  function handleUninstallApp() {
150
- emits('uninstallApp');
175
+ emits("uninstallApp");
151
176
  }
152
177
 
153
178
  function handleOpenSetting() {
154
- emits('openSetting');
179
+ emits("openSetting");
155
180
  }
156
181
  </script>
@@ -23,3 +23,8 @@ export type CategorizedMiniApp = {
23
23
  upcomingMiniApps: MiniAppDetail[];
24
24
  availableMiniApps: MiniAppDetail[];
25
25
  };
26
+
27
+ export type MiniAppPermissionResult = {
28
+ status: boolean;
29
+ reason?: string;
30
+ };