openxiangda 1.0.131 → 1.0.133

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/lib/cli.js CHANGED
@@ -86,6 +86,7 @@ async function main(argv) {
86
86
  if (command === 'function') return appFunction(rest);
87
87
  if (command === 'connector') return connector(rest);
88
88
  if (command === 'notification') return notification(rest);
89
+ if (command === 'organization') return organization(rest);
89
90
  if (command === 'permission') return permission(rest);
90
91
  if (command === 'settings') return settings(rest);
91
92
  if (command === 'resource') return resource(rest);
@@ -150,6 +151,7 @@ Usage:
150
151
  openxiangda function list|get|create|update|upsert|delete|invoke [--json-file file]
151
152
  openxiangda connector list|get|create|update|upsert|delete|invoke|download-test [--json-file file]
152
153
  openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send
154
+ openxiangda organization capabilities|department-list|department-get|department-create|department-update|account-list|account-get|account-create|account-update|account-reset-password
153
155
  openxiangda permission role-list|role-create|role-update|role-delete|role-bind|snapshot|audit
154
156
  openxiangda permission page-group-list|page-group-create|page-group-update|page-group-delete|page-group-bind
155
157
  openxiangda permission form-group-list|form-group-create|form-group-update|form-group-delete|form-group-bind
@@ -1952,8 +1954,10 @@ async function menu(args) {
1952
1954
  const data = await requestWithAuth(
1953
1955
  config,
1954
1956
  target.profileName,
1955
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(menuId)}`,
1956
- { method: 'DELETE' }
1957
+ apiPathWithPostDeleteAction(
1958
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(menuId)}`
1959
+ ),
1960
+ { method: 'POST' }
1957
1961
  );
