@madgex/fert 4.2.2 → 4.2.4

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.
@@ -28,6 +28,9 @@ jobs:
28
28
  ssh-agent -a $SSH_AUTH_SOCK > /dev/null
29
29
  ssh-add - <<< "${{ secrets.MADGEX_GITHUB_SSH_KEY }}"
30
30
 
31
+ - name: Authenticate with private NPM package
32
+ run: echo "//registry.npmjs.org/:_authToken=${{ secrets.MADGEX_NPM_TOKEN }}" > /home/runner/.npmrc
33
+
31
34
  - name: Install dependencies
32
35
  run: npm ci
33
36
  env:
@@ -6,7 +6,7 @@ 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');
9
+ const { getSchemaMeta } = require('../utils/getSchemaMeta.js');
10
10
  const ora = require('ora');
11
11
  const { mkdir, writeFile } = require('node:fs/promises');
12
12
  const Path = require('node:path');
@@ -26,34 +26,34 @@ const handleDownload = async (fertConfig, api, options) => {
26
26
 
27
27
  try {
28
28
  for (const [schemaName, schema] of Object.entries(api.schemas)) {
29
- const configs = await api.getSchemaKeys(schemaName);
29
+ const schemaMeta = getSchemaMeta(api.getSchema(schemaName));
30
+
31
+ if (schemaMeta.readOnly) {
32
+ // skip read-only config files
33
+ continue;
34
+ }
35
+
36
+ const configs = api.getSchemaKeys(schemaName);
30
37
 
31
38
  for (const configKey of configs) {
32
- const meta = getSchemaKeyMeta(schema, configKey);
39
+ const meta = getSchemaMeta(schema, configKey);
33
40
  if (meta.readOnly) {
41
+ // skip read-only config keys
34
42
  continue;
35
43
  }
36
44
 
37
45
  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
- };
46
+ const data = await api.getConfig(schemaName, configKey);
47
+
48
+ if (data.isDefault) {
49
+ continue;
56
50
  }
51
+
52
+ if (!resultObj[schemaName]) {
53
+ resultObj[schemaName] = {};
54
+ }
55
+
56
+ resultObj[schemaName][configKey] = data.result;
57
57
  } catch (error) {
58
58
  log.debug(
59
59
  `Unable to retrieve ${chalk.cyan(error.url || schemaName + '/' + configKey)}`,
@@ -11,7 +11,7 @@ describe('configs', () => {
11
11
  let writeFileMock;
12
12
  let handleDownload;
13
13
  let handleQuery;
14
- let handlePublish;
14
+ let collateConfigs;
15
15
 
16
16
  beforeEach(async (t) => {
17
17
  fertConfig = {
@@ -26,6 +26,10 @@ describe('configs', () => {
26
26
  schemas: {
27
27
  'jsfe-config': Joi.object({
28
28
  StrConfig: Joi.string().default('My new JSFE config'),
29
+ NumConfig: Joi.number().default(0),
30
+ StrConfigReadOnly: Joi.string()
31
+ .default('I am read-only')
32
+ .meta({ readOnly: true }),
29
33
  }),
30
34
  },
31
35
  fetch: async () => ({
@@ -49,7 +53,10 @@ describe('configs', () => {
49
53
 
50
54
  // Clear require cache to ensure we get a fresh copy with our mocks
51
55
  delete require.cache[require.resolve('./configs')];
52
- ({ handleDownload, handleQuery, handlePublish } = require('./configs'));
56
+ ({ handleDownload, handleQuery } = require('./configs'));
57
+
58
+ delete require.cache[require.resolve('../utils/configs')];
59
+ ({ collateConfigs } = require('../utils/configs'));
53
60
  });
54
61
 
55
62
  describe('handleDownload', () => {
@@ -115,18 +122,30 @@ describe('configs', () => {
115
122
  });
116
123
  });
117
124
 
118
- describe.skip('handlePublish', () => {
119
- let options;
125
+ describe('handlePublish', () => {
126
+ it('sets and deletes correct configs', async () => {
127
+ const localConfigs = {
128
+ 'jsfe-config': {
129
+ path: '',
130
+ data: {
131
+ StrConfig: 'default value',
132
+ // NumConfig is purposefully omitted & should be deleted from the api
133
+ },
134
+ },
135
+ };
120
136
 
121
- beforeEach(async () => {
122
- options = { publish: true };
123
- });
137
+ const { toSet, toRemove } = await collateConfigs(api, localConfigs);
138
+
139
+ assert.deepStrictEqual(toSet, {
140
+ 'jsfe-config': {
141
+ StrConfig: 'default value',
142
+ },
143
+ });
124
144
 
125
- it('publishes the configs', async () => {
126
- await handlePublish(fertConfig, api, options);
145
+ assert.deepStrictEqual(toRemove, { 'jsfe-config': ['NumConfig'] });
127
146
  });
128
147
  });
129
- describe.skip('handleQuery', () => {
148
+ describe('handleQuery', () => {
130
149
  let options;
131
150
 
132
151
  beforeEach(async () => {
@@ -154,12 +154,29 @@ const collateConfigs = (api, localConfigs) => {
154
154
 
155
155
  Object.entries(localConfigs).forEach(
156
156
  ([configName, { data: config = {} } = {}]) => {
157
+ const schema = api.getSchema(configName);
158
+ const isSchemaReadOnly = api._isSchemaReadOnly(schema);
159
+
160
+ if (isSchemaReadOnly) {
161
+ log.warn(`Skipping read-only schema: ${configName}`);
162
+ return;
163
+ }
164
+
157
165
  const configDefault = api._getDefaultConfig(configName);
158
166
 
159
167
  const unsetKeysWithDefaults = getUnsetKeysWithDefaults(
160
168
  configDefault,
161
169
  config
162
170
  );
171
+
172
+ // remove any keys that are read-only from the unset keys collection
173
+ // we don't want to be deleting those!
174
+ for (const key in unsetKeysWithDefaults) {
175
+ if (api._isSchemaReadOnly(schema.extract(key))) {
176
+ delete unsetKeysWithDefaults[key];
177
+ }
178
+ }
179
+
163
180
  toRemove[configName] = Object.keys(unsetKeysWithDefaults);
164
181
  toSet[configName] = config;
165
182
  }
@@ -217,4 +234,5 @@ module.exports = {
217
234
  getConfigAPI,
218
235
  validateLocalConfigs,
219
236
  updateProjectConfigs,
237
+ collateConfigs,
220
238
  };
@@ -0,0 +1,21 @@
1
+ const getSchemaMeta = function (schema, key = null) {
2
+ if (!schema || typeof schema.describe !== 'function') {
3
+ throw new Error('Schema is required');
4
+ }
5
+
6
+ try {
7
+ if (key) {
8
+ const keySchema = schema.extract(key);
9
+ if (!keySchema) {
10
+ throw new Error(`Key "${key}" not found in schema`);
11
+ }
12
+ return keySchema.describe().metas?.[0] || {};
13
+ }
14
+
15
+ return schema.describe().metas?.[0] || {};
16
+ } catch (error) {
17
+ throw new Error('Invalid Joi schema', { cause: error });
18
+ }
19
+ };
20
+
21
+ module.exports = { getSchemaMeta };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@madgex/fert",
3
- "version": "4.2.2",
3
+ "version": "4.2.4",
4
4
  "description": "Tool to help build the V6 branding",
5
5
  "bin": {
6
6
  "fert": "./bin/cli.js"
@@ -31,7 +31,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.6.0",
34
+ "@madgex/config-api-sdk": "^1.6.1",
35
35
  "@madgex/design-system": "^9.1.9",
36
36
  "@private/header-footer-podlet-server": "github:wiley/madgex-header-footer-podlet",
37
37
  "axios": "^1.7.9",
@@ -69,6 +69,7 @@
69
69
  "eslint-plugin-prettier": "^5.2.1",
70
70
  "globals": "^15.14.0",
71
71
  "husky": "^9.1.7",
72
+ "joi": "^17.13.3",
72
73
  "lint-staged": "^15.3.0",
73
74
  "prettier": "^3.4.2",
74
75
  "semantic-release": "^24.2.0"
@@ -1,14 +0,0 @@
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 };