@nocobase/plugin-user-data-sync 1.4.0-alpha

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/LICENSE.txt +159 -0
  2. package/README.md +1 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/Options.d.ts +12 -0
  6. package/dist/client/UserDataSyncSource.d.ts +10 -0
  7. package/dist/client/index.d.ts +21 -0
  8. package/dist/client/index.js +10 -0
  9. package/dist/client/locale/index.d.ts +10 -0
  10. package/dist/client/schemas/user-data-sync-sources.d.ts +155 -0
  11. package/dist/client/sourceType.d.ts +24 -0
  12. package/dist/externalVersion.js +24 -0
  13. package/dist/index.d.ts +10 -0
  14. package/dist/index.js +60 -0
  15. package/dist/locale/en-US.json +21 -0
  16. package/dist/locale/zh-CN.json +24 -0
  17. package/dist/server/actions/user-data.d.ts +16 -0
  18. package/dist/server/actions/user-data.js +64 -0
  19. package/dist/server/collections/user-data-sync-records-resources.d.ts +10 -0
  20. package/dist/server/collections/user-data-sync-records-resources.js +54 -0
  21. package/dist/server/collections/user-data-sync-records.d.ts +10 -0
  22. package/dist/server/collections/user-data-sync-records.js +85 -0
  23. package/dist/server/collections/user-data-sync-sources.d.ts +10 -0
  24. package/dist/server/collections/user-data-sync-sources.js +109 -0
  25. package/dist/server/collections/user-data-sync-tasks.d.ts +10 -0
  26. package/dist/server/collections/user-data-sync-tasks.js +131 -0
  27. package/dist/server/error.d.ts +21 -0
  28. package/dist/server/error.js +58 -0
  29. package/dist/server/index.d.ts +12 -0
  30. package/dist/server/index.js +56 -0
  31. package/dist/server/models/sync-source.d.ts +15 -0
  32. package/dist/server/models/sync-source.js +38 -0
  33. package/dist/server/plugin.d.ts +27 -0
  34. package/dist/server/plugin.js +100 -0
  35. package/dist/server/sync-source-manager.d.ts +28 -0
  36. package/dist/server/sync-source-manager.js +71 -0
  37. package/dist/server/sync-source.d.ts +42 -0
  38. package/dist/server/sync-source.js +107 -0
  39. package/dist/server/user-data-resource-manager.d.ts +108 -0
  40. package/dist/server/user-data-resource-manager.js +214 -0
  41. package/dist/server/user-data-sync-service.d.ts +23 -0
  42. package/dist/server/user-data-sync-service.js +130 -0
  43. package/dist/swagger/index.d.ts +116 -0
  44. package/dist/swagger/index.js +138 -0
  45. package/package.json +18 -0
  46. package/server.d.ts +2 -0
  47. package/server.js +1 -0
