oak-backend-base 3.3.4 → 3.4.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.
package/lib/AppLoader.js CHANGED
@@ -6,7 +6,7 @@ const fs_1 = require("fs");
6
6
  const path_1 = require("path");
7
7
  const node_schedule_1 = require("node-schedule");
8
8
  const env_1 = require("oak-domain/lib/compiler/env");
9
- const actionDef_1 = require("oak-domain/lib/store/actionDef");
9
+ const IntrinsicLogics_1 = require("oak-domain/lib/store/IntrinsicLogics");
10
10
  const lodash_1 = require("oak-domain/lib/utils/lodash");
11
11
  const uuid_1 = require("oak-domain/lib/utils/uuid");
12
12
  const types_1 = require("oak-domain/lib/types");
@@ -144,7 +144,7 @@ class AppLoader extends types_1.AppLoader {
144
144
  const triggers = this.requireSth('lib/triggers/index');
145
145
  const checkers = this.requireSth('lib/checkers/index');
146
146
  const { ActionDefDict } = require(`${this.path}/lib/oak-app-domain/ActionDefDict`);
147
- const { triggers: adTriggers, checkers: adCheckers } = (0, actionDef_1.makeIntrinsicCTWs)(this.dbStore.getSchema(), ActionDefDict);
147
+ const { triggers: adTriggers, checkers: adCheckers } = (0, IntrinsicLogics_1.makeIntrinsicCTWs)(this.dbStore.getSchema(), ActionDefDict);
148
148
  triggers.forEach((trigger) => this.registerTrigger(trigger));
149
149
  adTriggers.forEach((trigger) => this.registerTrigger(trigger));
150
150
  checkers.forEach((checker) => this.dbStore.registerChecker(checker));
@@ -333,7 +333,7 @@ class AppLoader extends types_1.AppLoader {
333
333
  startWatchers() {
334
334
  const watchers = this.requireSth('lib/watchers/index');
335
335
  const { ActionDefDict } = require(`${this.path}/lib/oak-app-domain/ActionDefDict`);
336
- const { watchers: adWatchers } = (0, actionDef_1.makeIntrinsicCTWs)(this.dbStore.getSchema(), ActionDefDict);
336
+ const { watchers: adWatchers } = (0, IntrinsicLogics_1.makeIntrinsicCTWs)(this.dbStore.getSchema(), ActionDefDict);
337
337
  const totalWatchers = watchers.concat(adWatchers);
338
338
  let count = 0;
339
339
  const execOne = async (watcher, start) => {
@@ -1,18 +1,18 @@
1
- import { EntityDict } from 'oak-domain/lib/types';
2
- import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
3
- import { BackendRuntimeContext } from 'oak-frontend-base';
4
- import { Namespace } from 'socket.io';
5
- export default class DataSubscriber<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> {
6
- private ns;
7
- private contextBuilder;
8
- private filterMap;
9
- private idEntityMap;
10
- constructor(ns: Namespace, contextBuilder: (scene?: string) => Promise<Context>);
11
- private formCreateRoomRoutine;
12
- /**
13
- * 来自外部的socket连接,监听数据变化
14
- */
15
- private startup;
16
- private sendRecord;
17
- onDataCommited(context: Context): void;
18
- }
1
+ import { EntityDict } from 'oak-domain/lib/types';
2
+ import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
3
+ import { BackendRuntimeContext } from 'oak-frontend-base';
4
+ import { Namespace } from 'socket.io';
5
+ export default class DataSubscriber<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> {
6
+ private ns;
7
+ private contextBuilder;
8
+ private filterMap;
9
+ private idEntityMap;
10
+ constructor(ns: Namespace, contextBuilder: (scene?: string) => Promise<Context>);
11
+ private formCreateRoomRoutine;
12
+ /**
13
+ * 来自外部的socket连接,监听数据变化
14
+ */
15
+ private startup;
16
+ private sendRecord;
17
+ onDataCommited(context: Context): void;
18
+ }
@@ -1,158 +1,158 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const lodash_1 = require("oak-domain/lib/utils/lodash");
4
- const oak_domain_1 = require("oak-domain");
5
- class DataSubscriber {
6
- ns;
7
- contextBuilder;
8
- filterMap;
9
- idEntityMap;
10
- constructor(ns, contextBuilder) {
11
- this.ns = ns;
12
- this.contextBuilder = contextBuilder;
13
- this.startup();
14
- this.filterMap = {};
15
- this.idEntityMap = {};
16
- }
17
- formCreateRoomRoutine(def) {
18
- const { id, entity, filter } = def;
19
- return (room) => {
20
- if (room === id) {
21
- console.log('instance:', process.env.NODE_APP_INSTANCE, 'add filter', room);
22
- // 本房间不存在,说明这个filter是新出现的
23
- if (this.filterMap[entity]) {
24
- // id的唯一性由前台保证,重复则无视
25
- Object.assign(this.filterMap[entity], {
26
- [id]: filter,
27
- });
28
- }
29
- else {
30
- Object.assign(this.filterMap, {
31
- [entity]: {
32
- [id]: filter,
33
- }
34
- });
35
- }
36
- this.idEntityMap[id] = entity;
37
- }
38
- };
39
- }
40
- /**
41
- * 来自外部的socket连接,监听数据变化
42
- */
43
- startup() {
44
- this.ns.on('connection', async (socket) => {
45
- try {
46
- const { 'oak-cxt': cxtStr } = socket.handshake.headers;
47
- const context = await this.contextBuilder(cxtStr);
48
- socket.userId = context.getCurrentUserId();
49
- socket.context = context;
50
- socket.idMap = {};
51
- socket.on('sub', async (data) => {
52
- try {
53
- console.log('instance:', process.env.NODE_APP_INSTANCE, 'on sub', JSON.stringify(data));
54
- await Promise.all(data.map(async (ele) => {
55
- const { id, entity, filter } = ele;
56
- // 尝试select此filter,如果失败说明权限越界
57
- await context.select(entity, {
58
- data: {
59
- id: 1,
60
- },
61
- filter,
62
- }, {});
63
- }));
64
- }
65
- catch (err) {
66
- socket.emit('error', err.toString());
67
- return;
68
- }
69
- data.forEach((ele) => {
70
- const createRoomRoutine = this.formCreateRoomRoutine(ele);
71
- this.ns.adapter.on('create-room', createRoomRoutine);
72
- socket.join(ele.id);
73
- this.ns.adapter.off('create-room', createRoomRoutine);
74
- });
75
- });
76
- socket.on('unsub', (ids) => {
77
- // console.log('instance:', process.env.NODE_APP_INSTANCE, 'on unsub', JSON.stringify(ids));
78
- ids.forEach((id) => {
79
- socket.leave(id);
80
- });
81
- });
82
- }
83
- catch (err) {
84
- socket.emit('error', err.toString());
85
- }
86
- });
87
- this.ns.adapter.on('delete-room', (room) => {
88
- const entity = this.idEntityMap[room];
89
- if (entity) {
90
- // console.log('instance:', process.env.NODE_APP_INSTANCE, 'remove filter', room);
91
- (0, lodash_1.unset)(this.filterMap[entity], room);
92
- (0, lodash_1.unset)(this.idEntityMap, room);
93
- }
94
- });
95
- this.ns.on('sendRecord', (entity, filter, record, isCreate) => {
96
- console.log('instance:', process.env.NODE_APP_INSTANCE, 'get record from another', JSON.stringify(entity));
97
- });
98
- }
99
- sendRecord(entity, filter, record, sid, isCreate) {
100
- if (entity === 'spContractApplyment') {
101
- console.log('instance:', process.env.NODE_APP_INSTANCE, 'sendRecord', JSON.stringify(entity));
102
- }
103
- this.ns.serverSideEmit('sendRecord', entity, filter, record, isCreate);
104
- if (this.filterMap[entity]) {
105
- Object.keys(this.filterMap[entity]).forEach(async (room) => {
106
- const context = await this.contextBuilder();
107
- const filter2 = this.filterMap[entity][room];
108
- let needSend = false;
109
- if (isCreate) {
110
- // 如果是插入数据肯定是单行,使用相容性检测
111
- const contained = await (0, oak_domain_1.checkFilterContains)(entity, context, filter2, filter, true);
112
- needSend = contained;
113
- }
114
- else {
115
- const repeled = await (0, oak_domain_1.checkFilterRepel)(entity, context, filter, filter2, true);
116
- needSend = !repeled;
117
- }
118
- if (needSend) {
119
- // console.log('instance:', process.env.NODE_APP_INSTANCE, 'needSend', JSON.stringify(room));
120
- if (sid) {
121
- this.ns.to(room).except(sid).emit('data', [record], [room]);
122
- }
123
- else {
124
- this.ns.to(room).emit('data', [record], [room]);
125
- }
126
- }
127
- });
128
- }
129
- }
130
- onDataCommited(context) {
131
- const sid = context.getSubscriberId();
132
- const { opRecords } = context;
133
- opRecords.forEach((record) => {
134
- const { a } = record;
135
- switch (a) {
136
- case 'c': {
137
- const { e, d } = record;
138
- this.sendRecord(e, d, record, sid, true);
139
- break;
140
- }
141
- case 'u': {
142
- const { e, d, f } = record;
143
- this.sendRecord(e, f, record, sid);
144
- break;
145
- }
146
- case 'r': {
147
- const { e, f } = record;
148
- this.sendRecord(e, f, record, sid);
149
- break;
150
- }
151
- default: {
152
- break;
153
- }
154
- }
155
- });
156
- }
157
- }
158
- exports.default = DataSubscriber;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const lodash_1 = require("oak-domain/lib/utils/lodash");
4
+ const oak_domain_1 = require("oak-domain");
5
+ class DataSubscriber {
6
+ ns;
7
+ contextBuilder;
8
+ filterMap;
9
+ idEntityMap;
10
+ constructor(ns, contextBuilder) {
11
+ this.ns = ns;
12
+ this.contextBuilder = contextBuilder;
13
+ this.startup();
14
+ this.filterMap = {};
15
+ this.idEntityMap = {};
16
+ }
17
+ formCreateRoomRoutine(def) {
18
+ const { id, entity, filter } = def;
19
+ return (room) => {
20
+ if (room === id) {
21
+ console.log('instance:', process.env.NODE_APP_INSTANCE, 'add filter', room);
22
+ // 本房间不存在,说明这个filter是新出现的
23
+ if (this.filterMap[entity]) {
24
+ // id的唯一性由前台保证,重复则无视
25
+ Object.assign(this.filterMap[entity], {
26
+ [id]: filter,
27
+ });
28
+ }
29
+ else {
30
+ Object.assign(this.filterMap, {
31
+ [entity]: {
32
+ [id]: filter,
33
+ }
34
+ });
35
+ }
36
+ this.idEntityMap[id] = entity;
37
+ }
38
+ };
39
+ }
40
+ /**
41
+ * 来自外部的socket连接,监听数据变化
42
+ */
43
+ startup() {
44
+ this.ns.on('connection', async (socket) => {
45
+ try {
46
+ const { 'oak-cxt': cxtStr } = socket.handshake.headers;
47
+ const context = await this.contextBuilder(cxtStr);
48
+ socket.userId = context.getCurrentUserId();
49
+ socket.context = context;
50
+ socket.idMap = {};
51
+ socket.on('sub', async (data) => {
52
+ try {
53
+ console.log('instance:', process.env.NODE_APP_INSTANCE, 'on sub', JSON.stringify(data));
54
+ await Promise.all(data.map(async (ele) => {
55
+ const { id, entity, filter } = ele;
56
+ // 尝试select此filter,如果失败说明权限越界
57
+ await context.select(entity, {
58
+ data: {
59
+ id: 1,
60
+ },
61
+ filter,
62
+ }, {});
63
+ }));
64
+ }
65
+ catch (err) {
66
+ socket.emit('error', err.toString());
67
+ return;
68
+ }
69
+ data.forEach((ele) => {
70
+ const createRoomRoutine = this.formCreateRoomRoutine(ele);
71
+ this.ns.adapter.on('create-room', createRoomRoutine);
72
+ socket.join(ele.id);
73
+ this.ns.adapter.off('create-room', createRoomRoutine);
74
+ });
75
+ });
76
+ socket.on('unsub', (ids) => {
77
+ // console.log('instance:', process.env.NODE_APP_INSTANCE, 'on unsub', JSON.stringify(ids));
78
+ ids.forEach((id) => {
79
+ socket.leave(id);
80
+ });
81
+ });
82
+ }
83
+ catch (err) {
84
+ socket.emit('error', err.toString());
85
+ }
86
+ });
87
+ this.ns.adapter.on('delete-room', (room) => {
88
+ const entity = this.idEntityMap[room];
89
+ if (entity) {
90
+ // console.log('instance:', process.env.NODE_APP_INSTANCE, 'remove filter', room);
91
+ (0, lodash_1.unset)(this.filterMap[entity], room);
92
+ (0, lodash_1.unset)(this.idEntityMap, room);
93
+ }
94
+ });
95
+ this.ns.on('sendRecord', (entity, filter, record, isCreate) => {
96
+ console.log('instance:', process.env.NODE_APP_INSTANCE, 'get record from another', JSON.stringify(entity));
97
+ });
98
+ }
99
+ sendRecord(entity, filter, record, sid, isCreate) {
100
+ if (entity === 'spContractApplyment') {
101
+ console.log('instance:', process.env.NODE_APP_INSTANCE, 'sendRecord', JSON.stringify(entity));
102
+ }
103
+ this.ns.serverSideEmit('sendRecord', entity, filter, record, isCreate);
104
+ if (this.filterMap[entity]) {
105
+ Object.keys(this.filterMap[entity]).forEach(async (room) => {
106
+ const context = await this.contextBuilder();
107
+ const filter2 = this.filterMap[entity][room];
108
+ let needSend = false;
109
+ if (isCreate) {
110
+ // 如果是插入数据肯定是单行,使用相容性检测
111
+ const contained = await (0, oak_domain_1.checkFilterContains)(entity, context, filter2, filter, true);
112
+ needSend = contained;
113
+ }
114
+ else {
115
+ const repeled = await (0, oak_domain_1.checkFilterRepel)(entity, context, filter, filter2, true);
116
+ needSend = !repeled;
117
+ }
118
+ if (needSend) {
119
+ // console.log('instance:', process.env.NODE_APP_INSTANCE, 'needSend', JSON.stringify(room));
120
+ if (sid) {
121
+ this.ns.to(room).except(sid).emit('data', [record], [room]);
122
+ }
123
+ else {
124
+ this.ns.to(room).emit('data', [record], [room]);
125
+ }
126
+ }
127
+ });
128
+ }
129
+ }
130
+ onDataCommited(context) {
131
+ const sid = context.getSubscriberId();
132
+ const { opRecords } = context;
133
+ opRecords.forEach((record) => {
134
+ const { a } = record;
135
+ switch (a) {
136
+ case 'c': {
137
+ const { e, d } = record;
138
+ this.sendRecord(e, d, record, sid, true);
139
+ break;
140
+ }
141
+ case 'u': {
142
+ const { e, d, f } = record;
143
+ this.sendRecord(e, f, record, sid);
144
+ break;
145
+ }
146
+ case 'r': {
147
+ const { e, f } = record;
148
+ this.sendRecord(e, f, record, sid);
149
+ break;
150
+ }
151
+ default: {
152
+ break;
153
+ }
154
+ }
155
+ });
156
+ }
157
+ }
158
+ exports.default = DataSubscriber;
package/lib/DbStore.js CHANGED
@@ -107,7 +107,7 @@ class DbStore extends oak_db_1.MysqlStore {
107
107
  this.executor.registerTrigger(trigger);
108
108
  }
109
109
  registerChecker(checker) {
110
- this.executor.registerChecker(checker);
110
+ this.executor.registerChecker(checker, this.getSchema());
111
111
  }
112
112
  setOnVolatileTrigger(onVolatileTrigger) {
113
113
  this.executor.setOnVolatileTrigger(onVolatileTrigger);
@@ -197,6 +197,7 @@ class Synchronizer {
197
197
  // 每个pushEntityNode代表配置的一个remoteEntity
198
198
  await Promise.all(pushEntityNodes.map(async (node) => {
199
199
  const { projection, groupByUsers, getRemotePushInfo: getRemoteAccessInfo, endpoint, actions, onSynchronized } = node;
200
+ // 定义中应该不可能没有actions
200
201
  if (!actions || actions.includes(action)) {
201
202
  const pushed = [];
202
203
  const rows = await context.select(targetEntity, {
@@ -344,7 +345,9 @@ class Synchronizer {
344
345
  strict: 'makeSure',
345
346
  check: (operation) => {
346
347
  const { data } = operation;
347
- return pushEntities.includes(data.targetEntity);
348
+ const { targetEntity, action } = data;
349
+ return pushEntities.includes(data.targetEntity)
350
+ && !!this.pushAccessMap[targetEntity].find(({ actions }) => !actions || actions.includes(action));
348
351
  },
349
352
  fn: async ({ ids }, context) => {
350
353
  (0, assert_1.default)(ids.length === 1);
@@ -1,16 +1,16 @@
1
- import { EntityDict } from 'oak-domain/lib/types';
2
- import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
3
- import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext';
4
- import { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncRemoteConfigBase, SyncSelfConfigBase, SyncConfig } from 'oak-domain/lib/types/Sync';
5
- interface SyncRemoteConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {
6
- getRemotePushInfo: (userId: string) => Promise<RemotePushInfo>;
7
- getRemotePullInfo: (id: string) => Promise<RemotePullInfo>;
8
- }
9
- interface SyncSelfConfigWrapper<ED extends EntityDict & BaseEntityDict> extends SyncSelfConfigBase<ED> {
10
- getSelfEncryptInfo: () => Promise<SelfEncryptInfo>;
11
- }
12
- export interface SyncConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> {
13
- self: SyncSelfConfigWrapper<ED>;
14
- remotes: Array<SyncRemoteConfigWrapper<ED, Cxt>>;
15
- }
16
- export { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncConfig, };
1
+ import { EntityDict } from 'oak-domain/lib/types';
2
+ import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
3
+ import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext';
4
+ import { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncRemoteConfigBase, SyncSelfConfigBase, SyncConfig } from 'oak-domain/lib/types/Sync';
5
+ interface SyncRemoteConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {
6
+ getRemotePushInfo: (userId: string) => Promise<RemotePushInfo>;
7
+ getRemotePullInfo: (id: string) => Promise<RemotePullInfo>;
8
+ }
9
+ interface SyncSelfConfigWrapper<ED extends EntityDict & BaseEntityDict> extends SyncSelfConfigBase<ED> {
10
+ getSelfEncryptInfo: () => Promise<SelfEncryptInfo>;
11
+ }
12
+ export interface SyncConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> {
13
+ self: SyncSelfConfigWrapper<ED>;
14
+ remotes: Array<SyncRemoteConfigWrapper<ED, Cxt>>;
15
+ }
16
+ export { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncConfig, };
package/lib/types/Sync.js CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- ;
4
- ;
5
- ;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ ;
4
+ ;
5
+ ;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-backend-base",
3
- "version": "3.3.4",
3
+ "version": "3.4.0",
4
4
  "description": "oak-backend-base",
5
5
  "main": "lib/index",
6
6
  "author": {
@@ -20,10 +20,10 @@
20
20
  "mysql": "^2.18.1",
21
21
  "mysql2": "^2.3.3",
22
22
  "node-schedule": "^2.1.0",
23
- "oak-common-aspect": "^2.2.5",
24
- "oak-db": "^3.1.0",
25
- "oak-domain": "^4.2.8",
26
- "oak-frontend-base": "^4.2.7",
23
+ "oak-common-aspect": "^2.3.0",
24
+ "oak-db": "^3.2.0",
25
+ "oak-domain": "^4.3.0",
26
+ "oak-frontend-base": "^4.3.0",
27
27
  "socket.io": "^4.7.2",
28
28
  "socket.io-client": "^4.7.2",
29
29
  "uuid": "^8.3.2"