@achs/env 2.0.0 → 3.1.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.
Files changed (136) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.json +329 -0
  3. package/.vscode/extensions.json +18 -0
  4. package/.vscode/launch.json +30 -0
  5. package/.vscode/settings.json +29 -0
  6. package/CHANGELOG.md +13 -0
  7. package/README.md +14 -7
  8. package/jest.config.json +28 -0
  9. package/package.json +16 -16
  10. package/{arguments.js → src/arguments.ts} +38 -14
  11. package/src/commands/env.command.ts +139 -0
  12. package/src/commands/export.command.ts +88 -0
  13. package/{commands/index.d.ts → src/commands/index.ts} +0 -1
  14. package/src/commands/pull.command.ts +52 -0
  15. package/src/commands/push.command.ts +48 -0
  16. package/src/commands/schema.command.ts +31 -0
  17. package/src/exec.ts +221 -0
  18. package/{index.d.ts → src/index.ts} +0 -1
  19. package/{interfaces/index.d.ts → src/interfaces/index.ts} +0 -1
  20. package/src/interfaces/loader.interface.ts +66 -0
  21. package/src/main.ts +6 -0
  22. package/src/providers/app-settings.provider.ts +67 -0
  23. package/src/providers/azure-key-vault.provider.ts +277 -0
  24. package/src/providers/index.ts +29 -0
  25. package/src/providers/local.provider.ts +44 -0
  26. package/src/providers/package-json.provider.ts +39 -0
  27. package/src/utils/command.util.ts +223 -0
  28. package/{utils/index.d.ts → src/utils/index.ts} +0 -1
  29. package/src/utils/interpolate.util.ts +65 -0
  30. package/src/utils/json.util.ts +116 -0
  31. package/{utils/logger.js → src/utils/logger.ts} +6 -6
  32. package/src/utils/normalize.util.ts +142 -0
  33. package/src/utils/schema.util.ts +191 -0
  34. package/tests/env/appsettings.json +32 -0
  35. package/tests/env/dev.env.json +12 -0
  36. package/tests/env/dev.local.env.json +9 -0
  37. package/tests/env/env.schema.json +225 -0
  38. package/tests/env/keys.json +7 -0
  39. package/tests/env/settings/schema.json +239 -0
  40. package/tests/env/settings/settings.json +22 -0
  41. package/tests/env.int.test.ts +42 -0
  42. package/tests/exec.ts +19 -0
  43. package/tests/export.int.test.ts +9 -0
  44. package/tests/pull-push.int.test.ts +15 -0
  45. package/tests/run.js +32 -0
  46. package/tests/schema.int.test.ts +9 -0
  47. package/tests/setup.ts +13 -0
  48. package/tsconfig.build.json +10 -0
  49. package/tsconfig.json +37 -0
  50. package/arguments.d.ts +0 -25
  51. package/arguments.d.ts.map +0 -1
  52. package/arguments.js.map +0 -1
  53. package/commands/env.command.d.ts +0 -8
  54. package/commands/env.command.d.ts.map +0 -1
  55. package/commands/env.command.js +0 -85
  56. package/commands/env.command.js.map +0 -1
  57. package/commands/export.command.d.ts +0 -8
  58. package/commands/export.command.d.ts.map +0 -1
  59. package/commands/export.command.js +0 -54
  60. package/commands/export.command.js.map +0 -1
  61. package/commands/index.d.ts.map +0 -1
  62. package/commands/index.js +0 -14
  63. package/commands/index.js.map +0 -1
  64. package/commands/pull.command.d.ts +0 -7
  65. package/commands/pull.command.d.ts.map +0 -1
  66. package/commands/pull.command.js +0 -39
  67. package/commands/pull.command.js.map +0 -1
  68. package/commands/push.command.d.ts +0 -7
  69. package/commands/push.command.d.ts.map +0 -1
  70. package/commands/push.command.js +0 -38
  71. package/commands/push.command.js.map +0 -1
  72. package/commands/schema.command.d.ts +0 -4
  73. package/commands/schema.command.d.ts.map +0 -1
  74. package/commands/schema.command.js +0 -18
  75. package/commands/schema.command.js.map +0 -1
  76. package/exec.d.ts +0 -3
  77. package/exec.d.ts.map +0 -1
  78. package/exec.js +0 -142
  79. package/exec.js.map +0 -1
  80. package/index.d.ts.map +0 -1
  81. package/index.js +0 -20
  82. package/index.js.map +0 -1
  83. package/interfaces/index.d.ts.map +0 -1
  84. package/interfaces/index.js +0 -18
  85. package/interfaces/index.js.map +0 -1
  86. package/interfaces/loader.interface.d.ts +0 -21
  87. package/interfaces/loader.interface.d.ts.map +0 -1
  88. package/interfaces/loader.interface.js +0 -3
  89. package/interfaces/loader.interface.js.map +0 -1
  90. package/main.d.ts +0 -3
  91. package/main.d.ts.map +0 -1
  92. package/main.js +0 -6
  93. package/main.js.map +0 -1
  94. package/providers/app-settings.provider.d.ts +0 -8
  95. package/providers/app-settings.provider.d.ts.map +0 -1
  96. package/providers/app-settings.provider.js +0 -50
  97. package/providers/app-settings.provider.js.map +0 -1
  98. package/providers/azure-key-vault.provider.d.ts +0 -22
  99. package/providers/azure-key-vault.provider.d.ts.map +0 -1
  100. package/providers/azure-key-vault.provider.js +0 -164
  101. package/providers/azure-key-vault.provider.js.map +0 -1
  102. package/providers/index.d.ts +0 -8
  103. package/providers/index.d.ts.map +0 -1
  104. package/providers/index.js +0 -28
  105. package/providers/index.js.map +0 -1
  106. package/providers/package-json.provider.d.ts +0 -8
  107. package/providers/package-json.provider.d.ts.map +0 -1
  108. package/providers/package-json.provider.js +0 -29
  109. package/providers/package-json.provider.js.map +0 -1
  110. package/tsconfig.build.tsbuildinfo +0 -1
  111. package/utils/command.util.d.ts +0 -13
  112. package/utils/command.util.d.ts.map +0 -1
  113. package/utils/command.util.js +0 -134
  114. package/utils/command.util.js.map +0 -1
  115. package/utils/index.d.ts.map +0 -1
  116. package/utils/index.js +0 -23
  117. package/utils/index.js.map +0 -1
  118. package/utils/interpolate.util.d.ts +0 -4
  119. package/utils/interpolate.util.d.ts.map +0 -1
  120. package/utils/interpolate.util.js +0 -33
  121. package/utils/interpolate.util.js.map +0 -1
  122. package/utils/json.util.d.ts +0 -5
  123. package/utils/json.util.d.ts.map +0 -1
  124. package/utils/json.util.js +0 -48
  125. package/utils/json.util.js.map +0 -1
  126. package/utils/logger.d.ts +0 -3
  127. package/utils/logger.d.ts.map +0 -1
  128. package/utils/logger.js.map +0 -1
  129. package/utils/normalize.util.d.ts +0 -3
  130. package/utils/normalize.util.d.ts.map +0 -1
  131. package/utils/normalize.util.js +0 -61
  132. package/utils/normalize.util.js.map +0 -1
  133. package/utils/schema.util.d.ts +0 -11
  134. package/utils/schema.util.d.ts.map +0 -1
  135. package/utils/schema.util.js +0 -100
  136. package/utils/schema.util.js.map +0 -1
