@madgex/fert 6.0.1 → 6.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.
package/constants.js CHANGED
@@ -1,57 +1,53 @@
1
- const fs = require('node:fs');
2
- const path = require('node:path');
3
- const os = require('node:os');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
4
 
5
- const { version: VERSION } = JSON.parse(fs.readFileSync(path.resolve(__dirname, './package.json')).toString());
5
+ export const { version: VERSION } = JSON.parse(
6
+ fs.readFileSync(path.resolve(import.meta.dirname, './package.json')).toString(),
7
+ );
6
8
 
7
- const ONE_MINUTE = 60000;
8
- const ONE_HOUR = ONE_MINUTE * 60;
9
- const ONE_DAY = ONE_HOUR * 24;
10
- const ONE_WEEK = ONE_DAY * 7;
9
+ export const ONE_MINUTE = 60000;
10
+ export const ONE_HOUR = ONE_MINUTE * 60;
11
+ export const ONE_DAY = ONE_HOUR * 24;
12
+ export const ONE_WEEK = ONE_DAY * 7;
11
13
 
12
- module.exports = {
13
- VERSION,
14
- TMP_DIR: fs.realpathSync(os.tmpdir()),
15
- FERT_PACKAGE_DIR: path.resolve('./'),
16
- CUSTOM_TEMPLATES_DIR: './pages',
17
- AWS_REGION: 'eu-west-1',
18
- PROPERTY_ID_API: 'https://property-identification-api.cs.madgexhosting.net/properties/',
19
- ASSETS_API_URL: 'https://asset-store.job.madgexhosting.net',
20
- BRAND_JSON_FILENAME: 'brand.json',
21
- FERT_CONFIG_FILENAME: 'fert.config.js',
22
- FERT_SERVICE_CONFIG_FILENAME: 'fert.service.config.js',
23
- ASSET_STORE_API: 'https://asset-store-api.{env}.madgexhosting.net/',
24
- UPLOAD_DIR: 'dist',
25
- /**
26
- * use `jobseekers-frontend` AWS keys for asset-store access, even for all services (e.g. recruiterservices-frontend).
27
- * 💡 Technically this should be `fert-service` key. It does not make sense to create `recruiterservices-frontend` with access too.
28
- * Possibly one to refactor in the future.
29
- * */
30
- AWS_PARAM_NAME:
31
- '/{Environment_Name}/jobboard/kong/internal/consumer-key/jobseekers-frontend_{fertConfig.client.rootClientPropertyId}',
32
- /**
33
- * important to have the correct service name and cpid so assets are uploaded to the correct unique place per-service.
34
- */
35
- REMOTE_UPLOAD_BASE: '/api/assets/{fertConfig.serviceName}/{fertConfig.clientPropertyId}',
36
- /**
37
- * invalidates the real asset store key path, which is related to `REMOTE_UPLOAD_BASE`
38
- * asset-store puts things in `rootClientPropertyId` based on the AWS_PARAM_NAME used, and the rest of the path relates to `REMOTE_UPLOAD_BASE`
39
- */
40
- ASSET_STORE_INVALIDATION_PATH: `/{fertConfig.client.rootClientPropertyId}/{fertConfig.serviceName}/{fertConfig.clientPropertyId}/*`,
41
- /**
42
- * cloud backend cache busting for updated assets.
43
- * assumption that assets are accessed on each service via a similar root.
44
- * e.g.
45
- * www.bigworkbag.com/_/jobseekers-frontend/assets/my-asset.png
46
- * recruiter.bigworkbag.com/_/recruiterservices-frontend/assets/my-asset.png
47
- */
48
- BRANDED_SITE_INVALIDATION_PATH: `/_/{fertConfig.serviceName}/assets/*`,
49
- ASSET_STORE_USER_GUID: 'a386d4b6-f2df-4b80-ad1f-0349e23f530b',
50
- ONE_MINUTE,
51
- ONE_HOUR,
52
- ONE_DAY,
53
- ONE_WEEK,
54
- CONFIG_API:
55
- 'https://configuration-api.job.madgexhosting.net/configs/override/{cpid}/production/clientconfig/{config}',
56
- CONFIG_DIR: 'config',
57
- };
14
+ export const TMP_DIR = fs.realpathSync(os.tmpdir());
15
+ export const FERT_PACKAGE_DIR = path.resolve('./');
16
+ export const CUSTOM_TEMPLATES_DIR = './pages';
17
+ export const AWS_REGION = 'eu-west-1';
18
+ export const PROPERTY_ID_API = 'https://property-identification-api.cs.madgexhosting.net/properties/';
19
+ export const ASSETS_API_URL = 'https://asset-store.job.madgexhosting.net';
20
+ export const BRAND_JSON_FILENAME = 'brand.json';
21
+ export const FERT_CONFIG_FILENAME = 'fert.config.js';
22
+ export const FERT_SERVICE_CONFIG_FILENAME = 'fert.service.config.js';
23
+ export const ASSET_STORE_API = 'https://asset-store-api.{env}.madgexhosting.net/';
24
+ export const UPLOAD_DIR = 'dist';
25
+ /**
26
+ * use `jobseekers-frontend` AWS keys for asset-store access, even for all services (e.g. recruiterservices-frontend).
27
+ * 💡 Technically this should be `fert-service` key. It does not make sense to create `recruiterservices-frontend` with access too.
28
+ * Possibly one to refactor in the future.
29
+ * */
30
+ export const AWS_PARAM_NAME =
31
+ '/{Environment_Name}/jobboard/kong/internal/consumer-key/jobseekers-frontend_{fertConfig.client.rootClientPropertyId}';
32
+ /**
33
+ * important to have the correct service name and cpid so assets are uploaded to the correct unique place per-service.
34
+ */
35
+ export const REMOTE_UPLOAD_BASE = '/api/assets/{fertConfig.serviceName}/{fertConfig.clientPropertyId}';
36
+ /**
37
+ * invalidates the real asset store key path, which is related to `REMOTE_UPLOAD_BASE`
38
+ * asset-store puts things in `rootClientPropertyId` based on the AWS_PARAM_NAME used, and the rest of the path relates to `REMOTE_UPLOAD_BASE`
39
+ */
40
+ export const ASSET_STORE_INVALIDATION_PATH = `/{fertConfig.client.rootClientPropertyId}/{fertConfig.serviceName}/{fertConfig.clientPropertyId}/*`;
41
+ /**
42
+ * cloud backend cache busting for updated assets.
43
+ * assumption that assets are accessed on each service via a similar root.
44
+ * e.g.
45
+ * www.bigworkbag.com/_/jobseekers-frontend/assets/my-asset.png
46
+ * recruiter.bigworkbag.com/_/recruiterservices-frontend/assets/my-asset.png
47
+ */
48
+ export const BRANDED_SITE_INVALIDATION_PATH = `/_/{fertConfig.serviceName}/assets/*`;
49
+ export const ASSET_STORE_USER_GUID = 'a386d4b6-f2df-4b80-ad1f-0349e23f530b';
50
+
51
+ export const CONFIG_API =
52
+ 'https://configuration-api.job.madgexhosting.net/configs/override/{cpid}/production/clientconfig/{config}';
53
+ export const CONFIG_DIR = 'config';
@@ -0,0 +1,19 @@
1
+ // eslint-disable-next-line n/no-unpublished-import
2
+ import madgexConfig from '@madgex/eslint-config-madgex';
3
+
4
+ export default [
5
+ {
6
+ ignores: [
7
+ '**/dist',
8
+ '**/temp',
9
+ '**/dist',
10
+ '**/*.json',
11
+ '**/*.json',
12
+ '**/.eslintrc.js',
13
+ '**/node_modules',
14
+ '**/repo-template',
15
+ 'eslint.config.mjs',
16
+ ],
17
+ },
18
+ ...madgexConfig,
19
+ ];
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@madgex/fert",
3
- "version": "6.0.1",
3
+ "version": "6.0.2",
4
4
  "description": "Tool to help build the V6 branding",
5
5
  "bin": {
6
6
  "fert": "./bin/cli.js"
7
7
  },
8
- "type": "commonjs",
8
+ "type": "module",
9
9
  "scripts": {
10
10
  "lint": "eslint .",
11
11
  "format": "prettier --write .",
12
12
  "lint-staged": "lint-staged",
13
13
  "semantic-release": "semantic-release",
14
- "test": "node --test ./bin/**/*.test.js",
14
+ "test": "node --test --experimental-test-module-mocks \"./bin/**/*.test.js\"",
15
15
  "prepare": "husky"
16
16
  },
17
17
  "repository": {
@@ -36,25 +36,26 @@
36
36
  "@private/header-footer-podlet-server": "github:wiley/madgex-header-footer-podlet",
37
37
  "axios": "^1.9.0",
38
38
  "cac": "^6.7.14",
39
- "chalk": "4.1.2",
40
- "chokidar": "^3.5.3",
39
+ "chalk": "^5.4.1",
40
+ "chokidar4": "npm:chokidar@^4.0.3",
41
41
  "debug": "^4.4.0",
42
42
  "dedent": "^1.5.3",
43
43
  "find-up-simple": "^1.0.1",
44
- "flat-cache": "^4.0.0",
44
+ "flat-cache": "^6.1.8",
45
45
  "form-data": "^4.0.2",
46
+ "joi": "^17.13.3",
46
47
  "lodash": "^4.17.21",
47
48
  "nunjucks": "^3.2.4",
48
49
  "open": "8.4.2",
49
50
  "ora": "5.4.1",
50
51
  "prompts": "^2.4.2",
51
- "rimraf": "^5.0.5",
52
+ "rimraf": "^6.0.1",
52
53
  "sass": "^1.87.0",
53
54
  "simple-git": "^3.27.0",
54
55
  "simple-update-notifier": "^2.0.0",
55
56
  "uuid-validate": "^0.0.3",
56
- "vite": "^4.5.14",
57
- "vite-plugin-static-copy": "^0.17.1"
57
+ "vite": "^6.3.4",
58
+ "vite-plugin-static-copy": "^2.3.1"
58
59
  },
