ee-core 2.0.0-beta.4 → 2.0.0-beta.7

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 (76) hide show
  1. package/addon/index.js +30 -0
  2. package/config/index.js +54 -0
  3. package/{module/const → const}/channel.js +4 -1
  4. package/{module/const → const}/index.js +1 -5
  5. package/{module/core → core}/lib/loader/ee_loader.js +1 -1
  6. package/{module/core → core}/lib/loader/file_loader.js +1 -0
  7. package/{module/core → core}/lib/loader/mixin/addon.js +1 -1
  8. package/{module/app → ee}/baseApp.js +2 -1
  9. package/{module/app → ee}/eeApp.js +20 -46
  10. package/ee/index.js +30 -0
  11. package/electron/index.js +32 -0
  12. package/electron/window.js +45 -0
  13. package/index.js +12 -13
  14. package/{module/jobs → jobs}/child/app.js +9 -15
  15. package/{module/jobs → jobs}/childPool/app.js +9 -15
  16. package/{module/message → message}/index.js +0 -2
  17. package/package.json +3 -5
  18. package/{module/ps → ps}/index.js +11 -4
  19. package/{module/socket → socket}/httpServer.js +12 -18
  20. package/socket/index.js +82 -0
  21. package/{module/socket → socket}/io.js +4 -0
  22. package/{module/socket → socket}/ipcServer.js +0 -2
  23. package/socket/socketServer.js +66 -0
  24. package/{module/storage → storage}/jsondbStorage.js +37 -0
  25. package/utils/is.js +145 -0
  26. package/module/app/index.js +0 -5
  27. package/module/socket/socketClient.js +0 -49
  28. package/module/socket/socketServer.js +0 -76
  29. package/module/socket/start.js +0 -22
  30. /package/{module/addon → addon}/window/index.js +0 -0
  31. /package/{module/bin → bin}/tools.js +0 -0
  32. /package/{module/config → config}/config.default.js +0 -0
  33. /package/{module/controller → controller}/index.js +0 -0
  34. /package/{module/core → core}/index.js +0 -0
  35. /package/{module/core → core}/lib/ee.js +0 -0
  36. /package/{module/core → core}/lib/loader/context_loader.js +0 -0
  37. /package/{module/core → core}/lib/loader/mixin/config.js +0 -0
  38. /package/{module/core → core}/lib/loader/mixin/controller.js +0 -0
  39. /package/{module/core → core}/lib/loader/mixin/service.js +0 -0
  40. /package/{module/core → core}/lib/utils/base_context_class.js +0 -0
  41. /package/{module/core → core}/lib/utils/function.js +0 -0
  42. /package/{module/core → core}/lib/utils/index.js +0 -0
  43. /package/{module/core → core}/lib/utils/sequencify.js +0 -0
  44. /package/{module/core → core}/lib/utils/timing.js +0 -0
  45. /package/{module/app → ee}/appLoader.js +0 -0
  46. /package/{module/app → ee}/application.js +0 -0
  47. /package/{module/exception → exception}/index.js +0 -0
  48. /package/{module/httpclient → httpclient}/index.js +0 -0
  49. /package/{module/jobs → jobs}/baseJobClass.js +0 -0
  50. /package/{module/jobs → jobs}/child/forkProcess.js +0 -0
  51. /package/{module/jobs → jobs}/child/index.js +0 -0
  52. /package/{module/jobs → jobs}/childPool/forkProcess.js +0 -0
  53. /package/{module/jobs → jobs}/childPool/index.js +0 -0
  54. /package/{module/jobs → jobs}/childPool/pool.js +0 -0
  55. /package/{module/jobs → jobs}/index.js +0 -0
  56. /package/{module/jobs → jobs}/renderer/index.js +0 -0
  57. /package/{module/jobs → jobs}/renderer/loadView.js +0 -0
  58. /package/{module/jobs → jobs}/unification.js +0 -0
  59. /package/{module/loader → loader}/index.js +0 -0
  60. /package/{module/log → log}/index.js +0 -0
  61. /package/{module/log → log}/logger.js +0 -0
  62. /package/{module/message → message}/childMessage.js +0 -0
  63. /package/{module/oldUtils → oldUtils}/index.js +0 -0
  64. /package/{module/service → service}/index.js +0 -0
  65. /package/{module/storage → storage}/index.js +0 -0
  66. /package/{module/storage → storage}/jsondb/adapters/Base.js +0 -0
  67. /package/{module/storage → storage}/jsondb/adapters/FileSync.js +0 -0
  68. /package/{module/storage → storage}/jsondb/main.js +0 -0
  69. /package/{module/storage → storage}/sqliteStorage.js +0 -0
  70. /package/{module/tools → tools}/encrypt.js +0 -0
  71. /package/{module/tools → tools}/replaceDist.js +0 -0
  72. /package/{module/utils → utils}/copyto.js +0 -0
  73. /package/{module/utils → utils}/helper.js +0 -0
  74. /package/{module/utils → utils}/index.js +0 -0
  75. /package/{module/utils → utils}/json.js +0 -0
  76. /package/{module/utils → utils}/wrap.js +0 -0
