apaas-oapi-client 0.1.40 → 1.0.0

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: apaas-shared
3
- description: "Use for aPaaS Node SDK shared setup and safety rules: client initialization, credentials, namespace, token cache, logger level, pagination defaults, retry expectations, write/delete confirmation, and error triage before using module-specific apaas skills."
3
+ description: "Use for aPaaS Node SDK shared setup and safety rules: client initialization, credentials, namespace, token cache, logger level, OpenAPI coverage, pagination defaults, retry expectations, write/delete confirmation, and error-code triage before using module-specific apaas skills."
4
4
  ---
5
5
 
6
6
  # aPaaS Shared
@@ -14,6 +14,8 @@ Use this skill before module-specific aPaaS SDK work.
14
14
  - Keep `clientId`, `clientSecret`, access tokens, and app secrets out of logs and final answers.
15
15
  - Prefer `client.setLoggerLevel(3)` for normal work, `4` for debugging, and `5` only when inspecting non-sensitive payloads.
16
16
  - Treat SDK responses with `code !== "0"` as failed even if the HTTP call succeeded.
17
+ - Read [references/openapi-coverage.md](references/openapi-coverage.md) when checking whether an API doc endpoint is already wrapped.
18
+ - Read [references/openapi-error-codes.md](references/openapi-error-codes.md) when triaging non-zero response codes.
17
19
 
