@cloudbase/app 3.0.4 → 3.0.6

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 (47) hide show
  1. package/dist/cjs/index.js +13 -9
  2. package/dist/cjs/libs/adapter-node/constants.d.ts +33 -0
  3. package/dist/cjs/libs/adapter-node/constants.js +38 -0
  4. package/dist/cjs/libs/adapter-node/context.d.ts +13 -0
  5. package/dist/cjs/libs/adapter-node/context.js +162 -0
  6. package/dist/cjs/libs/adapter-node/index.d.ts +23 -0
  7. package/dist/cjs/libs/adapter-node/index.js +124 -0
  8. package/dist/cjs/libs/adapter-node/metadata.d.ts +14 -0
  9. package/dist/cjs/libs/adapter-node/metadata.js +130 -0
  10. package/dist/cjs/libs/adapter-node/request.d.ts +38 -0
  11. package/dist/cjs/libs/adapter-node/request.js +440 -0
  12. package/dist/cjs/libs/adapter-node/tool.d.ts +2 -0
  13. package/dist/cjs/libs/adapter-node/tool.js +227 -0
  14. package/dist/cjs/libs/adapter-node/types.d.ts +78 -0
  15. package/dist/cjs/libs/adapter-node/types.js +3 -0
  16. package/dist/cjs/libs/adapter-node/utils.d.ts +17 -0
  17. package/dist/cjs/libs/adapter-node/utils.js +221 -0
  18. package/dist/esm/index.js +13 -9
  19. package/dist/esm/libs/adapter-node/constants.d.ts +33 -0
  20. package/dist/esm/libs/adapter-node/constants.js +35 -0
  21. package/dist/esm/libs/adapter-node/context.d.ts +13 -0
  22. package/dist/esm/libs/adapter-node/context.js +156 -0
  23. package/dist/esm/libs/adapter-node/index.d.ts +23 -0
  24. package/dist/esm/libs/adapter-node/index.js +118 -0
  25. package/dist/esm/libs/adapter-node/metadata.d.ts +14 -0
  26. package/dist/esm/libs/adapter-node/metadata.js +123 -0
  27. package/dist/esm/libs/adapter-node/request.d.ts +38 -0
  28. package/dist/esm/libs/adapter-node/request.js +437 -0
  29. package/dist/esm/libs/adapter-node/tool.d.ts +2 -0
  30. package/dist/esm/libs/adapter-node/tool.js +223 -0
  31. package/dist/esm/libs/adapter-node/types.d.ts +78 -0
  32. package/dist/esm/libs/adapter-node/types.js +2 -0
  33. package/dist/esm/libs/adapter-node/utils.d.ts +17 -0
  34. package/dist/esm/libs/adapter-node/utils.js +205 -0
  35. package/dist/miniprogram/index.js +1 -1
  36. package/package.json +20 -4
  37. package/src/index.ts +14 -2
  38. package/src/libs/adapter-node/constants.ts +42 -0
  39. package/src/libs/adapter-node/context.ts +238 -0
  40. package/src/libs/adapter-node/index.ts +166 -0
  41. package/src/libs/adapter-node/metadata.ts +69 -0
  42. package/src/libs/adapter-node/request.ts +486 -0
  43. package/src/libs/adapter-node/tool.ts +223 -0
  44. package/src/libs/adapter-node/types.ts +116 -0
  45. package/src/libs/adapter-node/utils.ts +182 -0
  46. package/webpack/web.prod.js +14 -13
  47. package/webpack/webpack.miniprogram.js +10 -3
