cyberia 3.0.1 → 3.0.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 (49) hide show
  1. package/.github/workflows/engine-cyberia.cd.yml +1 -0
  2. package/CHANGELOG.md +56 -1
  3. package/CLI-HELP.md +2 -4
  4. package/README.md +139 -0
  5. package/bin/build.js +5 -0
  6. package/bin/cyberia.js +385 -71
  7. package/bin/deploy.js +18 -26
  8. package/bin/file.js +3 -0
  9. package/bin/index.js +385 -71
  10. package/conf.js +32 -3
  11. package/deployment.yaml +2 -2
  12. package/manifests/cronjobs/dd-cron/dd-cron-backup.yaml +1 -1
  13. package/manifests/cronjobs/dd-cron/dd-cron-dns.yaml +1 -1
  14. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  15. package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
  16. package/manifests/ipfs/configmap.yaml +7 -0
  17. package/package.json +8 -8
  18. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.controller.js +2 -0
  19. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.model.js +7 -0
  20. package/src/api/atlas-sprite-sheet/atlas-sprite-sheet.service.js +93 -2
  21. package/src/api/file/file.controller.js +3 -13
  22. package/src/api/file/file.ref.json +0 -21
  23. package/src/api/ipfs/ipfs.controller.js +104 -0
  24. package/src/api/ipfs/ipfs.model.js +71 -0
  25. package/src/api/ipfs/ipfs.router.js +31 -0
  26. package/src/api/ipfs/ipfs.service.js +193 -0
  27. package/src/api/object-layer/README.md +139 -0
  28. package/src/api/object-layer/object-layer.controller.js +3 -0
  29. package/src/api/object-layer/object-layer.model.js +15 -1
  30. package/src/api/object-layer/object-layer.router.js +6 -10
  31. package/src/api/object-layer/object-layer.service.js +311 -182
  32. package/src/cli/cluster.js +30 -38
  33. package/src/cli/index.js +0 -1
  34. package/src/cli/run.js +14 -0
  35. package/src/client/components/core/LoadingAnimation.js +2 -3
  36. package/src/client/components/core/Modal.js +1 -1
  37. package/src/client/components/cyberia/ObjectLayerEngineModal.js +4 -5
  38. package/src/client/components/cyberia/ObjectLayerEngineViewer.js +280 -29
  39. package/src/client/services/ipfs/ipfs.service.js +144 -0
  40. package/src/client/services/object-layer/object-layer.management.js +161 -8
  41. package/src/index.js +1 -1
  42. package/src/runtime/express/Express.js +1 -1
  43. package/src/server/auth.js +18 -18
  44. package/src/server/ipfs-client.js +433 -0
  45. package/src/server/object-layer.js +649 -18
  46. package/src/server/semantic-layer-generator.js +1083 -0
  47. package/src/server/shape-generator.js +952 -0
  48. package/test/shape-generator.test.js +457 -0
  49. package/bin/ssl.js +0 -63
