@cloudbase/lowcode-builder 0.1.9 → 0.1.10

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.
@@ -52,6 +52,7 @@ const templateDir = config_1.appTemplateDir + '/mp/';
52
52
  const em = chalk_1.default.blue.bold;
53
53
  const error = chalk_1.default.redBright;
54
54
  async function generateWxMp({ weapps, projDir, appId, domain, materials, plugins, isProduction, deployMode, extraData, isMixMode, options, buildTypeList, isBrowserMpBuilder = false, }) {
55
+ var _a;
55
56
  const operationLabel = em('Wexin MiniProgram Generated');
56
57
  console.time(operationLabel);
57
58
  console.log('Generating ' + em('Wexin MiniProgram') + ' to ' + projDir);
@@ -195,6 +196,7 @@ async function generateWxMp({ weapps, projDir, appId, domain, materials, plugins
195
196
  appID: appId,
196
197
  resourceAppid: !!options.isCrossAccount ? options.resourceAppId : '',
197
198
  isProd: deployMode === types_1.DEPLOY_MODE.UPLOAD,
199
+ clientID: (_a = mainAppData.extra) === null || _a === void 0 ? void 0 : _a.clientId,
198
200
  },
199
201
  'datasources/datasource-profiles.js.tpl': {
200
202
  datasourceProfiles: (0, util_3.JsonToStringWithVariableName)((0, lowcode_generator_1.getDatasourceProfiles)(weapps.reduce((datasources, app) => {
@@ -400,6 +402,7 @@ async function generateFramework(appData, outDir, ctx) {
400
402
  isBare: false,
401
403
  appConfig: (0, util_3.JsonToStringWithVariableName)({
402
404
  id: ctx.appId,
405
+ envId: appData.envId,
403
406
  staticResourceDomain: ctx.domain || '',
404
407
  envVersion: (ctx === null || ctx === void 0 ? void 0 : ctx.isProduction) ? 'production' : 'preview',
405
408
  pages: appData.pageInstanceList
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudbase/lowcode-builder",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "云开发 Tencent CloudBase Framework Low Code Plugin,将低码配置生成完整项目并一键部署云开发资源。",
5
5
  "author": "yhsunshining@gmail.com",
6
6
  "homepage": "https://github.com/TencentCloudBase/cloudbase-framework#readme",
@@ -28,7 +28,7 @@
28
28
  "clean": "rm -rf lib && rm -rf dist",
29
29
  "build": "tsc",
30
30
  "test": "jest",
31
- "test:build": "ts-node ./__test__/build.ts",
31
+ "test:build": "ts-node ./__tests__/build.ts",
32
32
  "dev:web": "rm -rf dist && node ./webpack/scripts/web.pre.js && cross-env NODE_ENV=development webpack-dev-server --config ./webpack/web.config.js",
33
33
  "build:web": "rm -rf dist && node ./webpack/scripts/web.pre.js && cross-env NODE_ENV=production webpack --config ./webpack/web.config.js && node ./webpack/scripts/web.post.js"
34
34
  },
@@ -36,7 +36,7 @@
36
36
  "url": "https://github.com/TencentCloudBase/cloudbase-framework/issues"
37
37
  },
38
38
  "dependencies": {
39
- "@cloudbase/cals": "^0.3.3",
39
+ "@cloudbase/cals": "^0.3.28",
40
40
  "@cloudbase/lowcode-generator": "0.6.17-mpbeta.1",
41
41
  "axios": "^0.21.0",
42
42
  "browserfs": "^1.4.3",
@@ -11,9 +11,9 @@ import state from '../lowcode/state'
11
11
  import common from './common'
12
12
  <%} else {%>
13
13
  const state = {}
14
- const computed = {}
15
- const common = {}
16
- <%}%>
14
+ const computed = {}
15
+ const common = {}
16
+ <%}%>
17
17
 
18
18
  const mainAppKey = '__weappsMainApp'
19
19
 
@@ -22,12 +22,11 @@ export { process }
22
22
 
23
23
  function createGlboalApi() {
24
24
  const mpApp = createMpApp({
25
- appConfig: <%= appConfig %>;
25
+ appConfig: <%= appConfig %>
26
26
  });
27
27
  const globalAPI = {
28
28
  id: '<%= appId %>',
29
29
  domain: '<%= domain %>',
30
- activePage: null,
31
30
  pages: {},
32
31
  session: {
33
32
  //configure: sdk.configure,
@@ -1,9 +1,11 @@
1
- import { setConfig } from './datasources/index'
1
+ import { setConfig, getAccessToken, initTcb } from './datasources/index'
2
2
  import lifeCycle from './lowcode/lifecycle'
3
3
  import { app } from './app/weapps-api'
4
4
  import WxReportV2 from './common/wx_yypt_report_v2'
5
5
  // 引入数据源管理器并进行初始化
6
6
  import { EXTRA_API, createStateDataSourceVar, generateParamsParser } from './datasources/index'
7
+ import { redirectToLogin, findLoginPage, getAuthConfig } from './common/util'
8
+
7
9
  const $app = app;
8
10
  <% if (yyptConfig.yyptAppKey) { %>
9
11
  const wxReport = new WxReportV2({
@@ -24,12 +26,67 @@ const wxReport = new WxReportV2({
24
26
  if (!cfg.options || !cfg.options.showLoading) return
25
27
  app.showLoading()
26
28
  },
29
+ beforeCallFunction: async (params) => {
30
+ try {
31
+ const loginPage = findLoginPage();
32
+
33
+ let skip = false;
34
+ switch (params?.data?.methodName) {
35
+ case 'callWedaApi': {
36
+ if (['GetMiniProgramUserTicket', 'DescribeRuntimeResourceStrategy'].includes(params?.data?.params.action)) {
37
+ skip = true;
38
+ }
39
+ break;
40
+ }
41
+ }
42
+
43
+ // 后续做过滤处理
44
+ if (!loginPage || (params?.data?.mode === 'c' && skip)) {
45
+ return params;
46
+ }
47
+ // await initTcb();
48
+ const { accessToken } = await getAccessToken();
49
+ if (accessToken) {
50
+ params.data.accessToken = accessToken;
51
+ }
52
+ } catch (e) {
53
+ if (app?.cloud?.currentUser?.userType === "externalUser" && e?.error === 'unauthenticated') {
54
+ app.showToast({
55
+ title: '登录态失效',
56
+ icon: 'error',
57
+ });
58
+ }
59
+ console.error('beforeCallFunction error', e);
60
+ }
61
+ return params;
62
+ },
27
63
  afterDSRequest: (cfg, error, result) => {
28
64
  if (!cfg.options) return
29
65
  if (cfg.options.showLoading) app.hideLoading()
30
66
  if (!cfg.options.showToast) return
31
67
  const isSuccess = !error && result && !result.code
32
68
  app.showToast({ icon: isSuccess ? 'success' : 'error' })
69
+ },
70
+ async afterCallFunction(params, error, res) {
71
+ if (params?.data?.params?.action != 'DescribeRuntimeResourceStrategy' && ['InnerError.AuthFailure', 'InvalidAccessToken'].includes(res?.result?.code)) {
72
+ const loginPage = findLoginPage();
73
+ if (loginPage) {
74
+ const authConfig = await getAuthConfig();
75
+ let isAnonymous = true;
76
+ try {
77
+ const { accessToken } = await getAccessToken();
78
+ isAnonymous = !accessToken;
79
+ } catch (e) { }
80
+ if (isAnonymous && authConfig.RejectStrategy == 'to_login') {
81
+ redirectToLogin();
82
+ } else if (authConfig.RejectStrategy == 'show_warning') {
83
+ app.showToast({
84
+ title: '接口无访问权限',
85
+ icon: 'error',
86
+ });
87
+ }
88
+ }
89
+ }
33
90
  }
34
91
  })
35
92
 
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
4
+ var b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
5
+ exports.weBtoa = function (string) {
6
+ string = String(string);
7
+ var bitmap,
8
+ a,
9
+ b,
10
+ c,
11
+ result = "",
12
+ i = 0,
13
+ rest = string.length % 3;
14
+ for (; i < string.length; ) {
15
+ if (
16
+ (a = string.charCodeAt(i++)) > 255 ||
17
+ (b = string.charCodeAt(i++)) > 255 ||
18
+ (c = string.charCodeAt(i++)) > 255
19
+ )
20
+ throw new TypeError(
21
+ "Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."
22
+ );
23
+ bitmap = (a << 16) | (b << 8) | c;
24
+ result +=
25
+ b64.charAt((bitmap >> 18) & 63) +
26
+ b64.charAt((bitmap >> 12) & 63) +
27
+ b64.charAt((bitmap >> 6) & 63) +
28
+ b64.charAt(bitmap & 63);
29
+ }
30
+ return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
31
+ };
32
+ exports.weAtob = function (string) {
33
+ string = String(string).replace(/[\t\n\f\r ]+/g, "");
34
+ if (!b64re.test(string))
35
+ throw new TypeError(
36
+ "Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded."
37
+ );
38
+ string += "==".slice(2 - (string.length & 3));
39
+ var bitmap,
40
+ result = "",
41
+ r1,
42
+ r2,
43
+ i = 0;
44
+ for (; i < string.length; ) {
45
+ bitmap =
46
+ (b64.indexOf(string.charAt(i++)) << 18) |
47
+ (b64.indexOf(string.charAt(i++)) << 12) |
48
+ ((r1 = b64.indexOf(string.charAt(i++))) << 6) |
49
+ (r2 = b64.indexOf(string.charAt(i++)));
50
+ result +=
51
+ r1 === 64
52
+ ? String.fromCharCode((bitmap >> 16) & 255)
53
+ : r2 === 64
54
+ ? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
55
+ : String.fromCharCode(
56
+ (bitmap >> 16) & 255,
57
+ (bitmap >> 8) & 255,
58
+ bitmap & 255
59
+ );
60
+ }
61
+ return result;
62
+ };
63
+ function b64DecodeUnicode(str) {
64
+ return decodeURIComponent(
65
+ exports.weAtob(str).replace(/(.)/g, function (p) {
66
+ var code = p.charCodeAt(0).toString(16).toUpperCase();
67
+ if (code.length < 2) {
68
+ code = "0" + code;
69
+ }
70
+ return "%" + code;
71
+ })
72
+ );
73
+ }
74
+ function base64_url_decode(str) {
75
+ var output = str.replace(/-/g, "+").replace(/_/g, "/");
76
+ switch (output.length % 4) {
77
+ case 0:
78
+ break;
79
+ case 2:
80
+ output += "==";
81
+ break;
82
+ case 3:
83
+ output += "=";
84
+ break;
85
+ default:
86
+ throw "Illegal base64url string!";
87
+ }
88
+ try {
89
+ return b64DecodeUnicode(output);
90
+ } catch (err) {
91
+ return exports.weAtob(output);
92
+ }
93
+ }
94
+ function weappJwtDecode(token, options) {
95
+ if (typeof token !== "string") {
96
+ throw "Invalid token specified";
97
+ }
98
+ options = options || {};
99
+ var pos = options.header === true ? 0 : 1;
100
+ try {
101
+ return JSON.parse(base64_url_decode(token.split(".")[pos]));
102
+ } catch (e) {
103
+ throw "Invalid token specified: " + e.message;
104
+ }
105
+ }
106
+ exports.default = weappJwtDecode;
@@ -233,32 +233,135 @@ export function setter(context, path, value = undefined) {
233
233
  return lodashSet(context, path, value);
234
234
  }
235
235
 
236
+ export function findLoginPage() {
237
+ const { app } = getApp();
238
+ const { pages = [] } = app.__internal__.getConfig();
239
+ return pages.find(item => item.type === 'login');
240
+ }
241
+
242
+ let _AUTH_CONFIG_CACHE = null;
243
+ export async function getAuthConfig() {
244
+ const { app } = getApp();
245
+ if (_AUTH_CONFIG_CACHE) {
246
+ return _AUTH_CONFIG_CACHE;
247
+ }
248
+ try {
249
+ const res = await app.cloud.callWedaApi({
250
+ action: "DescribeRuntimeResourceStrategy",
251
+ data: {
252
+ ResourceType: `<%= isAdminPortal? 'modelApp' : 'app'%>`,
253
+ ResourceId: app.id,
254
+ },
255
+ });
256
+ const settingData = {};
257
+ // 云api不支持map只能传字符串,需要转换
258
+ res.forEach((item) => {
259
+ settingData[item.Key] = ['AllowRegister', 'NeedLogin'].includes(item.Key) ? item.Value === '1' : item.Value;
260
+ });
261
+ _AUTH_CONFIG_CACHE = settingData;
262
+ return _AUTH_CONFIG_CACHE;
263
+ } catch (e) {
264
+ return {
265
+ NeedLogin: false,
266
+ RejectStrategy: "show_warning",
267
+ };
268
+ }
269
+ }
270
+
271
+ let _AUTH_CACHE_MAP = {}
272
+ async function getAccessPermission(app, appId, pageId) {
273
+ const cacheKey = `${appId}-${pageId}`
274
+ if (_AUTH_CACHE_MAP[cacheKey] !== undefined) {
275
+ return _AUTH_CACHE_MAP[cacheKey];
276
+ }
277
+
278
+ let isAccess = false;
279
+ try {
280
+ const res = await app.cloud.callWedaApi({
281
+ action: 'DescribeResourcesPermission',
282
+ data: {
283
+ ResourceType: `<%= isAdminPortal? 'modelApp' : 'app'%>`,
284
+ ResourceIdList: [cacheKey],
285
+ AppResourceId: appId,
286
+ },
287
+ });
288
+ if (Array.isArray(res) && res.length > 0) {
289
+ isAccess = !!res[0].IsAccess;
290
+ }
291
+ _AUTH_CACHE_MAP[cacheKey] = isAccess;
292
+ } catch (e) {
293
+ console.warn('getAccessPermission', e);
294
+ }
295
+ return isAccess
296
+ }
297
+
236
298
  /**
237
299
  * 检查页面权限
238
300
  **/
239
- export async function checkAuth(app, appId, pageId) {
240
- return true
301
+ export async function checkAuth(app, appId, $page) {
302
+ const loginPage = findLoginPage(app);
303
+ if (loginPage?.id === $page.id) {
304
+ return true
305
+ }
241
306
  app.showNavigationBarLoading();
242
- const checkAuthResult = await app.cloud.callWedaApi({
243
- action: 'DescribeResourcesPermission',
244
- data: {
245
- ResourceType: `<%= isAdminPortal? 'modelApp' : 'app'%>`,
246
- ResourceIdList: [`${appId}-${pageId}`],
247
- },
248
- });
249
- let isLogin = false;
250
- if (Array.isArray(checkAuthResult) && checkAuthResult.length > 0) {
251
- isLogin = checkAuthResult[0]?.IsAccess || false;
307
+ const requestList = [getAccessPermission(app, appId, $page.id)];
308
+ // 暂时先认为有登录页则自定义登录功能开启且生效
309
+ if (loginPage) {
310
+ requestList.push(getAuthConfig(app));
252
311
  }
312
+ const [isAccess, authConfig] = await Promise.all(requestList);
253
313
  app.hideNavigationBarLoading();
254
314
 
255
- if (!isLogin) {
315
+ const { accessToken } = await getAccessToken()
316
+ const isAnonymousUser = !accessToken
317
+
318
+ if (!isAccess) {
319
+ if (isAnonymousUser && loginPage && (authConfig.NeedLogin || authConfig.RejectStrategy == 'to_login')) {
320
+ redirectToLogin($page);
321
+ } else {
322
+ app.showToast({
323
+ title: '页面无访问权限',
324
+ icon: 'error',
325
+ });
326
+ }
327
+ } else if (loginPage && authConfig.NeedLogin) {
328
+ // 此分支逻辑本不应该前端判断是否登录,历史原因后端短期内搞不定,后续后端优化后删除
329
+ try {
330
+ if (isAnonymousUser) {
331
+ redirectToLogin($page);
332
+ }
333
+ } catch (e) {
334
+ redirectToLogin($page);
335
+ }
336
+ }
337
+ return isAccess;
338
+ }
339
+
340
+ export function redirectToLogin(currentPage) {
341
+ // 去登录则清空权限缓存。
342
+ _AUTH_CACHE_MAP = {};
343
+ const { app } = getApp();
344
+ const loginPage = findLoginPage(app);
345
+ if (!currentPage) {
346
+ currentPage = app.utils.getCurrentPage() || {};
347
+ }
348
+ if (loginPage?.id === currentPage.id) {
349
+ return true
350
+ }
351
+ if (loginPage) {
352
+ app.redirectTo({
353
+ pageId: loginPage.id,
354
+ params: {
355
+ sourcePageId: currentPage.id,
356
+ sourcePageParams: currentPage.params
357
+ }
358
+ })
359
+ } else {
256
360
  app.showToast({
257
- title: '页面无访问权限',
361
+ title: '用户未登录',
258
362
  icon: 'error',
259
363
  });
260
364
  }
261
- return isLogin;
262
365
  }
263
366
 
264
367
  // 日期转换
@@ -23,9 +23,9 @@ export function createPage(
23
23
  const evtHandlers = createEventHandlers(evtListeners, context);
24
24
 
25
25
  function extractLifecyles() {
26
- const result = { };
27
- Object.keys(lifecycle).map(name=>{
28
- result[name] = function() {
26
+ const result = {};
27
+ Object.keys(lifecycle).map(name => {
28
+ result[name] = function () {
29
29
  return lifecycle[name].apply(this.getWeAppInst(), arguments)
30
30
  }
31
31
  })
@@ -73,7 +73,7 @@ export function createPage(
73
73
  onLoad(options) {
74
74
  const $page = this.getWeAppInst()
75
75
  setConfig({ currentPageId: $page.uuid });
76
- app.activePage = $page;
76
+ app.__internal__.activePage = $page;
77
77
  this._pageActive = true;
78
78
 
79
79
  let query = decodePageQuery(options || {});
@@ -100,14 +100,14 @@ export function createPage(
100
100
  async onShow() {
101
101
  const $page = this.getWeAppInst()
102
102
  setConfig({ currentPageId: $page.uuid });
103
- app.activePage = $page;
103
+ app.__internal__.activePage = $page;
104
104
  this._pageActive = true;
105
105
 
106
106
  const hook = lifecycle.onShow || lifecycle.onPageShow;
107
107
  hook && hook.call($page);
108
108
 
109
109
  // 权限检查
110
- if (await checkAuth(app, app.id, app.activePage.id)) {
110
+ if (await checkAuth(app, app.id, $page)) {
111
111
  this.setData({
112
112
  weDaHasLogin: true,
113
113
  });
@@ -11,6 +11,8 @@ export default {
11
11
  appID: '<%= appID %>',
12
12
  /** 云开发环境ID */
13
13
  envID: '<%= envID %>',
14
+ /** 应用端ID */
15
+ tcbClientId: '<%= clientID %>',
14
16
  /** 云开发资源所属的微信app id */
15
17
  resourceAppid: '<%= resourceAppid %>',
16
18
  /** 数据源描述对象数组 */
@@ -1,4 +1,4 @@
1
- import { WEDA_CLOUD_SDK } from '@cloudbase/weda-client'
1
+ import { _WEDA_CLOUD_SDK as WEDA_CLOUD_SDK } from '@cloudbase/weda-client'
2
2
  const {
3
3
  setConfig,
4
4
  initTcb,
@@ -8,7 +8,8 @@ const {
8
8
  generateParamsParser,
9
9
  EXTRA_API,
10
10
  DS_API,
11
- DS_SDK
11
+ DS_SDK,
12
+ getAccessToken,
12
13
  } = WEDA_CLOUD_SDK
13
14
 
14
15
  export {
@@ -19,7 +20,9 @@ export {
19
20
  CLOUD_SDK,
20
21
  DS_API,
21
22
  DS_SDK,
22
- setConfig
23
+ setConfig,
24
+ getAccessToken,
25
+ initTcb,
23
26
  }
24
27
 
25
28
  import config from './config'
@@ -3,7 +3,7 @@
3
3
  "version": "1.0.8",
4
4
  "scripts": {},
5
5
  "dependencies": {
6
- "@cloudbase/weda-client": "stable",
6
+ "@cloudbase/weda-client": "0.1.13-alpha.1",
7
7
  "mobx": "^5.15.4",
8
8
  "lodash.get": "^4.4.2",
9
9
  "lodash.set": "^4.3.2",
@@ -5,11 +5,11 @@
5
5
  "build-web": "rm -rf ./preivew && webpack --config ./webpack/webpack.web.prod.js"
6
6
  },
7
7
  "dependencies": {
8
- "@cloudbase/js-sdk": "1.5.3-alpha.0",
8
+ "@cloudbase/js-sdk": "2.4.0-beta.0",
9
9
  "@tcwd/weapps-core": "2.2.6",
10
10
  "@tcwd/weapps-sdk": "1.2.9",
11
11
  "@zxing/library": "^0.18.6",
12
- "@cloudbase/weda-client": "0.1.11",
12
+ "@cloudbase/weda-client": "0.2.0",
13
13
  "fastclick": "^1.0.6",
14
14
  "lodash": "^4.17.19",
15
15
  "mobx": "^5.15.4",
@@ -7,7 +7,7 @@ import { formatDate } from '../utils/date';
7
7
  import { getter, setter, _isMobile } from '../utils';
8
8
  import actionMap from './material-actions';
9
9
  import { scanCodeApi } from '../utils/scan-code-action';
10
- import { createWebApp, ACTIONS_KEY, ROUTER_KEY } from '@cloudbase/weda-client';
10
+ import { createWebApp, _ACTIONS_KEY as ACTIONS_KEY, _ROUTER_KEY as ROUTER_KEY } from '@cloudbase/weda-client';
11
11
  import { createDataset, EXTRA_API } from '../datasources/index'
12
12
 
13
13
  const mainAppKey = '__weappsMainApp';
@@ -11,6 +11,8 @@ export default {
11
11
  appID: '<%= appID %>',
12
12
  /** 云开发环境ID */
13
13
  envID: '<%= envID %>',
14
+ /** 应用端ID */
15
+ tcbClientId: '<%= clientID %>',
14
16
  /** 数据源描述对象数组 */
15
17
  dataSourceProfiles: dataSourceProfiles,
16
18
  /**
@@ -1,4 +1,4 @@
1
- import { WEDA_CLOUD_SDK } from '@cloudbase/weda-client'
1
+ import { _WEDA_CLOUD_SDK as WEDA_CLOUD_SDK } from '@cloudbase/weda-client'
2
2
  import config from './config';
3
3
 
4
4
  const {
@@ -10,7 +10,8 @@ const {
10
10
  generateParamsParser,
11
11
  EXTRA_API,
12
12
  DS_API,
13
- DS_SDK
13
+ DS_SDK,
14
+ getAccessToken,
14
15
  } = WEDA_CLOUD_SDK
15
16
 
16
17
  export {
@@ -21,7 +22,9 @@ export {
21
22
  CLOUD_SDK,
22
23
  DS_API,
23
24
  DS_SDK,
24
- setConfig
25
+ setConfig,
26
+ initTcb,
27
+ getAccessToken,
25
28
  }
26
29
 
27
30
  setConfig(config);