@@ -0,0 +1,116 @@
1
+ /** 自定义登录 Ticket 创建选项 */
2
+ export interface ICreateTicketOpts {
3
+ /** 刷新间隔(毫秒),默认 3600000(1小时) */
4
+ refresh?: number
5
+ /** 过期时间戳(毫秒),默认 7 天后 */
6
+ expire?: number
7
+ }
8
+
9
+ /** 用户信息查询结果 */
10
+ export interface IGetUserInfoResult {
11
+ openId: string
12
+ appId: string
13
+ uid: string
14
+ customUserId: string
15
+ isAnonymous: boolean
16
+ }
17
+
18
+ /** 云函数入口 context 参数结构 */
19
+ export interface IContextParam {
20
+ memory_limit_in_mb: number
21
+ time_limit_in_ms: number
22
+ request_id: string
23
+ /** 老架构环境变量字符串,分号分隔的 key=value */
24
+ environ?: string
25
+ /** 新架构环境变量 JSON 字符串 */
26
+ environment?: string
27
+ function_version: string
28
+ function_name: string
29
+ namespace: string
30
+ }
31
+
32
+ /** 用户信息查询请求参数 */
33
+ export interface IUserInfoQuery {
34
+ platform?: string
35
+ platformId?: string
36
+ uid?: string
37
+ }
38
+
39
+ /**
40
+ * 云函数运行时完整环境变量类型汇总
41
+ * 包含 SCF、TCB、微信相关的所有环境变量
42
+ */
43
+ export interface ICompleteCloudbaseContext {
44
+ /** SCF 日志配置 */
45
+ _SCF_TCB_LOG?: string
46
+ /** 登录类型 */
47
+ LOGINTYPE?: string
48
+ QQ_APPID?: string
49
+ QQ_OPENID?: string
50
+ /** SCF 命名空间 */
51
+ SCF_NAMESPACE: string
52
+ /** TCB 上下文配置 */
53
+ TCB_CONTEXT_CNFG?: string
54
+ /** TCB 上下文 key 列表,逗号分隔 */
55
+ TCB_CONTEXT_KEYS: string[]
56
+ TCB_CUSTOM_USER_ID?: string
57
+ /** 云开发环境 ID */
58
+ TCB_ENV: string
59
+ TCB_HTTP_CONTEXT?: string
60
+ TCB_ISANONYMOUS_USER?: string
61
+ TCB_ROUTE_KEY?: string
62
+ /** 请求序列 ID */
63
+ TCB_SEQID: string
64
+ TCB_SESSIONTOKEN?: string
65
+ /** 客户端来源 IP */
66
+ TCB_SOURCE_IP?: string
67
+ TCB_SOURCE?: string
68
+ TCB_TRACELOG?: string
69
+ /** 用户唯一标识 */
70
+ TCB_UUID?: string
71
+ /** 腾讯云运行环境标识 */
72
+ TENCENTCLOUD_RUNENV: string
73
+ TENCENTCLOUD_SECRETID: string
74
+ TENCENTCLOUD_SECRETKEY: string
75
+ TENCENTCLOUD_SESSIONTOKEN: string
76
+ /** 触发来源 */
77
+ TRIGGER_SRC: string
78
+ WX_API_TOKEN?: string
79
+ WX_APPID?: string
80
+ WX_CLIENTIP?: string
81
+ WX_CLIENTIPV6?: string
82
+ WX_CLOUDBASE_ACCESSTOKEN?: string
83
+ /** 微信上下文 key 列表,逗号分隔 */
84
+ WX_CONTEXT_KEYS: string[]
85
+ WX_OPENID?: string
86
+ WX_TRIGGER_API_TOKEN_V0?: string
87
+ WX_UNIONID?: string
88
+ }
89
+
90
+ /** getEndUserInfo 返回结果 */
91
+ export interface IGetEndUserInfoResult {
92
+ userInfo?: {
93
+ openId: string
94
+ appId: string
95
+ uid: string
96
+ customUserId: string
97
+ isAnonymous: boolean
98
+ }
99
+ requestId?: string
100
+ }
101
+
102
+ /** 自定义请求选项 */
103
+ export interface ICustomReqOpts {
104
+ /** 请求超时时间(毫秒) */
105
+ timeout?: number
106
+ }
107
+
108
+ /** 模板消息推送请求参数 */
109
+ export interface ITemplateNotifyReq {
110
+ /** 通知策略 ID */
111
+ notifyId: string
112
+ /** 通知模板变量键值对 */
113
+ data?: Record<string, unknown>
114
+ /** 点击消息打开的页面地址 */
115
+ url?: string
116
+ }
@@ -0,0 +1,182 @@
1
+ import { utils } from '@cloudbase/utilities'
2
+ import { ReadableStream } from 'web-streams-polyfill'
3
+ import { ERROR, checkCustomUserIdRegex } from './constants'
4
+ import { lookupAppId } from './metadata'
5
+
6
+ /** 从 @cloudbase/utilities 中提取的表单和查询字符串工具 */
7
+ export const { isFormData, toQueryString } = utils as {
8
+ isFormData: (obj: unknown) => boolean
9
+ toQueryString: (data: Record<string, any>) => string
10
+ }
11
+
12
+ /**
13
+ * 跨端安全获取环境变量
14
+ * Web 端、小游戏端等没有 process 全局对象,直接访问 process.env 会报错
15
+ */
16
+ export function getEnv(): Record<string, string | undefined>
17
+ export function getEnv(key: string): string | undefined
18
+ export function getEnv(key?: string): string | undefined | Record<string, string | undefined> {
19
+ if (typeof process === 'undefined' || !process.env) {
20
+ return key !== undefined ? undefined : {}
21
+ }
22
+ return key !== undefined ? process.env[key] : process.env
23
+ }
24
+
25
+ /** 判断当前是否在 SCF(云函数)运行环境中 */
26
+ export const checkIsInScf = () => getEnv('TENCENTCLOUD_RUNENV') === 'SCF'
27
+
28
+ export function checkIsInCBR() {
29
+ // CBR = CLOUDBASE_RUN
30
+ return !!getEnv('CBR_ENV_ID')
31
+ }
32
+
33
+ const kSumeruEnvSet = new Set(['formal', 'pre', 'test'])
34
+ export function checkIsInSumeru() {
35
+ // SUMERU_ENV=formal | test | pre
36
+ return kSumeruEnvSet.has(getEnv('SUMERU_ENV') || '')
37
+ }
38
+
39
+ export function isNonEmptyString(str: string) {
40
+ return typeof str === 'string' && str !== ''
41
+ }
42
+
43
+ export async function checkIsInTencentCloud(): Promise<boolean> {
44
+ if (getEnv('TENCENTCLOUD') === 'true') {
45
+ return true
46
+ }
47
+ return isNonEmptyString(await lookupAppId())
48
+ }
49
+
50
+ export const getCurrRunEnvTag = async (): Promise<string> => {
51
+ if (checkIsInScf()) {
52
+ return 'scf'
53
+ } if (checkIsInCBR()) {
54
+ return 'cbr'
55
+ } if (checkIsInSumeru()) {
56
+ return 'sumeru'
57
+ } if (await checkIsInTencentCloud()) {
58
+ return 'tencentcloud'
59
+ }
60
+ return 'unknown'
61
+ }
62
+
63
+ /**
64
+ * 校验自定义用户 ID 格式
65
+ * @throws 格式不合法时抛出 INVALID_PARAM 错误
66
+ */
67
+ export const validateUid = (uid: string): void => {
68
+ if (typeof uid !== 'string') {
69
+ throw { ...ERROR.INVALID_PARAM, message: 'uid must be a string' }
70
+ }
71
+ if (!checkCustomUserIdRegex.test(uid)) {
72
+ throw { ...ERROR.INVALID_PARAM, message: `Invalid uid: "${uid}"` }
73
+ }
74
+ }
75
+
76
+ /**
77
+ * 安全的 JSON 解析,解析失败时返回原始文本而非抛异常
78
+ * @param text - 待解析的字符串
79
+ * @returns 解析后的对象,空字符串返回 null,解析失败返回原始文本
80
+ */
81
+ export function safeParseJson(text: string): any {
82
+ if (!text || !text.trim()) {
83
+ return null
84
+ }
85
+ try {
86
+ return JSON.parse(text)
87
+ } catch (e) {
88
+ console.warn('catch an error', { e, text })
89
+ return text
90
+ }
91
+ }
92
+
93
+ /**
94
+ * 将对象的所有值转为字符串类型
95
+ * 用于将 headers 等对象统一为 Record<string, string>
96
+ */
97
+ export function obj2StrRecord(obj: object): Record<string, string> {
98
+ return Object.entries(obj).reduce<Record<string, string>>((acc, cur: [string, unknown]) => {
99
+ const [key, value] = cur
100
+ acc[key] = String(value)
101
+ return acc
102
+ }, {})
103
+ }
104
+
105
+ /**
106
+ * 将 HeadersInit 转为可索引的普通对象
107
+ * 兼容 Headers 实例和普通对象两种形式
108
+ */
109
+ export function headersInit2Indexable(h: HeadersInit) {
110
+ if (isHeaders(h)) {
111
+ const ret: Record<string, string> = {}
112
+ h.forEach((val, key) => {
113
+ ret[key] = val
114
+ })
115
+ return ret
116
+ }
117
+ return h
118
+
119
+ function isHeaders(h: HeadersInit): h is Headers {
120
+ try {
121
+ // Node 低版本可能没有全局 Headers
122
+ return h instanceof Headers
123
+ } catch (_) {
124
+ return false
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 手动解析查询字符串,避免 URLSearchParams 的兼容性问题
131
+ * 支持重复 key 自动转为数组
132
+ * @param search - 查询字符串,可带前导 ? 或 #
133
+ */
134
+ export function parseQueryString(search: string): Record<string, string | string[]> {
135
+ const params: any = {}
136
+ const cleanSearch = search.replace(/^[?#]/, '')
137
+
138
+ if (!cleanSearch) {
139
+ return params
140
+ }
141
+
142
+ const pairs = cleanSearch.split('&')
143
+
144
+ pairs.forEach((item) => {
145
+ let [key, value] = item.split('=')
146
+ key = decodeURIComponent(key)
147
+ value = decodeURIComponent(value || '')
148
+ if (key) {
149
+ if (params[key]) {
150
+ // 已存在同名 key,转为数组
151
+ if (Array.isArray(params[key])) {
152
+ params[key].push(value)
153
+ } else {
154
+ params[key] = [params[key], value]
155
+ }
156
+ } else {
157
+ params[key] = value
158
+ }
159
+ }
160
+ })
161
+ return params
162
+ }
163
+
164
+ /**
165
+ * 将 Node ReadableStream 转换为 Web ReadableStream (polyfill)
166
+ * 用于 fetch 流式响应在 Node 环境下的适配
167
+ */
168
+ export function createWebStreamFromNodeReadableStream(stream: NodeJS.ReadableStream): ReadableStream {
169
+ const asyncIterator = stream[Symbol.asyncIterator]()
170
+
171
+ return new ReadableStream({
172
+ async pull(controller) {
173
+ const next = await asyncIterator.next()
174
+
175
+ if (next.done) {
176
+ controller.close()
177
+ } else {
178
+ controller.enqueue(next.value)
179
+ }
180
+ },
181
+ })
182
+ }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-require-imports */
1
2
  const path = require('path')
2
3
  const webpack = require('webpack')
3
4
  const TerserPlugin = require('terser-webpack-plugin')
@@ -5,7 +6,7 @@ const TerserPlugin = require('terser-webpack-plugin')
5
6
  module.exports = function (options) {
6
7
  const { context, entry, output, mode, watch, externals, definePlugin = {}, optimization = {} } = options
7
8
  const isDevelopment = mode !== 'production'
8
- let plugins = [
9
+ const plugins = [
9
10
  new webpack.DefinePlugin(definePlugin),
10
11
  // new BundleAnalyzerPlugin()
11
12
  ].filter((item) => !!item)
@@ -82,19 +83,19 @@ module.exports = function (options) {
82
83
  ...optimization,
83
84
  ...(isDevelopment
84
85
  ? {
85
- minimize: false,
86
- removeAvailableModules: false,
87
- concatenateModules: true,
88
- }
86
+ minimize: false,
87
+ removeAvailableModules: false,
88
+ concatenateModules: true,
89
+ }
89
90
  : {
90
- minimizer: [
91
- new TerserPlugin({
92
- test: /\.js(\?.*)?$/i,
93
- cache: false,
94
- parallel: true,
95
- }),
96
- ],
97
- }),
91
+ minimizer: [
92
+ new TerserPlugin({
93
+ test: /\.js(\?.*)?$/i,
94
+ cache: false,
95
+ parallel: true,
96
+ }),
97
+ ],
98
+ }),
98
99
  },
99
100
  }
100
101
  }
@@ -1,4 +1,6 @@
1
+ /* eslint-disable @typescript-eslint/no-require-imports */
1
2
  const path = require('path')
3
+ const { ignoreNodeDepsPlugins } = require('../../../webpack.ignore-node-deps')
2
4
 
3
5
  const params = {
4
6
  context: path.resolve(__dirname, '../'),
@@ -8,17 +10,22 @@ const params = {
8
10
  output: {
9
11
  path: path.resolve(__dirname, '../dist/miniprogram'),
10
12
  filename: 'index.js',
11
- library: `tcboauth`,
13
+ library: 'tcboauth',
12
14
  libraryTarget: 'umd',
13
15
  umdNamedDefine: true,
14
16
  globalObject: 'typeof window !== "undefined"?window:this',
15
17
  },
16
18
  externals: {},
17
19
  definePlugin: {
18
- 'process.env.NODE_ENV': JSON.stringify('production'), // 注入环境变量,用于业务代码判断
20
+ 'process.env.NODE_ENV': JSON.stringify('production'),
19
21
  'process.env.IS_MP_BUILD': 'true',
22
+ 'process.env.IS_BROWSER_BUILD': 'true',
20
23
  'globalThis.IS_MP_BUILD': true,
21
24
  },
22
25
  }
23
26
 
24
- module.exports = require('./web.prod.js')(params)
27
+ const config = require('./web.prod.js')(params)
28
+
29
+ config.plugins.push(...ignoreNodeDepsPlugins)
30
+
31
+ module.exports = config