@@ -0,0 +1,457 @@
1
+ /**
2
+ * @module shape-generator.test
3
+ * @description Unit tests for the shape-generator module.
4
+ * Validates deterministic output with seeded RNG and basic shape generation.
5
+ * Uses 'chai' for assertions.
6
+ */
7
+
8
+ import { expect } from 'chai';
9
+ import { generateShape, registerShape, listShapes, toPixelCoords, renderGrid } from '../src/server/shape-generator.js';
10
+
11
+ describe('Shape Generator Module Tests', () => {
12
+ // --- Deterministic Seed Tests ---
13
+ describe('Deterministic output with seeded RNG', () => {
14
+ /**
15
+ * Test case 1: Same seed string produces identical points for a skull-bone shape.
16
+ */
17
+ it('should produce identical points for the same string seed ("fx-42") on a skull-bone shape', () => {
18
+ const opts = {
19
+ count: 50,
20
+ scale: 0.9,
21
+ rotation: 10,
22
+ jitter: 0.002,
23
+ noise: 0.15,
24
+ seed: 'fx-42',
25
+ color: 'rgba(220,20,60,1)',
26
+ };
27
+
28
+ const result1 = generateShape('skull-bone', opts);
29
+ const result2 = generateShape('skull-bone', opts);
30
+
31
+ // Both runs must produce the exact same number of points
32
+ expect(result1.points).to.have.lengthOf(50);
33
+ expect(result2.points).to.have.lengthOf(50);
34
+
35
+ // Every point must be identical
36
+ for (let i = 0; i < result1.points.length; i++) {
37
+ expect(result1.points[i].x).to.equal(result2.points[i].x, `Point ${i} x mismatch`);
38
+ expect(result1.points[i].y).to.equal(result2.points[i].y, `Point ${i} y mismatch`);
39
+ }
40
+
41
+ // Metadata must match
42
+ expect(result1.metadata.seed).to.equal(result2.metadata.seed);
43
+ expect(result1.metadata.key).to.equal('skull-bone');
44
+ expect(result1.metadata.color).to.equal('rgba(220,20,60,1)');
45
+ expect(result1.metadata.count).to.equal(50);
46
+ expect(result1.metadata.bbox).to.have.all.keys('minX', 'minY', 'maxX', 'maxY');
47
+ });
48
+
49
+ /**
50
+ * Test case 2: Same integer seed produces identical points for an ellipse shape.
51
+ */
52
+ it('should produce identical points for the same integer seed (12345) on an ellipse shape', () => {
53
+ const opts = {
54
+ count: 100,
55
+ seed: 12345,
56
+ a: 1.5,
57
+ b: 0.8,
58
+ jitter: 0.01,
59
+ noise: 0.05,
60
+ };
61
+
62
+ const result1 = generateShape('ellipse', opts);
63
+ const result2 = generateShape('ellipse', opts);
64
+
65
+ expect(result1.points).to.have.lengthOf(100);
66
+ expect(result2.points).to.have.lengthOf(100);
67
+
68
+ // Every point must be identical across runs
69
+ for (let i = 0; i < result1.points.length; i++) {
70
+ expect(result1.points[i].x).to.equal(result2.points[i].x, `Point ${i} x mismatch`);
71
+ expect(result1.points[i].y).to.equal(result2.points[i].y, `Point ${i} y mismatch`);
72
+ }
73
+
74
+ expect(result1.metadata.seed).to.equal(result2.metadata.seed);
75
+ expect(result1.metadata.key).to.equal('ellipse');
76
+ });
77
+ });
78
+
79
+ // --- Different seeds produce different results ---
80
+ describe('Different seeds produce different output', () => {
81
+ it('should produce different points when seeds differ', () => {
82
+ const opts1 = { count: 30, seed: 'alpha', jitter: 0.01 };
83
+ const opts2 = { count: 30, seed: 'beta', jitter: 0.01 };
84
+
85
+ const result1 = generateShape('circle', opts1);
86
+ const result2 = generateShape('circle', opts2);
87
+
88
+ // At least some points should differ
89
+ let hasDifference = false;
90
+ for (let i = 0; i < result1.points.length; i++) {
91
+ if (result1.points[i].x !== result2.points[i].x || result1.points[i].y !== result2.points[i].y) {
92
+ hasDifference = true;
93
+ break;
94
+ }
95
+ }
96
+ expect(hasDifference).to.be.true;
97
+ });
98
+ });
99
+
100
+ // --- Shape registry ---
101
+ describe('Shape registry', () => {
102
+ it('should list all built-in shapes', () => {
103
+ const shapes = listShapes();
104
+ expect(shapes).to.include.members([
105
+ 'circle',
106
+ 'ellipse',
107
+ 'parabola',
108
+ 'heart',
109
+ 'skull-bone',
110
+ 'star',
111
+ 'cactus',
112
+ 'pixel-art',
113
+ 'bezier-path',
114
+ ]);
115
+ });
116
+
117
+ it('should throw for an unknown shape key', () => {
118
+ expect(() => generateShape('nonexistent-shape')).to.throw(Error, /Unknown shape key/);
119
+ });
120
+
121
+ it('should allow registering and generating a custom shape', () => {
122
+ registerShape('diamond', (t) => {
123
+ const angle = t * Math.PI * 2;
124
+ const r = 1 / (Math.abs(Math.cos(angle)) + Math.abs(Math.sin(angle)));
125
+ return { x: r * Math.cos(angle), y: r * Math.sin(angle) };
126
+ });
127
+
128
+ expect(listShapes()).to.include('diamond');
129
+
130
+ const result = generateShape('diamond', { count: 40, seed: 99 });
131
+ expect(result.points).to.have.lengthOf(40);
132
+ expect(result.metadata.key).to.equal('diamond');
133
+ });
134
+ });
135
+
136
+ // --- Normalization and bounding box ---
137
+ describe('Normalization', () => {
138
+ it('should produce points within 0..1 when normalize=true (default)', () => {
139
+ const result = generateShape('star', { count: 60, seed: 7 });
140
+ for (const p of result.points) {
141
+ expect(p.x).to.be.at.least(0);
142
+ expect(p.x).to.be.at.most(1);
143
+ expect(p.y).to.be.at.least(0);
144
+ expect(p.y).to.be.at.most(1);
145
+ }
146
+ });
147
+
148
+ it('should produce points outside 0..1 when normalize=false', () => {
149
+ const result = generateShape('skull-bone', { count: 60, seed: 7, normalize: false });
150
+ // Skull-bone shape has range roughly -1..1, so some points should be negative
151
+ const hasNegative = result.points.some((p) => p.x < 0 || p.y < 0);
152
+ expect(hasNegative).to.be.true;
153
+ });
154
+ });
155
+
156
+ // --- toPixelCoords helper ---
157
+ describe('toPixelCoords helper', () => {
158
+ it('should scale normalized points to pixel dimensions', () => {
159
+ const normalized = [
160
+ { x: 0, y: 0 },
161
+ { x: 0.5, y: 0.5 },
162
+ { x: 1, y: 1 },
163
+ ];
164
+ const pixels = toPixelCoords(normalized, 800, 600);
165
+ expect(pixels[0]).to.deep.equal({ x: 0, y: 0 });
166
+ expect(pixels[1]).to.deep.equal({ x: 400, y: 300 });
167
+ expect(pixels[2]).to.deep.equal({ x: 800, y: 600 });
168
+ });
169
+ });
170
+
171
+ // --- Default options ---
172
+ describe('Default options', () => {
173
+ it('should generate 200 points by default', () => {
174
+ const result = generateShape('circle', { seed: 1 });
175
+ expect(result.points).to.have.lengthOf(200);
176
+ expect(result.metadata.count).to.equal(200);
177
+ });
178
+ });
179
+
180
+ // --- All built-in shapes generate without error ---
181
+ describe('All built-in shapes generate successfully', () => {
182
+ const shapes = [
183
+ 'circle',
184
+ 'ellipse',
185
+ 'parabola',
186
+ 'heart',
187
+ 'skull-bone',
188
+ 'star',
189
+ 'cactus',
190
+ 'pixel-art',
191
+ 'bezier-path',
192
+ ];
193
+
194
+ for (const key of shapes) {
195
+ it(`should generate shape "${key}" without error`, () => {
196
+ const result = generateShape(key, { count: 30, seed: 42 });
197
+ expect(result.points).to.have.lengthOf(30);
198
+ expect(result.metadata.key).to.equal(key);
199
+ expect(result.metadata).to.have.property('seed');
200
+ expect(result.metadata).to.have.property('bbox');
201
+ });
202
+ }
203
+ });
204
+
205
+ // --- Example usage (Node.js) with expected sample output ---
206
+ describe('Example usage – skull-bone shape first 5 points', () => {
207
+ it('should produce stable first 5 points for the documented example', () => {
208
+ const result = generateShape('skull-bone', {
209
+ count: 300,
210
+ scale: 0.9,
211
+ rotation: 10,
212
+ jitter: 0.002,
213
+ noise: 0.15,
214
+ seed: 'fx-42',
215
+ color: 'rgba(220,20,60,1)',
216
+ });
217
+
218
+ expect(result.points.length).to.equal(300);
219
+ expect(result.metadata.key).to.equal('skull-bone');
220
+ expect(result.metadata.color).to.equal('rgba(220,20,60,1)');
221
+
222
+ // Snapshot the first 5 points from a known run, then verify they remain stable
223
+ const first5 = result.points.slice(0, 5);
224
+
225
+ // Run a second time to confirm determinism
226
+ const result2 = generateShape('skull-bone', {
227
+ count: 300,
228
+ scale: 0.9,
229
+ rotation: 10,
230
+ jitter: 0.002,
231
+ noise: 0.15,
232
+ seed: 'fx-42',
233
+ color: 'rgba(220,20,60,1)',
234
+ });
235
+
236
+ const first5Again = result2.points.slice(0, 5);
237
+
238
+ for (let i = 0; i < 5; i++) {
239
+ expect(first5[i].x).to.equal(first5Again[i].x);
240
+ expect(first5[i].y).to.equal(first5Again[i].y);
241
+ }
242
+
243
+ // Log sample output for documentation purposes
244
+ console.log('\n Example output – first 5 points of skull-bone (seed: "fx-42"):');
245
+ console.log(' ' + JSON.stringify(first5));
246
+ });
247
+ });
248
+
249
+ // ===========================================================================
250
+ // intCoords — integer pixel-art grid mode
251
+ // ===========================================================================
252
+ describe('intCoords – integer pixel-art grid mode', () => {
253
+ // --- Basic contract: all points are integers within grid bounds ---
254
+ describe('Basic contract', () => {
255
+ it('should return integer-only coordinates within 0..gridSize-1', () => {
256
+ const result = generateShape('circle', { intCoords: 16, seed: 1 });
257
+
258
+ expect(result.metadata.gridWidth).to.equal(16);
259
+ expect(result.metadata.gridHeight).to.equal(16);
260
+
261
+ for (const p of result.points) {
262
+ expect(Number.isInteger(p.x)).to.be.true;
263
+ expect(Number.isInteger(p.y)).to.be.true;
264
+ expect(p.x).to.be.at.least(0);
265
+ expect(p.x).to.be.at.most(15);
266
+ expect(p.y).to.be.at.least(0);
267
+ expect(p.y).to.be.at.most(15);
268
+ }
269
+ });
270
+
271
+ it('should have no duplicate points', () => {
272
+ const result = generateShape('skull-bone', { intCoords: 16, seed: 42 });
273
+ const keys = new Set(result.points.map((p) => `${p.x},${p.y}`));
274
+ expect(keys.size).to.equal(result.points.length);
275
+ });
276
+
277
+ it('should accept intCoords as [width, height] array for rectangular grids', () => {
278
+ const result = generateShape('ellipse', { intCoords: [24, 12], seed: 7, a: 2, b: 0.8 });
279
+ expect(result.metadata.gridWidth).to.equal(24);
280
+ expect(result.metadata.gridHeight).to.equal(12);
281
+
282
+ for (const p of result.points) {
283
+ expect(p.x).to.be.at.least(0);
284
+ expect(p.x).to.be.at.most(23);
285
+ expect(p.y).to.be.at.least(0);
286
+ expect(p.y).to.be.at.most(11);
287
+ }
288
+ });
289
+
290
+ it('should accept intCoords=true and derive grid from count', () => {
291
+ const result = generateShape('circle', { intCoords: true, count: 20, seed: 5 });
292
+ expect(result.metadata.gridWidth).to.equal(20);
293
+ expect(result.metadata.gridHeight).to.equal(20);
294
+ });
295
+
296
+ it('should throw for intCoords grid smaller than 2×2', () => {
297
+ expect(() => generateShape('circle', { intCoords: 1 })).to.throw(Error, /at least 2×2/);
298
+ });
299
+ });
300
+
301
+ // --- Deterministic with intCoords ---
302
+ describe('Determinism with intCoords', () => {
303
+ it('should produce identical integer points for the same seed', () => {
304
+ const opts = { intCoords: 16, seed: 'pixel-test', jitter: 0.005, noise: 0.1 };
305
+ const r1 = generateShape('star', opts);
306
+ const r2 = generateShape('star', opts);
307
+
308
+ expect(r1.points.length).to.equal(r2.points.length);
309
+ for (let i = 0; i < r1.points.length; i++) {
310
+ expect(r1.points[i].x).to.equal(r2.points[i].x, `Point ${i} x mismatch`);
311
+ expect(r1.points[i].y).to.equal(r2.points[i].y, `Point ${i} y mismatch`);
312
+ }
313
+ });
314
+ });
315
+
316
+ // --- Contour connectivity: Bresenham should fill gaps ---
317
+ describe('Bresenham contour connectivity', () => {
318
+ it('should produce a connected contour (no gap > √2 between consecutive points)', () => {
319
+ const result = generateShape('skull-bone', { intCoords: 16, seed: 100 });
320
+ const pts = result.points;
321
+
322
+ // For a closed shape, also check last→first
323
+ for (let i = 0; i < pts.length; i++) {
324
+ const a = pts[i];
325
+ const b = pts[(i + 1) % pts.length];
326
+ const dist = Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2);
327
+ // Bresenham ensures consecutive cells differ by at most 1 in each axis
328
+ // but after dedup, the contour-order distance may be larger.
329
+ // We just verify no enormous gaps (> half the grid) which would indicate
330
+ // a broken rasterization.
331
+ expect(dist).to.be.below(
332
+ Math.max(result.metadata.gridWidth, result.metadata.gridHeight),
333
+ `Gap at index ${i}: (${a.x},${a.y})→(${b.x},${b.y}) dist=${dist.toFixed(2)}`,
334
+ );
335
+ }
336
+
337
+ // The total number of unique cells should be substantial for a 16×16 skull-bone
338
+ // (not just 3-4 dots on a diagonal).
339
+ expect(pts.length).to.be.at.least(20, 'Skull-bone on 16×16 should have at least 20 contour cells');
340
+ });
341
+
342
+ it('should produce enough cells to be recognizable on a tiny 8×8 grid', () => {
343
+ const result = generateShape('circle', { intCoords: 8, seed: 77 });
344
+ // A circle on 8×8 should touch a good number of cells
345
+ expect(result.points.length).to.be.at.least(12, 'Circle on 8×8 needs at least 12 cells');
346
+ });
347
+ });
348
+
349
+ // --- renderGrid helper ---
350
+ describe('renderGrid helper', () => {
351
+ it('should throw if ShapeResult lacks gridWidth/gridHeight', () => {
352
+ const normalResult = generateShape('circle', { count: 10, seed: 1 });
353
+ expect(() => renderGrid(normalResult)).to.throw(Error, /intCoords/);
354
+ });
355
+
356
+ it('should produce a grid string with correct dimensions', () => {
357
+ const result = generateShape('circle', { intCoords: 10, seed: 1 });
358
+ const grid = renderGrid(result);
359
+ const rows = grid.split('\n');
360
+ expect(rows.length).to.equal(10);
361
+ for (const row of rows) {
362
+ expect(row.length).to.equal(10);
363
+ }
364
+ });
365
+
366
+ it('should place filled chars at every point coordinate', () => {
367
+ const result = generateShape('circle', { intCoords: 12, seed: 3 });
368
+ const grid = renderGrid(result, { filled: '#', empty: '.' });
369
+ const rows = grid.split('\n');
370
+
371
+ for (const p of result.points) {
372
+ expect(rows[p.y][p.x]).to.equal('#', `Expected '#' at (${p.x},${p.y})`);
373
+ }
374
+ });
375
+ });
376
+
377
+ // --- Visual recognizability on 16×16 for every built-in shape ---
378
+ describe('All built-in shapes render recognizably on 16×16', () => {
379
+ const shapes = ['circle', 'ellipse', 'skull-bone', 'star', 'cactus', 'pixel-art'];
380
+
381
+ for (const key of shapes) {
382
+ it(`"${key}" should produce ≥15 contour cells on a 16×16 grid`, () => {
383
+ const result = generateShape(key, { intCoords: 16, seed: 42 });
384
+ const grid = renderGrid(result);
385
+
386
+ // Log the grid for visual inspection during test runs
387
+ console.log(`\n ${key} 16×16 (${result.points.length} cells):`);
388
+ for (const row of grid.split('\n')) {
389
+ console.log(' ' + row);
390
+ }
391
+
392
+ // A recognizable closed shape on 16×16 must have a reasonable number of cells.
393
+ // Anything below ~15 tends to look like random dots or a straight line.
394
+ expect(result.points.length).to.be.at.least(15, `${key} contour too sparse on 16×16`);
395
+ });
396
+ }
397
+
398
+ it('"parabola" (open) should produce ≥8 contour cells on a 16×16 grid', () => {
399
+ const result = generateShape('parabola', { intCoords: 16, seed: 42, closed: false });
400
+ const grid = renderGrid(result);
401
+
402
+ console.log(`\n parabola 16×16 (${result.points.length} cells):`);
403
+ for (const row of grid.split('\n')) {
404
+ console.log(' ' + row);
405
+ }
406
+
407
+ expect(result.points.length).to.be.at.least(8, 'parabola contour too sparse on 16×16');
408
+ });
409
+
410
+ it('"bezier-path" (open) should produce ≥8 contour cells on a 16×16 grid', () => {
411
+ const result = generateShape('bezier-path', { intCoords: 16, seed: 42, closed: false });
412
+ const grid = renderGrid(result);
413
+
414
+ console.log(`\n bezier-path 16×16 (${result.points.length} cells):`);
415
+ for (const row of grid.split('\n')) {
416
+ console.log(' ' + row);
417
+ }
418
+
419
+ expect(result.points.length).to.be.at.least(8, 'bezier-path contour too sparse on 16×16');
420
+ });
421
+ });
422
+
423
+ // --- 32×32 skull-bone visual check ---
424
+ describe('Larger grid visual check', () => {
425
+ it('should render a clearly recognizable skull-bone on 32×32', () => {
426
+ const result = generateShape('skull-bone', { intCoords: 32, seed: 'bones' });
427
+ const grid = renderGrid(result);
428
+
429
+ console.log(`\n skull-bone 32×32 (${result.points.length} cells):`);
430
+ for (const row of grid.split('\n')) {
431
+ console.log(' ' + row);
432
+ }
433
+
434
+ // A skull-bone on 32×32 should have a rich contour
435
+ expect(result.points.length).to.be.at.least(50);
436
+ expect(result.metadata.gridWidth).to.equal(32);
437
+ expect(result.metadata.gridHeight).to.equal(32);
438
+ });
439
+ });
440
+
441
+ // --- intCoords does NOT affect non-intCoords runs ---
442
+ describe('Backward compatibility', () => {
443
+ it('should not change output when intCoords is false (default)', () => {
444
+ const opts = { count: 50, seed: 'compat' };
445
+ const r1 = generateShape('circle', opts);
446
+ const r2 = generateShape('circle', { ...opts, intCoords: false });
447
+
448
+ expect(r1.points.length).to.equal(r2.points.length);
449
+ for (let i = 0; i < r1.points.length; i++) {
450
+ expect(r1.points[i].x).to.equal(r2.points[i].x);
451
+ expect(r1.points[i].y).to.equal(r2.points[i].y);
452
+ }
453
+ expect(r1.metadata).to.not.have.property('gridWidth');
454
+ });
455
+ });
456
+ });
457
+ });
package/bin/ssl.js DELETED
@@ -1,63 +0,0 @@
1
- import fs from 'fs';
2
- import read from 'read';
3
- import dotenv from 'dotenv';
4
- import { getRootDirectory, pbcopy, shellExec } from '../src/server/process.js';
5
- import { loggerFactory } from '../src/server/logger.js';
6
- import { Cmd, loadConf } from '../src/server/conf.js';
7
- import { buildSSL } from '../src/server/ssl.js';
8
-
9
- dotenv.config();
10
-
11
- const logger = loggerFactory(import.meta);
12
-
13
- await logger.setUpInfo();
14
-
15
- const [exe, dir, deployId, hosts] = process.argv;
16
-
17
- try {
18
- let cmd;
19
- await loadConf(deployId);
20
- shellExec(Cmd.conf(deployId));
21
- const confServer = JSON.parse(fs.readFileSync(`./conf/conf.server.json`, 'utf8'));
22
- for (const host of hosts.split(',')) {
23
- if (host in confServer) {
24
- const directory = confServer[host]['/']?.['directory'] ? confServer[host]['/']['directory'] : undefined;
25
- cmd = `sudo certbot certonly --webroot --webroot-path ${
26
- directory ? directory : `${getRootDirectory()}/public/${host}`
27
- } --cert-name ${host} -d ${host}`;
28
- // directory ? directory : `${getRootDirectory()}/public/${host}`
29
- // directory ? directory : `${getRootDirectory()}/public/www.${host.split('.').slice(-2).join('.')}`
30
-
31
- // You can get multi domain cert by specifying (extra) -d
32
- // For example
33
- // certbot -d example.com -d example.net -d www.example.org
34
-
35
- // delete all file (no increment live folder)
36
- // certbot delete --cert-name <domain>
37
-
38
- logger.info(`Run the following command`, cmd);
39
- try {
40
- await pbcopy(cmd);
41
- await read({ prompt: 'Command copy to clipboard, press enter to continue.\n' });
42
- } catch (error) {
43
- logger.error(error);
44
- }
45
- // Certificate
46
- if (process.argv.includes('build')) await buildSSL(host);
47
- logger.info('Certificate saved', host);
48
- } else throw new Error(`host not found: ${host}`);
49
- }
50
- // check for renewal conf:
51
- // /etc/letsencrypt/renewal
52
- // /etc/letsencrypt/live
53
- cmd = `sudo certbot renew --dry-run`;
54
- try {
55
- await pbcopy(cmd);
56
- } catch (error) {
57
- logger.error(error);
58
- }
59
- logger.info(`run the following command for renewal. Command copy to clipboard`, cmd);
60
- logger.info(`success install SLL`, hosts);
61
- } catch (error) {
62
- logger.error(error, error.stack);
63
- }