@@ -10,6 +10,7 @@ const fs = require('fs');
10
10
  const path = require('path');
11
11
  const _ = require('lodash');
12
12
  const Log = require('../log');
13
+ const Ps = require('../ps');
13
14
 
14
15
  /**
15
16
  * http server
@@ -19,12 +20,14 @@ class HttpServer {
19
20
  this.app = app;
20
21
  this.options = this.app.config.httpServer;
21
22
 
22
- if (!this.options.enable) {
23
+ if (this.options.enable == false) {
23
24
  return;
24
25
  }
25
26
 
26
- let port = process.env.EE_HTTP_PORT ? parseInt(process.env.EE_HTTP_PORT) : parseInt(this.getHttpPort());
27
- assert(typeof port === 'number', 'http port required, and must be a number');
27
+ let port = Ps.getHttpPort();
28
+ if (!port) {
29
+ throw new Error('[ee-core] [socket/HttpServer] http port required, and must be a number !');
30
+ }
28
31
 
29
32
  this.create();
30
33
  }
@@ -33,15 +36,15 @@ class HttpServer {
33
36
  * 创建服务
34
37
  */
35
38
  create () {
36
- const self = this;
39
+ const app = this.app;
37
40
  const httpServer = this.options;
38
41
  const isHttps = httpServer?.https?.enable ?? false;
39
42
  let sslOptions = {};
40
43
 
41
44
  if (isHttps === true) {
42
45
  httpServer.protocol = 'https://';
43
- const keyFile = path.join(this.app.config.homeDir, httpServer.https.key);
44
- const certFile = path.join(this.app.config.homeDir, httpServer.https.cert);
46
+ const keyFile = path.join(app.config.homeDir, httpServer.https.key);
47
+ const certFile = path.join(app.config.homeDir, httpServer.https.cert);
45
48
  assert(fs.existsSync(keyFile), 'ssl key file is required');
46
49
  assert(fs.existsSync(certFile), 'ssl cert file is required');
47
50
 
@@ -56,12 +59,12 @@ class HttpServer {
56
59
  .use(cors(corsOptions))
57
60
  .use(koaBody(httpServer.body))
58
61
  .use(async (ctx, next) => {
59
- ctx.eeApp = self.app;
62
+ ctx.eeApp = app;
60
63
  await next();
61
64
  })
62
65
  .use(this.dispatch);
63
66
 
64
- let msg = '[ee-core] [socket/httpServer] server is: ' + url;
67
+ let msg = '[ee-core] [socket/http] server is: ' + url;
65
68
  if (isHttps) {
66
69
  https.createServer(sslOptions, koaApp.callback()).listen(httpServer.port, (err) => {
67
70
  msg = err ? err : msg;
@@ -125,20 +128,11 @@ class HttpServer {
125
128
  const result = await fn.call(ctx.eeApp, args);
126
129
  ctx.response.body = result;
127
130
  } catch (err) {
128
- ctx.eeApp.console.error('[ee-core:http:server] throw error:', err);
131
+ Log.coreLogger.error('[ee-core/httpServer] throw error:', err);
129
132
  }
130
133
 
131
134
  await next();
132
135
  }
133
-
134
- /**
135
- * 获取http端口
136
- */
137
- getHttpPort () {
138
- const cdb = this.getCoreDB();
139
- const port = cdb.getItem('config').httpServer.port;
140
- return parseInt(port);
141
- }
142
136
  }
143
137
 
144
138
  module.exports = HttpServer;
@@ -0,0 +1,82 @@
1
+ 'use strict';
2
+
3
+ const IoServer = require('socket.io');
4
+ const IoClient = require('socket.io-client');
5
+ const Koa = require('koa');
6
+ const EESocketServer = Symbol('Ee#SocketServer');
7
+ const EEIpcServer = Symbol('Ee#IpcServer');
8
+ const EEHttpServer = Symbol('Ee#HttpServer');
9
+
10
+ const EeSocket = {
11
+
12
+ /**
13
+ * 提供基础库 - 避免用户重复安装
14
+ */
15
+ Koa,
16
+ IoServer,
17
+ IoClient,
18
+
19
+ /**
20
+ * 启动所有服务
21
+ */
22
+ startAll(app) {
23
+ this._createSocketServer(app);
24
+ this._createHttpServer(app);
25
+ this._createIpcServer(app);
26
+ },
27
+
28
+ /**
29
+ * 创建SocketServer
30
+ */
31
+ _createSocketServer(app) {
32
+ const SocketServer = require('./socketServer');
33
+ this[EESocketServer] = new SocketServer(app);
34
+
35
+ return this[EESocketServer];
36
+ },
37
+
38
+ /**
39
+ * 获取 Socket Server
40
+ */
41
+ getSocketServer() {
42
+ return this[EESocketServer] || null;
43
+ },
44
+
45
+ /**
46
+ * 创建 Http Server
47
+ */
48
+ _createHttpServer(app) {
49
+ const HttpServer = require('./httpServer');
50
+ this[EEHttpServer] = new HttpServer(app);
51
+
52
+ return this[EEHttpServer];
53
+ },
54
+
55
+ /**
56
+ * 获取 Http Server
57
+ */
58
+ getHttpServer() {
59
+ return this[EEHttpServer] || null;
60
+ },
61
+
62
+ /**
63
+ * 创建 IPC Server
64
+ */
65
+ _createIpcServer(app) {
66
+ const IpcServer = require('./ipcServer');
67
+ this[EEIpcServer] = new IpcServer(app);
68
+
69
+ return this[EEIpcServer];
70
+ },
71
+
72
+ /**
73
+ * 获取 IPC Server
74
+ */
75
+ getIpcServer() {
76
+ return this[EEIpcServer] || null;
77
+ },
78
+
79
+ }
80
+
81
+
82
+ module.exports = EeSocket;
@@ -1,5 +1,9 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * 该文件将废弃
5
+ */
6
+
3
7
  const IoServer = require('socket.io');
4
8
  const IoClient = require('socket.io-client');
5
9
  //const socketServer = require('./socketServer');
@@ -15,8 +15,6 @@ class IpcServer {
15
15
  }
16
16
 
17
17
  register () {
18
- console.log('[ee-core] [socket/IpcServer] register channels');
19
-
20
18
  const self = this;
21
19
  // 遍历方法
22
20
  const files = Utils.filePatterns();
@@ -0,0 +1,66 @@
1
+ 'use strict';
2
+
3
+ const { Server } = require('socket.io');
4
+ const is = require('is-type-of');
5
+ const Log = require('../log');
6
+ const Conf = require('../config');
7
+ const Ps = require('../ps');
8
+ const Channel = require('../const/channel');
9
+
10
+ /**
11
+ * socket server
12
+ */
13
+ class SocketServer {
14
+ constructor (app) {
15
+ this.app = app;
16
+ const options = Conf.getValue('socketServer');
17
+
18
+ if (options.enable == false) {
19
+ return;
20
+ }
21
+
22
+ let port = Ps.getSocketPort();
23
+ if (!port) {
24
+ throw new Error('[ee-core] [socket/socketServer] socekt port required, and must be a number !');
25
+ }
26
+
27
+ Log.coreLogger.info('[ee-core] [socket/socketServer] port is:', port);
28
+
29
+ this.io = new Server(port, options);
30
+ this.connec();
31
+ }
32
+
33
+ connec () {
34
+ const app = this.app;
35
+ this.io.on('connection', (socket) => {
36
+ const channel = Channel.socketIo.partySoftware;
37
+ socket.on(channel, async (message, callback) => {
38
+ Log.coreLogger.info('[ee-core] [socket/socketServer] socket id:' + socket.id + ' message cmd: ' + message.cmd);
39
+
40
+ try {
41
+ // 找函数
42
+ const cmd = message.cmd;
43
+ const args = message.params;
44
+ let fn = null;
45
+ if (is.string(cmd)) {
46
+ const actions = cmd.split('.');
47
+ let obj = app;
48
+ actions.forEach(key => {
49
+ obj = obj[key];
50
+ if (!obj) throw new Error(`class or function '${key}' not exists`);
51
+ });
52
+ fn = obj;
53
+ }
54
+ if (!fn) throw new Error('function not exists');
55
+
56
+ const result = await fn.call(app, args);
57
+ callback(result);
58
+ } catch (err) {
59
+ Log.coreLogger.error('[ee-core] [socket/socketServer] throw error:', err);
60
+ }
61
+ });
62
+ });
63
+ }
64
+ }
65
+
66
+ module.exports = SocketServer;
@@ -90,6 +90,43 @@ class JsondbStorage {
90
90
  .get(keyId)
91
91
  .value();
92
92
 
93
+ return data;
94
+ }
95
+
96
+ /**
97
+ * 设置config对象key属性的值
98
+ */
99
+ setConfigItem (key, value) {
100
+ assert(_.isString(key), `key must be a string`);
101
+ assert(key.length != 0, `key cannot be empty`);
102
+ assert(!this.storageKey.hasOwnProperty(key), `${key} is not allowed`);
103
+
104
+ let cacheKey = this.storageKey.cacheConfig;
105
+ if (!this.db.has(cacheKey).value()) {
106
+ this.db.set(cacheKey, {}).write();
107
+ }
108
+
109
+ let keyId = cacheKey + "." + key;
110
+ this.db
111
+ .set(keyId, value)
112
+ .write();
113
+
114
+ return true;
115
+ }
116
+
117
+ /**
118
+ * 获取config对象key属性的值
119
+ */
120
+ getConfigItem (key) {
121
+ assert(_.isString(key), `key must be a string`);
122
+ assert(key.length != 0, `key cannot be empty`);
123
+
124
+ let cacheKey = this.storageKey.cacheConfig;
125
+ let keyId = cacheKey + "." + key;
126
+ const data = this.db
127
+ .get(keyId)
128
+ .value();
129
+
93
130
  return data;
94
131
  }
95
132
  }
package/utils/is.js ADDED
@@ -0,0 +1,145 @@
1
+ 'use strict'
2
+
3
+ const semver = require('semver')
4
+ const gt = semver.gt
5
+ const lt = semver.lt
6
+ const release = require('os').release
7
+
8
+ const IS = {
9
+ // Checks if we are in renderer process
10
+ renderer() {
11
+ return process.type === 'renderer'
12
+ },
13
+ // Checks if we are in main process
14
+ main() {
15
+ return process.type === 'browser'
16
+ },
17
+ // Checks if we are under Mac OS
18
+ osx() {
19
+ return process.platform === 'darwin'
20
+ },
21
+ // Checks if we are under Mac OS
22
+ macOS() {
23
+ return this.osx()
24
+ },
25
+ // Checks if we are under Windows OS
26
+ windows() {
27
+ return process.platform === 'win32'
28
+ },
29
+ // Checks if we are under Linux OS
30
+ linux() {
31
+ return process.platform === 'linux'
32
+ },
33
+ // Checks if we are the processor's arch is x86
34
+ x86() {
35
+ return process.arch === 'ia32'
36
+ },
37
+ // Checks if we are the processor's arch is x64
38
+ x64() {
39
+ return process.arch === 'x64'
40
+ },
41
+ // Checks if the app is running in a sandbox on macOS
42
+ sandbox() {
43
+ return 'APP_SANDBOX_CONTAINER_ID' in process.env
44
+ },
45
+ // Checks if the app is running as a Mac App Store build
46
+ mas() {
47
+ return process.mas === true
48
+ },
49
+ // Checks if the app is running as a Windows Store (appx) build
50
+ windowsStore() {
51
+ return process.windowsStore === true
52
+ },
53
+ // checks if all the 'is functions' passed as arguments are true
54
+ all() {
55
+ const isFunctions = new Array(arguments.length)
56
+ for (var i = 0; i < isFunctions.length; i++) {
57
+ isFunctions[i] = arguments[i]
58
+ }
59
+ if (!isFunctions.length) return
60
+ for (i = 0; i < isFunctions.length; i++) {
61
+ if (!isFunctions[i]()) return false
62
+ }
63
+ return true
64
+ },
65
+ // checks if all the 'is functions' passed as arguments are false
66
+ none() {
67
+ const isFunctions = new Array(arguments.length)
68
+ for (var i = 0; i < isFunctions.length; i++) {
69
+ isFunctions[i] = arguments[i]
70
+ }
71
+ if (!isFunctions.length) return
72
+ for (i = 0; i < isFunctions.length; i++) {
73
+ if (isFunctions[i]()) return false
74
+ }
75
+ return true
76
+ },
77
+ // returns true if one of the 'is functions' passed as argument is true
78
+ one() {
79
+ const isFunctions = new Array(arguments.length)
80
+ for (var i = 0; i < isFunctions.length; i++) {
81
+ isFunctions[i] = arguments[i]
82
+ }
83
+ if (!isFunctions.length) return
84
+ for (i = 0; i < isFunctions.length; i++) {
85
+ if (isFunctions[i]()) return true
86
+ }
87
+ return false
88
+ },
89
+ // checks the if the given release is the same of the OS
90
+ release(requested) {
91
+ if (this.osx()) {
92
+ return requested === this._osxRelease()
93
+ } else if (this.windows()) {
94
+ requested = requested.split('.')
95
+ const actual = release().split('.')
96
+ if (requested.length === 2) {
97
+ return `${actual[0]}.${actual[1]}` === `${requested[0]}.${requested[1]}`
98
+ }
99
+ return `${actual[0]}.${actual[1]}.${actual[2]}` === `${requested[0]}.${requested[1]}.${requested[2]}`
100
+ } else {
101
+ // Not implemented for Linux yet
102
+ return null
103
+ }
104
+ },
105
+ // checks if the given release is greater than the current OS release
106
+ gtRelease(requested) {
107
+ if (this.osx()) {
108
+ return gt(requested, this._osxRelease())
109
+ } else if (this.windows()) {
110
+ requested = requested.split('.')
111
+ const actual = release().split('.')
112
+ if (requested.length === 2) {
113
+ return gt(`${requested[0]}.${requested[1]}.0`, `${actual[0]}.${actual[1]}.0`)
114
+ }
115
+ return gt(`${requested[0]}.${requested[1]}.${requested[2]}`, `${actual[0]}.${actual[1]}.${actual[2]}`)
116
+ } else {
117
+ // Not implemented for Linux yet
118
+ return null
119
+ }
120
+ },
121
+ // checks if the given release is less than the current OS release
122
+ ltRelease(requested) {
123
+ if (this.osx()) {
124
+ return lt(requested, this._osxRelease())
125
+ } else if (this.windows()) {
126
+ requested = requested.split('.')
127
+ const actual = release().split('.')
128
+ if (requested.length === 2) {
129
+ return lt(`${requested[0]}.${requested[1]}.0`, `${actual[0]}.${actual[1]}.0`)
130
+ }
131
+ return lt(`${requested[0]}.${requested[1]}.${requested[2]}`, `${actual[0]}.${actual[1]}.${actual[2]}`)
132
+ } else {
133
+ // Not implemented for Linux yet
134
+ return null
135
+ }
136
+ },
137
+
138
+ // returns the current osx release
139
+ _osxRelease () {
140
+ const actual = release().split('.')
141
+ return `10.${actual[0] - 4}.${actual[1]}`
142
+ }
143
+ }
144
+
145
+ module.exports = IS;
@@ -1,5 +0,0 @@
1
- const App = {
2
-
3
- }
4
-
5
- module.exports = App;
@@ -1,49 +0,0 @@
1
- 'use strict';
2
-
3
- const assert = require('assert');
4
- const IoClient = require('socket.io-client');
5
- const Constants = require('../const');
6
- const Storage = require('../storage');
7
-
8
- class SocketClient {
9
- constructor (port) {
10
- port = port ? parseInt(port) : this.getSocketcPort();
11
-
12
- assert(typeof port === 'number', 'port required, and must be a number');
13
-
14
- const url = 'http://localhost:' + port;
15
- console.log('[ee-core] [socket/socketClient] url:', url);
16
- this.client = IoClient(url);
17
- }
18
-
19
- static getInstance (port) {
20
- if (typeof this.instance === 'object') {
21
- return this.instance;
22
- }
23
- this.instance = new SocketClient(port);
24
- return this.instance;
25
- }
26
-
27
- call (method = '', ...params) {
28
- return new Promise((resolve, reject) => {
29
- // 获取通信频道
30
- const channel = Constants.socketIo.channel.partySoftware;
31
- this.client.emit(channel, { cmd: method, params: params }, (response) => {
32
- resolve(response);
33
- });
34
- });
35
- }
36
-
37
- getCoreDB () {
38
- const coreDB = Storage.connection('system');
39
- return coreDB;
40
- }
41
-
42
- getSocketcPort () {
43
- const cdb = this.getCoreDB();
44
- const port = cdb.getItem('config').socketServer.port;
45
- return parseInt(port);
46
- }
47
- }
48
-
49
- module.exports = SocketClient;
@@ -1,76 +0,0 @@
1
- 'use strict';
2
-
3
- const assert = require('assert');
4
- const { Server } = require('socket.io');
5
- const is = require('is-type-of');
6
- const Storage = require('../storage');
7
- const Constants = require('../const');
8
- const Log = require('../log');
9
-
10
- /**
11
- * socket server
12
- */
13
- class SocketServer {
14
- constructor (app) {
15
- this.app = app;
16
- const options = this.app.config.socketServer;
17
-
18
- if (!options.enable) {
19
- return;
20
- }
21
-
22
- let port = process.env.EE_SOCKET_PORT ? parseInt(process.env.EE_SOCKET_PORT) : parseInt(this.getSocketPort());
23
- assert(typeof port === 'number', 'socekt port required, and must be a number');
24
- this.consoleLogger.info('[ee-core] [socket/socketServer] port is:', port);
25
-
26
- // let opt = Object.assign({}, options);
27
- // delete opt.enable;
28
- this.io = new Server(port, options);
29
- this.connec();
30
- }
31
-
32
- connec () {
33
- const self = this;
34
- this.io.on('connection', (socket) => {
35
- const channel = Constants.socketIo.channel.partySoftware;
36
- socket.on(channel, async (message, callback) => {
37
- console.log('[ee-core] [socket/socketServer] socket id:' + socket.id + ' message cmd: ' + message.cmd);
38
-
39
- try {
40
- // 找函数
41
- const cmd = message.cmd;
42
- const args = message.params;
43
- let fn = null;
44
- if (is.string(cmd)) {
45
- const actions = cmd.split('.');
46
- let obj = self.app;
47
- actions.forEach(key => {
48
- obj = obj[key];
49
- if (!obj) throw new Error(`class or function '${key}' not exists`);
50
- });
51
- fn = obj;
52
- }
53
- if (!fn) throw new Error('function not exists');
54
-
55
- const result = await fn.call(self.app, args);
56
- callback(result);
57
- } catch (err) {
58
- Log.coreLogger.error('[ee-core] [socket/socketServer] throw error:', err);
59
- }
60
- });
61
- });
62
- }
63
-
64
- getCoreDB () {
65
- const coreDB = Storage.connection('system');
66
- return coreDB;
67
- }
68
-
69
- getSocketPort () {
70
- const cdb = this.getCoreDB();
71
- const port = cdb.getItem('config').socketServer.port;
72
- return port;
73
- }
74
- }
75
-
76
- module.exports = SocketServer;
@@ -1,22 +0,0 @@
1
- 'use strict';
2
-
3
- const SocketServer = require('./socketServer');
4
- const IpcServer = require('./ipcServer');
5
- const HttpServer = require('./httpServer');
6
-
7
- /**
8
- * server
9
- */
10
- module.exports = (app) => {
11
-
12
- // 启动 socket server
13
- new SocketServer(app);
14
-
15
- // 启动 http server
16
- new HttpServer(app);
17
-
18
- // 启动 electron ipc server
19
- new IpcServer(app);
20
-
21
- }
22
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes