@madgex/fert 4.1.1 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,10 +16,10 @@ jobs:
16
16
  - name: Checkout
17
17
  uses: actions/checkout@v4
18
18
  - name: Setup Node.js
19
- uses: actions/setup-node@v3
19
+ uses: actions/setup-node@v4
20
20
  with:
21
21
  cache: npm
22
- node-version: 20
22
+ node-version: 22
23
23
 
24
24
  - name: Setup SSH Keys and known_hosts
25
25
  env:
package/.husky/pre-commit CHANGED
@@ -1 +1,2 @@
1
1
  npm run lint-staged
2
+ npm run test
package/README.md CHANGED
@@ -217,4 +217,4 @@ Here are the default npm scripts in a Fert-scaffolded project.
217
217
 
218
218
  Its expected that a Jenkins pipeline will run `fert publish` to send all built assets to the Asset Store API.
219
219
 
220
- .
220
+ .
package/bin/cli.js CHANGED
@@ -44,6 +44,10 @@ const run = () => {
44
44
  '--publish <env>',
45
45
  'Publish configs to Configuration API environment "dev" or "production"'
46
46
  )
47
+ .option(
48
+ '--download <env>',
49
+ 'Download known configs from the Configuration API for environment "dev" or "production"'
50
+ )
47
51
  .option(
48
52
  '--query [configName]',
49
53
  'Describe known keys for a config, omit to list all known configs'
@@ -6,65 +6,167 @@ const {
6
6
  } = require('../utils/configs.js');
7
7
  const chalk = require('chalk');
8
8
  const { log } = require('../utils/logging.js');
9
+ const { getSchemaKeyMeta } = require('../utils/getSchemaKeyMeta.js');
10
+ const ora = require('ora');
11
+ const { mkdir, writeFile } = require('node:fs/promises');
12
+ const Path = require('node:path');
13
+ const { CONFIG_DIR } = require('../../constants.js');
9
14
 
10
- module.exports = async (root, options) => {
11
- const fertConfig = await resolveConfig(root, options);
12
- const api = await getConfigAPI(fertConfig);
15
+ const handleDownload = async (fertConfig, api, options) => {
16
+ const validTargets = ['dev', 'production'];
13
17
 
14
- if (!options.publish && !options.query) {
15
- console.log(chalk.red(`Missing required --publish or --query option`));
18
+ if (!validTargets.includes(options.download)) {
19
+ throw new Error(
20
+ `Missing or invalid --download option. Choose from [${validTargets}]`
21
+ );
16
22
  }
17
23
 
18
- if (options.publish) {
19
- const validTargets = ['dev', 'production'];
24
+ const spinner = ora('Downloading v6 configs...').start();
25
+ const resultObj = {};
20
26
 
21
- if (!validTargets.includes(options.publish)) {
22
- throw Error(
23
- `Missing or invalid --publish option. Choose from [${validTargets}]`
24
- );
25
- }
27
+ try {
28
+ for (const [schemaName, schema] of Object.entries(api.schemas)) {
29
+ const configs = await api.getSchemaKeys(schemaName);
26
30
 
27
- try {
28
- await validateLocalConfigs(fertConfig, { catch: false });
29
- await updateProjectConfigs(fertConfig, { environment: options.publish });
30
- } catch (err) {
31
- log.debug(err);
32
- process.exit(1);
33
- }
34
- } else if (options.query) {
35
- try {
36
- if (options.query !== true) {
37
- console.log(
38
- chalk.cyan(`\nGetting ${options.query} schema description...`)
39
- );
40
- const schema = api.schemas[options.query];
41
- if (!schema) {
42
- console.error(chalk.red(`Schema not found for ${options.query}`));
43
- return;
31
+ for (const configKey of configs) {
32
+ const meta = getSchemaKeyMeta(schema, configKey);
33
+ if (meta.readOnly) {
34
+ continue;
44
35
  }
45
36
 
46
- console.log(JSON.stringify(schema.describe().keys, null, 2));
47
- console.log(
48
- `\n${chalk.cyan('Defaults')}:\n${JSON.stringify(schema.validate({}), null, 2)}`
49
- );
50
- return;
37
+ try {
38
+ const data = await api.getConfig(schemaName, configKey, {
39
+ useSchema: false,
40
+ });
41
+ if (!data.isDefault) {
42
+ let result = data.result;
43
+ try {
44
+ result = JSON.parse(result);
45
+ } catch (error) {
46
+ log.debug(
47
+ `Unable to JSON parse ${chalk.cyan(data.response?.url || schemaName + '/' + configKey)} error:`,
48
+ error.message
49
+ );
50
+ }
51
+
52
+ resultObj[schemaName] = {
53
+ ...result[schemaName],
54
+ [configKey]: result,
55
+ };
56
+ }
57
+ } catch (error) {
58
+ log.debug(
59
+ `Unable to retrieve ${chalk.cyan(error.url || schemaName + '/' + configKey)}`,
60
+ error.message || error.statusText || error
61
+ );
62
+ }
51
63
  }
64
+ }
65
+
66
+ spinner.succeed();
67
+ } catch (error) {
68
+ spinner.fail(
69
+ `Error ${error.code ? `[${error.code}]` : ''}: ${error.message}`
70
+ );
71
+ throw error;
72
+ }
73
+
74
+ console.log(chalk.green('Saving files...'));
75
+
76
+ try {
77
+ await mkdir(CONFIG_DIR, { recursive: true });
78
+ } catch (error) {
79
+ log.debug(`Unable to create directory ${CONFIG_DIR}`, error);
80
+ // basically ignore error
81
+ }
82
+
83
+ for (const [schemaName, data] of Object.entries(resultObj)) {
84
+ const filePath = Path.join(CONFIG_DIR, `${schemaName}.json`);
85
+ await writeFile(filePath, JSON.stringify(data, null, 2));
86
+ console.log(` - ${schemaName}.json`);
87
+ }
88
+ };
89
+
90
+ const handlePublish = async (fertConfig, api, options) => {
91
+ const validTargets = ['dev', 'production'];
52
92
 
53
- console.log(chalk.cyan(`\nAvailable config schemas...`));
93
+ if (!validTargets.includes(options.publish)) {
94
+ throw new Error(
95
+ `Missing or invalid --publish option. Choose from [${validTargets}]`
96
+ );
97
+ }
98
+
99
+ try {
100
+ await validateLocalConfigs(fertConfig, { catch: false });
101
+ await updateProjectConfigs(fertConfig, { environment: options.publish });
102
+ console.log('upload');
103
+ } catch (err) {
104
+ log.debug(err);
105
+ process.exit(1);
106
+ }
107
+ };
108
+
109
+ const handleQuery = async (fertConfig, api, options) => {
110
+ try {
111
+ if (options.query !== true) {
54
112
  console.log(
55
- Object.keys(api.schemas)
56
- .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
57
- .map((key) => ` * ${key}`)
58
- .join('\n'),
59
- '\n'
113
+ chalk.cyan(
114
+ `\nGetting schema description for config: ${chalk.bold(options.query)}...`
115
+ )
60
116
  );
117
+ const schema = api.schemas[options.query];
118
+ if (!schema) {
119
+ console.error(
120
+ chalk.red(`Schema not found for ${chalk.bold(options.query)}`)
121
+ );
122
+ return;
123
+ }
61
124
 
125
+ console.log(JSON.stringify(schema.describe().keys, null, 2));
62
126
  console.log(
63
- 'Use `fert configs <configName>` to get a specific schema description'
127
+ `\n${chalk.cyan('Configs default values')}:\n${JSON.stringify(schema.validate({}).value, null, 2)}`
64
128
  );
65
- } catch (err) {
66
- log.debug(err);
67
- process.exit(1);
129
+ return;
68
130
  }
131
+
132
+ console.log(chalk.cyan(`\nAvailable config schemas...`));
133
+ console.log(
134
+ Object.keys(api.schemas)
135
+ .sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
136
+ .map((key) => ` * ${key}`)
137
+ .join('\n'),
138
+ '\n'
139
+ );
140
+
141
+ console.log(
142
+ 'Use `fert configs <configName>` to get a specific schema description'
143
+ );
144
+ } catch (err) {
145
+ log.debug(err);
146
+ process.exit(1);
69
147
  }
70
148
  };
149
+
150
+ module.exports = async (root, options) => {
151
+ const fertConfig = await resolveConfig(root, options);
152
+ const api = await getConfigAPI(fertConfig);
153
+
154
+ if (!options.publish && !options.query && !options.download) {
155
+ console.log(
156
+ chalk.red(`Missing required --publish, --query or --download option`)
157
+ );
158
+ return;
159
+ }
160
+
161
+ if (options.download) {
162
+ await handleDownload(fertConfig, api, options);
163
+ } else if (options.publish) {
164
+ await handlePublish(fertConfig, api, options);
165
+ } else if (options.query) {
166
+ await handleQuery(fertConfig, api, options);
167
+ }
168
+ };
169
+
170
+ module.exports.handleDownload = handleDownload;
171
+ module.exports.handlePublish = handlePublish;
172
+ module.exports.handleQuery = handleQuery;
@@ -0,0 +1,162 @@
1
+ const assert = require('node:assert');
2
+ const { describe, it, beforeEach } = require('node:test');
3
+ const fs = require('node:fs/promises');
4
+ const Path = require('node:path');
5
+ const Joi = require('joi');
6
+
7
+ describe('configs', () => {
8
+ let fertConfig;
9
+ let api;
10
+ let mkdirMock;
11
+ let writeFileMock;
12
+ let handleDownload;
13
+ let handleQuery;
14
+ let handlePublish;
15
+
16
+ beforeEach(async (t) => {
17
+ fertConfig = {
18
+ clientPropertyId: 'ff6102ff-0f4b-43d1-a2c7-83b835b8dee5',
19
+ };
20
+
21
+ const { ConfigAPI } = await import('@madgex/config-api-sdk');
22
+
23
+ api = new ConfigAPI({
24
+ clientPropertyId: fertConfig.clientPropertyId,
25
+ environment: 'dev',
26
+ schemas: {
27
+ 'jsfe-config': Joi.object({
28
+ StrConfig: Joi.string().default('My new JSFE config'),
29
+ }),
30
+ },
31
+ fetch: async () => ({
32
+ ok: true,
33
+ json: async () => ({
34
+ status: 'success',
35
+ data: [
36
+ {
37
+ configName: 'jsfe-config',
38
+ key: 'StrConfig',
39
+ value: '"hello"',
40
+ },
41
+ ],
42
+ }),
43
+ }),
44
+ });
45
+
46
+ // Set up mocks before requiring the module that uses them
47
+ mkdirMock = t.mock.method(fs, 'mkdir', async () => {});
48
+ writeFileMock = t.mock.method(fs, 'writeFile', async () => {});
49
+
50
+ // Clear require cache to ensure we get a fresh copy with our mocks
51
+ delete require.cache[require.resolve('./configs')];
52
+ ({ handleDownload, handleQuery, handlePublish } = require('./configs'));
53
+ });
54
+
55
+ describe('handleDownload', () => {
56
+ let options;
57
+
58
+ beforeEach(async () => {
59
+ options = { download: 'dev' };
60
+ });
61
+
62
+ it('iterates over known schemas', async () => {
63
+ await handleDownload(fertConfig, api, options);
64
+
65
+ assert.strictEqual(Object.keys(api.schemas).length, 1);
66
+ assert.strictEqual(mkdirMock.mock.calls.length, 1);
67
+ assert.strictEqual(mkdirMock.mock.calls[0].arguments[0], 'config');
68
+ assert.strictEqual(writeFileMock.mock.calls.length, 1); // Only one schema
69
+ });
70
+
71
+ it('saves to the expected place', async () => {
72
+ await handleDownload(fertConfig, api, options);
73
+
74
+ assert.strictEqual(writeFileMock.mock.calls.length, 1);
75
+
76
+ assert.strictEqual(
77
+ writeFileMock.mock.calls[0].arguments[0],
78
+ Path.join('config', 'jsfe-config.json')
79
+ );
80
+ });
81
+
82
+ it('writes the expected data', async () => {
83
+ await handleDownload(fertConfig, api, options);
84
+
85
+ assert.strictEqual(writeFileMock.mock.calls.length, 1);
86
+
87
+ const jsfeConfig = JSON.parse(writeFileMock.mock.calls[0].arguments[1]);
88
+ assert.strictEqual(Object.keys(jsfeConfig).length, 1);
89
+ assert.strictEqual(jsfeConfig.StrConfig, 'hello');
90
+ });
91
+
92
+ it('skips read-only keys', async () => {
93
+ // clone api object including prototype
94
+ const tweakedApi = Object.assign(
95
+ Object.create(Object.getPrototypeOf(api)),
96
+ api
97
+ );
98
+
99
+ tweakedApi.schemas = {
100
+ 'jsfe-config': Joi.object({
101
+ StrConfig: Joi.string().default('My new JSFE config'),
102
+ ReadOnlyConfig: Joi.string()
103
+ .default('I am read-only')
104
+ .meta({ readOnly: true }),
105
+ }),
106
+ };
107
+
108
+ await handleDownload(fertConfig, tweakedApi, options);
109
+
110
+ assert.strictEqual(writeFileMock.mock.calls.length, 1);
111
+
112
+ const jsfeConfig = JSON.parse(writeFileMock.mock.calls[0].arguments[1]);
113
+ assert.strictEqual(Object.keys(jsfeConfig).length, 1);
114
+ assert.strictEqual(jsfeConfig.ReadOnlyConfig, undefined);
115
+ });
116
+ });
117
+
118
+ describe.skip('handlePublish', () => {
119
+ let options;
120
+
121
+ beforeEach(async () => {
122
+ options = { publish: true };
123
+ });
124
+
125
+ it('publishes the configs', async () => {
126
+ await handlePublish(fertConfig, api, options);
127
+ });
128
+ });
129
+ describe.skip('handleQuery', () => {
130
+ let options;
131
+
132
+ beforeEach(async () => {
133
+ options = { query: true };
134
+ });
135
+
136
+ it('logs available schemas if query option is true', async () => {
137
+ await handleQuery(fertConfig, api, options);
138
+ });
139
+
140
+ it.skip('logs schema description if query option is valid', async (t) => {
141
+ const api = {
142
+ schemas: {
143
+ testSchema: {
144
+ describe: () => ({ keys: {} }),
145
+ validate: () => ({}),
146
+ },
147
+ },
148
+ };
149
+ const options = { query: 'testSchema' };
150
+ let logMessage = '';
151
+
152
+ t.mock.method(console, 'log', (message) => {
153
+ logMessage += message;
154
+ });
155
+
156
+ await handleQuery(api, options);
157
+
158
+ assert(logMessage.includes('Getting testSchema schema description...'));
159
+ assert(logMessage.includes('Defaults'));
160
+ });
161
+ });
162
+ });
@@ -4,6 +4,7 @@ const Hoek = require('@hapi/hoek');
4
4
  const { log } = require('../utils/logging');
5
5
  const chalk = require('chalk');
6
6
  const ora = require('ora');
7
+ const { CONFIG_DIR } = require('../../constants');
7
8
 
8
9
  /**
9
10
  * Validates the local configuration files against the provided schema.
@@ -18,6 +19,13 @@ const ora = require('ora');
18
19
  const validateLocalConfigs = async (fertConfig, options = { catch: true }) => {
19
20
  Hoek.assert(fertConfig, 'fertConfig is required');
20
21
 
22
+ const dir = path.join(fertConfig.workingDir, CONFIG_DIR);
23
+ if (!fs.existsSync(dir)) {
24
+ log.debug(`Directory does not exist: ${dir}`);
25
+
26
+ return;
27
+ }
28
+
21
29
  const api = await getConfigAPI({
22
30
  clientPropertyId: fertConfig.clientPropertyId,
23
31
  });
@@ -65,13 +73,8 @@ const getConfigAPI = async ({
65
73
  };
66
74
 
67
75
  const loadLocalConfigs = (fertConfig) => {
68
- const dir = path.join(fertConfig.workingDir, 'config');
76
+ const dir = path.join(fertConfig.workingDir, CONFIG_DIR);
69
77
  const configs = {};
70
-
71
- if (!fs.existsSync(dir)) {
72
- throw new Error(`Directory does not exist: ${dir}`);
73
- }
74
-
75
78
  const files = fs.readdirSync(dir);
76
79
 
77
80
  files.forEach((file) => {
@@ -110,8 +113,15 @@ const updateProjectConfigs = async (
110
113
  ) => {
111
114
  Hoek.assert(fertConfig, 'fertConfig is required');
112
115
 
116
+ const dir = path.join(fertConfig.workingDir, CONFIG_DIR);
113
117
  let spinner;
114
118
 
119
+ if (!fs.existsSync(dir)) {
120
+ log.debug(`Directory does not exist: ${dir}`);
121
+
122
+ return;
123
+ }
124
+
115
125
  try {
116
126
  const api = await getConfigAPI({
117
127
  clientPropertyId: fertConfig.clientPropertyId,
@@ -0,0 +1,45 @@
1
+ const assert = require('node:assert');
2
+ const { describe, it } = require('node:test');
3
+ const fs = require('node:fs');
4
+ const { validateLocalConfigs, updateProjectConfigs } = require('./configs');
5
+ const { log } = require('../utils/logging');
6
+
7
+ describe('configs', () => {
8
+ describe('validateLocalConfigs', () => {
9
+ it('logs debug message if config directory does not exist', async (t) => {
10
+ const fsSpy = t.mock.method(fs, 'existsSync');
11
+ const logSpy = t.mock.method(log, 'debug');
12
+ const fertConfig = { workingDir: '/non/existent/dir' };
13
+ let calls;
14
+
15
+ await validateLocalConfigs(fertConfig);
16
+
17
+ calls = fsSpy.mock.calls;
18
+ assert.strictEqual(calls[0].arguments[0], '/non/existent/dir/config');
19
+ assert.strictEqual(fsSpy.mock.calls[0].result, false);
20
+
21
+ calls = logSpy.mock.calls;
22
+ assert.strictEqual(calls.length, 1);
23
+ assert.strictEqual(typeof calls[0].arguments[0], 'string');
24
+ });
25
+ });
26
+
27
+ describe('updateProjectConfigs', () => {
28
+ it('logs debug message if config directory does not exist', async (t) => {
29
+ const fsSpy = t.mock.method(fs, 'existsSync');
30
+ const logSpy = t.mock.method(log, 'debug');
31
+ const fertConfig = { workingDir: '/non/existent/dir' };
32
+ let calls;
33
+
34
+ await updateProjectConfigs(fertConfig);
35
+
36
+ calls = fsSpy.mock.calls;
37
+ assert.strictEqual(calls[0].arguments[0], '/non/existent/dir/config');
38
+ assert.strictEqual(fsSpy.mock.calls[0].result, false);
39
+
40
+ calls = logSpy.mock.calls;
41
+ assert.strictEqual(calls.length, 1);
42
+ assert.strictEqual(typeof calls[0].arguments[0], 'string');
43
+ });
44
+ });
45
+ });
@@ -0,0 +1,14 @@
1
+ const getSchemaKeyMeta = function (schema, key) {
2
+ if (!schema) throw new Error('Schema is required');
3
+ if (!key) throw new Error('Key is required');
4
+
5
+ const keySchema = schema.extract(key);
6
+ if (!keySchema) {
7
+ throw new Error(`Key "${key}" not found in schema`);
8
+ }
9
+
10
+ const metas = keySchema.describe().metas;
11
+ return Array.isArray(metas) && metas.length > 0 ? metas[0] : {};
12
+ };
13
+
14
+ module.exports = { getSchemaKeyMeta };
@@ -108,6 +108,8 @@ exports.loadConfigFromFile = (workingDir) => {
108
108
  `Failed to load fert.config.js - ensure you're running fert on a branding repo & config exists.\n`
109
109
  );
110
110
 
111
+ console.error(err);
112
+
111
113
  process.exit(1);
112
114
  }
113
115
  };
package/constants.js CHANGED
@@ -51,4 +51,5 @@ module.exports = {
51
51
  ONE_WEEK,
52
52
  CONFIG_API:
53
53
  'https://configuration-api.job.madgexhosting.net/configs/override/{cpid}/production/clientconfig/{config}',
54
+ CONFIG_DIR: 'config',
54
55
  };
@@ -0,0 +1,53 @@
1
+ import prettier from 'eslint-plugin-prettier';
2
+ import globals from 'globals';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import js from '@eslint/js';
6
+ import { FlatCompat } from '@eslint/eslintrc';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ const compat = new FlatCompat({
11
+ baseDirectory: __dirname,
12
+ recommendedConfig: js.configs.recommended,
13
+ allConfig: js.configs.all,
14
+ });
15
+
16
+ export default [
17
+ {
18
+ ignores: [
19
+ '**/dist',
20
+ '**/temp',
21
+ '**/dist',
22
+ '**/*.json',
23
+ '**/*.json',
24
+ '**/.eslintrc.js',
25
+ '**/node_modules',
26
+ '**/repo-templates',
27
+ 'eslint.config.mjs',
28
+ ],
29
+ },
30
+ ...compat.extends('eslint:recommended', 'plugin:prettier/recommended'),
31
+ {
32
+ plugins: {
33
+ prettier,
34
+ },
35
+
36
+ languageOptions: {
37
+ globals: {
38
+ ...globals.node,
39
+ },
40
+
41
+ ecmaVersion: 'latest',
42
+ sourceType: 'commonjs',
43
+
44
+ parserOptions: {
45
+ requireConfigFile: false,
46
+ },
47
+ },
48
+
49
+ rules: {
50
+ 'prettier/prettier': 'error',
51
+ },
52
+ },
53
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madgex/fert",
3
- "version": "4.1.1",
3
+ "version": "4.2.0",
4
4
  "description": "Tool to help build the V6 branding",
5
5
  "bin": {
6
6
  "fert": "./bin/cli.js"
@@ -10,7 +10,7 @@
10
10
  "format": "prettier --write .",
11
11
  "lint-staged": "lint-staged",
12
12
  "semantic-release": "semantic-release",
13
- "test": "echo \"Error: no test specified\" && exit 1",
13
+ "test": "node --test ./bin/**/*.test.js",
14
14
  "prepare": "husky"
15
15
  },
16
16
  "repository": {
@@ -23,23 +23,23 @@
23
23
  "author": "Madgex",
24
24
  "license": "UNLICENSED",
25
25
  "dependencies": {
26
- "@aws-sdk/client-cloudfront": "^3.670.0",
27
- "@aws-sdk/client-ssm": "^3.670.0",
28
- "@aws-sdk/credential-providers": "^3.670.0",
29
- "@hapi/hapi": "^21.3.10",
30
- "@hapi/hoek": "^11.0.4",
26
+ "@aws-sdk/client-cloudfront": "^3.716.0",
27
+ "@aws-sdk/client-ssm": "^3.716.0",
28
+ "@aws-sdk/credential-providers": "^3.716.0",
29
+ "@hapi/hapi": "^21.3.12",
30
+ "@hapi/hoek": "^11.0.7",
31
31
  "@hapi/inert": "^7.1.0",
32
32
  "@hapi/vision": "^7.0.3",
33
33
  "@hapipal/toys": "^4.0.0",
34
- "@madgex/config-api-sdk": "^1.0.8",
35
- "@madgex/design-system": "^9.1.2",
34
+ "@madgex/config-api-sdk": "^1.0.12",
35
+ "@madgex/design-system": "^9.1.8",
36
36
  "@private/header-footer-podlet-server": "github:wiley/madgex-header-footer-podlet",
37
- "axios": "^1.7.7",
37
+ "axios": "^1.7.9",
38
38
  "cac": "^6.7.14",
39
39
  "chalk": "4.1.2",
40
40
  "chokidar": "^3.5.3",
41
41
  "dayjs": "^1.11.13",
42
- "debug": "^4.3.4",
42
+ "debug": "^4.4.0",
43
43
  "dedent": "^1.5.3",
44
44
  "flat-cache": "^4.0.0",
45
45
  "form-data": "^4.0.1",
@@ -49,7 +49,7 @@
49
49
  "ora": "5.4.1",
50
50
  "prompts": "^2.4.2",
51
51
  "rimraf": "^5.0.5",
52
- "sass": "^1.80.1",
52
+ "sass": "^1.83.0",
53
53
  "simple-git": "^3.27.0",
54
54
  "simple-update-notifier": "^2.0.0",
55
55
  "style-dictionary": "3.9.0",
@@ -58,17 +58,20 @@
58
58
  "vite-plugin-static-copy": "^0.17.1"
59
59
  },
60
60
  "devDependencies": {
61
- "@commitlint/cli": "^19.6.0",
61
+ "@commitlint/cli": "^19.6.1",
62
62
  "@commitlint/config-conventional": "^19.6.0",
63
+ "@eslint/eslintrc": "^3.2.0",
64
+ "@eslint/js": "^9.17.0",
63
65
  "commitizen": "^4.3.1",
64
66
  "cz-conventional-changelog": "^3.3.0",
65
- "eslint": "^8.53.0",
66
- "eslint-config-prettier": "^9.0.0",
67
- "eslint-plugin-prettier": "^5.0.1",
67
+ "eslint": "^9.17.0",
68
+ "eslint-config-prettier": "^9.1.0",
69
+ "eslint-plugin-prettier": "^5.2.1",
70
+ "globals": "^15.14.0",
68
71
  "husky": "^9.1.7",
69
- "lint-staged": "^15.2.10",
70
- "prettier": "^3.3.3",
71
- "semantic-release": "^22.0.8"
72
+ "lint-staged": "^15.3.0",
73
+ "prettier": "^3.4.2",
74
+ "semantic-release": "^24.2.0"
72
75
  },
73
76
  "peerDependencies": {
74
77
  "@ctrl/tinycolor": "^3.6.0"
package/shared/README.md CHANGED
@@ -1,4 +1,4 @@
1
1
  The docker file in this folder (`Dockerfile.brandingRepoPublish`) will be used by Jenkins to build and publish the repo assets to S3.
2
2
 
3
3
  When changes are pushed on a project repo, Jenkins will clone this repo, extract the docker file and use it to build and publish the assets to S3.
4
- If the changes are on a branch other than master, the assets will be sent to the jb-dev S3 bucket. If the changes are pushed to master, they will be sent to the production bucket.
4
+ If the changes are on a branch other than master, the assets will be sent to the jb-dev S3 bucket. If the changes are pushed to master, they will be sent to the production bucket.
package/.eslintignore DELETED
@@ -1,8 +0,0 @@
1
- dist
2
- temp
3
- **/dist
4
- *.json
5
- **/*.json
6
- !.eslintrc.js
7
- node_modules
8
- repo-templates
package/.eslintrc.js DELETED
@@ -1,15 +0,0 @@
1
- module.exports = {
2
- env: {
3
- node: true,
4
- es6: true,
5
- },
6
- plugins: ['prettier'],
7
- extends: ['eslint:recommended', 'plugin:prettier/recommended'],
8
- parserOptions: {
9
- requireConfigFile: false,
10
- ecmaVersion: 'latest',
11
- },
12
- rules: {
13
- 'prettier/prettier': 'error',
14
- },
15
- };