@uni2c/graphqlapi4mp 1.0.3 → 1.0.4

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 (2) hide show
  1. package/README.md +360 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,360 @@
1
+ # @uni2c/graphqlapi4mp
2
+
3
+ 一个轻量、零运行时依赖的 GraphQL SDL 解析与查询文本生成工具。它可以从 SDL 中提取 Query、Mutation、对象类型、标量和枚举,并根据配置生成 selection set 与完整的 GraphQL operation。
4
+
5
+ 适合需要在小程序、Node.js 或前端项目中根据既有 GraphQL Schema 动态构造查询,同时希望控制运行时代码体积的场景。
6
+
7
+ ## 特性
8
+
9
+ - 解析 GraphQL SDL 中的 `type`、`scalar` 和 `enum`
10
+ - 提取 `Query`、`Mutation` 根字段及参数类型
11
+ - 自动选择标量和枚举字段
12
+ - 按配置递归展开对象字段
13
+ - 生成 Query 或 Mutation 文本
14
+ - 同时支持 ESM 和 CommonJS
15
+ - 内置 TypeScript 类型声明
16
+ - 零运行时依赖
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ npm install @uni2c/graphqlapi4mp
22
+ ```
23
+
24
+ 也可以使用 pnpm 或 yarn:
25
+
26
+ ```bash
27
+ pnpm add @uni2c/graphqlapi4mp
28
+ # 或
29
+ yarn add @uni2c/graphqlapi4mp
30
+ ```
31
+
32
+ ## 模块导入
33
+
34
+ ESM / TypeScript:
35
+
36
+ ```ts
37
+ import {
38
+ buildGraphQLQuery,
39
+ buildSelectionFields,
40
+ parseSDL,
41
+ } from '@uni2c/graphqlapi4mp';
42
+ ```
43
+
44
+ CommonJS:
45
+
46
+ ```js
47
+ const {
48
+ buildGraphQLQuery,
49
+ buildSelectionFields,
50
+ parseSDL,
51
+ } = require('@uni2c/graphqlapi4mp');
52
+ ```
53
+
54
+ ## 完整示例
55
+
56
+ 假设有以下 SDL:
57
+
58
+ ```graphql
59
+ scalar DateTime
60
+
61
+ enum UserStatus {
62
+ ACTIVE
63
+ DISABLED
64
+ }
65
+
66
+ type Query {
67
+ user(id: ID!, includeDisabled: Boolean = false): User
68
+ }
69
+
70
+ type User {
71
+ id: ID!
72
+ name: String!
73
+ status: UserStatus!
74
+ createdAt: DateTime!
75
+ profile: Profile
76
+ }
77
+
78
+ type Profile {
79
+ bio: String
80
+ website: String
81
+ }
82
+ ```
83
+
84
+ 解析 SDL、选择返回字段并生成查询:
85
+
86
+ ```ts
87
+ import {
88
+ buildGraphQLQuery,
89
+ buildSelectionFields,
90
+ parseSDL,
91
+ type GraphQLOperation,
92
+ } from '@uni2c/graphqlapi4mp';
93
+
94
+ const sdl = `
95
+ scalar DateTime
96
+ enum UserStatus { ACTIVE DISABLED }
97
+
98
+ type Query {
99
+ user(id: ID!, includeDisabled: Boolean = false): User
100
+ }
101
+
102
+ type User {
103
+ id: ID!
104
+ name: String!
105
+ status: UserStatus!
106
+ createdAt: DateTime!
107
+ profile: Profile
108
+ }
109
+
110
+ type Profile {
111
+ bio: String
112
+ website: String
113
+ }
114
+ `;
115
+
116
+ const schema = parseSDL(sdl);
117
+ const sourceOperation = schema.query.user;
118
+
119
+ if (!sourceOperation) {
120
+ throw new Error('Query.user 不存在');
121
+ }
122
+
123
+ const operation: GraphQLOperation = {
124
+ ...sourceOperation,
125
+ fields: buildSelectionFields(schema, sourceOperation, {
126
+ profile: {
127
+ website: false,
128
+ },
129
+ }),
130
+ };
131
+
132
+ const query = buildGraphQLQuery(operation, 'query');
133
+ console.log(query);
134
+ ```
135
+
136
+ 输出:
137
+
138
+ ```graphql
139
+ query user($id: ID!, $includeDisabled: Boolean) {
140
+ user(
141
+ id: $id
142
+ includeDisabled: $includeDisabled
143
+ ) {
144
+ id
145
+ name
146
+ status
147
+ createdAt
148
+ profile {
149
+ bio
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ 请求时将变量单独传给 GraphQL 客户端:
156
+
157
+ ```ts
158
+ const variables = {
159
+ id: 'user-1',
160
+ includeDisabled: false,
161
+ };
162
+
163
+ await fetch('/graphql', {
164
+ method: 'POST',
165
+ headers: {
166
+ 'content-type': 'application/json',
167
+ },
168
+ body: JSON.stringify({ query, variables }),
169
+ });
170
+ ```
171
+
172
+ ## API
173
+
174
+ ### `parseSDL(sdl)`
175
+
176
+ 解析 SDL 字符串并返回 Schema 元数据。
177
+
178
+ ```ts
179
+ const schema = parseSDL(sdl);
180
+
181
+ schema.query; // Query 根字段
182
+ schema.mutation; // Mutation 根字段
183
+ schema.types; // 所有已解析的对象类型
184
+ schema.scalars; // 内置标量和自定义标量
185
+ schema.enums; // 枚举名称
186
+ ```
187
+
188
+ 返回类型:
189
+
190
+ ```ts
191
+ interface SchemaMeta {
192
+ query: Record<string, SchemaField>;
193
+ mutation: Record<string, SchemaField>;
194
+ types: Record<string, SchemaType>;
195
+ scalars: Set<string>;
196
+ enums: Set<string>;
197
+ }
198
+ ```
199
+
200
+ 字段的 `type` 会保留 GraphQL 类型修饰符,例如 `ID!`、`[User!]!`。
201
+
202
+ ### `buildSelectionFields(schema, operation, config?)`
203
+
204
+ 根据 operation 返回类型构造 selection set 字段树。
205
+
206
+ 规则:
207
+
208
+ - 标量和枚举字段默认包含
209
+ - 对象字段默认不展开
210
+ - 对象字段配置为 `true` 时展开,并包含其直接标量/枚举字段
211
+ - 对象字段配置为对象时,按该配置递归展开
212
+ - 任意字段配置为 `false` 时排除
213
+
214
+ ```ts
215
+ const fields = buildSelectionFields(schema, schema.query.user, {
216
+ name: false,
217
+ profile: {
218
+ bio: true,
219
+ website: false,
220
+ },
221
+ });
222
+ ```
223
+
224
+ 返回值类似:
225
+
226
+ ```ts
227
+ [
228
+ 'id',
229
+ 'status',
230
+ 'createdAt',
231
+ {
232
+ name: 'profile',
233
+ fields: ['bio'],
234
+ },
235
+ ]
236
+ ```
237
+
238
+ 注意:对标量字段设置 `true` 不会改变行为,因为标量字段本来就会默认包含。
239
+
240
+ ### `buildGraphQLQuery(operation, operationType?)`
241
+
242
+ 将 operation 转换为完整 GraphQL 文本。
243
+
244
+ ```ts
245
+ const query = buildGraphQLQuery(operation); // 默认为 query
246
+ const mutation = buildGraphQLQuery(operation, 'mutation');
247
+ ```
248
+
249
+ operation 的参数定义来自 SDL,生成器会同时生成变量声明和字段参数引用。它只生成查询文本,不负责提供实际变量值或发送网络请求。
250
+
251
+ ### `buildQuery(operation, operationType?)`
252
+
253
+ `buildGraphQLQuery` 的兼容别名。新代码建议使用 `buildGraphQLQuery`。
254
+
255
+ ### `unwrapType(type)`
256
+
257
+ 移除 GraphQL 列表和非空修饰符,返回基础类型名称。
258
+
259
+ ```ts
260
+ unwrapType('User'); // User
261
+ unwrapType('User!'); // User
262
+ unwrapType('[User!]!'); // User
263
+ ```
264
+
265
+ ## Mutation 示例
266
+
267
+ ```graphql
268
+ type Mutation {
269
+ updateUser(id: ID!, name: String!): User
270
+ }
271
+ ```
272
+
273
+ ```ts
274
+ const sourceOperation = schema.mutation.updateUser;
275
+ const mutation = buildGraphQLQuery(
276
+ {
277
+ ...sourceOperation,
278
+ fields: buildSelectionFields(schema, sourceOperation),
279
+ },
280
+ 'mutation',
281
+ );
282
+ ```
283
+
284
+ 输出:
285
+
286
+ ```graphql
287
+ mutation updateUser($id: ID!, $name: String!) {
288
+ updateUser(
289
+ id: $id
290
+ name: $name
291
+ ) {
292
+ id
293
+ name
294
+ status
295
+ createdAt
296
+ }
297
+ }
298
+ ```
299
+
300
+ ## 手动指定 selection set
301
+
302
+ 不使用 `buildSelectionFields` 时,也可以自行构造字段树:
303
+
304
+ ```ts
305
+ const query = buildGraphQLQuery({
306
+ name: 'user',
307
+ type: 'User',
308
+ args: { id: 'ID!' },
309
+ fields: [
310
+ 'id',
311
+ 'name',
312
+ {
313
+ name: 'profile',
314
+ fields: ['bio'],
315
+ },
316
+ ],
317
+ });
318
+ ```
319
+
320
+ ## 当前解析范围
321
+
322
+ 该库面向查询生成所需的轻量 SDL 元数据提取,并不是完整的 GraphQL 规范验证器。目前应注意:
323
+
324
+ - 根类型按常规名称 `Query` 和 `Mutation` 识别
325
+ - 解析对象 `type`、`scalar` 和 `enum`
326
+ - 支持字段参数、列表类型、非空类型、默认值与指令的跳过处理
327
+ - 不解析 `input`、`interface`、`union`、fragment 或 directive 定义为可查询对象
328
+ - 不验证字段值,也不执行 GraphQL operation
329
+
330
+ 需要完整 Schema 校验、执行或 introspection 时,应配合标准 GraphQL 实现使用。
331
+
332
+ ## 发布产物
333
+
334
+ 包通过条件导出自动选择模块格式:
335
+
336
+ - ESM:`dist/index.mjs`
337
+ - CommonJS:`dist/index.cjs`
338
+ - TypeScript 声明:`dist/index.d.ts`
339
+
340
+ 项目构建时会自动检查产物体积;超过预算或出现未登记文件时构建失败。
341
+
342
+ ## 开发
343
+
344
+ ```bash
345
+ npm install
346
+ npm run typecheck
347
+ npm test
348
+ ```
349
+
350
+ 其他命令:
351
+
352
+ ```bash
353
+ npm run build # 构建 CJS、ESM 和类型声明,并检查体积
354
+ npm run size # 检查 dist 文件及体积预算
355
+ npm run test:demo # 使用项目内大型 SDL 运行演示脚本
356
+ ```
357
+
358
+ ## License
359
+
360
+ ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uni2c/graphqlapi4mp",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Parse GraphQL SDL and build GraphQL operation documents.",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",