@agung_dhewe/webapps 1.1.2

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 (130) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +2 -0
  3. package/jsconfig.json +10 -0
  4. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.css +2 -0
  5. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +11 -0
  6. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +1 -0
  7. package/libs/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
  8. package/libs/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
  9. package/libs/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
  10. package/libs/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
  11. package/libs/fgta5js-dist/fonts/karla.css +142 -0
  12. package/libs/webmodule/module-edit.css +163 -0
  13. package/libs/webmodule/module-footer.css +22 -0
  14. package/libs/webmodule/module-list.css +25 -0
  15. package/libs/webmodule/module.css +52 -0
  16. package/libs/webmodule/module.js +195 -0
  17. package/libs/webmodule/pagehelper.mjs +45 -0
  18. package/modules/generator/appgen-components.mjs +142 -0
  19. package/modules/generator/appgen-icons.mjs +6 -0
  20. package/modules/generator/appgen-io.mjs +784 -0
  21. package/modules/generator/appgen-ui-search.mjs +173 -0
  22. package/modules/generator/appgen-ui-unique.mjs +153 -0
  23. package/modules/generator/appgen-ui.mjs +1181 -0
  24. package/modules/generator/generator-context.mjs +18 -0
  25. package/modules/generator/generator-designtemplate.html +1508 -0
  26. package/modules/generator/generator-ext.html +0 -0
  27. package/modules/generator/generator-ext.mjs +3 -0
  28. package/modules/generator/generator.css +642 -0
  29. package/modules/generator/generator.mjs +195 -0
  30. package/modules/generator/generator.png +0 -0
  31. package/modules/generator/generatorEdit.html +185 -0
  32. package/modules/generator/generatorEdit.mjs +238 -0
  33. package/modules/generator/generatorList.html +32 -0
  34. package/modules/generator/generatorList.mjs +243 -0
  35. package/modules/login/login.css +11 -0
  36. package/modules/login/login.html +12 -0
  37. package/modules/login/login.mjs +111 -0
  38. package/package.json +46 -0
  39. package/percobaan/simmpan-ke-minio.js +24 -0
  40. package/src/api.js +80 -0
  41. package/src/apis/generator.api.js +226 -0
  42. package/src/apis/login.api.js +109 -0
  43. package/src/bucket.js +24 -0
  44. package/src/context.js +26 -0
  45. package/src/datalog.sql +22 -0
  46. package/src/datarecords.js +0 -0
  47. package/src/db.js +61 -0
  48. package/src/generator/createApiExtenderModule.js +54 -0
  49. package/src/generator/createApiModule.js +218 -0
  50. package/src/generator/createIcon.js +62 -0
  51. package/src/generator/createInfoAboutExtender.js +42 -0
  52. package/src/generator/createInfoLogs.js +41 -0
  53. package/src/generator/createInfoRecordExtender.js +41 -0
  54. package/src/generator/createModuleContext.js +48 -0
  55. package/src/generator/createModuleDetilEditHtml.js +110 -0
  56. package/src/generator/createModuleDetilEditMjs.js +172 -0
  57. package/src/generator/createModuleDetilListHtml.js +146 -0
  58. package/src/generator/createModuleDetilListMjs.js +73 -0
  59. package/src/generator/createModuleEjs.js +51 -0
  60. package/src/generator/createModuleExtenderHtml.js +43 -0
  61. package/src/generator/createModuleExtenderMjs.js +43 -0
  62. package/src/generator/createModuleHeaderEditHtml.js +148 -0
  63. package/src/generator/createModuleHeaderEditMjs.js +197 -0
  64. package/src/generator/createModuleHeaderListHtml.js +144 -0
  65. package/src/generator/createModuleHeaderListMjs.js +67 -0
  66. package/src/generator/createModuleMjs.js +67 -0
  67. package/src/generator/createModuleRollup.js +42 -0
  68. package/src/generator/createProgramData.js +96 -0
  69. package/src/generator/createTable.js +156 -0
  70. package/src/generator/ddl.js +475 -0
  71. package/src/generator/helper.js +149 -0
  72. package/src/generator/templates/__rollup-module.ejs +90 -0
  73. package/src/generator/templates/api-extender-module.js.ejs +0 -0
  74. package/src/generator/templates/api-module.js.ejs +818 -0
  75. package/src/generator/templates/module-context.ejs +16 -0
  76. package/src/generator/templates/module-ext-about.ejs +1 -0
  77. package/src/generator/templates/module-ext-record.ejs +1 -0
  78. package/src/generator/templates/module-ext.html.ejs +3 -0
  79. package/src/generator/templates/module-ext.mjs.ejs +21 -0
  80. package/src/generator/templates/module-logs.ejs +14 -0
  81. package/src/generator/templates/module.ejs.ejs +48 -0
  82. package/src/generator/templates/module.mjs.ejs +256 -0
  83. package/src/generator/templates/moduleDetilEdit.html.ejs +34 -0
  84. package/src/generator/templates/moduleDetilEdit.mjs.ejs +792 -0
  85. package/src/generator/templates/moduleDetilList.html.ejs +26 -0
  86. package/src/generator/templates/moduleDetilList.mjs.ejs +319 -0
  87. package/src/generator/templates/moduleHeaderEdit.html.ejs +53 -0
  88. package/src/generator/templates/moduleHeaderEdit.mjs.ejs +807 -0
  89. package/src/generator/templates/moduleHeaderList.html.ejs +24 -0
  90. package/src/generator/templates/moduleHeaderList.mjs.ejs +308 -0
  91. package/src/generator/templates/sqlAddField.ejs +3 -0
  92. package/src/generator/templates/sqlAddForeignKey.ejs +12 -0
  93. package/src/generator/templates/sqlAddUniqueIndex.ejs +4 -0
  94. package/src/generator/templates/sqlCreateTable.ejs +9 -0
  95. package/src/generator/templates/sqlDropForeignKey.ejs +3 -0
  96. package/src/generator/templates/sqlDropUniqueIndex.ejs +4 -0
  97. package/src/generator/templates/sqlModifyField.ejs +6 -0
  98. package/src/generator/trygenerate.js +83 -0
  99. package/src/generator/worker.js +389 -0
  100. package/src/helper.js +82 -0
  101. package/src/logger.js +39 -0
  102. package/src/router.js +84 -0
  103. package/src/routers/defaultLoginApi.js +29 -0
  104. package/src/routers/defaultLoginAsset.js +18 -0
  105. package/src/routers/defaultLoginPage.js +36 -0
  106. package/src/routers/defaultRootIndex.js +16 -0
  107. package/src/routers/downloadHandler.js +51 -0
  108. package/src/routers/fileUploadApi.js +15 -0
  109. package/src/routers/generatorApi.js +30 -0
  110. package/src/routers/generatorAsset.js +18 -0
  111. package/src/routers/generatorPage.js +37 -0
  112. package/src/routers/handleError.js +43 -0
  113. package/src/routers/handleModuleNotfound.js +12 -0
  114. package/src/routers/moduleApi.js +34 -0
  115. package/src/routers/modulePage.js +102 -0
  116. package/src/sequencerdoc.js +311 -0
  117. package/src/sequencerline.js +214 -0
  118. package/src/session.js +57 -0
  119. package/src/startup.js +59 -0
  120. package/src/webapps.js +239 -0
  121. package/src/workermanager.js +83 -0
  122. package/templates/_lib_debug.ejs +11 -0
  123. package/templates/_lib_production.ejs +5 -0
  124. package/templates/application.page.ejs +143 -0
  125. package/templates/generator.page.ejs +131 -0
  126. package/templates/index.page.ejs +24 -0
  127. package/templates/login.page.ejs +102 -0
  128. package/templates/moduleError.ejs +16 -0
  129. package/templates/moduleNotfound.ejs +14 -0
  130. package/webapps.code-workspace +11 -0
