logic-auto 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.
@@ -0,0 +1,471 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const mm = require('micromatch');
4
+ const at = require('./auto-task');
5
+
6
+ class DependResolver {
7
+
8
+ /*_______________________________________*/
9
+ // protectd
10
+ _auto = null;
11
+ _list = [];
12
+ _paths = [];
13
+ _task = at.AutoTask.getInstance();
14
+ // _entry = this._task.entry;
15
+
16
+ /*_______________________________________*/
17
+ //private
18
+ #patterns = [];
19
+
20
+ constructor(auto, json) {
21
+ this._auto = auto;
22
+ if (json) this.#load(json);
23
+ // this.#patterns.push({target: '**', include: '**'});
24
+ }
25
+
26
+
27
+ /*_______________________________________*/
28
+ // public method
29
+
30
+ /**
31
+ * 객체 얻기
32
+ * @returns {this}
33
+ */
34
+ getObject() {
35
+
36
+ var obj = { pattern: []};
37
+
38
+ this.#patterns.forEach( val => { obj.pattern.push(val) });
39
+ return obj;
40
+ }
41
+
42
+ /**
43
+ * 해결대상과 해결참조 읽기 (불러오기)
44
+ */
45
+ read() {
46
+ this._readOriginal();
47
+ this._readReference();
48
+ }
49
+
50
+ /**
51
+ * 의존성 처리
52
+ */
53
+ resolve() {
54
+
55
+ let arr, OriginalPath, data, keyword;
56
+ let list = [];
57
+ const entry = this._task.entry;
58
+
59
+ // 이벤트 발생
60
+ this._auto._onResolve(this._task.cursor, this._auto);
61
+
62
+ // 원본 소스 조회
63
+ for (let i = 0; i < this._list.length; i++) {
64
+ arr = this.#getPathList(this._list[i]);
65
+ data = this._list[i].origin.data;
66
+ // 참조 대상 조회
67
+ for (let ii = 0; ii < arr.length; ii++) {
68
+ // 대상의 상대, 절대 경로
69
+ list = []; // 초기화
70
+ OriginalPath = arr[ii].OriginalPath;
71
+ for (let iii = 0; iii < arr[ii].paths.length; iii++) {
72
+ keyword = arr[ii].paths[iii].info;
73
+ // list = list.concat(this.#getMatch(keyword, data, arr[ii].paths[iii].type)); // 벼열 합침
74
+ list = list.concat(this.#getMatch(keyword, data, arr[ii].paths[iii].type, this._list[i].origin.name)); // REVIEW:: 디버깅시
75
+ }
76
+ // 참조가 있으면 등록
77
+ if (list.length > 0) {
78
+ this._list[i].origin.addDepend(OriginalPath, list);
79
+ }
80
+ }
81
+ }
82
+
83
+ // 관계파일 자동 저장시
84
+ if (this._auto === entry && entry.isSaveRelation === true) this.saveRelation();
85
+
86
+ // 이벤트 발생
87
+ this._auto._onResolved(this._task.cursor, this._auto);
88
+ }
89
+
90
+ /**
91
+ * 의존성 정보 저장 : __Relation.json
92
+ */
93
+ saveRelation() {
94
+
95
+ const entry = this._task.entry;
96
+ const saveName = this._task.FILE.RELATION;
97
+ let obj = {};
98
+
99
+ // 내부함수 : relation.json 객체 생성
100
+ function createRelation(collection, obj) {
101
+
102
+ let elem, name, oriPath, depPath;
103
+
104
+ for (let i = 0; i < collection.count; i++) {
105
+ elem = collection[i];
106
+ oriPath = collection[i].localPath;
107
+ obj[oriPath] = {};
108
+ elem._dep.forEach(v => {
109
+ depPath = v.ref.localPath;
110
+ obj[oriPath][depPath] = [];
111
+ if (v.pos) {
112
+ // 정렬
113
+ v.pos.sort(function (a,b) {
114
+ if (a.idx > b.idx) return 1;
115
+ if (a.idx === b.idx) return 0;
116
+ if (a.idx < b.idx) return -1;
117
+ });
118
+ // 샆입
119
+ v.pos.forEach(vv => {
120
+ obj[oriPath][depPath].push({
121
+ idx: vv.idx,
122
+ line: vv.line,
123
+ key: vv.key
124
+ });
125
+ });
126
+ }
127
+ });
128
+ }
129
+ }
130
+
131
+ createRelation(entry.out, obj); // out 관계 객체 생성
132
+ createRelation(entry.src, obj); // src 관계 객체 생성
133
+
134
+ console.log(`${saveName} 파일 저장`);
135
+ let data = JSON.stringify(obj, null, '\t');
136
+ fs.writeFileSync(entry.dir + path.sep + saveName, data, 'utf8');
137
+ }
138
+
139
+ /**
140
+ * 포함할 경로 설정
141
+ * @param {*} target 대상 원보 glob 패턴
142
+ * @param {*} include 포함할 패턴
143
+ * @param {*} exclude 제외할 패ㄴ
144
+ */
145
+ setPattern(target, include, exclude) {
146
+ this.#patterns.push({
147
+ target: target,
148
+ include: include,
149
+ exclude: exclude,
150
+ });
151
+ }
152
+
153
+ /**
154
+ * src, out, vir 경로에 대한 패턴 경로 얻기 : _paths[*]
155
+ * @param {string} localPath
156
+ * @returns {array<string>}
157
+ */
158
+ getPattern(localPath) {
159
+
160
+ let target = [], include = [], exclude =[];
161
+ let arr = [], list;
162
+
163
+ list = this._getList(localPath);
164
+ if (list.length < 0) {
165
+ return arr;
166
+ }
167
+
168
+ // 소스에 포함되는 패턴 조회
169
+ for(let i = 0; i < this.#patterns.length; i++) {
170
+ if (mm.isMatch(localPath, this.#patterns[i].target)) {
171
+ target.push(this.#patterns[i].target);
172
+ include.push(this.#patterns[i].include);
173
+ exclude.push(this.#patterns[i].exclude);
174
+ }
175
+ }
176
+
177
+ // 전체 적용패턴이 없을 경우 모두 리턴
178
+ if (target.length === 0) return this._getPaths();
179
+
180
+ // include 패턴 적용
181
+ arr = mm.match(this._getPaths(), include);
182
+ // exclude 패턴 적용
183
+ arr = mm.not(arr, exclude);
184
+
185
+ return arr;
186
+ }
187
+
188
+ /**
189
+ * src, out, vir 경로에 대한 패턴 객체 얻기 : _paths[*]
190
+ * @param {string} localPath
191
+ * @returns {array<string>}}
192
+ */
193
+ getPatternObj(localPath) {
194
+
195
+ let arr = [];
196
+ let pattern = this.getPattern(localPath);
197
+
198
+ // 대상에 정의된 패턴이 없으면 전체 리턴
199
+ if (pattern.length === 0) return this._paths;
200
+
201
+ for (let i = 0; i < this._paths.length; i++) {
202
+ if (pattern.indexOf(this._paths[i].path) > -1 ) arr.push(this._paths[i]);
203
+ }
204
+ return arr;
205
+ }
206
+
207
+ /*_______________________________________*/
208
+ // protected method
209
+
210
+ /**
211
+ * 참조 경로 배열 리턴
212
+ * @returns {array}
213
+ */
214
+ _getPaths(isObj) {
215
+
216
+ let arr = [];
217
+
218
+ for (let i = 0; i < this._paths.length; i++) {
219
+ arr.push(this._paths[i].path);
220
+ }
221
+ return arr;
222
+ }
223
+
224
+ /**
225
+ * 원본 경로 배열 리턴
226
+ * @returns {array}
227
+ */
228
+ _getList(isObj) {
229
+
230
+ let arr = [];
231
+
232
+ for (let i = 0; i < this._list.length; i++) {
233
+ arr.push(this._list[i].path);
234
+ }
235
+ return arr;
236
+ }
237
+
238
+
239
+ /**
240
+ * patterns : 패턴
241
+ * 대상패턴, 포함패턴[*], 제외패턴[*]
242
+ * src/*.js, **
243
+ * 파일에 대한 패턴이 중복되는 이슈가 있다.
244
+ * - 경로를 기준으로 대상패턴을 조회한다.
245
+ * - 대상에 대한 패턴을 조회하여 적합한 파일을 찾는다.
246
+ * - list별 paths를 가져외서 의존성을 해결한다.
247
+ */
248
+
249
+ /**
250
+ * 원본 읽기 (해결대상)
251
+ */
252
+ _readOriginal() {
253
+
254
+ function createObject(OriginalPath, location, alias = '') {
255
+ let objPath = {
256
+ path: OriginalPath.localPath,
257
+ origin: OriginalPath,
258
+ location: location,
259
+ include: ['*.*'],
260
+ exclude: [],
261
+ };
262
+ return objPath;
263
+ }
264
+
265
+ // src 가져오기
266
+ for (let i = 0; i < this._auto.src.count; i++) {
267
+ this._list.push(createObject(this._auto.src[i], 'src'));
268
+ }
269
+ // out 가져오기
270
+ for (let i = 0; i < this._auto.out.count; i++) {
271
+ this._list.push(createObject(this._auto.out[i], 'out'));
272
+ }
273
+ }
274
+
275
+ /**
276
+ * 참조대상 읽기
277
+ */
278
+ _readReference() {
279
+
280
+ let alias = '';
281
+
282
+ function createObject(OriginalPath, location, alias = '') {
283
+ let objPath = {
284
+ path: OriginalPath.localPath,
285
+ origin: OriginalPath,
286
+ location: location,
287
+ alias: alias,
288
+ };
289
+ return objPath;
290
+ }
291
+
292
+ // src 가져오기
293
+ for (let i = 0; i < this._auto.src.count; i++) {
294
+ this._paths.push(createObject(this._auto.src[i], 'src'));
295
+ }
296
+ // out 가져오기
297
+ for (let i = 0; i < this._auto.out.count; i++) {
298
+ this._paths.push(createObject(this._auto.out[i], 'out'));
299
+ }
300
+ // dep 가져오기
301
+ for (let i = 0; i < this._auto.dep.count; i++) {
302
+ alias = this._auto.dep.properties[i]; // 별칭 얻기
303
+ for (let ii = 0; ii < this._auto.dep[i].count; ii++) {
304
+ this._paths.push(createObject(this._auto.dep[i][ii], 'dep', alias));
305
+ }
306
+ }
307
+ // vir 가져오기
308
+ for (let i = 0; i < this._auto.vir.count; i++) {
309
+ this._paths.push(createObject(this._auto.vir[i], 'vir'));
310
+ }
311
+ }
312
+
313
+ /*_______________________________________*/
314
+ // private method
315
+
316
+ /**
317
+ * 설정파일 로딩
318
+ * @param {JSON} json
319
+ */
320
+ #load(json) {
321
+
322
+ let obj;
323
+
324
+ if (json && Array.isArray(json.pattern)) {
325
+ for (let i = 0; i < json.pattern.length; i++) {
326
+ obj = json.pattern[i];
327
+ if (obj.target && (obj.include || obj.exclude)) this.#patterns.push(obj);
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * _ref 참조경로에 대한 상대경로와 절대경로를 배열로 리턴
334
+ * @param {*} obj
335
+ * @returns {array}
336
+ */
337
+ #getPathList(obj) {
338
+ //
339
+ let arr = [];
340
+ let relativePath = null;
341
+ let OriginalPath, dir, localPath, aliasPath;
342
+ let paths = [];
343
+
344
+ // 내부함수
345
+ function createPathList(OriginalPath, ...paths) {
346
+ let key = {
347
+ OriginalPath: OriginalPath,
348
+ paths: paths, // {type: 절대(1), 상대(2), 사용자(3) | info: }
349
+ };
350
+ return key;
351
+ }
352
+
353
+ paths = this.getPatternObj(obj.path);
354
+
355
+ /**
356
+ * src 참조위치 : src, out, dep
357
+ * out 참조위치 : out (자신만 참조) <= 너무 폐쇠적인 구조임
358
+ */
359
+ // if (obj.location === 'src') {
360
+ // for (let i = 0; i < paths.length; i++) {
361
+ // OriginalPath = paths[i].origin;
362
+ // if (['src', 'out'].indexOf(paths[i].location) > -1) {
363
+ // // 절대경로
364
+ // localPath = path.sep + OriginalPath.localPath;
365
+ // dir = path.dirname(obj.origin.fullPath);
366
+ // // 상대경로
367
+ // relativePath = path.relative(dir, OriginalPath.fullPath);
368
+ // // arr.push(createPathList(OriginalPath, localPath, relativePath));
369
+ // arr.push(createPathList(OriginalPath, { type: 1, info: localPath }, { type: 2, info: relativePath }));
370
+ // } else if (paths[i].location === 'dep') {
371
+ // // 절대경로 (가상경로)
372
+ // aliasPath = path.sep + this._auto.LOC.DEP + path.sep + paths[i].alias + path.sep + OriginalPath.subPath;
373
+ // dir = path.dirname(obj.origin.fullPath);
374
+ // // 상대경로
375
+ // relativePath = path.relative(dir, this._auto.dir + path.sep + aliasPath);
376
+ // // arr.push(createPathList(OriginalPath, aliasPath, relativePath));
377
+ // arr.push(createPathList(OriginalPath, { type: 1, info: aliasPath }, { type: 2, info: relativePath }));
378
+ // }
379
+ // }
380
+ // } else if (obj.location === 'out') {
381
+ // for (let i = 0; i < paths.length; i++) {
382
+ // OriginalPath = paths[i].origin;
383
+ // if (['out'].indexOf(paths[i].location) > -1) {
384
+ // // 절대경로
385
+ // localPath = path.sep + OriginalPath.localPath;
386
+ // // 상대경로
387
+ // dir = path.dirname(obj.origin.fullPath);
388
+ // relativePath = path.relative(dir, OriginalPath.fullPath);
389
+ // // arr.push(createPathList(OriginalPath, localPath, relativePath));
390
+ // arr.push(createPathList(OriginalPath, { type: 1, info: localPath }, { type: 2, info: relativePath }));
391
+ // }
392
+ // }
393
+ // }
394
+ if (obj.location === 'src' || obj.location === 'out') {
395
+ for (let i = 0; i < paths.length; i++) {
396
+ OriginalPath = paths[i].origin;
397
+ if (['src', 'out'].indexOf(paths[i].location) > -1) {
398
+ // 절대경로
399
+ localPath = path.sep + OriginalPath.localPath;
400
+ dir = path.dirname(obj.origin.fullPath);
401
+ // 상대경로
402
+ relativePath = path.relative(dir, OriginalPath.fullPath);
403
+ // arr.push(createPathList(OriginalPath, localPath, relativePath));
404
+ arr.push(createPathList(OriginalPath, { type: 1, info: localPath }, { type: 2, info: relativePath }));
405
+ } else if (paths[i].location === 'dep') {
406
+ // 절대경로 (가상경로)
407
+ aliasPath = path.sep + this._auto.LOC.DEP + path.sep + paths[i].alias + path.sep + OriginalPath.subPath;
408
+ dir = path.dirname(obj.origin.fullPath);
409
+ // 상대경로
410
+ relativePath = path.relative(dir, this._auto.dir + path.sep + aliasPath);
411
+ // arr.push(createPathList(OriginalPath, aliasPath, relativePath));
412
+ arr.push(createPathList(OriginalPath, { type: 1, info: aliasPath }, { type: 2, info: relativePath }));
413
+ }
414
+ }
415
+ }
416
+ return arr;
417
+ }
418
+
419
+ /**
420
+ * 경로키로 내용(data)를 매칭 목록 객체를 얻는다.
421
+ * 매칭 객체 {idx, key, line, col }
422
+ * @param {*} strPath
423
+ * @param {*} data
424
+ * @param {*} type 절대, 상대
425
+ * @param {*} filename? 파일명 로그용
426
+ * @returns {array}
427
+ */
428
+ #getMatch(strPath, data, type = null, filename) {
429
+
430
+ let reg
431
+ let rArr = [];
432
+ let index;
433
+ let str = strPath;
434
+ let part, line, arrLine = [], column;
435
+
436
+ str = str.replaceAll('\\', "\\\\");
437
+ //str = str.replaceAll('/', '\/');
438
+ str = str.replaceAll('.', '\\.');
439
+
440
+ str = "(?:[^\\w\\\\/\\.])" + str + "(?:[^\\w\\\\/\\.])";
441
+
442
+ reg = RegExp(str, 'gi');
443
+
444
+ while(reg.exec(data)) {
445
+ if (reg.lastIndex === 0) break;
446
+
447
+ index = reg.lastIndex - strPath.length - 1
448
+ // line, column 구하기
449
+ part = data.substring(0, index); // 내용 조각
450
+ arrLine = part.split('\n');
451
+ line = arrLine.length;
452
+ column = arrLine[line - 1].length;
453
+ // if (line > 0) column = arrLine[line - 1].length;
454
+ // else column = index;
455
+
456
+ rArr.push({
457
+ idx: index,
458
+ key: strPath,
459
+ line: line,
460
+ col: column,
461
+ type: type,
462
+ });
463
+
464
+ // console.log(data)
465
+ if (this._auto?.isLog) console.log(`${filename} :: idx:${index} line:${line} column:${column} key:${strPath}`)
466
+ }
467
+ return rArr;
468
+ }
469
+ }
470
+
471
+ exports.DependResolver = DependResolver;