1958
1962
  if (target.bound.resources?.menus?.[menuKey]) {
1959
1963
  delete target.bound.resources.menus[menuKey];
@@ -1973,7 +1977,7 @@ async function menu(args) {
1973
1977
  const menuId = resolveMenuId(target.bound, menuCode, flags);
1974
1978
  const desired = normalizeMenuDirectBody(target.bound, { ...body, code: body.code || menuCode });
1975
1979
  const data = await runDirectRequest(config, target, flags, {
1976
- method: 'PUT',
1980
+ method: 'POST',
1977
1981
  path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(menuId)}`,
1978
1982
  body: desired,
1979
1983
  }, { returnData: true });
@@ -2180,8 +2184,10 @@ async function workflow(args) {
2180
2184
  const data = await requestWithAuth(
2181
2185
  config,
2182
2186
  target.profileName,
2183
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/workflows/${encodeURIComponent(workflowId)}`,
2184
- { method: 'DELETE' }
2187
+ apiPathWithPostDeleteAction(
2188
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/workflows/${encodeURIComponent(workflowId)}`
2189
+ ),
2190
+ { method: 'POST' }
2185
2191
  );
2186
2192
  if (target.bound.resources?.workflows?.[workflowKey]) {
2187
2193
  delete target.bound.resources.workflows[workflowKey];
@@ -2485,8 +2491,10 @@ async function automation(args) {
2485
2491
  const data = await requestWithAuth(
2486
2492
  config,
2487
2493
  target.profileName,
2488
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/automations/${encodeURIComponent(automationId)}`,
2489
- { method: 'DELETE' }
2494
+ apiPathWithPostDeleteAction(
2495
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/automations/${encodeURIComponent(automationId)}`
2496
+ ),
2497
+ { method: 'POST' }
2490
2498
  );
2491
2499
  if (target.bound.resources?.automations?.[automationKey]) {
2492
2500
  delete target.bound.resources.automations[automationKey];
@@ -2949,10 +2957,13 @@ async function notification(args) {
2949
2957
  const { flags, positional } = parseArgs(rest);
2950
2958
  if (wantsSubcommandHelp(subcommand, flags)) {
2951
2959
  print([
2952
- '用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send',
2960
+ '用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send|capabilities|dingding-preview|dingding-send',
2953
2961
  ' preview <notificationType|templateCode> [--form-code code|--form-uuid FORM_XXX] --body-json \'{"payload":{"title":"测试"}}\'',
2954
2962
  ' send <notificationType> --body-json \'{"recipientId":"USER_ID","payload":{"title":"测试"}}\' --force',
2955
2963
  ' batch-send <notificationType> --body-json \'{"recipients":[{"recipientId":"USER_ID","payload":{}}]}\' --force',
2964
+ ' capabilities --json',
2965
+ ' dingding-preview <notificationType> [--template-code code|--template-id id] --body-json \'{"payload":{"title":"测试"}}\'',
2966
+ ' dingding-send <notificationType> --body-json \'{"recipientId":"USER_ID","payload":{"title":"测试"}}\' --force',
2956
2967
  ].join('\n'));
2957
2968
  return;
2958
2969
  }
@@ -2981,7 +2992,7 @@ async function notification(args) {
2981
2992
  if (!code) fail('notification template-upsert 缺少 template code');
2982
2993
  const normalized = normalizeNotificationTemplateManifest(target.bound, { ...body, ...template, code });
2983
2994
  const data = await runDirectRequest(config, target, flags, {
2984
- method: 'PUT',
2995
+ method: 'POST',
2985
2996
  path: `${appPrefix}/templates/${encodeURIComponent(code)}`,
2986
2997
  body: normalized,
2987
2998
  }, { returnData: true });
@@ -2998,8 +3009,8 @@ async function notification(args) {
2998
3009
  const code = positional[0] || flags.code;
2999
3010
  if (!code || !flags.force) fail('用法: openxiangda notification template-delete <templateCode> --force');
3000
3011
  return runDirectRequest(config, target, flags, {
3001
- method: 'DELETE',
3002
- path: `${appPrefix}/templates/${encodeURIComponent(code)}`,
3012
+ method: 'POST',
3013
+ path: apiPathWithPostDeleteAction(`${appPrefix}/templates/${encodeURIComponent(code)}`),
3003
3014
  });
3004
3015
  }
3005
3016
  if (subcommand === 'type-list') {
@@ -3023,7 +3034,7 @@ async function notification(args) {
3023
3034
  if (!code) fail('notification type-upsert 缺少 notificationType');
3024
3035
  const normalized = normalizeNotificationTypeConfigManifest(target.bound, { ...body, ...configBody, notificationType: code });
3025
3036
  const data = await runDirectRequest(config, target, flags, {
3026
- method: 'PUT',
3037
+ method: 'POST',
3027
3038
  path: `${appPrefix}/type-configs/${encodeURIComponent(code)}`,
3028
3039
  body: normalized,
3029
3040
  }, { returnData: true });
@@ -3043,8 +3054,29 @@ async function notification(args) {
3043
3054
  const code = positional[0] || flags.code;
3044
3055
  if (!code || !flags.force) fail('用法: openxiangda notification type-delete <notificationType> --force');
3045
3056
  return runDirectRequest(config, target, flags, {
3046
- method: 'DELETE',
3047
- path: `${appPrefix}/type-configs/${encodeURIComponent(code)}`,
3057
+ method: 'POST',
3058
+ path: apiPathWithPostDeleteAction(`${appPrefix}/type-configs/${encodeURIComponent(code)}`),
3059
+ });
3060
+ }
3061
+ if (subcommand === 'capabilities') {
3062
+ return runDirectRequest(config, target, flags, {
3063
+ method: 'GET',
3064
+ path: `${appPrefix}/dingtalk/capabilities`,
3065
+ strictEnvelope: true,
3066
+ });
3067
+ }
3068
+ if (subcommand === 'dingding-preview' || subcommand === 'dingding-send') {
3069
+ if (subcommand === 'dingding-send' && !flags.force) {
3070
+ fail('openxiangda notification dingding-send 是发送动作,必须加 --force');
3071
+ }
3072
+ const code = positional[0] || flags.code;
3073
+ const rawBody = readDirectJsonBody(flags, `notification ${subcommand}`, { optional: true });
3074
+ const body = buildDingTalkNotificationActionBody(target, code, rawBody, flags);
3075
+ return runDirectRequest(config, target, flags, {
3076
+ method: 'POST',
3077
+ path: `${appPrefix}/dingtalk/${subcommand === 'dingding-send' ? 'send' : 'preview'}`,
3078
+ body,
3079
+ strictEnvelope: true,
3048
3080
  });
3049
3081
  }
3050
3082
  if (['preview', 'send', 'batch-send'].includes(subcommand)) {
@@ -3071,7 +3103,170 @@ async function notification(args) {
3071
3103
  });
3072
3104
  }
3073
3105
 
3074
- fail('用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send');
3106
+ fail('用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send|capabilities|dingding-preview|dingding-send');
3107
+ }
3108
+
3109
+ async function organization(args) {
3110
+ const { subcommand, rest } = parseSubcommandArgs(args);
3111
+ const { flags, positional } = parseArgs(rest);
3112
+ if (wantsSubcommandHelp(subcommand, flags)) {
3113
+ print([
3114
+ '用法: openxiangda organization capabilities|department-list|department-get|department-create|department-update|account-list|account-get|account-create|account-update|account-reset-password',
3115
+ ' capabilities --json',
3116
+ ' department-list --json',
3117
+ ' department-get <departmentId> --json',
3118
+ ' department-create --body-json \'{"name":"销售部"}\' --force',
3119
+ ' department-update <departmentId> --body-json \'{"name":"华东销售"}\' --force',
3120
+ ' account-list [--keyword text|--department-ids id1,id2] --json',
3121
+ ' account-get <userId> --json',
3122
+ ' account-create --body-json \'{"username":"u1","password":"P@ssw0rd","name":"张三"}\' --force',
3123
+ ' account-update <userId> --body-json \'{"name":"张三"}\' --force',
3124
+ ' account-reset-password <userId> --body-json \'{"newPassword":"P@ssw0rd"}\' --force',
3125
+ ].join('\n'));
3126
+ return;
3127
+ }
3128
+
3129
+ const config = loadConfig();
3130
+ const target = getWorkspaceTarget(config, flags.profile || config.currentProfile, flags);
3131
+ const appPrefix = `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/organization`;
3132
+
3133
+ if (subcommand === 'capabilities') {
3134
+ return runDirectRequest(config, target, flags, {
3135
+ method: 'GET',
3136
+ path: `${appPrefix}/capabilities`,
3137
+ strictEnvelope: true,
3138
+ });
3139
+ }
3140
+
3141
+ if (subcommand === 'department-list') {
3142
+ return runDirectRequest(config, target, flags, {
3143
+ method: 'GET',
3144
+ path: `${appPrefix}/departments`,
3145
+ strictEnvelope: true,
3146
+ });
3147
+ }
3148
+
3149
+ if (subcommand === 'department-get') {
3150
+ const departmentId = positional[0] || flags['department-id'] || flags.id;
3151
+ if (!departmentId) fail('用法: openxiangda organization department-get <departmentId>');
3152
+ return runDirectRequest(config, target, flags, {
3153
+ method: 'GET',
3154
+ path: `${appPrefix}/departments/${encodeURIComponent(departmentId)}`,
3155
+ strictEnvelope: true,
3156
+ });
3157
+ }
3158
+
3159
+ if (subcommand === 'department-create') {
3160
+ if (!flags.force) fail('openxiangda organization department-create 是写操作,必须加 --force');
3161
+ const body = readDirectJsonBody(flags, 'organization department-create');
3162
+ return runDirectRequest(config, target, flags, {
3163
+ method: 'POST',
3164
+ path: `${appPrefix}/departments`,
3165
+ body,
3166
+ strictEnvelope: true,
3167
+ });
3168
+ }
3169
+
3170
+ if (subcommand === 'department-update') {
3171
+ if (!flags.force) fail('openxiangda organization department-update 是写操作,必须加 --force');
3172
+ const departmentId = positional[0] || flags['department-id'] || flags.id;
3173
+ if (!departmentId) fail('用法: openxiangda organization department-update <departmentId> --body-json ... --force');
3174
+ const body = readDirectJsonBody(flags, 'organization department-update');
3175
+ return runDirectRequest(config, target, flags, {
3176
+ method: 'POST',
3177
+ path: `${appPrefix}/departments/${encodeURIComponent(departmentId)}`,
3178
+ body,
3179
+ strictEnvelope: true,
3180
+ });
3181
+ }
3182
+
3183
+ if (subcommand === 'account-list') {
3184
+ return runDirectRequest(config, target, flags, {
3185
+ method: 'GET',
3186
+ path: apiPathWithQuery(`${appPrefix}/accounts`, {
3187
+ ids: flags.ids,
3188
+ departmentIds: flags['department-ids'],
3189
+ keyword: flags.keyword,
3190
+ name: flags.name,
3191
+ username: flags.username,
3192
+ phone: flags.phone,
3193
+ email: flags.email,
3194
+ jobNumber: flags['job-number'],
3195
+ page: flags.page,
3196
+ pageSize: flags['page-size'] || flags.limit,
3197
+ }),
3198
+ strictEnvelope: true,
3199
+ });
3200
+ }
3201
+
3202
+ if (subcommand === 'account-get') {
3203
+ const userId = positional[0] || flags['user-id'] || flags.id;
3204
+ if (!userId) fail('用法: openxiangda organization account-get <userId>');
3205
+ return runDirectRequest(config, target, flags, {
3206
+ method: 'GET',
3207
+ path: `${appPrefix}/accounts/${encodeURIComponent(userId)}`,
3208
+ strictEnvelope: true,
3209
+ });
3210
+ }
3211
+
3212
+ if (subcommand === 'account-create') {
3213
+ if (!flags.force) fail('openxiangda organization account-create 是写操作,必须加 --force');
3214
+ const body = readDirectJsonBody(flags, 'organization account-create');
3215
+ return runDirectRequest(config, target, flags, {
3216
+ method: 'POST',
3217
+ path: `${appPrefix}/accounts`,
3218
+ body,
3219
+ strictEnvelope: true,
3220
+ });
3221
+ }
3222
+
3223
+ if (subcommand === 'account-update') {
3224
+ if (!flags.force) fail('openxiangda organization account-update 是写操作,必须加 --force');
3225
+ const userId = positional[0] || flags['user-id'] || flags.id;
3226
+ if (!userId) fail('用法: openxiangda organization account-update <userId> --body-json ... --force');
3227
+ const body = readDirectJsonBody(flags, 'organization account-update');
3228
+ if (Object.prototype.hasOwnProperty.call(body || {}, 'password')) {
3229
+ fail('account-update 不允许包含 password,请使用 account-reset-password');
3230
+ }
3231
+ return runDirectRequest(config, target, flags, {
3232
+ method: 'POST',
3233
+ path: `${appPrefix}/accounts/${encodeURIComponent(userId)}`,
3234
+ body,
3235
+ strictEnvelope: true,
3236
+ });
3237
+ }
3238
+
3239
+ if (subcommand === 'account-reset-password') {
3240
+ if (!flags.force) fail('openxiangda organization account-reset-password 是密码写操作,必须加 --force');
3241
+ const userId = positional[0] || flags['user-id'] || flags.id;
3242
+ if (!userId) fail('用法: openxiangda organization account-reset-password <userId> --body-json ... --force');
3243
+ const body = readDirectJsonBody(flags, 'organization account-reset-password');
3244
+ if (!body.newPassword) fail('account-reset-password body 缺少 newPassword');
3245
+ return runDirectRequest(config, target, flags, {
3246
+ method: 'POST',
3247
+ path: `${appPrefix}/accounts/${encodeURIComponent(userId)}/password/reset`,
3248
+ body,
3249
+ strictEnvelope: true,
3250
+ });
3251
+ }
3252
+
3253
+ fail('用法: openxiangda organization capabilities|department-list|department-get|department-create|department-update|account-list|account-get|account-create|account-update|account-reset-password');
3254
+ }
3255
+
3256
+ function buildDingTalkNotificationActionBody(target, code, rawBody = {}, flags = {}) {
3257
+ const body = { ...(rawBody || {}) };
3258
+ if (flags['template-code'] && !body.templateCode) body.templateCode = flags['template-code'];
3259
+ if (flags['template-id'] && !body.templateId) body.templateId = flags['template-id'];
3260
+ if (code && !body.notificationType && !body.templateCode && !body.templateId && !body.code) {
3261
+ body.notificationType = code;
3262
+ }
3263
+ const formUuid =
3264
+ body.formUuid ||
3265
+ flags['form-uuid'] ||
3266
+ resolveOptionalFormUuid(target.bound, body.formCode || flags['form-code']);
3267
+ if (formUuid) body.formUuid = formUuid;
3268
+ delete body.formCode;
3269
+ return body;
3075
3270
  }
3076
3271
 
3077
3272
  async function normalizeNotificationPreviewBody(config, target, code, rawBody = {}, flags = {}) {
@@ -3213,7 +3408,7 @@ async function permission(args) {
3213
3408
  const target = getWorkspaceTarget(config, profileName, flags);
3214
3409
  const roleId = resolveRoleId(target.bound, roleCode, flags);
3215
3410
  const data = await runDirectRequest(config, target, flags, {
3216
- method: 'PUT',
3411
+ method: 'POST',
3217
3412
  path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(roleId)}`,
3218
3413
  body: {
3219
3414
  code: body.code || roleCode,
@@ -3235,8 +3430,10 @@ async function permission(args) {
3235
3430
  const target = getWorkspaceTarget(config, profileName, flags);
3236
3431
  const roleId = resolveRoleId(target.bound, roleKey, flags);
3237
3432
  const data = await runDirectRequest(config, target, flags, {
3238
- method: 'DELETE',
3239
- path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(roleId)}`,
3433
+ method: 'POST',
3434
+ path: apiPathWithPostDeleteAction(
3435
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(roleId)}`
3436
+ ),
3240
3437
  }, { returnData: true });
3241
3438
  if (!flags['dry-run'] && target.bound.resources?.roles?.[roleKey]) {
3242
3439
  delete target.bound.resources.roles[roleKey];
@@ -3391,7 +3588,7 @@ async function permission(args) {
3391
3588
  const groupId = flags['group-id'] || target.bound.resources?.pagePermissionGroups?.[groupCode]?.groupId || groupCode;
3392
3589
  const normalized = normalizePagePermissionGroupDirectBody(target.bound, { ...body, code: body.code || groupCode });
3393
3590
  const data = await runDirectRequest(config, target, flags, {
3394
- method: 'PUT',
3591
+ method: 'POST',
3395
3592
  path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(groupId)}`,
3396
3593
  body: normalized,
3397
3594
  }, { returnData: true });
@@ -3408,8 +3605,10 @@ async function permission(args) {
3408
3605
  const target = getWorkspaceTarget(config, profileName, flags);
3409
3606
  const groupId = flags['group-id'] || target.bound.resources?.pagePermissionGroups?.[groupKey]?.groupId || groupKey;
3410
3607
  const data = await runDirectRequest(config, target, flags, {
3411
- method: 'DELETE',
3412
- path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(groupId)}`,
3608
+ method: 'POST',
3609
+ path: apiPathWithPostDeleteAction(
3610
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(groupId)}`
3611
+ ),
3413
3612
  }, { returnData: true });
3414
3613
  if (!flags['dry-run'] && target.bound.resources?.pagePermissionGroups?.[groupKey]) {
3415
3614
  delete target.bound.resources.pagePermissionGroups[groupKey];
@@ -3525,7 +3724,7 @@ async function permission(args) {
3525
3724
  const groupId = flags['group-id'] || target.bound.resources?.formPermissionGroups?.[groupCode]?.groupId || groupCode;
3526
3725
  const normalized = normalizeFormPermissionGroupManifest(target.bound, { ...body, code: body.code || groupCode, formUuid });
3527
3726
  const data = await runDirectRequest(config, target, flags, {
3528
- method: 'PUT',
3727
+ method: 'POST',
3529
3728
  path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(groupId)}`,
3530
3729
  body: normalized,
3531
3730
  }, { returnData: true });
@@ -3543,8 +3742,10 @@ async function permission(args) {
3543
3742
  if (!groupKey || !formUuid || !flags.force) fail('用法: openxiangda permission form-group-delete <groupCode|groupId> --form-code code|--form-uuid FORM --force');
3544
3743
  const groupId = flags['group-id'] || target.bound.resources?.formPermissionGroups?.[groupKey]?.groupId || groupKey;
3545
3744
  const data = await runDirectRequest(config, target, flags, {
3546
- method: 'DELETE',
3547
- path: `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(groupId)}`,
3745
+ method: 'POST',
3746
+ path: apiPathWithPostDeleteAction(
3747
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(groupId)}`
3748
+ ),
3548
3749
  }, { returnData: true });
3549
3750
  if (!flags['dry-run'] && target.bound.resources?.formPermissionGroups?.[groupKey]) {
3550
3751
  delete target.bound.resources.formPermissionGroups[groupKey];
@@ -3659,7 +3860,7 @@ async function settings(args) {
3659
3860
  target.profileName,
3660
3861
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/settings`,
3661
3862
  {
3662
- method: 'PUT',
3863
+ method: 'POST',
3663
3864
  body: {
3664
3865
  settings: readJsonArg(flags['settings-json'], 'settings-json'),
3665
3866
  },
@@ -3694,7 +3895,7 @@ async function settings(args) {
3694
3895
  target.profileName,
3695
3896
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/field-indexes`,
3696
3897
  {
3697
- method: 'PUT',
3898
+ method: 'POST',
3698
3899
  body: {
3699
3900
  indexes: readJsonArg(flags['indexes-json'], 'indexes-json'),
3700
3901
  },
@@ -3729,7 +3930,7 @@ async function settings(args) {
3729
3930
  target.profileName,
3730
3931
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/data-management`,
3731
3932
  {
3732
- method: 'PUT',
3933
+ method: 'POST',
3733
3934
  body: {
3734
3935
  config: readJsonArg(flags['config-json'], 'config-json'),
3735
3936
  },
@@ -3761,7 +3962,7 @@ async function settings(args) {
3761
3962
  target.profileName,
3762
3963
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/public-access`,
3763
3964
  {
3764
- method: 'PUT',
3965
+ method: 'POST',
3765
3966
  body: {
3766
3967
  isPublic: flags.public === undefined ? true : String(flags.public) !== 'false',
3767
3968
  description: flags.description || '',
@@ -3779,8 +3980,10 @@ async function settings(args) {
3779
3980
  const data = await requestWithAuth(
3780
3981
  config,
3781
3982
  target.profileName,
3782
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/public-access`,
3783
- { method: 'DELETE' }
3983
+ apiPathWithPostDeleteAction(
3984
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/public-access`
3985
+ ),
3986
+ { method: 'POST' }
3784
3987
  );
3785
3988
  if (flags.json) return writeJson(data);
3786
3989
  print(JSON.stringify(data, null, 2));
@@ -4556,6 +4759,7 @@ async function commands(args) {
4556
4759
  'function list|get|create|update|upsert|delete|invoke',
4557
4760
  'connector list|get|create|update|upsert|delete|invoke|download-test',
4558
4761
  'notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send',
4762
+ 'organization capabilities|department-list|department-get|department-create|department-update|account-list|account-get|account-create|account-update|account-reset-password',
4559
4763
  'permission role-list|role-create|role-update|role-delete|role-bind|role-users|role-add-users|snapshot|audit',
4560
4764
  'permission page-group-list|page-group-create|page-group-update|page-group-delete|page-group-bind',
4561
4765
  'permission form-group-list|form-group-create|form-group-update|form-group-delete|form-group-bind|form-summary|menu-permissions',
@@ -4773,8 +4977,8 @@ async function directResourceCrud(config, target, spec) {
4773
4977
  const code = positional[0] || flags.code;
4774
4978
  if (!code || !flags.force) fail(`用法: openxiangda ${spec.commandName} delete <code> --force`);
4775
4979
  const data = await runDirectRequest(config, target, flags, {
4776
- method: 'DELETE',
4777
- path: `${basePath}/${encodeURIComponent(code)}`,
4980
+ method: 'POST',
4981
+ path: apiPathWithPostDeleteAction(`${basePath}/${encodeURIComponent(code)}`),
4778
4982
  }, { returnData: true });
4779
4983
  if (!flags['dry-run']) removeDirectStateResource(target, spec.resourceType, code);
4780
4984
  return outputDirectResult(data, flags);
@@ -4797,7 +5001,7 @@ async function directResourceCrud(config, target, spec) {
4797
5001
  ? spec.normalizeBody(rawBody)
4798
5002
  : rawBody;
4799
5003
 
4800
- let method = subcommand === 'create' ? (spec.createMethod || 'POST') : (spec.updateMethod || 'PUT');
5004
+ let method = subcommand === 'create' ? (spec.createMethod || 'POST') : (spec.updateMethod || 'POST');
4801
5005
  let requestPath = subcommand === 'create'
4802
5006
  ? (spec.createPath || basePath)
4803
5007
  : (spec.updatePath || `${basePath}/${encodeURIComponent(code)}`);
@@ -4818,7 +5022,7 @@ async function directResourceCrud(config, target, spec) {
4818
5022
  body: spec.createBody ? spec.createBody(rawBody, normalizedBody) : normalizedBody,
4819
5023
  },
4820
5024
  update: {
4821
- method: spec.updateMethod || 'PUT',
5025
+ method: spec.updateMethod || 'POST',
4822
5026
  path: spec.updatePath || `${basePath}/${encodeURIComponent(code)}`,
4823
5027
  body: spec.updateBody ? spec.updateBody(rawBody, normalizedBody) : normalizedBody,
4824
5028
  },
@@ -4830,7 +5034,7 @@ async function directResourceCrud(config, target, spec) {
4830
5034
  `${basePath}/${encodeURIComponent(code)}`
4831
5035
  );
4832
5036
  action = existing ? 'update' : 'create';
4833
- method = existing ? (spec.updateMethod || 'PUT') : (spec.createMethod || 'POST');
5037
+ method = existing ? (spec.updateMethod || 'POST') : (spec.createMethod || 'POST');
4834
5038
  requestPath = existing
4835
5039
  ? (spec.updatePath || `${basePath}/${encodeURIComponent(code)}`)
4836
5040
  : (spec.createPath || basePath);
@@ -6368,6 +6572,13 @@ function validateNotificationChannels(label, channelsConfig, errors) {
6368
6572
  errors.push(`${label}: 不支持的通知渠道 ${channel}`);
6369
6573
  }
6370
6574
  validateNoSensitiveNotificationConfig(`${label}.channelsConfig.${channel}`, config, errors);
6575
+ if (channel === 'dingding') {
6576
+ validateDingTalkNotificationConfig(
6577
+ `${label}.channelsConfig.${channel}`,
6578
+ config,
6579
+ errors
6580
+ );
6581
+ }
6371
6582
  }
6372
6583
  }
6373
6584
 
@@ -6382,6 +6593,62 @@ function validateNoSensitiveNotificationConfig(label, value, errors) {
6382
6593
  }
6383
6594
  }
6384
6595
 
6596
+ function validateDingTalkNotificationConfig(label, value, errors) {
6597
+ const config = value?.config || {};
6598
+ if (!config || typeof config !== 'object' || Array.isArray(config)) return;
6599
+ if (
6600
+ config.deliveryMode !== undefined &&
6601
+ !['card_preferred', 'card_only', 'work_notice_only'].includes(
6602
+ String(config.deliveryMode)
6603
+ )
6604
+ ) {
6605
+ errors.push(`${label}.config.deliveryMode: 只能是 card_preferred、card_only 或 work_notice_only`);
6606
+ }
6607
+ const card = config.card || {};
6608
+ if (card && typeof card === 'object' && !Array.isArray(card)) {
6609
+ if (
6610
+ card.mode !== undefined &&
6611
+ !['standard', 'custom'].includes(String(card.mode))
6612
+ ) {
6613
+ errors.push(`${label}.config.card.mode: 只能是 standard 或 custom`);
6614
+ }
6615
+ if (
6616
+ card.mode === 'custom' &&
6617
+ card.paramMap !== undefined &&
6618
+ (!card.paramMap ||
6619
+ typeof card.paramMap !== 'object' ||
6620
+ Array.isArray(card.paramMap))
6621
+ ) {
6622
+ errors.push(`${label}.config.card.paramMap: custom 卡片 paramMap 必须是对象`);
6623
+ }
6624
+ if (
6625
+ card.fieldConfigs !== undefined &&
6626
+ !Array.isArray(card.fieldConfigs)
6627
+ ) {
6628
+ errors.push(`${label}.config.card.fieldConfigs: 必须是数组`);
6629
+ }
6630
+ }
6631
+ }
6632
+
6633
+ function resolveNotificationChannelEnvReferences(value) {
6634
+ if (!value || typeof value !== 'object') return value;
6635
+ if (Array.isArray(value)) {
6636
+ return value.map(item => resolveNotificationChannelEnvReferences(item));
6637
+ }
6638
+ const next = {};
6639
+ for (const [key, item] of Object.entries(value)) {
6640
+ if (
6641
+ ['cardTemplateId', 'dingTalkTemplateId'].includes(key) &&
6642
+ isEnvReference(item)
6643
+ ) {
6644
+ next[key] = resolveEnvReference(item, `DingTalk ${key}`);
6645
+ } else {
6646
+ next[key] = resolveNotificationChannelEnvReferences(item);
6647
+ }
6648
+ }
6649
+ return next;
6650
+ }
6651
+
6385
6652
  function resourceLabel(kind, item) {
6386
6653
  return `${kind}:${item.code || item.__source || item.__index || '?'}`;
6387
6654
  }
@@ -7178,7 +7445,7 @@ async function publishRoleResources(config, target, roles, result, options = {})
7178
7445
  config,
7179
7446
  target.profileName,
7180
7447
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(existing.id)}`,
7181
- { method: 'PUT', body }
7448
+ { method: 'POST', body }
7182
7449
  )
7183
7450
  : await requestWithAuth(
7184
7451
  config,
@@ -7236,7 +7503,7 @@ async function publishFormSettingsResources(config, target, settingsItems, resul
7236
7503
  config,
7237
7504
  target.profileName,
7238
7505
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/settings`,
7239
- { method: 'PUT', body: { settings: item.settings } }
7506
+ { method: 'POST', body: { settings: item.settings } }
7240
7507
  );
7241
7508
  }
7242
7509
  if (item.indexes !== undefined) {
@@ -7244,7 +7511,7 @@ async function publishFormSettingsResources(config, target, settingsItems, resul
7244
7511
  config,
7245
7512
  target.profileName,
7246
7513
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/field-indexes`,
7247
- { method: 'PUT', body: { indexes: item.indexes } }
7514
+ { method: 'POST', body: { indexes: item.indexes } }
7248
7515
  );
7249
7516
  }
7250
7517
  if (item.dataManagement !== undefined) {
@@ -7252,7 +7519,7 @@ async function publishFormSettingsResources(config, target, settingsItems, resul
7252
7519
  config,
7253
7520
  target.profileName,
7254
7521
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/data-management`,
7255
- { method: 'PUT', body: { config: item.dataManagement } }
7522
+ { method: 'POST', body: { config: item.dataManagement } }
7256
7523
  );
7257
7524
  }
7258
7525
  if (item.publicAccess !== undefined) {
@@ -7260,12 +7527,15 @@ async function publishFormSettingsResources(config, target, settingsItems, resul
7260
7527
  typeof item.publicAccess === 'object'
7261
7528
  ? item.publicAccess
7262
7529
  : { isPublic: Boolean(item.publicAccess) };
7530
+ const publicAccessPath = `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/public-access`;
7263
7531
  await requestWithAuth(
7264
7532
  config,
7265
7533
  target.profileName,
7266
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/public-access`,
7534
+ publicAccess.isPublic === false
7535
+ ? apiPathWithPostDeleteAction(publicAccessPath)
7536
+ : publicAccessPath,
7267
7537
  {
7268
- method: publicAccess.isPublic === false ? 'DELETE' : 'PUT',
7538
+ method: 'POST',
7269
7539
  body: {
7270
7540
  isPublic: publicAccess.isPublic !== false,
7271
7541
  description: publicAccess.description || '',
@@ -7309,7 +7579,7 @@ async function publishMenuResources(config, target, menus, result, options = {})
7309
7579
  config,
7310
7580
  target.profileName,
7311
7581
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(existing.id)}`,
7312
- { method: 'PUT', body }
7582
+ { method: 'POST', body }
7313
7583
  )
7314
7584
  : await requestWithAuth(
7315
7585
  config,
@@ -7401,7 +7671,7 @@ async function publishNotificationResources(config, target, notifications, resul
7401
7671
  config,
7402
7672
  target.profileName,
7403
7673
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/notifications/templates/${encodeURIComponent(template.code)}`,
7404
- { method: 'PUT', body }
7674
+ { method: 'POST', body }
7405
7675
  );
7406
7676
  if (data?.id) {
7407
7677
  saveNotificationTemplateResource(target, template.code, data.id, {
@@ -7428,7 +7698,7 @@ async function publishNotificationResources(config, target, notifications, resul
7428
7698
  config,
7429
7699
  target.profileName,
7430
7700
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/notifications/type-configs/${encodeURIComponent(configItem.notificationType)}`,
7431
- { method: 'PUT', body }
7701
+ { method: 'POST', body }
7432
7702
  );
7433
7703
  const stateCode = configItem.code || notificationTypeConfigDesiredKey(target.bound, configItem);
7434
7704
  if (data?.id) {
@@ -7494,7 +7764,7 @@ async function publishWorkflowResources(config, target, workflows, result, optio
7494
7764
  config,
7495
7765
  target.profileName,
7496
7766
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/workflows/${encodeURIComponent(existing.id)}`,
7497
- { method: 'PUT', body }
7767
+ { method: 'POST', body }
7498
7768
  )
7499
7769
  : await requestWithAuth(
7500
7770
  config,
@@ -7586,7 +7856,7 @@ async function publishAutomationResources(config, target, automations, result, o
7586
7856
  config,
7587
7857
  target.profileName,
7588
7858
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/automations/${encodeURIComponent(existing.id)}`,
7589
- { method: 'PUT', body }
7859
+ { method: 'POST', body }
7590
7860
  )
7591
7861
  : await requestWithAuth(
7592
7862
  config,
@@ -7649,7 +7919,7 @@ async function publishFunctionResources(config, target, functions, result, optio
7649
7919
  config,
7650
7920
  target.profileName,
7651
7921
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/functions/${encodeURIComponent(code)}`,
7652
- { method: 'PUT', body }
7922
+ { method: 'POST', body }
7653
7923
  )
7654
7924
  : await requestWithAuth(
7655
7925
  config,
@@ -7685,7 +7955,7 @@ async function publishAuthConfigResources(config, target, authConfigs, result, o
7685
7955
  config,
7686
7956
  target.profileName,
7687
7957
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/auth/configs/${encodeURIComponent(code)}`,
7688
- { method: 'PUT', body }
7958
+ { method: 'POST', body }
7689
7959
  )
7690
7960
  : await requestWithAuth(
7691
7961
  config,
@@ -7720,7 +7990,7 @@ async function publishDataViewResources(config, target, dataViews, result, optio
7720
7990
  config,
7721
7991
  target.profileName,
7722
7992
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/data-views/${encodeURIComponent(dataViewItem.code)}`,
7723
- { method: 'PUT', body }
7993
+ { method: 'POST', body }
7724
7994
  )
7725
7995
  : await requestWithAuth(
7726
7996
  config,
@@ -7766,7 +8036,7 @@ async function publishStorageConfigResources(config, target, storageConfigs, res
7766
8036
  config,
7767
8037
  target.profileName,
7768
8038
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`,
7769
- { method: 'PUT', body }
8039
+ { method: 'POST', body }
7770
8040
  )
7771
8041
  : await requestWithAuth(
7772
8042
  config,
@@ -7796,7 +8066,7 @@ async function publishDataViewPermissionGroups(config, target, dataViewCode, per
7796
8066
  target.profileName,
7797
8067
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/data-views/${encodeURIComponent(dataViewCode)}/permission-groups`,
7798
8068
  {
7799
- method: 'PUT',
8069
+ method: 'POST',
7800
8070
  body: {
7801
8071
  groups: permissionGroups,
7802
8072
  },
@@ -7818,7 +8088,7 @@ async function publishRouteResources(config, target, routes, result, options = {
7818
8088
  config,
7819
8089
  target.profileName,
7820
8090
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/routes/${encodeURIComponent(code)}`,
7821
- { method: 'PUT', body }
8091
+ { method: 'POST', body }
7822
8092
  )
7823
8093
  : await requestWithAuth(
7824
8094
  config,
@@ -7856,7 +8126,7 @@ async function publishPublicAccessPolicyResources(config, target, policies, resu
7856
8126
  config,
7857
8127
  target.profileName,
7858
8128
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/public-access/policies/${encodeURIComponent(code)}`,
7859
- { method: 'PUT', body }
8129
+ { method: 'POST', body }
7860
8130
  )
7861
8131
  : await requestWithAuth(
7862
8132
  config,
@@ -7997,7 +8267,7 @@ async function publishPagePermissionGroupResources(config, target, groups, resul
7997
8267
  config,
7998
8268
  target.profileName,
7999
8269
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(existing.id)}`,
8000
- { method: 'PUT', body }
8270
+ { method: 'POST', body }
8001
8271
  )
8002
8272
  : await requestWithAuth(
8003
8273
  config,
@@ -8056,7 +8326,7 @@ async function publishFormPermissionGroupResources(config, target, groups, resul
8056
8326
  config,
8057
8327
  target.profileName,
8058
8328
  `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(existing.id)}`,
8059
- { method: 'PUT', body }
8329
+ { method: 'POST', body }
8060
8330
  )
8061
8331
  : await requestWithAuth(
8062
8332
  config,
@@ -8146,8 +8416,10 @@ async function pruneRoles(config, target, desired, result) {
8146
8416
  await requestWithAuth(
8147
8417
  config,
8148
8418
  target.profileName,
8149
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(role.id)}`,
8150
- { method: 'DELETE' }
8419
+ apiPathWithPostDeleteAction(
8420
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/roles/${encodeURIComponent(role.id)}`
8421
+ ),
8422
+ { method: 'POST' }
8151
8423
  );
8152
8424
  });
8153
8425
  }
@@ -8166,8 +8438,10 @@ async function pruneConnectors(config, target, desired, result) {
8166
8438
  await requestWithAuth(
8167
8439
  config,
8168
8440
  target.profileName,
8169
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/connectors/${encodeURIComponent(code)}`,
8170
- { method: 'DELETE' }
8441
+ apiPathWithPostDeleteAction(
8442
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/connectors/${encodeURIComponent(code)}`
8443
+ ),
8444
+ { method: 'POST' }
8171
8445
  );
8172
8446
  });
8173
8447
  }
@@ -8187,8 +8461,10 @@ async function pruneMenus(config, target, desired, result) {
8187
8461
  await requestWithAuth(
8188
8462
  config,
8189
8463
  target.profileName,
8190
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(menu.id)}`,
8191
- { method: 'DELETE' }
8464
+ apiPathWithPostDeleteAction(
8465
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/menus/${encodeURIComponent(menu.id)}`
8466
+ ),
8467
+ { method: 'POST' }
8192
8468
  );
8193
8469
  });
8194
8470
  }
@@ -8218,8 +8494,10 @@ async function pruneWorkflows(config, target, desired, result) {
8218
8494
  await requestWithAuth(
8219
8495
  config,
8220
8496
  target.profileName,
8221
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/workflows/${encodeURIComponent(workflow.id)}`,
8222
- { method: 'DELETE' }
8497
+ apiPathWithPostDeleteAction(
8498
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/workflows/${encodeURIComponent(workflow.id)}`
8499
+ ),
8500
+ { method: 'POST' }
8223
8501
  );
8224
8502
  });
8225
8503
  }
@@ -8249,8 +8527,10 @@ async function pruneAutomations(config, target, desired, result) {
8249
8527
  await requestWithAuth(
8250
8528
  config,
8251
8529
  target.profileName,
8252
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/automations/${encodeURIComponent(automation.id)}`,
8253
- { method: 'DELETE' }
8530
+ apiPathWithPostDeleteAction(
8531
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/automations/${encodeURIComponent(automation.id)}`
8532
+ ),
8533
+ { method: 'POST' }
8254
8534
  );
8255
8535
  });
8256
8536
  }
@@ -8272,8 +8552,10 @@ async function pruneDataViews(config, target, desired, result) {
8272
8552
  await requestWithAuth(
8273
8553
  config,
8274
8554
  target.profileName,
8275
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/data-views/${encodeURIComponent(code)}`,
8276
- { method: 'DELETE' }
8555
+ apiPathWithPostDeleteAction(
8556
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/data-views/${encodeURIComponent(code)}`
8557
+ ),
8558
+ { method: 'POST' }
8277
8559
  );
8278
8560
  });
8279
8561
  }
@@ -8295,8 +8577,10 @@ async function pruneStorageConfigs(config, target, desired, result) {
8295
8577
  await requestWithAuth(
8296
8578
  config,
8297
8579
  target.profileName,
8298
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`,
8299
- { method: 'DELETE' }
8580
+ apiPathWithPostDeleteAction(
8581
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/storage-configs/${encodeURIComponent(code)}`
8582
+ ),
8583
+ { method: 'POST' }
8300
8584
  );
8301
8585
  });
8302
8586
  }
@@ -8318,8 +8602,10 @@ async function pruneFunctions(config, target, desired, result) {
8318
8602
  await requestWithAuth(
8319
8603
  config,
8320
8604
  target.profileName,
8321
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/functions/${encodeURIComponent(code)}`,
8322
- { method: 'DELETE' }
8605
+ apiPathWithPostDeleteAction(
8606
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/functions/${encodeURIComponent(code)}`
8607
+ ),
8608
+ { method: 'POST' }
8323
8609
  );
8324
8610
  });
8325
8611
  }
@@ -8341,8 +8627,10 @@ async function pruneAuthConfigs(config, target, desired, result) {
8341
8627
  await requestWithAuth(
8342
8628
  config,
8343
8629
  target.profileName,
8344
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/auth/configs/${encodeURIComponent(code)}`,
8345
- { method: 'DELETE' }
8630
+ apiPathWithPostDeleteAction(
8631
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/auth/configs/${encodeURIComponent(code)}`
8632
+ ),
8633
+ { method: 'POST' }
8346
8634
  );
8347
8635
  });
8348
8636
  }
@@ -8364,8 +8652,10 @@ async function pruneRoutes(config, target, desired, result) {
8364
8652
  await requestWithAuth(
8365
8653
  config,
8366
8654
  target.profileName,
8367
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/routes/${encodeURIComponent(code)}`,
8368
- { method: 'DELETE' }
8655
+ apiPathWithPostDeleteAction(
8656
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/routes/${encodeURIComponent(code)}`
8657
+ ),
8658
+ { method: 'POST' }
8369
8659
  );
8370
8660
  });
8371
8661
  }
@@ -8387,8 +8677,10 @@ async function prunePublicAccessPolicies(config, target, desired, result) {
8387
8677
  await requestWithAuth(
8388
8678
  config,
8389
8679
  target.profileName,
8390
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/public-access/policies/${encodeURIComponent(code)}`,
8391
- { method: 'DELETE' }
8680
+ apiPathWithPostDeleteAction(
8681
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/public-access/policies/${encodeURIComponent(code)}`
8682
+ ),
8683
+ { method: 'POST' }
8392
8684
  );
8393
8685
  });
8394
8686
  }
@@ -8410,8 +8702,10 @@ async function prunePagePermissionGroups(config, target, desired, result) {
8410
8702
  await requestWithAuth(
8411
8703
  config,
8412
8704
  target.profileName,
8413
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(group.id)}`,
8414
- { method: 'DELETE' }
8705
+ apiPathWithPostDeleteAction(
8706
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/page-permission-groups/${encodeURIComponent(group.id)}`
8707
+ ),
8708
+ { method: 'POST' }
8415
8709
  );
8416
8710
  });
8417
8711
  }
@@ -8441,8 +8735,10 @@ async function pruneFormPermissionGroups(config, target, desired, result) {
8441
8735
  await requestWithAuth(
8442
8736
  config,
8443
8737
  target.profileName,
8444
- `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(group.id)}`,
8445
- { method: 'DELETE' }
8738
+ apiPathWithPostDeleteAction(
8739
+ `/openxiangda-api/v1/apps/${encodeURIComponent(target.appType)}/forms/${encodeURIComponent(formUuid)}/permission-groups/${encodeURIComponent(group.id)}`
8740
+ ),
8741
+ { method: 'POST' }
8446
8742
  );
8447
8743
  });
8448
8744
  }
@@ -9146,7 +9442,9 @@ function normalizeNotificationTemplateManifest(bound, template) {
9146
9442
  name: template.name || template.code,
9147
9443
  content: template.content || '',
9148
9444
  description: template.description || '',
9149
- channelsConfig: template.channelsConfig,
9445
+ channelsConfig: resolveNotificationChannelEnvReferences(
9446
+ template.channelsConfig
9447
+ ),
9150
9448
  level,
9151
9449
  formUuid,
9152
9450
  priority: template.priority,
@@ -10529,6 +10827,16 @@ function findWorkspaceRoot(startPath) {
10529
10827
  return process.cwd();
10530
10828
  }
10531
10829
 
10830
+ function apiPathWithPostDeleteAction(apiPath) {
10831
+ const value = String(apiPath || '');
10832
+ const queryIndex = value.indexOf('?');
10833
+ const base = queryIndex >= 0 ? value.slice(0, queryIndex) : value;
10834
+ const suffix = queryIndex >= 0 ? value.slice(queryIndex) : '';
10835
+ if (!base || base === '/') return '/delete' + suffix;
10836
+ if (/(^|\/)delete(\/|$)/.test(base)) return value;
10837
+ return base.replace(/\/$/, '') + '/delete' + suffix;
10838
+ }
10839
+
10532
10840
  function apiPathWithQuery(apiPath, query) {
10533
10841
  const params = new URLSearchParams();
10534
10842
  for (const [key, value] of Object.entries(query || {})) {