@@ -0,0 +1,24 @@
1
+ <div class="search-container">
2
+ <div id="<%= modulePart %>-pnl_search" class="search-parameters">
3
+ <input id="<%= modulePart %>-txt_searchtext" fgta5-component="Textbox" placeholder="search" autocomplete="off" spellcheck="false" binding="searchtext" data-searchinput>
4
+ </div>
5
+ <button id="<%= modulePart %>-btn_gridload">Load</button>
6
+ </div>
7
+
8
+ <table id="<%= modulePart %>-tbl" fgta5-component="Gridview">
9
+ <thead>
10
+ <tr data-header key="<%= section.primaryKey %>"><% fields.forEach(field => { %>
11
+ <th data-name="<%= field.dataName %>" binding="<%= field.binding %>" <%- field.additionalAttributes %>><%= field.label %></th><% }); %>
12
+ </tr>
13
+ </thead>
14
+ </table>
15
+
16
+
17
+
18
+ <div class="footer-buttons-container">
19
+ <div></div>
20
+ <div>
21
+ <button id="<%=modulePart%>-btn_new" data-action="<%= moduleSection %>-new" data-sectionsource="<%=modulePart%>-section">New</button>
22
+ </div>
23
+ <div></div>
24
+ </div>
@@ -0,0 +1,308 @@
1
+ import Context from './<%= moduleName %>-context.mjs'
2
+ import * as Extender from './<%= moduleName %>-ext.mjs'
3
+
4
+
5
+ const Crsl = Context.Crsl
6
+ const CurrentSectionId = Context.Sections.<%= modulePart %>
7
+ const CurrentSection = Crsl.Items[CurrentSectionId]
8
+ const CurrentState = {}
9
+
10
+ const tbl = new $fgta5.Gridview('<%= modulePart %>-tbl')
11
+ const pnl_search = document.getElementById('<%= modulePart %>-pnl_search')
12
+ const btn_gridload = new $fgta5.ActionButton('<%= modulePart %>-btn_gridload')
13
+
14
+ export const Section = CurrentSection
15
+ export const SearchParams = {}
16
+
17
+ export async function init(self, args) {
18
+ console.log('initializing <%= modulePart %> ...')
19
+
20
+ // add event listener
21
+ tbl.addEventListener('nextdata', async evt=>{ tbl_nextdata(self, evt) })
22
+ tbl.addEventListener('sorting', async evt=>{ tbl_sorting(self, evt) })
23
+
24
+
25
+ // tambahkan event lain di extender: rowrender, rowremoving
26
+ // dapatkan parameternya di evt.detail
27
+ const fn_addTableEvents_name = '<%= sectionName %>List_addTableEvents'
28
+ const fn_addTableEvents = Extender[fn_addTableEvents_name]
29
+ if (typeof fn_addTableEvents === 'function') {
30
+ fn_addTableEvents(self, tbl)
31
+ }
32
+
33
+ if (Module.isMobileDevice()) {
34
+ tbl.addEventListener('cellclick', async evt=>{ tbl_cellclick(self, evt) })
35
+ } else {
36
+ tbl.addEventListener('celldblclick', async evt=>{ tbl_cellclick(self, evt) })
37
+ }
38
+
39
+ btn_gridload.addEventListener('click', async evt=>{ btn_gridload_click(self, evt) })
40
+
41
+
42
+ try {
43
+ // extract custom search panel from template
44
+ const tplSearchPanel = document.querySelector('template[name="custom-search-panel"]')
45
+ if (tplSearchPanel!=null) {
46
+ const clone = tplSearchPanel.content.cloneNode(true); // salin isi template
47
+ pnl_search.prepend(clone)
48
+ }
49
+
50
+ // setup search panel
51
+ const cmps = pnl_search.querySelectorAll('[fgta5-component][binding]')
52
+ for (var cmp of cmps) {
53
+ var id = cmp.getAttribute('id')
54
+ var componentname = cmp.getAttribute('fgta5-component')
55
+ var binding = cmp.getAttribute('binding')
56
+ SearchParams[binding] = new $fgta5[componentname](id)
57
+ }
58
+
59
+ // saat user ketik tombol enter di text search, lakukan load data
60
+ const obj_searchtext = document.getElementById('<%= modulePart %>-txt_searchtext')
61
+ const btn_load = document.getElementById('<%= modulePart %>-btn_gridload')
62
+ obj_searchtext.addEventListener('keydown', (evt)=>{
63
+ if (evt.key.toLowerCase()=='enter') {
64
+ evt.stopPropagation()
65
+ btn_load.click()
66
+ obj_searchtext.blur()
67
+ }
68
+ })
69
+
70
+
71
+ // <%= modulePart %>-ext.mjs, export function initSearchParams(self, SearchParams) {}
72
+ const fn_initSearchParams_name = '<%= sectionName %>List_initSearchParams'
73
+ const fn_initSearchParams = Extender[fn_initSearchParams_name]
74
+ if (typeof fn_initSearchParams === 'function') {
75
+ fn_initSearchParams(self, SearchParams)
76
+ } else {
77
+ console.warn(`'initSearchParams' tidak diimplementasikan di extender`)
78
+ }
79
+
80
+ } catch (err) {
81
+ throw err
82
+ } finally {
83
+ // load data
84
+ if (args.autoLoadGridData===true) {
85
+ loadData(self)
86
+ }
87
+ }
88
+
89
+
90
+ }
91
+
92
+ export async function loadData(self) {
93
+ await tbl.clear()
94
+ tbl_loadData(self)
95
+ }
96
+
97
+
98
+ export function getGrid(self) {
99
+ return tbl
100
+ }
101
+
102
+ export function getCurrentRow(self) {
103
+ return CurrentState.SelectedRow
104
+ }
105
+
106
+ export function addNewRow(self, data) {
107
+ const tr = tbl.addRow(data)
108
+ setCurrentRow(self, tr)
109
+ }
110
+
111
+ export function updateCurrentRow(self, data) {
112
+ const tr = CurrentState.SelectedRow
113
+
114
+ try {
115
+ tbl.updateRow(tr, data)
116
+ } catch (err) {
117
+ throw err
118
+ }
119
+ }
120
+
121
+ export function removeCurrentRow(self) {
122
+ const tr = CurrentState.SelectedRow
123
+ tbl.removeRow(tr)
124
+ }
125
+
126
+ export function selectNextRow(self) {
127
+ const tr = CurrentState.SelectedRow
128
+ if (tr.nextElementSibling) {
129
+ tbl.CurrentRow = tr.nextElementSibling
130
+ openRow(self, tr.nextElementSibling)
131
+ }
132
+ }
133
+
134
+ export function selectPreviousRow(self) {
135
+ const tr = CurrentState.SelectedRow
136
+ if (tr.previousElementSibling) {
137
+ tbl.CurrentRow = tr.previousElementSibling
138
+ openRow(self, tr.previousElementSibling)
139
+ }
140
+ }
141
+
142
+
143
+ export function setPagingButton(self, editModule) {
144
+ const tr = CurrentState.SelectedRow
145
+
146
+ if (tr.previousElementSibling) {
147
+ editModule.disablePrevButton(self, false)
148
+ } else {
149
+ editModule.disablePrevButton(self, true)
150
+ }
151
+
152
+ if (tr.nextElementSibling) {
153
+ editModule.disableNextButton(self, false)
154
+ } else {
155
+ editModule.disableNextButton(self, true)
156
+ }
157
+
158
+ }
159
+
160
+ export function keyboardAction(self, actionName, evt) {
161
+ if (actionName=='up') {
162
+ tbl.previousRecord()
163
+ } else if (actionName=='down') {
164
+ tbl.nextRecord()
165
+ } else if (actionName=='enter') {
166
+ const <%= moduleEdit %> = self.Modules.<%= moduleEdit %>
167
+ <%= moduleEdit %>.Section.show({}, ()=>{
168
+ openRow(self, tbl.CurrentRow)
169
+ })
170
+ } else if (actionName=='typing') {
171
+ evt.preventDefault();
172
+ evt.stopPropagation();
173
+
174
+ const obj_searchtext = document.getElementById('<%= modulePart %>-txt_searchtext')
175
+ const key = evt.key
176
+ obj_searchtext.focus()
177
+ if (key=='Backspace') {
178
+ Module.deleteAtCursor(obj_searchtext, 'backspace');
179
+ } else if (key=='Delete') {
180
+ Module.deleteAtCursor(obj_searchtext, 'delete');
181
+ } else {
182
+ Module.insertAtCursor(obj_searchtext, evt.key);
183
+ }
184
+ }
185
+ }
186
+
187
+
188
+ function setCurrentRow(self, tr) {
189
+ CurrentState.SelectedRow = tr
190
+ }
191
+
192
+ async function openRow(self, tr) {
193
+ const keyvalue = tr.getAttribute('keyvalue')
194
+ const key = tr.getAttribute('key')
195
+
196
+ const <%= moduleEdit %> = self.Modules.<%= moduleEdit %>
197
+ <%= moduleEdit %>.clearForm(self, 'loading...')
198
+
199
+ try {
200
+ setCurrentRow(self, tr)
201
+ CurrentState.SelectedRow.keyValue = keyvalue
202
+ CurrentState.SelectedRow.key = key
203
+ await <%= moduleEdit %>.openSelectedData(self, {key:key, keyvalue:keyvalue})
204
+ } catch (err) {
205
+ console.error(err)
206
+ await $fgta5.MessageBox.error(err.message)
207
+
208
+ setCurrentRow(self, null)
209
+ CurrentSection.show() // kembalikan ke list kalau error saat buka data
210
+ }
211
+
212
+
213
+ // matikan atau nyalakan button prev/next sesuai kondisi
214
+ setPagingButton(self, <%= moduleEdit %>)
215
+ }
216
+
217
+ async function listRows(self, criteria, offset,limit, sort) {
218
+ const url = `/${Context.moduleName}/header-list`
219
+ try {
220
+ const columns = []
221
+ const result = await Module.apiCall(url, {
222
+ columns,
223
+ criteria,
224
+ offset,
225
+ limit,
226
+ sort
227
+ })
228
+ return result
229
+ } catch (err) {
230
+ throw err
231
+ }
232
+ }
233
+
234
+ async function tbl_nextdata(self, evt) {
235
+ const criteria = evt.detail.criteria
236
+ const limit = evt.detail.limit
237
+ const offset = evt.detail.nextoffset
238
+ const sort = evt.detail.sort
239
+
240
+ await tbl_loadData(self, {criteria, limit, offset, sort})
241
+ tbl.scrollToFooter()
242
+ }
243
+
244
+ function tbl_sorting(self, evt) {
245
+ tbl.clear()
246
+ const sort = evt.detail.sort
247
+ const criteria = evt.detail.Criteria
248
+ tbl_loadData(self, {criteria, sort})
249
+ }
250
+
251
+ function tbl_cellclick(self, evt) {
252
+ const tr = evt.detail.tr
253
+
254
+ const <%= moduleEdit %> = self.Modules.<%= moduleEdit %>
255
+ <%= moduleEdit %>.Section.show({}, (evt)=>{
256
+ openRow(self, tr)
257
+ })
258
+
259
+
260
+ }
261
+
262
+ async function tbl_loadData(self, params={}) {
263
+ console.log('loading <%= moduleSection %> data')
264
+ console.log(params)
265
+
266
+ const { criteria={}, limit=0, offset=0, sort={} } = params
267
+
268
+ // isi criteria
269
+ for (var key in SearchParams) {
270
+ var cmp = SearchParams[key]
271
+ var valid = cmp.validate()
272
+ if (!valid) {
273
+ console.error('ada yang belum diisi')
274
+ return false
275
+ }
276
+ criteria[key] = SearchParams[key].value
277
+ }
278
+
279
+
280
+ // cek sorting
281
+ if (sort===undefined) {
282
+ sort = tbl.getSort()
283
+ }
284
+
285
+
286
+ let mask = $fgta5.Modal.createMask()
287
+ try {
288
+ const result = await listRows(self, criteria, offset,limit, sort)
289
+
290
+ if (offset===0) {
291
+ tbl.clear()
292
+ }
293
+ tbl.addRows(result.data)
294
+ tbl.setNext(result.nextoffset, result.limit)
295
+ } catch (err) {
296
+ console.error(err)
297
+ $fgta5.MessageBox.error(err.message)
298
+ } finally {
299
+ mask.close()
300
+ mask = null
301
+ }
302
+
303
+ }
304
+
305
+ function btn_gridload_click(self, evt) {
306
+ setCurrentRow(self, null)
307
+ loadData(self)
308
+ }
@@ -0,0 +1,3 @@
1
+ -- ADD <%=fieldname%>
2
+ alter table <%=schema%>."<%=tablename%>" add <%=fieldname%> <%=type%> <%=setnull%> <%-setdefault%>;
3
+ comment on column <%=schema%>."<%=tablename%>".<%=fieldname%> is '<%-description%>';
@@ -0,0 +1,12 @@
1
+ -- Add Foreign Key Constraint <% fkList.forEach(fk => { %>
2
+ ALTER TABLE <%= schema %>."<%= tablename %>"
3
+ ADD CONSTRAINT <%= fk.ref_name %>
4
+ FOREIGN KEY (<%= fk.fieldname %>)
5
+ REFERENCES <%= fk.ref_schema %>."<%= fk.ref_tablename %>"(<%= fk.ref_fieldname %>);
6
+
7
+
8
+ -- Add As Index, drop dulu jika sudah ada
9
+ DROP INDEX IF EXISTS <%= schema %>.idx_<%= fk.ref_name %>;
10
+ CREATE INDEX idx_<%= fk.ref_name %> ON <%= schema %>."<%= tablename %>"(<%= fk.fieldname %>);
11
+
12
+ <% }) %>
@@ -0,0 +1,4 @@
1
+ -- Add unique index <% data.forEach(uniq => { %>
2
+ alter table <%= schema %>."<%= tablename %>"
3
+ add constraint <%= uniq.uniquename %> unique (<%- uniq.uniquefields %>);
4
+ <% }); %>
@@ -0,0 +1,9 @@
1
+ /* =============================================
2
+ * CREATE TABLE <%=schema%>."<%=tablename%>"
3
+ * ============================================*/
4
+ create table <%=schema%>."<%=tablename%>" (
5
+ <%=fieldname%> <%=type%>,
6
+ constraint <%=tablename%>_pk primary key (<%=fieldname%>)
7
+ );
8
+ comment on table <%=schema%>."<%=tablename%>" is '<%-tabledescr%>';
9
+
@@ -0,0 +1,3 @@
1
+ -- Drop Existing Foreign Key Constraint <% existingFk.forEach(fk => { %>
2
+ ALTER TABLE <%= schema %>."<%= tablename %>" DROP CONSTRAINT <%= fk.constraint_name %>;<% }) %>
3
+
@@ -0,0 +1,4 @@
1
+ -- Drop existing unique index <% existingUniques.forEach(uniq => { %>
2
+ alter table <%=schema%>."<%=tablename%>"
3
+ drop constraint <%= uniq.constraint_name %>;
4
+ <% }); %>
@@ -0,0 +1,6 @@
1
+ -- MODIFY <%=fieldname%>
2
+ alter table <%=schema%>."<%=tablename%>"
3
+ alter column <%=fieldname%> type <%=type%>,
4
+ <%-alterdefault%>,
5
+ <%=alternull%>;
6
+ comment on column <%=schema%>."<%=tablename%>".<%=fieldname%> is '<%-description%>';
@@ -0,0 +1,83 @@
1
+ import dotenv from 'dotenv'
2
+ import { Worker } from 'worker_threads'
3
+
4
+ dotenv.config()
5
+
6
+
7
+
8
+ console.log('Testing Generator')
9
+
10
+ const args = process.argv.slice(2)
11
+ const generator_id = args[0]
12
+
13
+ if (generator_id==null) {
14
+ console.log("\n\n\x1b[1m\x1b[31mERROR\x1b[0m")
15
+ console.log("format: npm run generate \x1b[33m<generator_id>\x1b[0m\n\n")
16
+ process.exit(1)
17
+ }
18
+
19
+
20
+ const workerTimeoutMs = 1*60*1000
21
+
22
+
23
+ await main(generator_id)
24
+
25
+
26
+ async function main(generator_id) {
27
+ console.log(`Start to generate program id:'${generator_id}'`)
28
+
29
+ try {
30
+ const workerPath = './src/generator/worker.js'
31
+ const worker = new Worker(workerPath, {
32
+ workerData: {
33
+ generator_id,
34
+ user_id: 1,
35
+ user_name: 'coredeveloper',
36
+ ipaddress: 'local-cli'
37
+ }
38
+ }, workerTimeoutMs)
39
+
40
+ const timeoutId = setTimeout(()=>{
41
+ console.log("\n\n\x1b[1m\x1b[31mERROR\x1b[0m")
42
+ console.log('Worker timeout')
43
+ worker.terminate()
44
+ }, workerTimeoutMs)
45
+
46
+
47
+ worker.on('message', (info)=>{
48
+ clearTimeout(timeoutId)
49
+ console.log(info.message)
50
+ if (info.done===true) {
51
+ worker.done = true
52
+ worker.terminate()
53
+ }
54
+ })
55
+
56
+
57
+ worker.on('error', (err)=>{
58
+ clearTimeout(timeoutId)
59
+ console.log("\n\n\x1b[1m\x1b[31mERROR\x1b[0m")
60
+ console.error(err)
61
+ console.log("\n\n")
62
+ worker.terminate()
63
+ })
64
+
65
+
66
+ worker.on('exit', (code)=>{
67
+ clearTimeout(timeoutId)
68
+ if (worker.done===true) {
69
+ console.log('Worker finished')
70
+ } else {
71
+ console.log(`Worker exited with code ${code}`)
72
+ }
73
+ console.log("\n\n")
74
+ })
75
+
76
+
77
+ } catch (err) {
78
+ console.log("\n\n\x1b[1m\x1b[31mERROR\x1b[0m")
79
+ console.log(err.message)
80
+ process.exit(1)
81
+ }
82
+ }
83
+