18
20
  ```ts
19
21
  import { apaas } from "apaas-oapi-client";
@@ -39,8 +41,9 @@ client.setLoggerLevel(3);
39
41
  ## Module Routing
40
42
 
41
43
  - Object metadata and record CRUD: use `apaas-object`.
44
+ - OQL, cross-object search, constant objects, and datasets: use `apaas-object`.
42
45
  - Object and field schema changes: use `apaas-schema`.
43
- - Cloud functions and automation flows: use `apaas-function-flow`.
46
+ - Cloud functions, automation flows, workflow status, user tasks, and Lark integration tokens: use `apaas-function-flow`.
44
47
  - Builder page metadata and links: use `apaas-builder`.
45
48
  - Global options and variables: use `apaas-global`.
46
49
  - User/department ID exchange and attachments: use `apaas-exchange-attachment`.
@@ -1,4 +1,4 @@
1
1
  interface:
2
2
  display_name: "aPaaS Shared"
3
- short_description: "aPaaS SDK 认证、凭证、安全与通用调用规则指南"
4
- default_prompt: "Use $apaas-shared to initialize aPaaS SDK access safely."
3
+ short_description: "aPaaS SDK 认证、凭证、安全、OpenAPI 覆盖与错误码规则指南"
4
+ default_prompt: "Use $apaas-shared to initialize aPaaS SDK access and route OpenAPI/error-code work safely."
@@ -0,0 +1,33 @@
1
+ # OpenAPI Coverage
2
+
3
+ Source snapshot: API doc share for namespace `package_154107__c`, fetched on 2026-06-30. The left navigation contained 167 doc nodes and 72 unique current endpoints after normalizing namespace/object placeholders.
4
+
5
+ ## Current SDK Coverage
6
+
7
+ | Doc area | Endpoints | SDK entry |
8
+ | --- | --- | --- |
9
+ | Auth | `POST /auth/v1/appToken` | `client.init()` / token cache |
10
+ | Page | list/detail/link | `client.page.list`, `client.page.detail`, `client.page.url` |
11
+ | Object metadata | object list, object metadata, field metadata | `client.object.list*`, `client.object.metadata.*` |
12
+ | Object records | get/list/create/update/delete/batch | `client.object.search/create/update/delete.*` |
13
+ | Object other APIs | OQL, cross-object search | `client.object.oql`, `client.object.search.recordsAcrossObjects*` |
14
+ | Schema | batch create/update/delete objects | `client.schema.create/update/delete`, plus staged helpers |
15
+ | Constant objects | `_currency`, `_country`, `_timeZone` records and metadata | `client.constant.records`, `record`, `metadata.*` |
16
+ | Dataset | dataset list | `client.dataset.list`, `client.dataset.listWithIterator` |
17
+ | Attachments | files and images | `client.attachment.file.*`, `client.attachment.avatar.*` |
18
+ | Global config | global options and variables | `client.global.options.*`, `client.global.variables.*` |
19
+ | Workflow execution | async execution status, flow detail | `client.workflow.execution.status`, `client.workflow.definition.detail` |
20
+ | Workflow user tasks | task/instance list, detail, agree/reject/transfer/add assignee/cc/expedite/cancel/rollback/chat | `client.workflow.userTask.*` |
21
+ | Flow invocation | v1/v2 flow execute | `client.automation.v1.execute`, `client.automation.v2.execute` |
22
+ | Lark integration | default/custom app and tenant tokens | `client.integration.lark.*` |
23
+ | Feishu ID exchange | v2 user/department exchange | `client.user.*`, `client.department.*` |
24
+
25
+ ## Deprecated Docs
26
+
27
+ The doc tree also exposes `历史版本(不推荐)`. Do not add those endpoints as default SDK methods unless a user explicitly asks for legacy compatibility. Prefer current `/v1/data/...`, `/api/data/v1/...`, `/api/flow/v1/...`, and `/api/integration/v1/...` endpoints.
28
+
29
+ ## Validation Checklist
30
+
31
+ - Run `npm test -- --runInBand` after endpoint changes.
32
+ - Run `npm run build` so `dist/index.d.ts` exposes new methods.
33
+ - Run `npm pack --dry-run --json` and verify `skills/` plus `dist/` are included.
@@ -0,0 +1,55 @@
1
+ # OpenAPI Error Codes
2
+
3
+ All OpenAPI responses use `code`, `msg`, and often `data`. Treat `code !== "0"` as failed even when HTTP status is 200.
4
+
5
+ ```json
6
+ {
7
+ "code": "k_op_ec_10100",
8
+ "msg": "Request parameters are not valid: userId is empty"
9
+ }
10
+ ```
11
+
12
+ ## Families
13
+
14
+ The 2026-06-30 API doc bundle listed 531 error codes:
15
+
16
+ | Family | Prefix | Count | Typical area |
17
+ | --- | --- | ---: | --- |
18
+ | 通用 | `k_ec_` | 26 | generic parameter, permission, naming, unsupported |
19
+ | OpenAPI | `k_op_ec_` | 19 | auth, request parsing, rate limit, backend errors |
20
+ | 身份集成 | `k_ident_` | 38 | identity provider, user/account integration |
21
+ | 元数据 | `k_mt_ec_` | 329 | object/field/schema metadata, record constraints |
22
+ | 规则引擎 | `k_ru_ec_` | 24 | rule/formula/field picker validation |
23
+ | 流程 | `k_wf_ec_` | 70 | workflow definition, execution, user tasks |
24
+ | 权限 | `k_perm_ec_` | 10 | permission and security group errors |
25
+ | 图片/附件 | `k_img_ec_` | 15 | image/file upload, preview, storage |
26
+
27
+ ## High-Signal Codes
28
+
29
+ | Code | Meaning | First action |
30
+ | --- | --- | --- |
31
+ | `k_ec_000009` | 权限不足 | Verify app permission, namespace, and API credential scope. |
32
+ | `k_ec_000011` | 缺少必填参数 | Compare payload with SDK method params and doc body/query/path fields. |
33
+ | `k_ec_000012` | 必填参数为空 | Check empty strings, empty arrays, and missing nested fields. |
34
+ | `k_ec_000015` | 请求参数不合法 | Read `msg`; for schema writes also run `client.schema.validateResponse`. |
35
+ | `k_op_ec_10100` | 请求参数不合法 | Validate body shape and enum values. |
36
+ | `k_op_ec_10101` | 无法解析 body | Check JSON serialization and `Content-Type: application/json`. |
37
+ | `k_op_ec_10102` | URL 路径参数错误 | Check path params such as object, field, task, flow, or integration API names. |
38
+ | `k_op_ec_10201` | 鉴权失败 | Re-init client and verify `clientId/clientSecret`. |
39
+ | `k_op_ec_10203` | 无访问权限 | Check package role and API credential permission. |
40
+ | `k_op_ec_20003` | 请求被限流 | Reduce concurrency; prefer iterator helpers and ID cursor pagination. |
41
+ | `k_mt_ec_900064` | 字段被报表/页面/规则引用,无法删除 | Remove dependent page/rule/report references before schema delete. |
42
+ | `k_mt_ec_900075` | 一次最多创建或更新 1000 条记录 | Split record writes into chunks. |
43
+ | `k_wf_ec_2001002` | 缺少流程入参 | Re-read flow definition and required input params. |
44
+ | `k_wf_ec_2001005` | 流程实例 ID 不存在 | Verify `execution_id` or approval instance ID from list/status APIs. |
45
+ | `k_wf_ec_2001008` | 幂等键已使用 | Generate a new idempotency key before resubmit. |
46
+ | `k_perm_ec_000001` | 权限不足 | Do not retry blindly; fix permission first. |
47
+ | `k_img_ec_000004` | 附件超过 100M | Compress or split file before upload. |
48
+ | `k_img_ec_000011` | 文件 ID 错误 | Re-read upload response and avoid mixing image/file IDs. |
49
+
50
+ ## Triage Rules
51
+
52
+ - Do not rely on HTTP status alone.
53
+ - Log `code`, `msg`, and safe request identifiers; do not log secrets or access tokens.
54
+ - For batch APIs, inspect item-level status in `data.items` because the request can be partially successful.
55
+ - For schema writes, `code: "0"` with `data: null` is a silent failure and must be treated as failed.
@@ -83,9 +83,24 @@ Create/update schema payloads use snake_case keys:
83
83
  - Option source: `type.settings.option_source`
84
84
  - Global option API name: `type.settings.global_option_api_name`
85
85
 
86
+ OpenAPI write payloads require color short codes, while metadata returns color names. The SDK normalizes these metadata names before writing:
87
+
88
+ | Metadata color | OpenAPI write code |
89
+ |---|---|
90
+ | `blue` | `B` |
91
+ | `cyan` | `W` |
92
+ | `green` | `G` |
93
+ | `yellow` | `Y` |
94
+ | `orange` | `O` |
95
+ | `red` | `R` |
96
+ | `magenta` | `V` |
97
+ | `purple` | `P` |
98
+ | `blueMagenta` | `I` |
99
+ | `grey` | `N` |
100
+
86
101
  Do not copy metadata `optionList` back into `schema.update`; convert it to `options`.
87
102
 
88
- Use `getOptionColor(index)` from the SDK to assign colors in this stable 10-color cycle.
103
+ Use `getOptionColor(index)` from the SDK to assign metadata color names in this stable 10-color cycle. Use `getOptionColorCode(color)` only when constructing raw OpenAPI payloads outside the SDK normalizer.
89
104
 
90
105
  ## Batch update (`batch_update`) rules
91
106
 
@@ -100,3 +115,5 @@ Use `getOptionColor(index)` from the SDK to assign colors in this stable 10-colo
100
115
  ## Canonical machine-readable source
101
116
 
102
117
  Use `/Users/Ethan/apaas/apaas-sdk/node-client/src/field-schema-rules.ts` as the source of truth for code.
118
+
119
+ The SDK exports `SQL_TYPE_TO_SCHEMA_TYPE`, `COLUMN_NAME_SEMANTIC_RULES`, and `SQL_CONSTRAINT_TO_SETTINGS` for SQL/ER conversion workflows.
@@ -96,6 +96,25 @@ export const OPTION_COLOR_LIST = [
96
96
 
97
97
  export type OptionColor = typeof OPTION_COLOR_LIST[number];
98
98
 
99
+ export const OPTION_COLOR_CODE_BY_NAME: Record<OptionColor, string> = {
100
+ blue: 'B',
101
+ cyan: 'W',
102
+ green: 'G',
103
+ yellow: 'Y',
104
+ orange: 'O',
105
+ red: 'R',
106
+ magenta: 'V',
107
+ purple: 'P',
108
+ blueMagenta: 'I',
109
+ grey: 'N'
110
+ } as const;
111
+
112
+ export const OPTION_COLOR_NAME_BY_CODE = Object.fromEntries(
113
+ Object.entries(OPTION_COLOR_CODE_BY_NAME).map(([name, code]) => [code, name])
114
+ ) as Record<string, OptionColor>;
115
+
116
+ export type OptionColorCode = typeof OPTION_COLOR_CODE_BY_NAME[OptionColor];
117
+
99
118
  export function getOptionColor(index: number): OptionColor {
100
119
  if (!Number.isInteger(index) || index < 0) {
101
120
  throw new Error('Option color index must be a non-negative integer.');
@@ -104,6 +123,18 @@ export function getOptionColor(index: number): OptionColor {
104
123
  return OPTION_COLOR_LIST[index % OPTION_COLOR_LIST.length];
105
124
  }
106
125
 
126
+ export function getOptionColorCode(color: OptionColor): OptionColorCode {
127
+ return OPTION_COLOR_CODE_BY_NAME[color] as OptionColorCode;
128
+ }
129
+
130
+ export function normalizeOptionColorForSchema(color: unknown): unknown {
131
+ if (typeof color !== 'string') {
132
+ return color;
133
+ }
134
+
135
+ return OPTION_COLOR_CODE_BY_NAME[color as OptionColor] || color;
136
+ }
137
+
107
138
  export const OPTION_COLOR_RULES = {
108
139
  allowedColors: OPTION_COLOR_LIST,
109
140
  assignment: 'Use OPTION_COLOR_LIST in order and cycle from the beginning when options exceed 10.',
@@ -124,6 +155,8 @@ export const OPTION_COLOR_RULES = {
124
155
  typeName: 'enum',
125
156
  optionsPath: 'type.settings.options',
126
157
  colorPath: 'type.settings.options[].color',
158
+ colorInput: 'SDK accepts metadata color names and normalizes them to OpenAPI color codes before writing.',
159
+ colorCodeByName: OPTION_COLOR_CODE_BY_NAME,
127
160
  sourcePath: 'type.settings.option_source',
128
161
  globalOptionPath: 'type.settings.global_option_api_name'
129
162
  }
@@ -210,7 +243,7 @@ export const FIELD_SCHEMA_RULES: FieldCreateRule[] = [
210
243
  }
211
244
  ]
212
245
  },
213
- notes: `Do not send create type as \`option\`. Metadata returns optionList/optionSource/globalOptionAPIName; create/update expects options/option_source/global_option_api_name. Available option colors: ${OPTION_COLOR_LIST.join(', ')}.`
246
+ notes: `Do not send create type as \`option\`. Metadata returns optionList/optionSource/globalOptionAPIName; create/update expects options/option_source/global_option_api_name. The SDK accepts metadata color names and sends OpenAPI color codes (${Object.entries(OPTION_COLOR_CODE_BY_NAME).map(([name, code]) => `${name}=${code}`).join(', ')}).`
214
247
  },