59
60
  "devDependencies": {
60
61
  "@commitlint/cli": "^19.8.0",
@@ -63,7 +64,6 @@
63
64
  "@madgex/prettier-config-madgex": "^2.0.0",
64
65
  "eslint": "^9.25.1",
65
66
  "husky": "^9.1.7",
66
- "joi": "^17.13.3",
67
67
  "lint-staged": "^15.5.1",
68
68
  "prettier": "^3.5.3",
69
69
  "semantic-release": "^24.2.3"
@@ -1,4 +1,4 @@
1
- module.exports = [
1
+ export default [
2
2
  {
3
3
  type: 'onPreResponse',
4
4
  method: async (request, h) => {
package/server/index.js CHANGED
@@ -1,103 +1,7 @@
1
- const Hapi = require('@hapi/hapi');
2
- const Toys = require('@hapipal/toys');
3
- const path = require('node:path');
4
- const { log } = require('../bin/utils/logging');
5
- const podletServer = require('@private/header-footer-podlet-server');
6
- const { VERSION, PROPERTY_ID_API, ASSETS_API_URL } = require('../constants');
1
+ import { devServer } from './server';
7
2
 
8
- exports.devServer = async ({ start, fertConfig = {} } = {}) => {
9
- const server = Hapi.server({
10
- port: 0, // 0 === random unused port
11
- host: fertConfig.cli?.host ?? 'localhost',
12
- });
3
+ process.on('unhandledRejection', (err) => {
4
+ throw err;
5
+ });
13
6
 
14
- // "the path prefix used to locate static resources (files and view templates) when relative paths are used"
15
- // https://hapi.dev/api/?v=21.3.2#-serverpathrelativeto
16
- server.path(fertConfig.workingDir);
17
-
18
- // make incoming fertConfig available server-wide
19
- server.decorate('server', 'fertConfig', ({ update } = {}) => {
20
- if (update) {
21
- // eslint-disable-next-line no-param-reassign
22
- fertConfig = update;
23
- }
24
-
25
- return fertConfig;
26
- });
27
-
28
- // load in the podletServer to the dev servers app namespace
29
- // server.app.podletServer = await podletServer({ start: false, fertConfig });
30
- await server.register({
31
- plugin: podletServer,
32
- options: {
33
- version: `${VERSION}-fert`,
34
- isFert: true,
35
- isProd: false,
36
- templatePath: [path.resolve(fertConfig.workingDir, 'templates')],
37
- clientPropertiesApi: PROPERTY_ID_API,
38
- assetsApiUrl: ASSETS_API_URL,
39
- layout: fertConfig.serviceName,
40
- },
41
- routes: { prefix: '/_podlet' },
42
- });
43
-
44
- // add template support to hapi and setup the nunjucks engine
45
- await server.register([
46
- // require('blipp'),
47
- require('@hapi/vision'),
48
- require('@hapi/inert'),
49
- {
50
- plugin: require('./plugins/hapi-vite'),
51
- options: {
52
- watch: ['/templates/**/*', '/public/tokens/**/*'].map((p) => path.join(fertConfig.workingDir, p)),
53
- root: path.resolve(fertConfig.workingDir),
54
- entry: path.join(fertConfig.workingDir, fertConfig.entry),
55
- log: log.debug,
56
- },
57
- },
58
- ]);
59
-
60
- server.views(require('./view-manager')(server));
61
-
62
- // mocked logged in
63
- Toys.auth.strategy(server, 'mock-user', (request, h) => {
64
- if (Object.prototype.hasOwnProperty.call(request.query, 'loggedin')) {
65
- const user = {
66
- email: 'email@madgex.com',
67
- firstName: 'Samus',
68
- lastName: 'Aran',
69
- userId: 'b5699145-e867-4b47-8b18-f81247948dbb',
70
- username: 'Samus Aran',
71
- };
72
-
73
- return h.authenticated({ credentials: user });
74
- }
75
-
76
- return h.continue;
77
- });
78
-
79
- // routes
80
- server.route(require('./routes/public')({ fertConfig }));
81
- server.route(require('./routes/views'));
82
- server.ext(require('./extensions/error-logging'));
83
-
84
- if (start) {
85
- await server.start();
86
-
87
- log.debug(`Hapi server started at ${server.info.uri}`);
88
-
89
- return server;
90
- }
91
-
92
- await server.initialize();
93
-
94
- return server;
95
- };
96
-
97
- if (require.main === module) {
98
- exports.devServer({ start: true });
99
-
100
- process.on('unhandledRejection', (err) => {
101
- throw err;
102
- });
103
- }
7
+ devServer({ start: true });
@@ -1,6 +1,8 @@
1
- const { createServer } = require('vite');
2
- const chokidar = require('chokidar');
3
- const Hoek = require('@hapi/hoek');
1
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
2
+ import { glob } from 'node:fs/promises';
3
+ import { createServer } from 'vite';
4
+ import chokidar from 'chokidar4';
5
+ import * as Hoek from '@hapi/hoek';
4
6
 
5
7
  const internals = {};
6
8
 
@@ -10,7 +12,7 @@ internals.defaults = {
10
12
  log: console.log,
11
13
  };
12
14
 
13
- module.exports = {
15
+ export default {
14
16
  name: 'hapi-vite',
15
17
  register: async (server, options = {}) => {
16
18
  // eslint-disable-next-line no-param-reassign
@@ -41,7 +43,8 @@ module.exports = {
41
43
  await server.app.viteServer.listen();
42
44
 
43
45
  if (options.watch && options.watch.length) {
44
- chokidar.watch(options.watch).on('all', (event, path) => {
46
+ const watchList = await Array.fromAsync(glob(options.watch));
47
+ chokidar.watch(watchList).on('all', (event, path) => {
45
48
  log(event, path);
46
49
  if (event === 'add' || event === 'change') {
47
50
  server.app.viteServer.ws.send({
@@ -1,4 +1,6 @@
1
- module.exports = ({ fertConfig }) => [
1
+ import { fileURLToPath } from 'node:url';
2
+
3
+ export default ({ fertConfig }) => [
2
4
  {
3
5
  method: 'get',
4
6
  path: `/_/${fertConfig.serviceName}/assets/{p*}`,
@@ -31,7 +33,7 @@ module.exports = ({ fertConfig }) => [
31
33
  path: '/design-system.css',
32
34
  handler: {
33
35
  file: {
34
- path: require.resolve('@madgex/design-system/index.css'),
36
+ path: fileURLToPath(import.meta.resolve('@madgex/design-system/index.css')),
35
37
  confine: false, // allow access outside of the fert project (helpful during dev)
36
38
  },
37
39
  },
@@ -1,11 +1,9 @@
1
- const fs = require('fs');
2
- const path = require('node:path');
3
- const { CUSTOM_TEMPLATES_DIR } = require('../../constants');
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import Joi from 'joi';
4
+ import { CUSTOM_TEMPLATES_DIR } from '../../constants.js';
4
5
 
5
- // eslint-disable-next-line n/no-unpublished-require
6
- const Joi = require('joi');
7
-
8
- module.exports = {
6
+ export default {
9
7
  method: 'GET',
10
8
  path: '/{page*}',
11
9
  handler: async (request, h) => {
@@ -0,0 +1,104 @@
1
+ import path from 'node:path';
2
+ import Hapi from '@hapi/hapi';
3
+ import Toys from '@hapipal/toys';
4
+ import Vision from '@hapi/vision';
5
+ import Inert from '@hapi/inert';
6
+ import HapiVite from './plugins/hapi-vite.js';
7
+ import viewManager from './view-manager.js';
8
+
9
+ import { log } from '../bin/utils/logging.js';
10
+ import podletServer from '@private/header-footer-podlet-server';
11
+ import { VERSION, PROPERTY_ID_API, ASSETS_API_URL } from '../constants.js';
12
+
13
+ import routesPublic from './routes/public.js';
14
+ import routesViews from './routes/views.js';
15
+ import extensionErrorLogging from './extensions/error-logging.js';
16
+
17
+ export async function devServer({ start, fertConfig = {} } = {}) {
18
+ const server = Hapi.server({
19
+ port: 0, // 0 === random unused port
20
+ host: fertConfig.cli?.host ?? 'localhost',
21
+ });
22
+
23
+ // "the path prefix used to locate static resources (files and view templates) when relative paths are used"
24
+ // https://hapi.dev/api/?v=21.3.2#-serverpathrelativeto
25
+ server.path(fertConfig.workingDir);
26
+
27
+ // make incoming fertConfig available server-wide
28
+ server.decorate('server', 'fertConfig', ({ update } = {}) => {
29
+ if (update) {
30
+ // eslint-disable-next-line no-param-reassign
31
+ fertConfig = update;
32
+ }
33
+
34
+ return fertConfig;
35
+ });
36
+
37
+ // load in the podletServer to the dev servers app namespace
38
+ // server.app.podletServer = await podletServer({ start: false, fertConfig });
39
+ await server.register({
40
+ plugin: podletServer,
41
+ options: {
42
+ version: `${VERSION}-fert`,
43
+ isFert: true,
44
+ isProd: false,
45
+ templatePath: [path.resolve(fertConfig.workingDir, 'templates')],
46
+ clientPropertiesApi: PROPERTY_ID_API,
47
+ assetsApiUrl: ASSETS_API_URL,
48
+ layout: fertConfig.serviceName,
49
+ },
50
+ routes: { prefix: '/_podlet' },
51
+ });
52
+
53
+ // add template support to hapi and setup the nunjucks engine
54
+ await server.register([
55
+ Vision,
56
+ Inert,
57
+ {
58
+ plugin: HapiVite,
59
+ options: {
60
+ watch: ['/templates/**/*', '/public/tokens/**/*'].map((p) => path.join(fertConfig.workingDir, p)),
61
+ root: path.resolve(fertConfig.workingDir),
62
+ entry: path.join(fertConfig.workingDir, fertConfig.entry),
63
+ log: log.debug,
64
+ },
65
+ },
66
+ ]);
67
+
68
+ server.views(viewManager(server));
69
+
70
+ // mocked logged in
71
+ Toys.auth.strategy(server, 'mock-user', (request, h) => {
72
+ if (Object.prototype.hasOwnProperty.call(request.query, 'loggedin')) {
73
+ const user = {
74
+ email: 'email@madgex.com',
75
+ firstName: 'Samus',
76
+ lastName: 'Aran',
77
+ userId: 'b5699145-e867-4b47-8b18-f81247948dbb',
78
+ username: 'Samus Aran',
79
+ };
80
+
81
+ return h.authenticated({ credentials: user });
82
+ }
83
+
84
+ return h.continue;
85
+ });
86
+
87
+ // routes
88
+ server.route(routesPublic({ fertConfig }));
89
+ server.route(routesViews);
90
+
91
+ server.ext(extensionErrorLogging);
92
+
93
+ if (start) {
94
+ await server.start();
95
+
96
+ log.debug(`Hapi server started at ${server.info.uri}`);
97
+
98
+ return server;
99
+ }
100
+
101
+ await server.initialize();
102
+
103
+ return server;
104
+ }
@@ -1,8 +1,8 @@
1
- const Nunjucks = require('nunjucks');
2
- const path = require('node:path');
3
- const { CUSTOM_TEMPLATES_DIR } = require('../constants');
1
+ import path from 'node:path';
2
+ import Nunjucks from 'nunjucks';
3
+ import { CUSTOM_TEMPLATES_DIR } from '../constants.js';
4
4
 
5
- module.exports = (server) => {
5
+ export default (server) => {
6
6
  const fertConfig = server.fertConfig();
7
7
 
8
8
  return {
@@ -31,7 +31,7 @@ module.exports = (server) => {
31
31
  },
32
32
  path: [
33
33
  path.join(fertConfig.workingDir, CUSTOM_TEMPLATES_DIR), // user-created 'pages'
34
- path.join(__dirname, './templates'), // fert-local base templates
34
+ path.join(import.meta.dirname, './templates'), // fert-local base templates
35
35
  ],
36
36
  isCached: false,
37
37
  async context(request) {
package/vite.config.js CHANGED
@@ -1,10 +1,10 @@
1
- const { defineConfig } = require('vite');
2
- const { viteStaticCopy } = require('vite-plugin-static-copy');
1
+ import { defineConfig } from 'vite';
2
+ import { viteStaticCopy } from 'vite-plugin-static-copy';
3
3
 
4
- module.exports = defineConfig({
4
+ export default defineConfig({
5
5
  build: {
6
6
  // generate manifest.json in outDir
7
- manifest: true,
7
+ manifest: 'manifest.json',
8
8
  },
9
9
  plugins: [
10
10
  viteStaticCopy({