@@ -0,0 +1,214 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var user_data_resource_manager_exports = {};
28
+ __export(user_data_resource_manager_exports, {
29
+ UserDataResource: () => UserDataResource,
30
+ UserDataResourceManager: () => UserDataResourceManager
31
+ });
32
+ module.exports = __toCommonJS(user_data_resource_manager_exports);
33
+ var import_utils = require("@nocobase/utils");
34
+ class UserDataResource {
35
+ name;
36
+ accepts;
37
+ db;
38
+ logger;
39
+ constructor(db, logger) {
40
+ this.db = db;
41
+ this.logger = logger;
42
+ }
43
+ get syncRecordRepo() {
44
+ return this.db.getRepository("userDataSyncRecords");
45
+ }
46
+ get syncRecordResourceRepo() {
47
+ return this.db.getRepository("userDataSyncRecordsResources");
48
+ }
49
+ }
50
+ class UserDataResourceManager {
51
+ resources = new import_utils.Toposort();
52
+ syncRecordRepo;
53
+ syncRecordResourceRepo;
54
+ logger;
55
+ registerResource(resource, options) {
56
+ if (!resource.name) {
57
+ throw new Error('"name" for user data synchronize resource is required');
58
+ }
59
+ if (!resource.accepts) {
60
+ throw new Error('"accepts" for user data synchronize resource is required');
61
+ }
62
+ this.resources.add(resource, { tag: resource.name, ...options });
63
+ }
64
+ set db(value) {
65
+ this.syncRecordRepo = value.getRepository("userDataSyncRecords");
66
+ this.syncRecordResourceRepo = value.getRepository("userDataSyncRecordsResources");
67
+ }
68
+ async saveOriginRecords(data) {
69
+ for (const record of data.records) {
70
+ if (record.uid === void 0) {
71
+ throw new Error(`record must has uid, error record: ${JSON.stringify(record)}`);
72
+ }
73
+ const syncRecord = await this.syncRecordRepo.findOne({
74
+ where: {
75
+ sourceName: data.sourceName,
76
+ sourceUk: record.uid,
77
+ dataType: data.dataType
78
+ }
79
+ });
80
+ if (syncRecord) {
81
+ syncRecord.lastMetaData = syncRecord.metaData;
82
+ syncRecord.metaData = record;
83
+ await syncRecord.save();
84
+ } else {
85
+ await this.syncRecordRepo.create({
86
+ values: {
87
+ sourceName: data.sourceName,
88
+ sourceUk: record.uid,
89
+ dataType: data.dataType,
90
+ metaData: record
91
+ }
92
+ });
93
+ }
94
+ }
95
+ }
96
+ async findOriginRecords({ sourceName, dataType, sourceUks }) {
97
+ return await this.syncRecordRepo.find({
98
+ appends: ["resources"],
99
+ filter: { sourceName, dataType, sourceUk: { $in: sourceUks } }
100
+ });
101
+ }
102
+ async addResourceToOriginRecord({ recordId, resource, resourcePk }) {
103
+ const syncRecord = await this.syncRecordRepo.findOne({
104
+ filter: {
105
+ id: recordId
106
+ }
107
+ });
108
+ if (syncRecord) {
109
+ await syncRecord.createResource({
110
+ resource,
111
+ resourcePk
112
+ });
113
+ }
114
+ }
115
+ async removeResourceFromOriginRecord({ recordId, resource, resourcePk }) {
116
+ const recordResource = await this.syncRecordResourceRepo.findOne({
117
+ where: {
118
+ recordId,
119
+ resource,
120
+ resourcePk
121
+ }
122
+ });
123
+ if (recordResource) {
124
+ await recordResource.destroy();
125
+ }
126
+ }
127
+ async updateOrCreate(data) {
128
+ var _a, _b, _c, _d, _e;
129
+ await this.saveOriginRecords(data);
130
+ const { dataType, sourceName, records, matchKey } = data;
131
+ const sourceUks = records.map((record) => record.uid);
132
+ let processed = false;
133
+ const syncResults = [];
134
+ for (const resource of this.resources.nodes) {
135
+ if (!resource.accepts.includes(dataType)) {
136
+ continue;
137
+ }
138
+ const associateResource = resource.name;
139
+ processed = true;
140
+ const originRecords = await this.findOriginRecords({ sourceName, sourceUks, dataType });
141
+ if (!(originRecords && originRecords.length)) {
142
+ continue;
143
+ }
144
+ const successRecords = [];
145
+ const failedRecords = [];
146
+ for (const originRecord of originRecords) {
147
+ const resourceRecords = (_a = originRecord.resources) == null ? void 0 : _a.filter(
148
+ (r) => r.resource === associateResource
149
+ );
150
+ let recordResourceChangeds;
151
+ if (resourceRecords && resourceRecords.length > 0) {
152
+ const resourcePks = resourceRecords.map((r) => r.resourcePk);
153
+ try {
154
+ recordResourceChangeds = await resource.update(originRecord, resourcePks, matchKey);
155
+ (_b = this.logger) == null ? void 0 : _b.debug(`update record success. Data changed: ${JSON.stringify(recordResourceChangeds)}`);
156
+ successRecords.push(originRecord.metaData);
157
+ } catch (error) {
158
+ (_c = this.logger) == null ? void 0 : _c.warn(`update record error: ${error.message}`, { originRecord });
159
+ failedRecords.push({ record: originRecord.metaData, message: error.message });
160
+ continue;
161
+ }
162
+ } else {
163
+ try {
164
+ recordResourceChangeds = await resource.create(originRecord, matchKey);
165
+ (_d = this.logger) == null ? void 0 : _d.debug(`create record success. Data changed: ${JSON.stringify(recordResourceChangeds)}`);
166
+ successRecords.push(originRecord.metaData);
167
+ } catch (error) {
168
+ (_e = this.logger) == null ? void 0 : _e.warn(`create record error: ${error.message}`, { originRecord });
169
+ failedRecords.push({ record: originRecord.metaData, message: error.message });
170
+ continue;
171
+ }
172
+ }
173
+ if (!recordResourceChangeds || recordResourceChangeds.length === 0) {
174
+ continue;
175
+ }
176
+ for (const { resourcesPk, isDeleted } of recordResourceChangeds) {
177
+ if (isDeleted) {
178
+ await this.removeResourceFromOriginRecord({
179
+ recordId: originRecord.id,
180
+ resource: associateResource,
181
+ resourcePk: resourcesPk
182
+ });
183
+ } else {
184
+ await this.addResourceToOriginRecord({
185
+ recordId: originRecord.id,
186
+ resource: associateResource,
187
+ resourcePk: resourcesPk
188
+ });
189
+ }
190
+ }
191
+ }
192
+ syncResults.push({
193
+ resource: associateResource,
194
+ detail: {
195
+ count: {
196
+ all: originRecords.length,
197
+ success: successRecords.length,
198
+ failed: failedRecords.length
199
+ },
200
+ failedRecords
201
+ }
202
+ });
203
+ }
204
+ if (!processed) {
205
+ throw new Error(`dataType "${dataType}" is not support`);
206
+ }
207
+ return syncResults;
208
+ }
209
+ }
210
+ // Annotate the CommonJS export names for ESM import in node:
211
+ 0 && (module.exports = {
212
+ UserDataResource,
213
+ UserDataResourceManager
214
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import { SyncResult, UserDataResourceManager } from './user-data-resource-manager';
10
+ import { SyncSourceManager } from './sync-source-manager';
11
+ import { Context } from '@nocobase/actions';
12
+ import { SyncSource } from './sync-source';
13
+ import { Logger } from '@nocobase/logger';
14
+ export declare class UserDataSyncService {
15
+ resourceManager: UserDataResourceManager;
16
+ sourceManager: SyncSourceManager;
17
+ logger: Logger;
18
+ constructor(resourceManager: UserDataResourceManager, sourceManager: SyncSourceManager, logger: Logger);
19
+ pull(sourceName: string, ctx: Context): Promise<void>;
20
+ push(data: any): Promise<SyncResult[]>;
21
+ retry(sourceId: number, taskId: number, ctx: Context): Promise<void>;
22
+ runSync(source: SyncSource, task: any, ctx: Context): Promise<void>;
23
+ }
@@ -0,0 +1,130 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var user_data_sync_service_exports = {};
28
+ __export(user_data_sync_service_exports, {
29
+ UserDataSyncService: () => UserDataSyncService
30
+ });
31
+ module.exports = __toCommonJS(user_data_sync_service_exports);
32
+ var import_error = require("./error");
33
+ class UserDataSyncService {
34
+ resourceManager;
35
+ sourceManager;
36
+ logger;
37
+ constructor(resourceManager, sourceManager, logger) {
38
+ this.resourceManager = resourceManager;
39
+ this.sourceManager = sourceManager;
40
+ this.logger = logger;
41
+ }
42
+ async pull(sourceName, ctx) {
43
+ const source = await this.sourceManager.getByName(sourceName, ctx);
44
+ const task = await source.newTask();
45
+ await source.beginTask(task.id);
46
+ ctx.log.info("begin sync task of source", { source: sourceName, sourceType: source.instance.sourceType });
47
+ this.runSync(source, task, ctx);
48
+ }
49
+ async push(data) {
50
+ const { dataType, records } = data;
51
+ if (dataType === void 0) {
52
+ throw new Error("dataType for user data synchronize is required");
53
+ }
54
+ if (dataType !== "user" && dataType !== "department") {
55
+ throw new Error("dataType must be user or department");
56
+ }
57
+ if (records === void 0) {
58
+ throw new Error("records for user data synchronize is required");
59
+ }
60
+ if (records.length === 0) {
61
+ throw new Error("records must have at least one piece of data");
62
+ }
63
+ const userData = {
64
+ dataType: data.dataType,
65
+ matchKey: data.matchKey,
66
+ records: data.records,
67
+ sourceName: data.sourceName ? data.sourceName : "api"
68
+ };
69
+ this.logger.info({
70
+ source: data.sourceName ? data.sourceName : "api",
71
+ sourceType: "api",
72
+ data
73
+ });
74
+ return await this.resourceManager.updateOrCreate(userData);
75
+ }
76
+ async retry(sourceId, taskId, ctx) {
77
+ const source = await this.sourceManager.getById(sourceId, ctx);
78
+ const task = await source.retryTask(taskId);
79
+ ctx.log.info("retry sync task of source", {
80
+ source: source.instance.name,
81
+ sourceType: source.instance.name,
82
+ task: task.id
83
+ });
84
+ this.runSync(source, task, ctx);
85
+ }
86
+ async runSync(source, task, ctx) {
87
+ const currentTimeMillis = (/* @__PURE__ */ new Date()).getTime();
88
+ try {
89
+ ctx.log.info("begin pull data of source", {
90
+ source: source.instance.name,
91
+ sourceType: source.instance.sourceType
92
+ });
93
+ const data = await source.pull();
94
+ this.logger.info({
95
+ source: source.instance.name,
96
+ sourceType: source.instance.sourceType,
97
+ batch: task.batch,
98
+ data
99
+ });
100
+ ctx.log.info("end pull data of source", { source: source.instance.name, sourceType: source.instance.sourceType });
101
+ ctx.log.info("begin update data of source", {
102
+ source: source.instance.name,
103
+ sourceType: source.instance.sourceType
104
+ });
105
+ for (const item of data) {
106
+ await this.resourceManager.updateOrCreate(item);
107
+ }
108
+ ctx.log.info("end update data of source", {
109
+ source: source.instance.name,
110
+ sourceType: source.instance.sourceType
111
+ });
112
+ const costTime = (/* @__PURE__ */ new Date()).getTime() - currentTimeMillis;
113
+ await source.endTask({ taskId: task.id, success: true, cost: costTime });
114
+ } catch (err) {
115
+ ctx.log.error(
116
+ `sync task of source: ${source.instance.name} sourceType: ${source.instance.sourceType} error: ${err.message}`,
117
+ { method: "runSync", err: err.stack, cause: err.cause }
118
+ );
119
+ let message = err.message;
120
+ if (err instanceof import_error.ExternalAPIError) {
121
+ message = "The sync source API call failed. Please check the logs to troubleshoot the issue.";
122
+ }
123
+ await source.endTask({ taskId: task.id, success: false, message });
124
+ }
125
+ }
126
+ }
127
+ // Annotate the CommonJS export names for ESM import in node:
128
+ 0 && (module.exports = {
129
+ UserDataSyncService
130
+ });
@@ -0,0 +1,116 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ declare const _default: {
10
+ info: {
11
+ title: string;
12
+ };
13
+ paths: {
14
+ '/userData:push': {
15
+ post: {
16
+ description: string;
17
+ tags: string[];
18
+ security: any[];
19
+ requestBody: {
20
+ content: {
21
+ 'application/json': {
22
+ schema: {
23
+ type: string;
24
+ items: {
25
+ $ref: string;
26
+ };
27
+ };
28
+ };
29
+ };
30
+ };
31
+ responses: {
32
+ 200: {
33
+ description: string;
34
+ };
35
+ };
36
+ };
37
+ };
38
+ };
39
+ components: {
40
+ schemas: {
41
+ userData: {
42
+ type: string;
43
+ description: string;
44
+ properties: {
45
+ dataType: {
46
+ type: string;
47
+ description: string;
48
+ };
49
+ uniqueKey: {
50
+ type: string;
51
+ description: string;
52
+ };
53
+ records: {
54
+ type: string;
55
+ description: string;
56
+ items: {
57
+ type: string;
58
+ };
59
+ };
60
+ sourceName: {
61
+ type: string;
62
+ description: string;
63
+ };
64
+ };
65
+ };
66
+ user: {
67
+ type: string;
68
+ description: string;
69
+ properties: {
70
+ id: {
71
+ type: string;
72
+ description: string;
73
+ };
74
+ nickname: {
75
+ type: string;
76
+ description: string;
77
+ };
78
+ email: {
79
+ type: string;
80
+ description: string;
81
+ };
82
+ phone: {
83
+ type: string;
84
+ description: string;
85
+ };
86
+ departments: {
87
+ type: string;
88
+ description: string;
89
+ items: {
90
+ type: string;
91
+ };
92
+ };
93
+ };
94
+ };
95
+ department: {
96
+ type: string;
97
+ description: string;
98
+ properties: {
99
+ id: {
100
+ type: string;
101
+ description: string;
102
+ };
103
+ name: {
104
+ type: string;
105
+ description: string;
106
+ };
107
+ parentId: {
108
+ type: string;
109
+ description: string;
110
+ };
111
+ };
112
+ };
113
+ };
114
+ };
115
+ };
116
+ export default _default;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name in all)
16
+ __defProp(target, name, { get: all[name], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+ var swagger_exports = {};
28
+ __export(swagger_exports, {
29
+ default: () => swagger_default
30
+ });
31
+ module.exports = __toCommonJS(swagger_exports);
32
+ var swagger_default = {
33
+ info: {
34
+ title: "NocoBase API - User data synchronization plugin"
35
+ },
36
+ paths: {
37
+ "/userData:push": {
38
+ post: {
39
+ description: "Push user data",
40
+ tags: ["Push"],
41
+ security: [],
42
+ requestBody: {
43
+ content: {
44
+ "application/json": {
45
+ schema: {
46
+ type: "array",
47
+ items: {
48
+ $ref: "#/components/schemas/userData"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ },
54
+ responses: {
55
+ 200: {
56
+ description: "ok"
57
+ }
58
+ }
59
+ }
60
+ }
61
+ },
62
+ components: {
63
+ schemas: {
64
+ userData: {
65
+ type: "object",
66
+ description: "\u7528\u6237\u6570\u636E",
67
+ properties: {
68
+ dataType: {
69
+ type: "string",
70
+ description: "\u6570\u636E\u7C7B\u578B, \u76EE\u524D\u53EF\u9009\u503C\u4E3A: user, department"
71
+ },
72
+ uniqueKey: {
73
+ type: "string",
74
+ description: "\u552F\u4E00\u952E"
75
+ },
76
+ records: {
77
+ type: "array",
78
+ description: "\u6570\u636E, \u82E5 dataType \u4E3A user, \u5219\u4E3A\u7528\u6237\u6570\u636E\u5B57\u6BB5\u89C1schemas/user, \u82E5 dataType \u4E3A department, \u5219\u4E3A\u90E8\u95E8\u6570\u636E\u5B57\u6BB5\u89C1schemas/department",
79
+ items: {
80
+ type: "object"
81
+ }
82
+ },
83
+ sourceName: {
84
+ type: "string",
85
+ description: "\u6570\u636E\u6E90\u540D\u79F0"
86
+ }
87
+ }
88
+ },
89
+ user: {
90
+ type: "object",
91
+ description: "\u7528\u6237",
92
+ properties: {
93
+ id: {
94
+ type: "integer",
95
+ description: "ID"
96
+ },
97
+ nickname: {
98
+ type: "string",
99
+ description: "\u6635\u79F0"
100
+ },
101
+ email: {
102
+ type: "string",
103
+ description: "\u90AE\u7BB1"
104
+ },
105
+ phone: {
106
+ type: "string",
107
+ description: "\u624B\u673A\u53F7"
108
+ },
109
+ departments: {
110
+ type: "array",
111
+ description: "\u6240\u5C5E\u90E8\u95E8, \u90E8\u95E8ID \u6570\u7EC4",
112
+ items: {
113
+ type: "string"
114
+ }
115
+ }
116
+ }
117
+ },
118
+ department: {
119
+ type: "object",
120
+ description: "\u90E8\u95E8",
121
+ properties: {
122
+ id: {
123
+ type: "string",
124
+ description: "ID"
125
+ },
126
+ name: {
127
+ type: "string",
128
+ description: "\u540D\u79F0"
129
+ },
130
+ parentId: {
131
+ type: "string",
132
+ description: "\u7236\u7EA7\u90E8\u95E8ID"
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ };
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@nocobase/plugin-user-data-sync",
3
+ "displayName": "User data synchronization",
4
+ "displayName.zh-CN": "用户数据同步",
5
+ "description": "Provide user data source management and user data synchronization interface. The data source can be DingTalk, WeCom, etc., and can be expanded.",
6
+ "description.zh-CN": "提供用户数据源管理,用户数据同步接口,数据源可为钉钉、企业微信等,可扩展。",
7
+ "version": "1.4.0-alpha",
8
+ "main": "dist/server/index.js",
9
+ "peerDependencies": {
10
+ "@nocobase/client": "1.x",
11
+ "@nocobase/server": "1.x",
12
+ "@nocobase/test": "1.x"
13
+ },
14
+ "keywords": [
15
+ "Users & permissions"
16
+ ],
17
+ "gitHead": "f097a2bddec152522b5645bd5d451f4c866d2060"
18
+ }
package/server.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './dist/server';
2
+ export { default } from './dist/server';
package/server.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/server/index.js');