215
248
  {
216
249
  metadataType: 'boolean',
@@ -359,6 +392,67 @@ export const SCHEMA_TYPE_MISMATCHES: Array<{
359
392
  schemaType: rule.schemaType
360
393
  }));
361
394
 
395
+ export interface SqlTypeMapping {
396
+ /** SQL type regex pattern, case-insensitive. */
397
+ sqlPattern: string;
398
+ /** Mapped aPaaS schema type. */
399
+ schemaType: SchemaFieldType;
400
+ /** Settings derivation rule. */
401
+ settingsMapping: string;
402
+ }
403
+
404
+ export const SQL_TYPE_TO_SCHEMA_TYPE: SqlTypeMapping[] = [
405
+ { sqlPattern: 'VARCHAR\\(\\d+\\)|CHAR\\(\\d+\\)', schemaType: 'text', settingsMapping: 'max_length from (n), multiline: false' },
406
+ { sqlPattern: 'TEXT|LONGTEXT|MEDIUMTEXT|TINYTEXT|CLOB', schemaType: 'text', settingsMapping: 'multiline: true, max_length: 100000' },
407
+ { sqlPattern: 'INT|INTEGER|BIGINT|SMALLINT|TINYINT(?!\\(1\\))|MEDIUMINT|SERIAL', schemaType: 'bigint', settingsMapping: 'required/unique from constraints' },
408
+ { sqlPattern: 'FLOAT|DOUBLE|REAL', schemaType: 'float', settingsMapping: 'decimal_places_number: 2' },
409
+ { sqlPattern: 'DECIMAL\\(\\d+,\\d+\\)|NUMERIC\\(\\d+,\\d+\\)', schemaType: 'decimal', settingsMapping: 'decimal_places from scale (s)' },
410
+ { sqlPattern: 'DATE', schemaType: 'date', settingsMapping: 'required from constraints' },
411
+ { sqlPattern: 'DATETIME|TIMESTAMP', schemaType: 'datetime', settingsMapping: 'required from constraints' },
412
+ { sqlPattern: 'BOOLEAN|BOOL|TINYINT\\(1\\)|BIT', schemaType: 'boolean', settingsMapping: 'default_value from DEFAULT' },
413
+ { sqlPattern: 'ENUM\\(.*\\)', schemaType: 'enum', settingsMapping: 'options from enum values, colors auto-assigned with getOptionColor(index)' },
414
+ { sqlPattern: 'BLOB|BINARY|VARBINARY|LONGBLOB|MEDIUMBLOB', schemaType: 'attachment', settingsMapping: 'any_type: true' },
415
+ { sqlPattern: 'JSON', schemaType: 'richText', settingsMapping: 'only when JSON stores rich text content' }
416
+ ];
417
+
418
+ export interface ColumnNameSemanticRule {
419
+ /** Column name regex pattern, case-insensitive. */
420
+ columnPattern: string;
421
+ /** Inferred aPaaS schema type. */
422
+ schemaType: SchemaFieldType;
423
+ /** Inference notes. */
424
+ notes: string;
425
+ }
426
+
427
+ export const COLUMN_NAME_SEMANTIC_RULES: ColumnNameSemanticRule[] = [
428
+ { columnPattern: '(^|_)(e?mail)(s?$|_)', schemaType: 'email', notes: 'Column name contains email/mail' },
429
+ { columnPattern: '(^|_)(phone|mobile|tel)(s?$|_)', schemaType: 'phone', notes: 'Column name contains phone/mobile/tel' },
430
+ { columnPattern: '(^|_)(avatar|logo|profile_image)(s?$|_)', schemaType: 'avatar', notes: 'Column name contains avatar/logo' },
431
+ { columnPattern: '(^|_)(region|province|city|district|address)(s?$|_)', schemaType: 'region', notes: 'Column name implies geographic data' }
432
+ ];
433
+
434
+ export interface SqlConstraintMapping {
435
+ /** SQL constraint. */
436
+ sqlConstraint: string;
437
+ /** Mapped aPaaS settings field. */
438
+ settingsField: string;
439
+ /** Mapped value. */
440
+ settingsValue: string;
441
+ /** Mapping notes. */
442
+ notes: string;
443
+ }
444
+
445
+ export const SQL_CONSTRAINT_TO_SETTINGS: SqlConstraintMapping[] = [
446
+ { sqlConstraint: 'NOT NULL', settingsField: 'required', settingsValue: 'true', notes: 'Maps to required: true' },
447
+ { sqlConstraint: 'UNIQUE', settingsField: 'unique', settingsValue: 'true', notes: 'Maps to unique: true' },
448
+ { sqlConstraint: 'PRIMARY KEY', settingsField: '-', settingsValue: '-', notes: 'Ignored: aPaaS uses system _id' },
449
+ { sqlConstraint: 'AUTO_INCREMENT', settingsField: '-', settingsValue: '-', notes: 'Ignored: aPaaS _id auto-increments. For business serial numbers, use auto_number' },
450
+ { sqlConstraint: 'FOREIGN KEY', settingsField: 'referenced_object_api_name', settingsValue: '(target table)', notes: 'Convert to lookup field' },
451
+ { sqlConstraint: 'DEFAULT', settingsField: 'default_value', settingsValue: '(value)', notes: 'Only boolean type supports default_value in aPaaS' },
452
+ { sqlConstraint: 'CHECK', settingsField: '-', settingsValue: '-', notes: 'Not supported in aPaaS, handle in application logic' },
453
+ { sqlConstraint: 'INDEX', settingsField: '-', settingsValue: '-', notes: 'Not applicable, aPaaS manages indexing automatically' }
454
+ ];
455
+
362
456
  export const BATCH_UPDATE_REQUIREMENTS = {
363
457
  add: 'Use operator=add with full field definition.',
364
458
  replace: 'Use operator=replace and include full `type` (name + settings). Label-only replace fails.',
@@ -92,8 +92,8 @@ export interface CreateObjectDefinition {
92
92
  label: MultilingualText;
93
93
  /** 对象设置(可选) */
94
94
  settings?: ObjectSettings;
95
- /** 字段列表(必填,至少包含一个自定义字段) */
96
- fields: CreateFieldDefinition[];
95
+ /** 字段列表(可选)。schema.create 会忽略 fields,安全做法是先建空壳,再用 schema.update 添加字段。 */
96
+ fields?: CreateFieldDefinition[];
97
97
  }
98
98
 
99
99
  /**