@@ -0,0 +1,191 @@
1
+ import Ajv, { Format, JSONSchemaType, ValidateFunction } from 'ajv';
2
+ import addFormats from 'ajv-formats';
3
+ import toJsonSchema, { Options } from 'to-json-schema';
4
+
5
+ const FORMAT_REGEXPS: Record<string, Format> = {
6
+ 'ip-address':
7
+ /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d{1,2})$/,
8
+
9
+ color: /^(#?([\dA-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b\s*,\s*\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b\s*,\s*\b(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/,
10
+
11
+ hostname:
12
+ /^(?=.{1,255}$)[\dA-Za-z](?:(?:[\dA-Za-z]|-){0,61}[\dA-Za-z])?(?:\.[\dA-Za-z](?:(?:[\dA-Za-z]|-){0,61}[\dA-Za-z])?)*\.?$/,
13
+
14
+ alphanumeric: /^[\dA-Za-z]+$/,
15
+
16
+ 'utc-millisec': (input: string) => !Number.isNaN(+input),
17
+
18
+ alpha: /^[A-Za-z]+$/,
19
+
20
+ style: /\s*(.+?):\s*([^;]+);?/g,
21
+
22
+ phone: /^\+(?:\d ?){6,14}\d$/
23
+ };
24
+
25
+ /**
26
+ * Generates JSON schema from JSON template/object.
27
+ *
28
+ * @export
29
+ * @param {Record<string, unknown>} json json object
30
+ * @param {Options} [options]
31
+ *
32
+ * @returns {*} {Record<string, unknown>}
33
+ */
34
+ export function schemaFrom(
35
+ json: Record<string, unknown>,
36
+ options?: Options & { nullable?: boolean }
37
+ ): Record<string, unknown> {
38
+ return toJsonSchema(json, {
39
+ required: false,
40
+ ...options,
41
+ postProcessFnc: (type, schema, value, defaultFunc) => {
42
+ if (value !== json) {
43
+ schema.type = [type];
44
+ schema.nullable = options?.nullable ?? false;
45
+ }
46
+
47
+ return defaultFunc(type, schema, value);
48
+ }
49
+ });
50
+ }
51
+
52
+ /**
53
+ * Validates if a object is a JSON schema.
54
+ *
55
+ * @export
56
+ * @param {Record<string, unknown>} schema
57
+ *
58
+ * @returns {boolean} if is a JSON schema
59
+ */
60
+ export function isJsonSchemaObject(
61
+ schema: Record<string, unknown>
62
+ ): schema is JSONSchemaType<object> {
63
+ if (schema.type === 'object') return true;
64
+
65
+ return Array.isArray(schema.type) && schema.type.includes('object');
66
+ }
67
+
68
+ /**
69
+ * Converts a JSON schema to JSON template.
70
+ *
71
+ * @export
72
+ * @param {Record<string, unknown>} schema JSON schema
73
+ * @param {Record<string, any>} [container] template container
74
+ *
75
+ * @returns {unknown} object or default value
76
+ */
77
+ export function schemaToJson(
78
+ schema: Record<string, unknown>,
79
+ container: Record<string, any> = {}
80
+ ): unknown {
81
+ if (isJsonSchemaObject(schema)) {
82
+ for (const key in schema.properties)
83
+ container[key] = schemaToJson(schema.properties[key]);
84
+
85
+ return container;
86
+ } else {
87
+ return schema.default ?? (schema.nullable ? null : undefined);
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Flatten a JSON schema.
93
+ *
94
+ * @export
95
+ * @param {Record<string, unknown>} schema JSON schema
96
+ * @param {string} [parentKey] previous level key
97
+ * @param {string} [nestingDelimiter] char for delimit nesting levels
98
+ * @param {Record<string, any>} [container] result container
99
+ *
100
+ * @returns {Record<string, unknown>} flattened schema
101
+ */
102
+ export function flatSchema(
103
+ schema: Record<string, unknown>,
104
+ parentKey = '',
105
+ nestingDelimiter = '__',
106
+ container: Record<string, any> = {}
107
+ ): Record<string, unknown> {
108
+ if (isJsonSchemaObject(schema)) {
109
+ for (const key in schema.properties) {
110
+ if (key[0] === '#') continue;
111
+
112
+ // global property, but prefix removed for injection
113
+ const subKey =
114
+ parentKey + (parentKey ? nestingDelimiter : '') + key;
115
+
116
+ container = {
117
+ ...container,
118
+ ...flatSchema(schema.properties[key], subKey, nestingDelimiter)
119
+ };
120
+ }
121
+
122
+ return container;
123
+ } else {
124
+ return { [parentKey]: schema };
125
+ }
126
+ }
127
+
128
+ /**
129
+ * Creates a JSON schema validator using AJV.
130
+ *
131
+ * @see https://ajv.js.org/
132
+ *
133
+ * @export
134
+ * @param {Record<string, object>} schema json schema by provider
135
+ * @param {boolean} enableFormats whether formats are enabled
136
+ *
137
+ * @returns {ValidateFunction} validators
138
+ */
139
+ export function createValidator(
140
+ schema: Record<string, unknown>,
141
+ enableFormats = true
142
+ ): ValidateFunction {
143
+ const ajv = new Ajv({
144
+ allErrors: true,
145
+ allowUnionTypes: true
146
+ });
147
+
148
+ if (enableFormats) {
149
+ addFormats(ajv, { mode: 'fast' });
150
+
151
+ for (const key in FORMAT_REGEXPS)
152
+ ajv.addFormat(key, FORMAT_REGEXPS[key]);
153
+ }
154
+
155
+ return ajv.compile(schema);
156
+ }
157
+
158
+ /**
159
+ * Creates a JSON schema validator lookup using AJV.
160
+ *
161
+ * @see https://ajv.js.org/
162
+ *
163
+ * @export
164
+ * @param {Record<string, object>} schemaLookup json schema by provider
165
+ * @param {boolean} enableFormats whether formats are enabled
166
+ *
167
+ * @returns {Record<string, ValidateFunction>} validators lookup
168
+ */
169
+ export function createValidators(
170
+ schemaLookup: Record<string, object>,
171
+ enableFormats = true
172
+ ): Record<string, ValidateFunction> {
173
+ const ajv = new Ajv({
174
+ allErrors: true,
175
+ allowUnionTypes: true
176
+ });
177
+
178
+ if (enableFormats) {
179
+ addFormats(ajv, { mode: 'fast' });
180
+
181
+ for (const key in FORMAT_REGEXPS)
182
+ ajv.addFormat(key, FORMAT_REGEXPS[key]);
183
+ }
184
+
185
+ const validators: Record<string, ValidateFunction> = {};
186
+
187
+ for (const key in schemaLookup)
188
+ validators[key] = ajv.compile(schemaLookup[key]);
189
+
190
+ return validators;
191
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "|DEFAULT|": {
3
+ "VAR1": "v1_default"
4
+ },
5
+ "|MODE|": {
6
+ "build": {
7
+ "NODE_ENV": "production"
8
+ },
9
+ "debug": {
10
+ "NODE_ENV": "development"
11
+ },
12
+ "test": {
13
+ "NODE_ENV": "test"
14
+ }
15
+ },
16
+ "|ENV|": {
17
+ "dev": {
18
+ "C1": "V1",
19
+ "C2": "V2",
20
+ "C3": 3,
21
+ "GROUP1": {
22
+ "VAR1": null,
23
+ "VAR2": "G1V2",
24
+ "VAR3": true,
25
+ "GROUP2": {
26
+ "VAR1": "G1G2V1"
27
+ }
28
+ },
29
+ "C4": "23"
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "VAR1": true,
3
+ "VAR2": false,
4
+ "VAR3": 12,
5
+ "VAR4": "any",
6
+ "ARR1": [1, "val", true],
7
+ "GROUP2": {
8
+ "VAR1": "g1v1",
9
+ "VAR2": "g1v2"
10
+ },
11
+ "$SECRET": "ANY SECRET"
12
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "VAR4": "any_local",
3
+ "GROUP1": {
4
+ "VAR1": null
5
+ },
6
+ "GROUP2": {
7
+ "VAR2": "g1v2_local"
8
+ }
9
+ }
@@ -0,0 +1,225 @@
1
+ {
2
+ "package-json": {
3
+ "type": "object",
4
+ "properties": {
5
+ "ENV": {
6
+ "type": [
7
+ "string"
8
+ ],
9
+ "nullable": true
10
+ },
11
+ "VERSION": {
12
+ "type": [
13
+ "string"
14
+ ],
15
+ "nullable": true
16
+ },
17
+ "PROJECT": {
18
+ "type": [
19
+ "string"
20
+ ],
21
+ "nullable": true
22
+ },
23
+ "NAME": {
24
+ "type": [
25
+ "string"
26
+ ],
27
+ "nullable": true
28
+ },
29
+ "TITLE": {
30
+ "type": [
31
+ "string"
32
+ ],
33
+ "nullable": true
34
+ },
35
+ "DESCRIPTION": {
36
+ "type": [
37
+ "string"
38
+ ],
39
+ "nullable": true
40
+ }
41
+ }
42
+ },
43
+ "app-settings": {
44
+ "type": "object",
45
+ "properties": {
46
+ "VAR1": {
47
+ "type": [
48
+ "string"
49
+ ],
50
+ "nullable": true
51
+ },
52
+ "C1": {
53
+ "type": [
54
+ "string"
55
+ ],
56
+ "nullable": true
57
+ },
58
+ "C2": {
59
+ "type": [
60
+ "string"
61
+ ],
62
+ "nullable": true
63
+ },
64
+ "C3": {
65
+ "type": [
66
+ "integer"
67
+ ],
68
+ "nullable": true
69
+ },
70
+ "GROUP1": {
71
+ "type": [
72
+ "object"
73
+ ],
74
+ "properties": {
75
+ "VAR1": {
76
+ "type": [
77
+ "null"
78
+ ],
79
+ "nullable": true
80
+ },
81
+ "VAR2": {
82
+ "type": [
83
+ "string"
84
+ ],
85
+ "nullable": true
86
+ },
87
+ "VAR3": {
88
+ "type": [
89
+ "boolean"
90
+ ],
91
+ "nullable": true
92
+ },
93
+ "GROUP2": {
94
+ "type": [
95
+ "object"
96
+ ],
97
+ "properties": {
98
+ "VAR1": {
99
+ "type": [
100
+ "string"
101
+ ],
102
+ "nullable": true
103
+ }
104
+ },
105
+ "nullable": true
106
+ }
107
+ },
108
+ "nullable": true
109
+ },
110
+ "C4": {
111
+ "type": [
112
+ "string"
113
+ ],
114
+ "format": "utc-millisec",
115
+ "nullable": true
116
+ },
117
+ "NODE_ENV": {
118
+ "type": [
119
+ "string"
120
+ ],
121
+ "nullable": true
122
+ }
123
+ }
124
+ },
125
+ "azure-key-vault": {
126
+ "type": "object",
127
+ "properties": {
128
+ "VAR1": {
129
+ "type": [
130
+ "boolean"
131
+ ],
132
+ "nullable": true
133
+ },
134
+ "VAR2": {
135
+ "type": [
136
+ "boolean"
137
+ ],
138
+ "nullable": true
139
+ },
140
+ "VAR3": {
141
+ "type": [
142
+ "integer"
143
+ ],
144
+ "nullable": true
145
+ },
146
+ "VAR4": {
147
+ "type": [
148
+ "string"
149
+ ],
150
+ "nullable": true
151
+ },
152
+ "ARR1": {
153
+ "type": [
154
+ "array"
155
+ ],
156
+ "nullable": true
157
+ },
158
+ "GROUP2": {
159
+ "type": [
160
+ "object"
161
+ ],
162
+ "properties": {
163
+ "VAR1": {
164
+ "type": [
165
+ "string"
166
+ ],
167
+ "nullable": true
168
+ },
169
+ "VAR2": {
170
+ "type": [
171
+ "string"
172
+ ],
173
+ "nullable": true
174
+ }
175
+ },
176
+ "nullable": true
177
+ },
178
+ "$SECRET": {
179
+ "type": [
180
+ "string"
181
+ ],
182
+ "nullable": true
183
+ }
184
+ }
185
+ },
186
+ "local": {
187
+ "type": "object",
188
+ "properties": {
189
+ "VAR4": {
190
+ "type": [
191
+ "string"
192
+ ],
193
+ "nullable": true
194
+ },
195
+ "GROUP1": {
196
+ "type": [
197
+ "object"
198
+ ],
199
+ "properties": {
200
+ "VAR1": {
201
+ "type": [
202
+ "null"
203
+ ],
204
+ "nullable": true
205
+ }
206
+ },
207
+ "nullable": true
208
+ },
209
+ "GROUP2": {
210
+ "type": [
211
+ "object"
212
+ ],
213
+ "properties": {
214
+ "VAR2": {
215
+ "type": [
216
+ "string"
217
+ ],
218
+ "nullable": true
219
+ }
220
+ },
221
+ "nullable": true
222
+ }
223
+ }
224
+ }
225
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "dev": {
3
+ "clientId": "96ae96c9-16e0-464e-a348-4c688b56ca31",
4
+ "clientSecret": "UTWuJsx3awfJ6RA5jaDsXWurqDr2yaEj",
5
+ "tenantId": "26df232c-d473-4615-9e8f-d2397aeed3ba"
6
+ }
7
+ }