@jungvonmatt/contentful-ssg 1.0.4 → 1.0.5

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/dist/cli.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import path from 'path';
3
3
  import chalk from 'chalk';
4
4
  import { existsSync } from 'fs';
5
+ import { readFile } from 'fs/promises';
5
6
  import { outputFile } from 'fs-extra';
6
7
  import prettier from 'prettier';
7
8
  import { Command } from 'commander';
@@ -44,7 +45,17 @@ program
44
45
  if (verified.directory?.startsWith('/')) {
45
46
  verified.directory = path.relative(process.cwd(), verified.directory);
46
47
  }
47
- const environmentKeys = Object.keys(environmentConfig).filter((key) => environmentConfig[key] === verified[key]);
48
+ const environmentKeys = Object.keys(environmentConfig);
49
+ if (environmentConfig && existsSync('.env')) {
50
+ const envSource = await readFile('.env', 'utf8');
51
+ const nextEnvSource = envSource
52
+ .replace(/(CONTENTFUL_SPACE_ID\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.spaceId}$2`)
53
+ .replace(/(CONTENTFUL_ENVIRONMENT_ID\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.environmentId}$2`)
54
+ .replace(/(CONTENTFUL_MANAGEMENT_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.managementToken}$2`)
55
+ .replace(/(CONTENTFUL_PREVIEW_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.previewAccessToken}$2`)
56
+ .replace(/(CONTENTFUL_DELIVERY_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.accessToken}$2`);
57
+ await outputFile('.env', nextEnvSource);
58
+ }
48
59
  const cleanedConfig = omitKeys(verified, 'preview', 'verbose', 'rootDir', 'resolvedPlugins', 'host', 'managementToken', ...environmentKeys);
49
60
  let content = '';
50
61
  if (useTypescript) {
@@ -1,3 +1,3 @@
1
1
  import type { Config, ContentfulConfig } from '../types.js';
2
- export declare const getEnvironmentConfig: () => ContentfulConfig;
2
+ export declare const getEnvironmentConfig: (strict?: boolean) => ContentfulConfig;
3
3
  export declare const getConfig: (args?: Partial<Config>) => Promise<Config>;
@@ -72,13 +72,13 @@ const loadConfig = async (moduleName) => {
72
72
  });
73
73
  return explorer.search();
74
74
  };
75
- export const getEnvironmentConfig = () => removeEmpty({
75
+ export const getEnvironmentConfig = (strict = true) => removeEmpty({
76
76
  spaceId: process.env.CONTENTFUL_SPACE_ID,
77
77
  environmentId: process.env.CONTENTFUL_ENVIRONMENT_ID,
78
78
  managementToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN,
79
79
  previewAccessToken: process.env.CONTENTFUL_PREVIEW_TOKEN,
80
80
  accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN,
81
- });
81
+ }, strict);
82
82
  export const getConfig = async (args) => {
83
83
  const defaultOptions = {
84
84
  environmentId: 'master',
@@ -87,18 +87,18 @@ export const getConfig = async (args) => {
87
87
  plugins: [],
88
88
  resolvedPlugins: [],
89
89
  };
90
- const environmentOptions = getEnvironmentConfig();
90
+ const environmentOptions = getEnvironmentConfig(false);
91
91
  let contentfulCliOptions = {};
92
92
  try {
93
93
  const contentfulConfig = await loadConfig('contentful');
94
- if (!contentfulConfig.isEmpty) {
94
+ if (contentfulConfig && !contentfulConfig.isEmpty) {
95
95
  const { managementToken, activeSpaceId, activeEnvironmentId, host } = contentfulConfig.config;
96
96
  contentfulCliOptions = removeEmpty({
97
97
  spaceId: activeSpaceId,
98
98
  managementToken,
99
99
  environmentId: activeEnvironmentId,
100
100
  host,
101
- });
101
+ }, false);
102
102
  }
103
103
  }
104
104
  catch (error) {
@@ -116,7 +116,7 @@ export const getConfig = async (args) => {
116
116
  args.rootDir = process.cwd();
117
117
  try {
118
118
  const configFile = await loadConfig('contentful-ssg');
119
- if (!configFile.isEmpty) {
119
+ if (configFile && !configFile.isEmpty) {
120
120
  configFileOptions = configFile.config;
121
121
  args.rootDir = dirname(configFile.filepath);
122
122
  if (configFileOptions.directory && !isAbsolute(configFileOptions.directory)) {
@@ -5,7 +5,8 @@ export declare const isObject: (something: any) => boolean;
5
5
  export declare const getEntries: <T>(obj: T) => Entries<T>;
6
6
  export declare const fromEntries: <T = [string, unknown][]>(entries: Entries<T>) => T;
7
7
  export declare const omitKeys: <T, K extends keyof T>(obj: T, ...keys: K[]) => T;
8
- export declare const removeEmpty: <T>(iterable: T) => T;
8
+ export declare const filterKeys: <T, K extends keyof T>(obj: T, ...keys: K[]) => T;
9
+ export declare const removeEmpty: <T>(iterable: T, strict?: boolean) => T;
9
10
  export declare const snakeCaseKeys: <T>(iterable: T) => T;
10
11
  export declare const groupBy: <T extends Record<string, unknown>>(array: T[], key: keyof T) => Record<string, T[]>;
11
12
  export {};
@@ -8,14 +8,19 @@ export const omitKeys = (obj, ...keys) => {
8
8
  const filtered = entries.filter(([key]) => !keys.includes(key));
9
9
  return fromEntries(filtered);
10
10
  };
11
- export const removeEmpty = (iterable) => {
11
+ export const filterKeys = (obj, ...keys) => {
12
+ const entries = getEntries(obj);
13
+ const filtered = entries.filter(([key]) => keys.includes(key));
14
+ return fromEntries(filtered);
15
+ };
16
+ export const removeEmpty = (iterable, strict = true) => {
12
17
  if (Array.isArray(iterable)) {
13
18
  return iterable
14
- .filter((v) => v !== null && v !== undefined)
19
+ .filter((v) => v !== null && v !== undefined && (strict || Boolean(v)))
15
20
  .map((v) => (v === Object(v) ? removeEmpty(v) : v));
16
21
  }
17
22
  return fromEntries(getEntries(iterable)
18
- .filter(([, v]) => v !== null && v !== undefined)
23
+ .filter(([, v]) => v !== null && v !== undefined && (strict || Boolean(v)))
19
24
  .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v]));
20
25
  };
21
26
  export const snakeCaseKeys = (iterable) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungvonmatt/contentful-ssg",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
@@ -9,6 +9,7 @@
9
9
  ".": "./dist/index.js",
10
10
  "./lib/object": "./dist/lib/object.js",
11
11
  "./lib/array": "./dist/lib/array.js",
12
+ "./lib/utils": "./dist/lib/utils.js",
12
13
  "./lib/contentful": "./dist/lib/contentful.js",
13
14
  "./lib/hook-manager": "./dist/lib/hook-manager.js",
14
15
  "./lib/file-manager": "./dist/lib/file-manager.js",
@@ -23,6 +24,9 @@
23
24
  ".": [
24
25
  "./dist/types.d.ts"
25
26
  ],
27
+ "lib/utils": [
28
+ "./dist/lib/utils.d.ts"
29
+ ],
26
30
  "lib/object": [
27
31
  "./dist/lib/object.d.ts"
28
32
  ],
@@ -139,5 +143,5 @@
139
143
  "module": "es2020"
140
144
  }
141
145
  },
142
- "gitHead": "9da40bcd4fa8124cf7ae3ff6a2dcfca91c82c4fb"
146
+ "gitHead": "03741b4add20ce95e1cd539bc46b7630cddcc2c3"
143
147
  }
package/src/cli.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  import path from 'path';
5
5
  import chalk from 'chalk';
6
6
  import { existsSync } from 'fs';
7
+ import { readFile } from 'fs/promises';
7
8
  import { outputFile } from 'fs-extra';
8
9
  import prettier from 'prettier';
9
10
  import { Command } from 'commander';
@@ -67,9 +68,34 @@ program
67
68
  verified.directory = path.relative(process.cwd(), verified.directory);
68
69
  }
69
70
 
70
- const environmentKeys: Array<keyof ContentfulConfig> = (
71
- Object.keys(environmentConfig) as Array<keyof ContentfulConfig>
72
- ).filter((key) => environmentConfig[key] === verified[key]);
71
+ const environmentKeys: Array<keyof ContentfulConfig> = Object.keys(
72
+ environmentConfig
73
+ ) as Array<keyof ContentfulConfig>;
74
+
75
+ // Update .env file
76
+ if (environmentConfig && existsSync('.env')) {
77
+ const envSource = await readFile('.env', 'utf8');
78
+ const nextEnvSource = envSource
79
+ .replace(/(CONTENTFUL_SPACE_ID\s*=\s*['"]?)[^'"]*(['"]?)/, `$1${verified.spaceId}$2`)
80
+ .replace(
81
+ /(CONTENTFUL_ENVIRONMENT_ID\s*=\s*['"]?)[^'"]*(['"]?)/,
82
+ `$1${verified.environmentId}$2`
83
+ )
84
+ .replace(
85
+ /(CONTENTFUL_MANAGEMENT_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/,
86
+ `$1${verified.managementToken}$2`
87
+ )
88
+ .replace(
89
+ /(CONTENTFUL_PREVIEW_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/,
90
+ `$1${verified.previewAccessToken}$2`
91
+ )
92
+ .replace(
93
+ /(CONTENTFUL_DELIVERY_TOKEN\s*=\s*['"]?)[^'"]*(['"]?)/,
94
+ `$1${verified.accessToken}$2`
95
+ );
96
+
97
+ await outputFile('.env', nextEnvSource);
98
+ }
73
99
 
74
100
  const cleanedConfig = omitKeys(
75
101
  verified,
package/src/lib/config.ts CHANGED
@@ -105,14 +105,17 @@ const loadConfig = async (moduleName: string): Promise<CosmiconfigResult> => {
105
105
  return explorer.search();
106
106
  };
107
107
 
108
- export const getEnvironmentConfig = (): ContentfulConfig =>
109
- removeEmpty({
110
- spaceId: process.env.CONTENTFUL_SPACE_ID!,
111
- environmentId: process.env.CONTENTFUL_ENVIRONMENT_ID!,
112
- managementToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN!,
113
- previewAccessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
114
- accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN!,
115
- });
108
+ export const getEnvironmentConfig = (strict = true): ContentfulConfig =>
109
+ removeEmpty(
110
+ {
111
+ spaceId: process.env.CONTENTFUL_SPACE_ID!,
112
+ environmentId: process.env.CONTENTFUL_ENVIRONMENT_ID!,
113
+ managementToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN!,
114
+ previewAccessToken: process.env.CONTENTFUL_PREVIEW_TOKEN!,
115
+ accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN!,
116
+ },
117
+ strict
118
+ );
116
119
 
117
120
  /**
118
121
  * Get configuration
@@ -127,22 +130,25 @@ export const getConfig = async (args?: Partial<Config>): Promise<Config> => {
127
130
  resolvedPlugins: [],
128
131
  };
129
132
 
130
- const environmentOptions = getEnvironmentConfig();
133
+ const environmentOptions = getEnvironmentConfig(false);
131
134
  let contentfulCliOptions: Partial<ContentfulConfig> = {};
132
135
 
133
136
  try {
134
137
  // Get configuration from contentful rc file (created by the contentful cli command)
135
138
  const contentfulConfig = await loadConfig('contentful');
136
- if (!contentfulConfig.isEmpty) {
139
+ if (contentfulConfig && !contentfulConfig.isEmpty) {
137
140
  const { managementToken, activeSpaceId, activeEnvironmentId, host } =
138
141
  contentfulConfig.config as ContentfulRcConfig;
139
142
 
140
- contentfulCliOptions = removeEmpty({
141
- spaceId: activeSpaceId,
142
- managementToken,
143
- environmentId: activeEnvironmentId,
144
- host,
145
- });
143
+ contentfulCliOptions = removeEmpty(
144
+ {
145
+ spaceId: activeSpaceId,
146
+ managementToken,
147
+ environmentId: activeEnvironmentId,
148
+ host,
149
+ },
150
+ false
151
+ );
146
152
  }
147
153
  } catch (error: unknown) {
148
154
  if (typeof error === 'string') {
@@ -159,7 +165,7 @@ export const getConfig = async (args?: Partial<Config>): Promise<Config> => {
159
165
  try {
160
166
  // Get configuration from contentful-ssg rc file
161
167
  const configFile = await loadConfig('contentful-ssg');
162
- if (!configFile.isEmpty) {
168
+ if (configFile && !configFile.isEmpty) {
163
169
  configFileOptions = configFile.config as Partial<Config>;
164
170
  args.rootDir = dirname(configFile.filepath);
165
171
  if (configFileOptions.directory && !isAbsolute(configFileOptions.directory)) {
@@ -1,5 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/naming-convention */
2
- import { isObject, omitKeys, removeEmpty, snakeCaseKeys, groupBy } from './object';
2
+ import { isObject, omitKeys, filterKeys, removeEmpty, snakeCaseKeys, groupBy } from './object';
3
3
 
4
4
  test('isObject', async () => {
5
5
  const arr = [];
@@ -17,6 +17,11 @@ test('omitKeys', () => {
17
17
  expect(value).toEqual({ b: 2 });
18
18
  });
19
19
 
20
+ test('filterKeys', () => {
21
+ const value = filterKeys({ a: 1, b: 2, c: 3 }, 'a', 'c');
22
+ expect(value).toEqual({ a: 1, c: 3 });
23
+ });
24
+
20
25
  test('removeEmpty', () => {
21
26
  const value = removeEmpty({
22
27
  a: { c: undefined },
@@ -26,6 +31,16 @@ test('removeEmpty', () => {
26
31
  expect(value).toEqual({ a: {}, c: [1, { x: 1, z: [7] }, 3, 5] });
27
32
  });
28
33
 
34
+
35
+ test('removeEmpty non-strict', () => {
36
+ const value = removeEmpty({
37
+ a: "",
38
+ b: 0,
39
+ c: 1,
40
+ }, false);
41
+ expect(value).toEqual({ c: 1 });
42
+ });
43
+
29
44
  test('groupBy', () => {
30
45
  const value = groupBy(
31
46
  [
package/src/lib/object.ts CHANGED
@@ -30,16 +30,27 @@ export const omitKeys = <T, K extends keyof T>(obj: T, ...keys: K[]): T => {
30
30
  return fromEntries(filtered);
31
31
  };
32
32
 
33
+ /**
34
+ * Filter values by key from object
35
+ * @param {*} obj
36
+ * @param {*} keys
37
+ */
38
+ export const filterKeys = <T, K extends keyof T>(obj: T, ...keys: K[]): T => {
39
+ const entries: Entries<T> = getEntries(obj);
40
+ const filtered = entries.filter(([key]) => keys.includes(key as K));
41
+ return fromEntries(filtered);
42
+ };
43
+
33
44
  /**
34
45
  * Recursive remove empty items (null,undefined) from object
35
46
  * @param iterable Source object
36
47
  * @returns Cleaned object
37
48
  */
38
- export const removeEmpty = <T>(iterable: T): T => {
49
+ export const removeEmpty = <T>(iterable: T, strict = true): T => {
39
50
  if (Array.isArray(iterable)) {
40
51
  return (
41
52
  iterable
42
- .filter((v) => v !== null && v !== undefined)
53
+ .filter((v) => v !== null && v !== undefined && (strict || Boolean(v)))
43
54
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
44
55
  .map((v) => (v === Object(v) ? removeEmpty(v) : v)) as unknown as T
45
56
  );
@@ -47,7 +58,7 @@ export const removeEmpty = <T>(iterable: T): T => {
47
58
 
48
59
  return fromEntries(
49
60
  getEntries(iterable)
50
- .filter(([, v]) => v !== null && v !== undefined)
61
+ .filter(([, v]) => v !== null && v !== undefined && (strict || Boolean(v)))
51
62
  .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
52
63
  );
53
64
  };