underpost 2.8.876 → 2.8.878

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.
@@ -30,9 +30,8 @@ jobs:
30
30
  echo "Starting remote release deploy"
31
31
  cd /home/dd/engine
32
32
  npm install -g underpost
33
- underpost config set GITHUB_TOKEN ${{ secrets.GITHUB_TOKEN }}
33
+ underpost run secret
34
34
  node bin run --dev pull
35
35
  underpost run secret
36
36
  underpost run underpost-config
37
- node bin run --dev pull
38
37
  underpost run ssh-deploy engine-test
package/README.md CHANGED
@@ -51,6 +51,10 @@
51
51
 
52
52
 
53
53
 
54
+
55
+
56
+
57
+
54
58
 
55
59
 
56
60
 
@@ -59,7 +63,7 @@
59
63
  <!-- badges -->
60
64
 
61
65
 
62
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.876)](https://socket.dev/npm/package/underpost/overview/2.8.876) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
66
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.ci.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.878)](https://socket.dev/npm/package/underpost/overview/2.8.878) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
63
67
 
64
68
 
65
69
  <!-- end-badges -->
@@ -99,6 +103,10 @@
99
103
 
100
104
 
101
105
 
106
+
107
+
108
+
109
+
102
110
 
103
111
 
104
112
 
@@ -148,7 +156,7 @@ Run dev client server
148
156
  npm run dev
149
157
  ```
150
158
  <!-- -->
151
- ## underpost ci/cd cli v2.8.876
159
+ ## underpost ci/cd cli v2.8.878
152
160
 
153
161
  ### Usage: `underpost [options] [command]`
154
162
  ```
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.8.876
1
+ ## underpost ci/cd cli v2.8.878
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -51,6 +51,7 @@ Arguments:
51
51
 
52
52
  Options:
53
53
  --deploy-id Crete deploy ID conf env files
54
+ --cluster Create deploy ID cluster files and sync to current cluster
54
55
  --dev Sets the development cli context
55
56
  -h, --help display help for command
56
57
 
@@ -609,6 +610,8 @@ Options:
609
610
  --command <command-array> Array of commands to run.
610
611
  --args <args-array> Array of arguments to pass to the command.
611
612
  --dev Sets the development context environment for the script.
613
+ --build Set builder context runner
614
+ --replicas <replicas> Sets a custom number of replicas for deployment.
612
615
  --pod-name <pod-name> Optional: Specifies the pod name for test execution.
613
616
  --volume-host-path <volume-host-path> Optional: Specifies the volume host path for test execution.
614
617
  --volume-mount-path <volume-mount-path> Optional: Specifies the volume mount path for test execution.
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-default-development-blue
20
- image: localhost/rockylinux9-underpost:v2.8.876
20
+ image: localhost/rockylinux9-underpost:v2.8.878
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-default-development-green
103
- image: localhost/rockylinux9-underpost:v2.8.876
103
+ image: localhost/rockylinux9-underpost:v2.8.878
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -17,13 +17,13 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-test-development-blue
20
- image: localhost/rockylinux9-underpost:v2.8.876
20
+ image: localhost/rockylinux9-underpost:v2.8.878
21
21
  # resources:
22
22
  # requests:
23
- # memory: "96294Ki"
23
+ # memory: "94Ki"
24
24
  # cpu: "75m"
25
25
  # limits:
26
- # memory: "1540709Ki"
26
+ # memory: "1504Ki"
27
27
  # cpu: "1200m"
28
28
  command:
29
29
  - /bin/sh
@@ -104,13 +104,13 @@ spec:
104
104
  spec:
105
105
  containers:
106
106
  - name: dd-test-development-green
107
- image: localhost/rockylinux9-underpost:v2.8.876
107
+ image: localhost/rockylinux9-underpost:v2.8.878
108
108
  # resources:
109
109
  # requests:
110
- # memory: "96294Ki"
110
+ # memory: "94Ki"
111
111
  # cpu: "75m"
112
112
  # limits:
113
- # memory: "1540709Ki"
113
+ # memory: "1504Ki"
114
114
  # cpu: "1200m"
115
115
  command:
116
116
  - /bin/sh
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.8.876",
5
+ "version": "2.8.878",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -20,7 +20,21 @@ const FileController = {
20
20
  get: async (req, res, options) => {
21
21
  try {
22
22
  const result = await FileService.get(req, res, options);
23
- if (result instanceof Buffer) return res.status(200).end(result);
23
+ if (result instanceof Buffer) {
24
+ if (
25
+ process.env.NODE_ENV === 'development' ||
26
+ req.hostname === options.host ||
27
+ (options.origins && options.origins.find((o) => o.match(req.hostname)))
28
+ ) {
29
+ res.set('Cross-Origin-Resource-Policy', 'cross-origin');
30
+ return res.status(200).end(result);
31
+ }
32
+ return res.status(403).json({
33
+ status: 'error',
34
+ message: 'Forbidden',
35
+ });
36
+ }
37
+
24
38
  return res.status(200).json({
25
39
  status: 'success',
26
40
  data: result,
@@ -48,9 +48,10 @@ const UserRouter = (options) => {
48
48
  check: fs.readFileSync(`./src/client/public/default/assets/mailer/api-user-check.png`),
49
49
  },
50
50
  header: (res) => {
51
- res.header('Access-Control-Allow-Origin', '*');
52
- res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
53
- res.header('Content-Type', 'image/png');
51
+ res.set('Cross-Origin-Resource-Policy', 'cross-origin');
52
+ res.set('Access-Control-Allow-Origin', '*');
53
+ res.set('Access-Control-Allow-Headers', '*');
54
+ res.set('Content-Type', 'image/png');
54
55
  },
55
56
  };
56
57
 
package/src/cli/deploy.js CHANGED
@@ -384,7 +384,8 @@ EOF`);
384
384
  if (!options.remove === true) {
385
385
  if (!options.disableUpdateDeployment) shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
386
386
  shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml`);
387
- if (UnderpostDeploy.API.isValidTLSContext({ host, env, options }))
387
+
388
+ if (UnderpostDeploy.API.isValidTLSContext({ host: Object.keys(confServer)[0], env, options }))
388
389
  shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
389
390
  }
390
391
  }
package/src/cli/index.js CHANGED
@@ -24,6 +24,7 @@ program
24
24
  .command('new')
25
25
  .argument('<app-name>', 'The name or deploy-id of the application to create.')
26
26
  .option('--deploy-id', 'Crete deploy ID conf env files')
27
+ .option('--cluster', 'Create deploy ID cluster files and sync to current cluster')
27
28
  .option('--dev', 'Sets the development cli context')
28
29
  .description('Initializes a new Underpost project with a predefined structure.')
29
30
  .action(Underpost.repo.new);
@@ -350,6 +351,8 @@ program
350
351
  .option('--command <command-array>', 'Array of commands to run.')
351
352
  .option('--args <args-array>', 'Array of arguments to pass to the command.')
352
353
  .option('--dev', 'Sets the development context environment for the script.')
354
+ .option('--build', 'Set builder context runner')
355
+ .option('--replicas <replicas>', 'Sets a custom number of replicas for deployment.')
353
356
  .option('--pod-name <pod-name>', 'Optional: Specifies the pod name for test execution.')
354
357
  .option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
355
358
  .option('--volume-mount-path <volume-mount-path>', 'Optional: Specifies the volume mount path for test execution.')
@@ -90,7 +90,7 @@ class UnderpostRepository {
90
90
  );
91
91
  },
92
92
 
93
- new(repositoryName, options = { dev: false, deployId: false }) {
93
+ new(repositoryName, options = { dev: false, deployId: false, cluster: false }) {
94
94
  return new Promise(async (resolve, reject) => {
95
95
  try {
96
96
  await logger.setUpInfo();
@@ -99,7 +99,7 @@ class UnderpostRepository {
99
99
  return resolve(
100
100
  await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), ':'),
101
101
  );
102
- if (options.deployId === true) return Config.deployIdFactory(repositoryName);
102
+ if (options.deployId === true) return Config.deployIdFactory(repositoryName, options);
103
103
  const npmRoot = getNpmRootPath();
104
104
  const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
105
105
  const destFolder = `./${repositoryName}`;
@@ -160,10 +160,18 @@ class UnderpostRepository {
160
160
  `Version mismatch: deploy-version:${packageJsonDeploy.version} !== engine-version:${packageJsonEngine.version},
161
161
  Prevent build private config repo.`,
162
162
  );
163
- return { validVersion: false };
163
+ return {
164
+ validVersion: false,
165
+ engineVersion: packageJsonEngine.version,
166
+ deployVersion: packageJsonDeploy.version,
167
+ };
164
168
  }
165
169
  shellExec(`node bin/build ${deployId} conf`);
166
- return { validVersion: true };
170
+ return {
171
+ validVersion: true,
172
+ engineVersion: packageJsonEngine.version,
173
+ deployVersion: packageJsonDeploy.version,
174
+ };
167
175
  },
168
176
  };
169
177
  }
package/src/cli/run.js CHANGED
@@ -8,6 +8,7 @@ import { range, setPad, timer } from '../client/components/core/CommonJs.js';
8
8
  import UnderpostDeploy from './deploy.js';
9
9
  import UnderpostRootEnv from './env.js';
10
10
  import UnderpostRepository from './repository.js';
11
+ import os from 'os';
11
12
 
12
13
  const logger = loggerFactory(import.meta);
13
14
 
@@ -20,6 +21,8 @@ class UnderpostRun {
20
21
  imageName: '',
21
22
  containerName: '',
22
23
  namespace: '',
24
+ build: false,
25
+ replicas: 1,
23
26
  };
24
27
  static RUNNERS = {
25
28
  'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
@@ -104,6 +107,8 @@ class UnderpostRun {
104
107
  },
105
108
  'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
106
109
  const baseCommand = options.dev || true ? 'node bin' : 'underpost';
110
+ shellExec(`${baseCommand} run clean`);
111
+ shellExec(`${baseCommand} push ./engine-private ${process.env.GITHUB_USERNAME}/engine-private`);
107
112
  shellCd('/home/dd/engine');
108
113
  shellExec(`git reset`);
109
114
  shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
@@ -154,17 +159,21 @@ class UnderpostRun {
154
159
  const env = options.dev ? 'development' : 'production';
155
160
  const baseCommand = options.dev || true ? 'node bin' : 'underpost';
156
161
  shellExec(`${baseCommand} run clean`);
157
- const defaultPaht = ['dd', 1, ``, 'kind-control-plane'];
158
- let [deployId, replicas, image, node] = path ? path.split(',') : defaultPaht;
159
- deployId = deployId ?? defaultPaht[0];
160
- replicas = replicas ?? defaultPaht[1];
161
- image = image ?? defaultPaht[2];
162
- node = node ?? defaultPaht[3];
162
+ const defaultPath = ['dd-default', 1, ``, ``, 'kind-control-plane'];
163
+ let [deployId, replicas, versions, image, node] = path ? path.split(',') : defaultPath;
164
+ deployId = deployId ?? defaultPath[0];
165
+ replicas = replicas ?? defaultPath[1];
166
+ versions = versions ?? defaultPath[2];
167
+ image = image ?? defaultPath[3];
168
+ node = node ?? defaultPath[4];
163
169
  shellExec(
164
170
  `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
165
171
  replicas ?? 1
166
- } --node ${node}${image ? ` --image ${image}` : ''} ${deployId} ${env}`,
172
+ } --node ${node}${image ? ` --image ${image}` : ''}${
173
+ versions ? ` --versions ${versions.replaceAll('+', ',')}` : ''
174
+ } dd ${env}`,
167
175
  );
176
+ if (!options.build) shellExec(`${baseCommand} deploy --kubeadm ${deployId} ${env}`);
168
177
  },
169
178
  'ls-deployments': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
170
179
  console.table(await UnderpostDeploy.API.get(path, 'deployments'));
@@ -303,13 +312,21 @@ class UnderpostRun {
303
312
  },
304
313
  deploy: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
305
314
  const deployId = path;
306
- const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
315
+ const { validVersion, deployVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
307
316
  if (!validVersion) throw new Error('Version mismatch');
308
317
  const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
309
318
  const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
310
319
  const env = 'production';
311
320
  const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
312
- shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
321
+
322
+ if (options.build === true) {
323
+ // deployId, replicas, versions, image, node
324
+ shellExec(
325
+ `node bin run sync ${deployId},${options.replicas ?? 1},${targetTraffic},${
326
+ options.imageName ?? `localhost/rockylinux9-underpost:${deployVersion}`
327
+ },${os.hostname()}`,
328
+ );
329
+ } else shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
313
330
 
314
331
  let checkStatusIteration = 0;
315
332
  const checkStatusIterationMsDelay = 1000;
@@ -17,10 +17,6 @@ import { SocketIoDefault } from './components/default/SocketIoDefault.js';
17
17
  import { ElementsDefault } from './components/default/ElementsDefault.js';
18
18
  import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
19
19
 
20
- const htmlMainBody = async () => {
21
- return html`<span>Hello World!!</span>`;
22
- };
23
-
24
20
  window.onload = () =>
25
21
  Worker.instance({
26
22
  router: RouterDefault,
@@ -29,7 +25,7 @@ window.onload = () =>
29
25
  await TranslateCore.Init();
30
26
  await TranslateDefault.Init();
31
27
  await Responsive.Init();
32
- await MenuDefault.Render({ htmlMainBody });
28
+ await MenuDefault.Render();
33
29
  await SocketIo.Init({
34
30
  channels: ElementsDefault.Data,
35
31
  path: `/`,
@@ -4,7 +4,6 @@ import { loggerFactory } from './Logger.js';
4
4
  import { LogIn } from './LogIn.js';
5
5
  import { LogOut } from './LogOut.js';
6
6
  import { NotificationManager } from './NotificationManager.js';
7
- import { SignUp } from './SignUp.js';
8
7
  import { Translate } from './Translate.js';
9
8
  import { s } from './VanillaJs.js';
10
9
 
@@ -137,11 +137,7 @@ const Content = {
137
137
  case 'svg':
138
138
  case 'gif':
139
139
  case 'png': {
140
- const url = options.url
141
- ? options.url
142
- : file._id
143
- ? getApiBaseUrl({ id: file._id, endpoint: 'file/blob' })
144
- : URL.createObjectURL(getBlobFromUint8ArrayFile(file.data.data, file.mimetype));
140
+ const url = Content.urlFactory(options);
145
141
  const imgRender = html`<img
146
142
  class="in ${options.class}"
147
143
  ${styleFactory(options.style, `${renderChessPattern(50)}`)}
@@ -151,11 +147,7 @@ const Content = {
151
147
  break;
152
148
  }
153
149
  case 'pdf': {
154
- const url = options.url
155
- ? options.url
156
- : file._id
157
- ? getApiBaseUrl({ id: file._id, endpoint: 'file/blob' })
158
- : URL.createObjectURL(getBlobFromUint8ArrayFile(file.data.data, file.mimetype));
150
+ const url = Content.urlFactory(options);
159
151
  render += html`<iframe
160
152
  class="in ${options.class} iframe-${options.idModal}"
161
153
  ${styleFactory(options.style)}
@@ -189,6 +181,15 @@ const Content = {
189
181
  if (options.raw) return render;
190
182
  append(container, render);
191
183
  },
184
+ urlFactory: function (options) {
185
+ return options.url
186
+ ? options.url
187
+ : options.file?.data?.data
188
+ ? URL.createObjectURL(getBlobFromUint8ArrayFile(options.file.data.data, options.file.mimetype))
189
+ : options.file._id
190
+ ? getApiBaseUrl({ id: options.file._id, endpoint: 'file/blob' })
191
+ : null;
192
+ },
192
193
  };
193
194
 
194
195
  export { Content };
@@ -35,8 +35,6 @@ const getWsBaseUrl = (options = { id: '', endpoint: '', wsBasePath: '' }) =>
35
35
  const headersFactory = (headerId = '') => {
36
36
  const headers = {
37
37
  Authorization: Auth.getJWT(),
38
- withCredentials: true,
39
- credentials: 'include', // no cors: 'same-origin'
40
38
  };
41
39
  switch (headerId) {
42
40
  case 'file':
@@ -71,29 +69,12 @@ const CoreService = {
71
69
  return reject(error);
72
70
  }),
73
71
  ),
74
- getRandomImage: (options = { category: ['city'], mimetype: 'image/jpg' }) => {
75
- const src = `https://api.api-ninjas.com/v1/randomimage?category=${options.category[0]}`;
76
- return new Promise((resolve) => {
77
- fetch(src, {
78
- headers: { 'X-Api-Key': 'FyITmcxRXkCaUehbX6K0/g==uxZcFKL0dZUUg48G', Accept: options.mimetype },
79
- })
80
- .then((res) => res.blob())
81
- .then(async (blob) => {
82
- return resolve({
83
- file: {
84
- mimetype: 'image/jpg',
85
- name: 'image.jpg',
86
- },
87
- url: URL.createObjectURL(blob),
88
- });
89
- });
90
- });
91
- },
92
72
  post: (options = { id: '', body: {} }) =>
93
73
  new Promise((resolve, reject) =>
94
74
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
95
75
  method: 'POST',
96
76
  headers: headersFactory(),
77
+ credentials: 'include',
97
78
  body: payloadFactory(options.body),
98
79
  })
99
80
  .then(async (res) => {
@@ -113,6 +94,7 @@ const CoreService = {
113
94
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
114
95
  method: 'PUT',
115
96
  headers: headersFactory(),
97
+ credentials: 'include',
116
98
  body: payloadFactory(options.body),
117
99
  })
118
100
  .then(async (res) => {
@@ -132,6 +114,7 @@ const CoreService = {
132
114
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
133
115
  method: 'GET',
134
116
  headers: headersFactory(),
117
+ credentials: 'include',
135
118
  })
136
119
  .then(async (res) => {
137
120
  return await res.json();
@@ -150,6 +133,7 @@ const CoreService = {
150
133
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
151
134
  method: 'DELETE',
152
135
  headers: headersFactory(),
136
+ credentials: 'include',
153
137
  body: payloadFactory(options.body),
154
138
  })
155
139
  .then(async (res) => {
@@ -14,6 +14,7 @@ const DefaultService = {
14
14
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
15
15
  method: 'POST',
16
16
  headers: headersFactory(),
17
+ credentials: 'include',
17
18
  body: payloadFactory(options.body),
18
19
  })
19
20
  .then(async (res) => {
@@ -33,6 +34,7 @@ const DefaultService = {
33
34
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
34
35
  method: 'PUT',
35
36
  headers: headersFactory(),
37
+ credentials: 'include',
36
38
  body: payloadFactory(options.body),
37
39
  })
38
40
  .then(async (res) => {
@@ -56,6 +58,7 @@ const DefaultService = {
56
58
  fetch(url.toString(), {
57
59
  method: 'GET',
58
60
  headers: headersFactory(),
61
+ credentials: 'include',
59
62
  })
60
63
  .then(async (res) => {
61
64
  return await res.json();
@@ -75,6 +78,7 @@ const DefaultService = {
75
78
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
76
79
  method: 'DELETE',
77
80
  headers: headersFactory(),
81
+ credentials: 'include',
78
82
  body: payloadFactory(options.body),
79
83
  })
80
84
  .then(async (res) => {
@@ -14,6 +14,7 @@ const TestService = {
14
14
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
15
15
  method: 'POST',
16
16
  headers: headersFactory(),
17
+ credentials: 'include',
17
18
  body: payloadFactory(options.body),
18
19
  })
19
20
  .then(async (res) => {
@@ -33,6 +34,7 @@ const TestService = {
33
34
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
34
35
  method: 'GET',
35
36
  headers: headersFactory(),
37
+ credentials: 'include',
36
38
  })
37
39
  .then(async (res) => {
38
40
  return await res.json();
@@ -51,6 +53,7 @@ const TestService = {
51
53
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
52
54
  method: 'DELETE',
53
55
  headers: headersFactory(),
56
+ credentials: 'include',
54
57
  body: payloadFactory(options.body),
55
58
  })
56
59
  .then(async (res) => {
@@ -22,6 +22,7 @@ const UserService = {
22
22
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
23
23
  method: 'POST',
24
24
  headers: headersFactory(),
25
+ credentials: 'include',
25
26
  body: payloadFactory(options.body),
26
27
  })
27
28
  .then(async (res) => {
@@ -47,6 +48,7 @@ const UserService = {
47
48
  fetch(url, {
48
49
  method: 'GET',
49
50
  headers: headersFactory(),
51
+ credentials: 'include',
50
52
  })
51
53
  .then(async (res) => {
52
54
  return await res.json();
@@ -66,6 +68,7 @@ const UserService = {
66
68
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
67
69
  method: 'DELETE',
68
70
  headers: headersFactory(),
71
+ credentials: 'include',
69
72
  body: payloadFactory(options.body),
70
73
  })
71
74
  .then(async (res) => {
@@ -85,6 +88,7 @@ const UserService = {
85
88
  fetch(getApiBaseUrl({ id: options.id, endpoint }), {
86
89
  method: 'PUT',
87
90
  headers: headersFactory(options.headerId),
91
+ credentials: 'include',
88
92
  body: payloadFactory(options.body),
89
93
  })
90
94
  .then(async (res) => {
package/src/index.js CHANGED
@@ -35,7 +35,7 @@ class Underpost {
35
35
  * @type {String}
36
36
  * @memberof Underpost
37
37
  */
38
- static version = 'v2.8.876';
38
+ static version = 'v2.8.878';
39
39
  /**
40
40
  * Repository cli API
41
41
  * @static
@@ -523,6 +523,7 @@ function applySecurity(app, opts = {}) {
523
523
 
524
524
  // Content-Security-Policy: include nonce from res.locals
525
525
  // Note: We avoid 'unsafe-inline' on script/style. Use nonces or hashes.
526
+ const httpDirective = process.env.NODE_ENV === 'production' ? 'https:' : 'http:';
526
527
  app.use(
527
528
  helmet.contentSecurityPolicy({
528
529
  useDefaults: true,
@@ -530,16 +531,16 @@ function applySecurity(app, opts = {}) {
530
531
  defaultSrc: ["'self'"],
531
532
  baseUri: ["'self'"],
532
533
  blockAllMixedContent: [],
533
- fontSrc: ["'self'", 'https:', 'data:'],
534
+ fontSrc: ["'self'", httpDirective, 'data:'],
534
535
  frameAncestors: frameAncestors,
535
- imgSrc: ["'self'", 'data:', 'https:'],
536
+ imgSrc: ["'self'", 'data:', httpDirective],
536
537
  objectSrc: ["'none'"],
537
538
  // script-src and script-src-elem include dynamic nonce
538
539
  scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`],
539
540
  scriptSrcElem: ["'self'", (req, res) => `'nonce-${res.locals.nonce}'`],
540
541
  // style-src: avoid 'unsafe-inline' when possible; if you must inline styles,
541
542
  // use a nonce for them too (or hash).
542
- styleSrc: ["'self'", 'https:', (req, res) => `'nonce-${res.locals.nonce}'`],
543
+ styleSrc: ["'self'", httpDirective, (req, res) => `'nonce-${res.locals.nonce}'`],
543
544
  // deny plugins
544
545
  objectSrc: ["'none'"],
545
546
  },
@@ -552,7 +553,7 @@ function applySecurity(app, opts = {}) {
552
553
  origin: origin || false,
553
554
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
554
555
  credentials: true,
555
- allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'withcredentials'],
556
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'Accept', 'withcredentials', 'credentials'],
556
557
  maxAge: 600,
557
558
  }),
558
559
  );
@@ -33,12 +33,13 @@ const Config = {
33
33
  else if (deployContext.startsWith('dd-')) return loadConf(deployContext, process.env.NODE_ENV, subConf);
34
34
  if (deployContext === 'proxy') Config.buildProxy(deployContext, deployList, subConf);
35
35
  },
36
- deployIdFactory: function (deployId = 'dd-default') {
36
+ deployIdFactory: function (deployId = 'dd-default', options = { cluster: false }) {
37
37
  if (!deployId.startsWith('dd-')) deployId = `dd-${deployId}`;
38
38
 
39
39
  logger.info('Build deployId', deployId);
40
40
 
41
41
  const folder = `./engine-private/conf/${deployId}`;
42
+ const repoName = `engine-${deployId.split('dd-')[1]}`;
42
43
 
43
44
  if (!fs.existsSync(folder)) fs.mkdirSync(folder, { recursive: true });
44
45
  fs.writeFileSync(
@@ -56,10 +57,44 @@ const Config = {
56
57
  fs.readFileSync('./.env.test', 'utf8').replaceAll('dd-default', deployId),
57
58
  'utf8',
58
59
  );
59
- fs.writeFileSync(`${folder}/package.json`, fs.readFileSync('./package.json', 'utf8'), 'utf8');
60
+ fs.writeFileSync(
61
+ `${folder}/package.json`,
62
+ fs.readFileSync('./package.json', 'utf8').replaceAll('dd-default', deployId),
63
+ 'utf8',
64
+ );
60
65
 
61
66
  this.buildTmpConf(folder);
62
67
 
68
+ if (options.cluster === true) {
69
+ fs.writeFileSync(
70
+ `./.github/workflows/${repoName}.cd.yml`,
71
+ fs.readFileSync(`./.github/workflows/engine-test.cd.yml`, 'utf8').replaceAll('test', deployId.split('dd-')[1]),
72
+ 'utf8',
73
+ );
74
+ fs.writeFileSync(
75
+ `./.github/workflows/${repoName}.ci.yml`,
76
+ fs.readFileSync(`./.github/workflows/engine-test.ci.yml`, 'utf8').replaceAll('test', deployId.split('dd-')[1]),
77
+ 'utf8',
78
+ );
79
+ shellExec(`node bin/deploy update-default-conf ${deployId}`);
80
+ fs.writeFileSync(
81
+ `./engine-private/deploy/dd.router`,
82
+ fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').trim() + `,${deployId}`,
83
+ 'utf8',
84
+ );
85
+ const updateRepo = (stage = 1) => {
86
+ shellExec(`git add . && git commit -m "Add base deployId ${deployId} cluster files stage:${stage}"`);
87
+ shellExec(
88
+ `cd engine-private && git add . && git commit -m "Add base deployId ${deployId} cluster files stage:${stage}"`,
89
+ );
90
+ };
91
+ updateRepo(1);
92
+ shellExec(`node bin run --build --dev sync`);
93
+ updateRepo(2);
94
+ shellExec(`node bin run --build sync`);
95
+ updateRepo(3);
96
+ }
97
+
63
98
  return { deployIdFolder: folder, deployId };
64
99
  },
65
100
  buildTmpConf: function (folder = './conf') {
@@ -63,6 +63,7 @@ const buildRuntime = async () => {
63
63
  singleReplica,
64
64
  replicas,
65
65
  valkey,
66
+ apiBaseHost,
66
67
  } = confServer[host][path];
67
68
 
68
69
  const { redirectTarget, singleReplicaHost } = await getInstanceContext({
@@ -116,9 +117,6 @@ const buildRuntime = async () => {
116
117
  // set logger
117
118
  app.use(loggerMiddleware(import.meta));
118
119
 
119
- // instance public static
120
- app.use('/', express.static(directory ? directory : `.${rootHostPath}`));
121
-
122
120
  // js src compression
123
121
  app.use(compression({ filter: shouldCompress }));
124
122
  function shouldCompress(req, res) {
@@ -163,6 +161,9 @@ const buildRuntime = async () => {
163
161
  return next();
164
162
  });
165
163
 
164
+ // instance public static
165
+ app.use('/', express.static(directory ? directory : `.${rootHostPath}`));
166
+
166
167
  // security
167
168
  applySecurity(app, {
168
169
  origin: origins.concat(
@@ -188,99 +189,104 @@ const buildRuntime = async () => {
188
189
  await UnderpostStartUp.API.listenPortController(app, port, runningData);
189
190
  break;
190
191
  }
192
+ // instance server
193
+ const server = createServer({}, app);
194
+ if (peer) currentPort++;
191
195
 
192
- const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
193
- if (fs.existsSync(swaggerJsonPath)) {
194
- // logger.info('Build swagger serve', swaggerJsonPath);
196
+ if (!apiBaseHost) {
197
+ const swaggerJsonPath = `./public/${host}${path === '/' ? path : `${path}/`}swagger-output.json`;
198
+ if (fs.existsSync(swaggerJsonPath)) {
199
+ // logger.info('Build swagger serve', swaggerJsonPath);
195
200
 
196
- const swaggerInstance =
197
- (swaggerDoc) =>
198
- (...args) =>
199
- swaggerUi.setup(swaggerDoc)(...args);
201
+ const swaggerInstance =
202
+ (swaggerDoc) =>
203
+ (...args) =>
204
+ swaggerUi.setup(swaggerDoc)(...args);
200
205
 
201
- const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
206
+ const swaggerDoc = JSON.parse(fs.readFileSync(swaggerJsonPath, 'utf8'));
202
207
 
203
- app.use(`${path === '/' ? `/api-docs` : `${path}/api-docs`}`, swaggerUi.serve, swaggerInstance(swaggerDoc));
204
- }
208
+ app.use(
209
+ `${path === '/' ? `/api-docs` : `${path}/api-docs`}`,
210
+ swaggerUi.serve,
211
+ swaggerInstance(swaggerDoc),
212
+ );
213
+ }
205
214
 
206
- if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
215
+ if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
207
216
 
208
- // valkey server
209
- if (valkey) await createValkeyConnection({ host, path }, valkey);
217
+ // valkey server
218
+ if (valkey) await createValkeyConnection({ host, path }, valkey);
210
219
 
211
- if (mailer) {
212
- const mailerSsrConf = confSSR[getCapVariableName(client)];
213
- await MailerProvider.load({
214
- id: `${host}${path}`,
215
- meta: `mailer-${host}${path}`,
216
- host,
217
- path,
218
- ...mailer,
219
- templates: mailerSsrConf ? mailerSsrConf.mailer : {},
220
- });
221
- }
222
- if (apis) {
223
- const authMiddleware = authMiddlewareFactory({ host, path });
220
+ if (mailer) {
221
+ const mailerSsrConf = confSSR[getCapVariableName(client)];
222
+ await MailerProvider.load({
223
+ id: `${host}${path}`,
224
+ meta: `mailer-${host}${path}`,
225
+ host,
226
+ path,
227
+ ...mailer,
228
+ templates: mailerSsrConf ? mailerSsrConf.mailer : {},
229
+ });
230
+ }
231
+ if (apis) {
232
+ const authMiddleware = authMiddlewareFactory({ host, path });
233
+
234
+ const apiPath = `${path === '/' ? '' : path}/${process.env.BASE_API}`;
235
+ for (const api of apis)
236
+ await (async () => {
237
+ const { ApiRouter } = await import(`../api/${api}/${api}.router.js`);
238
+ const router = ApiRouter({ host, path, apiPath, mailer, db, authMiddleware, origins });
239
+ // router.use(cors({ origin: origins }));
240
+ // logger.info('Load api router', { host, path: apiPath, api });
241
+ app.use(`${apiPath}/${api}`, router);
242
+ })();
243
+ }
224
244
 
225
- const apiPath = `${path === '/' ? '' : path}/${process.env.BASE_API}`;
226
- for (const api of apis)
245
+ if (ws)
227
246
  await (async () => {
228
- const { ApiRouter } = await import(`../api/${api}/${api}.router.js`);
229
- const router = ApiRouter({ host, path, apiPath, mailer, db, authMiddleware });
230
- // router.use(cors({ origin: origins }));
231
- // logger.info('Load api router', { host, path: apiPath, api });
232
- app.use(`${apiPath}/${api}`, router);
247
+ const { createIoServer } = await import(`../ws/${ws}/${ws}.ws.server.js`);
248
+ // logger.info('Load socket.io ws router', { host, ws });
249
+ // start socket.io
250
+ const { options, meta } = await createIoServer(server, {
251
+ host,
252
+ path,
253
+ db,
254
+ port,
255
+ origins,
256
+ });
257
+ await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), port, {
258
+ runtime: 'nodejs',
259
+ client: null,
260
+ host,
261
+ path: options.path,
262
+ meta,
263
+ });
233
264
  })();
234
- }
235
265
 
236
- // load ssr
237
- const ssr = await ssrMiddlewareFactory({ app, directory, rootHostPath, path });
238
- for (const [_, ssrMiddleware] of Object.entries(ssr)) app.use(ssrMiddleware);
239
-
240
- // instance server
241
- const server = createServer({}, app);
242
-
243
- if (ws)
244
- await (async () => {
245
- const { createIoServer } = await import(`../ws/${ws}/${ws}.ws.server.js`);
246
- // logger.info('Load socket.io ws router', { host, ws });
247
- // start socket.io
248
- const { options, meta } = await createIoServer(server, {
266
+ if (peer) {
267
+ const peerPort = newInstance(currentPort);
268
+ const { options, meta, peerServer } = await createPeerServer({
269
+ port: peerPort,
270
+ devPort: port,
271
+ origins,
249
272
  host,
250
273
  path,
251
- db,
252
- port,
253
- origins,
254
274
  });
255
- await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), port, {
275
+
276
+ await UnderpostStartUp.API.listenPortController(peerServer, peerPort, {
256
277
  runtime: 'nodejs',
257
278
  client: null,
258
279
  host,
259
280
  path: options.path,
260
281
  meta,
261
282
  });
262
- })();
263
-
264
- if (peer) {
265
- currentPort++;
266
- const peerPort = newInstance(currentPort);
267
- const { options, meta, peerServer } = await createPeerServer({
268
- port: peerPort,
269
- devPort: port,
270
- origins,
271
- host,
272
- path,
273
- });
274
-
275
- await UnderpostStartUp.API.listenPortController(peerServer, peerPort, {
276
- runtime: 'nodejs',
277
- client: null,
278
- host,
279
- path: options.path,
280
- meta,
281
- });
283
+ }
282
284
  }
283
285
 
286
+ // load ssr
287
+ const ssr = await ssrMiddlewareFactory({ app, directory, rootHostPath, path });
288
+ for (const [_, ssrMiddleware] of Object.entries(ssr)) app.use(ssrMiddleware);
289
+
284
290
  await UnderpostStartUp.API.listenPortController(server, port, runningData);
285
291
 
286
292
  break;