@geekmidas/cli 0.29.0 → 0.31.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.
- package/dist/{config-BhryDQEq.cjs → config-BAE9LFC1.cjs} +2 -2
- package/dist/{config-BhryDQEq.cjs.map → config-BAE9LFC1.cjs.map} +1 -1
- package/dist/{config-C9bdq0l-.mjs → config-BC5n1a2D.mjs} +2 -2
- package/dist/{config-C9bdq0l-.mjs.map → config-BC5n1a2D.mjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +2 -2
- package/dist/{index-CWN-bgrO.d.mts → index-C7TkoYmt.d.mts} +5 -1
- package/dist/index-C7TkoYmt.d.mts.map +1 -0
- package/dist/{index-DEWYvYvg.d.cts → index-CpchsC9w.d.cts} +5 -1
- package/dist/index-CpchsC9w.d.cts.map +1 -0
- package/dist/index.cjs +58 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +58 -9
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-BCEFhkLh.mjs → openapi-CjYeF-Tg.mjs} +2 -2
- package/dist/{openapi-BCEFhkLh.mjs.map → openapi-CjYeF-Tg.mjs.map} +1 -1
- package/dist/{openapi-D82bBqG7.cjs → openapi-a-e3Y8WA.cjs} +2 -2
- package/dist/{openapi-D82bBqG7.cjs.map → openapi-a-e3Y8WA.cjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.mjs +3 -3
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +1 -1
- package/dist/workspace/index.d.mts +1 -1
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-DQjmv9lk.mjs → workspace-DFJ3sWfY.mjs} +19 -3
- package/dist/{workspace-DQjmv9lk.mjs.map → workspace-DFJ3sWfY.mjs.map} +1 -1
- package/dist/{workspace-CiZBOjf9.cjs → workspace-My0A4IRO.cjs} +19 -3
- package/dist/{workspace-CiZBOjf9.cjs.map → workspace-My0A4IRO.cjs.map} +1 -1
- package/package.json +4 -4
- package/src/dev/__tests__/entry.spec.ts +140 -0
- package/src/dev/__tests__/index.spec.ts +223 -0
- package/src/dev/index.ts +329 -5
- package/src/index.ts +30 -16
- package/src/init/__tests__/generators.spec.ts +17 -9
- package/src/init/versions.ts +1 -1
- package/src/workspace/__tests__/schema.spec.ts +114 -0
- package/src/workspace/schema.ts +23 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/index-CWN-bgrO.d.mts.map +0 -1
- package/dist/index-DEWYvYvg.d.cts.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
"lodash.kebabcase": "^4.1.1",
|
|
49
49
|
"openapi-typescript": "^7.4.2",
|
|
50
50
|
"prompts": "~2.4.2",
|
|
51
|
-
"@geekmidas/errors": "~0.1.0",
|
|
52
|
-
"@geekmidas/envkit": "~0.4.0",
|
|
53
51
|
"@geekmidas/constructs": "~0.6.0",
|
|
52
|
+
"@geekmidas/errors": "~0.1.0",
|
|
53
|
+
"@geekmidas/logger": "~0.4.0",
|
|
54
54
|
"@geekmidas/schema": "~0.1.0",
|
|
55
|
-
"@geekmidas/
|
|
55
|
+
"@geekmidas/envkit": "~0.5.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/lodash.kebabcase": "^4.1.9",
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { mkdir, readFile, rm } from 'node:fs/promises';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { createEntryWrapper, findSecretsRoot } from '../index';
|
|
6
|
+
|
|
7
|
+
describe('findSecretsRoot', () => {
|
|
8
|
+
let testDir: string;
|
|
9
|
+
|
|
10
|
+
beforeEach(async () => {
|
|
11
|
+
testDir = join(tmpdir(), `gkm-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
12
|
+
await mkdir(testDir, { recursive: true });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(async () => {
|
|
16
|
+
await rm(testDir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return startDir when no .gkm/secrets exists', () => {
|
|
20
|
+
const result = findSecretsRoot(testDir);
|
|
21
|
+
expect(result).toBe(testDir);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should find secrets in current directory', async () => {
|
|
25
|
+
await mkdir(join(testDir, '.gkm', 'secrets'), { recursive: true });
|
|
26
|
+
|
|
27
|
+
const result = findSecretsRoot(testDir);
|
|
28
|
+
expect(result).toBe(testDir);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should find secrets in parent directory', async () => {
|
|
32
|
+
const childDir = join(testDir, 'apps', 'auth');
|
|
33
|
+
await mkdir(childDir, { recursive: true });
|
|
34
|
+
await mkdir(join(testDir, '.gkm', 'secrets'), { recursive: true });
|
|
35
|
+
|
|
36
|
+
const result = findSecretsRoot(childDir);
|
|
37
|
+
expect(result).toBe(testDir);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should find secrets in grandparent directory', async () => {
|
|
41
|
+
const grandchildDir = join(testDir, 'apps', 'auth', 'src');
|
|
42
|
+
await mkdir(grandchildDir, { recursive: true });
|
|
43
|
+
await mkdir(join(testDir, '.gkm', 'secrets'), { recursive: true });
|
|
44
|
+
|
|
45
|
+
const result = findSecretsRoot(grandchildDir);
|
|
46
|
+
expect(result).toBe(testDir);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should prefer closer secrets directory', async () => {
|
|
50
|
+
// Create secrets in both parent and child
|
|
51
|
+
const childDir = join(testDir, 'apps', 'auth');
|
|
52
|
+
await mkdir(join(testDir, '.gkm', 'secrets'), { recursive: true });
|
|
53
|
+
await mkdir(join(childDir, '.gkm', 'secrets'), { recursive: true });
|
|
54
|
+
|
|
55
|
+
const result = findSecretsRoot(childDir);
|
|
56
|
+
expect(result).toBe(childDir);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
describe('createEntryWrapper', () => {
|
|
61
|
+
let testDir: string;
|
|
62
|
+
|
|
63
|
+
beforeEach(async () => {
|
|
64
|
+
testDir = join(tmpdir(), `gkm-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
65
|
+
await mkdir(testDir, { recursive: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
afterEach(async () => {
|
|
69
|
+
await rm(testDir, { recursive: true, force: true });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should create wrapper without secrets injection', async () => {
|
|
73
|
+
const wrapperPath = join(testDir, 'wrapper.ts');
|
|
74
|
+
const entryPath = '/path/to/entry.ts';
|
|
75
|
+
|
|
76
|
+
await createEntryWrapper(wrapperPath, entryPath, undefined);
|
|
77
|
+
|
|
78
|
+
const content = await readFile(wrapperPath, 'utf-8');
|
|
79
|
+
|
|
80
|
+
expect(content).toContain("import '/path/to/entry.ts'");
|
|
81
|
+
expect(content).not.toContain('Credentials');
|
|
82
|
+
expect(content).toContain("Entry wrapper generated by 'gkm dev --entry'");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should create wrapper with secrets injection', async () => {
|
|
86
|
+
const wrapperPath = join(testDir, 'wrapper.ts');
|
|
87
|
+
const entryPath = '/path/to/entry.ts';
|
|
88
|
+
const secretsPath = '/path/to/secrets.json';
|
|
89
|
+
|
|
90
|
+
await createEntryWrapper(wrapperPath, entryPath, secretsPath);
|
|
91
|
+
|
|
92
|
+
const content = await readFile(wrapperPath, 'utf-8');
|
|
93
|
+
|
|
94
|
+
expect(content).toContain(
|
|
95
|
+
"import { Credentials } from '@geekmidas/envkit/credentials'",
|
|
96
|
+
);
|
|
97
|
+
expect(content).toContain(secretsPath);
|
|
98
|
+
expect(content).toContain('Object.assign(Credentials');
|
|
99
|
+
expect(content).toContain("import '/path/to/entry.ts'");
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should inject secrets before entry import', async () => {
|
|
103
|
+
const wrapperPath = join(testDir, 'wrapper.ts');
|
|
104
|
+
const entryPath = '/path/to/entry.ts';
|
|
105
|
+
const secretsPath = '/path/to/secrets.json';
|
|
106
|
+
|
|
107
|
+
await createEntryWrapper(wrapperPath, entryPath, secretsPath);
|
|
108
|
+
|
|
109
|
+
const content = await readFile(wrapperPath, 'utf-8');
|
|
110
|
+
|
|
111
|
+
const credentialsIndex = content.indexOf('Credentials');
|
|
112
|
+
const importIndex = content.indexOf("import '/path/to/entry.ts'");
|
|
113
|
+
|
|
114
|
+
expect(credentialsIndex).toBeGreaterThan(-1);
|
|
115
|
+
expect(importIndex).toBeGreaterThan(-1);
|
|
116
|
+
expect(credentialsIndex).toBeLessThan(importIndex);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should include shebang line', async () => {
|
|
120
|
+
const wrapperPath = join(testDir, 'wrapper.ts');
|
|
121
|
+
const entryPath = '/path/to/entry.ts';
|
|
122
|
+
|
|
123
|
+
await createEntryWrapper(wrapperPath, entryPath, undefined);
|
|
124
|
+
|
|
125
|
+
const content = await readFile(wrapperPath, 'utf-8');
|
|
126
|
+
|
|
127
|
+
expect(content.startsWith('#!/usr/bin/env node')).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('should handle Windows-style paths', async () => {
|
|
131
|
+
const wrapperPath = join(testDir, 'wrapper.ts');
|
|
132
|
+
const entryPath = 'C:\\Users\\test\\project\\src\\index.ts';
|
|
133
|
+
|
|
134
|
+
await createEntryWrapper(wrapperPath, entryPath, undefined);
|
|
135
|
+
|
|
136
|
+
const content = await readFile(wrapperPath, 'utf-8');
|
|
137
|
+
|
|
138
|
+
expect(content).toContain(entryPath);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
findAvailablePort,
|
|
14
14
|
generateAllDependencyEnvVars,
|
|
15
15
|
isPortAvailable,
|
|
16
|
+
loadSecretsForApp,
|
|
16
17
|
normalizeHooksConfig,
|
|
17
18
|
normalizeProductionConfig,
|
|
18
19
|
normalizeStudioConfig,
|
|
@@ -967,3 +968,225 @@ describe('Workspace Dev Server', () => {
|
|
|
967
968
|
});
|
|
968
969
|
});
|
|
969
970
|
});
|
|
971
|
+
|
|
972
|
+
describe('loadSecretsForApp', () => {
|
|
973
|
+
let testDir: string;
|
|
974
|
+
|
|
975
|
+
beforeEach(() => {
|
|
976
|
+
testDir = join(
|
|
977
|
+
tmpdir(),
|
|
978
|
+
`gkm-secrets-test-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
979
|
+
);
|
|
980
|
+
mkdirSync(testDir, { recursive: true });
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
afterEach(() => {
|
|
984
|
+
if (existsSync(testDir)) {
|
|
985
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* Helper to create a secrets file in legacy (unencrypted) format.
|
|
991
|
+
* This matches the StageSecrets structure.
|
|
992
|
+
*/
|
|
993
|
+
function createSecretsFile(
|
|
994
|
+
stage: string,
|
|
995
|
+
secrets: Record<string, string>,
|
|
996
|
+
root = testDir,
|
|
997
|
+
) {
|
|
998
|
+
const secretsDir = join(root, '.gkm', 'secrets');
|
|
999
|
+
mkdirSync(secretsDir, { recursive: true });
|
|
1000
|
+
const stageSecrets = {
|
|
1001
|
+
stage,
|
|
1002
|
+
createdAt: new Date().toISOString(),
|
|
1003
|
+
updatedAt: new Date().toISOString(),
|
|
1004
|
+
services: {},
|
|
1005
|
+
urls: {},
|
|
1006
|
+
custom: secrets,
|
|
1007
|
+
};
|
|
1008
|
+
writeFileSync(
|
|
1009
|
+
join(secretsDir, `${stage}.json`),
|
|
1010
|
+
JSON.stringify(stageSecrets, null, 2),
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
describe('single app mode (no appName)', () => {
|
|
1015
|
+
it('should return secrets as-is without mapping', async () => {
|
|
1016
|
+
createSecretsFile('development', {
|
|
1017
|
+
DATABASE_URL: 'postgresql://localhost/mydb',
|
|
1018
|
+
JWT_SECRET: 'super-secret',
|
|
1019
|
+
NODE_ENV: 'development',
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1023
|
+
|
|
1024
|
+
expect(secrets).toEqual({
|
|
1025
|
+
DATABASE_URL: 'postgresql://localhost/mydb',
|
|
1026
|
+
JWT_SECRET: 'super-secret',
|
|
1027
|
+
NODE_ENV: 'development',
|
|
1028
|
+
});
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
it('should try dev stage first, then development', async () => {
|
|
1032
|
+
createSecretsFile('dev', {
|
|
1033
|
+
DATABASE_URL: 'postgresql://localhost/devdb',
|
|
1034
|
+
});
|
|
1035
|
+
createSecretsFile('development', {
|
|
1036
|
+
DATABASE_URL: 'postgresql://localhost/developmentdb',
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1040
|
+
|
|
1041
|
+
// Should use 'dev' stage since it's checked first
|
|
1042
|
+
expect(secrets.DATABASE_URL).toBe('postgresql://localhost/devdb');
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
it('should fallback to development if dev does not exist', async () => {
|
|
1046
|
+
createSecretsFile('development', {
|
|
1047
|
+
DATABASE_URL: 'postgresql://localhost/developmentdb',
|
|
1048
|
+
});
|
|
1049
|
+
|
|
1050
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1051
|
+
|
|
1052
|
+
expect(secrets.DATABASE_URL).toBe(
|
|
1053
|
+
'postgresql://localhost/developmentdb',
|
|
1054
|
+
);
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
it('should return empty object if no secrets exist', async () => {
|
|
1058
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1059
|
+
|
|
1060
|
+
expect(secrets).toEqual({});
|
|
1061
|
+
});
|
|
1062
|
+
});
|
|
1063
|
+
|
|
1064
|
+
describe('workspace app mode (with appName)', () => {
|
|
1065
|
+
it('should map {APP}_DATABASE_URL to DATABASE_URL', async () => {
|
|
1066
|
+
createSecretsFile('development', {
|
|
1067
|
+
AUTH_DATABASE_URL: 'postgresql://auth_user:pass@localhost/authdb',
|
|
1068
|
+
API_DATABASE_URL: 'postgresql://api_user:pass@localhost/apidb',
|
|
1069
|
+
JWT_SECRET: 'shared-secret',
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
const authSecrets = await loadSecretsForApp(testDir, 'auth');
|
|
1073
|
+
|
|
1074
|
+
expect(authSecrets.DATABASE_URL).toBe(
|
|
1075
|
+
'postgresql://auth_user:pass@localhost/authdb',
|
|
1076
|
+
);
|
|
1077
|
+
// Original prefixed secrets are also available
|
|
1078
|
+
expect(authSecrets.AUTH_DATABASE_URL).toBe(
|
|
1079
|
+
'postgresql://auth_user:pass@localhost/authdb',
|
|
1080
|
+
);
|
|
1081
|
+
expect(authSecrets.JWT_SECRET).toBe('shared-secret');
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
it('should map API secrets correctly', async () => {
|
|
1085
|
+
createSecretsFile('development', {
|
|
1086
|
+
AUTH_DATABASE_URL: 'postgresql://auth_user:pass@localhost/authdb',
|
|
1087
|
+
API_DATABASE_URL: 'postgresql://api_user:pass@localhost/apidb',
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
const apiSecrets = await loadSecretsForApp(testDir, 'api');
|
|
1091
|
+
|
|
1092
|
+
expect(apiSecrets.DATABASE_URL).toBe(
|
|
1093
|
+
'postgresql://api_user:pass@localhost/apidb',
|
|
1094
|
+
);
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
it('should not override DATABASE_URL if no prefixed version exists', async () => {
|
|
1098
|
+
createSecretsFile('development', {
|
|
1099
|
+
DATABASE_URL: 'postgresql://localhost/maindb',
|
|
1100
|
+
JWT_SECRET: 'secret',
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
// Asking for 'auth' app but AUTH_DATABASE_URL doesn't exist
|
|
1104
|
+
const authSecrets = await loadSecretsForApp(testDir, 'auth');
|
|
1105
|
+
|
|
1106
|
+
// Should keep the original DATABASE_URL since there's no AUTH_DATABASE_URL
|
|
1107
|
+
expect(authSecrets.DATABASE_URL).toBe('postgresql://localhost/maindb');
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
it('should handle uppercase app names in secrets', async () => {
|
|
1111
|
+
createSecretsFile('development', {
|
|
1112
|
+
MYSERVICE_DATABASE_URL: 'postgresql://localhost/myservicedb',
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
// App name is lowercase but secrets are uppercase prefixed
|
|
1116
|
+
const secrets = await loadSecretsForApp(testDir, 'myservice');
|
|
1117
|
+
|
|
1118
|
+
expect(secrets.DATABASE_URL).toBe('postgresql://localhost/myservicedb');
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
it('should return empty object if no secrets exist for app', async () => {
|
|
1122
|
+
const secrets = await loadSecretsForApp(testDir, 'api');
|
|
1123
|
+
|
|
1124
|
+
expect(secrets).toEqual({});
|
|
1125
|
+
});
|
|
1126
|
+
});
|
|
1127
|
+
|
|
1128
|
+
describe('service credentials mapping', () => {
|
|
1129
|
+
it('should include postgres service credentials', async () => {
|
|
1130
|
+
const secretsDir = join(testDir, '.gkm', 'secrets');
|
|
1131
|
+
mkdirSync(secretsDir, { recursive: true });
|
|
1132
|
+
const stageSecrets = {
|
|
1133
|
+
stage: 'development',
|
|
1134
|
+
createdAt: new Date().toISOString(),
|
|
1135
|
+
updatedAt: new Date().toISOString(),
|
|
1136
|
+
services: {
|
|
1137
|
+
postgres: {
|
|
1138
|
+
username: 'postgres',
|
|
1139
|
+
password: 'postgres123',
|
|
1140
|
+
database: 'myapp',
|
|
1141
|
+
host: 'localhost',
|
|
1142
|
+
port: 5432,
|
|
1143
|
+
},
|
|
1144
|
+
},
|
|
1145
|
+
urls: {},
|
|
1146
|
+
custom: { NODE_ENV: 'development' },
|
|
1147
|
+
};
|
|
1148
|
+
writeFileSync(
|
|
1149
|
+
join(secretsDir, 'development.json'),
|
|
1150
|
+
JSON.stringify(stageSecrets, null, 2),
|
|
1151
|
+
);
|
|
1152
|
+
|
|
1153
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1154
|
+
|
|
1155
|
+
expect(secrets.POSTGRES_USER).toBe('postgres');
|
|
1156
|
+
expect(secrets.POSTGRES_PASSWORD).toBe('postgres123');
|
|
1157
|
+
expect(secrets.POSTGRES_DB).toBe('myapp');
|
|
1158
|
+
expect(secrets.POSTGRES_HOST).toBe('localhost');
|
|
1159
|
+
expect(secrets.POSTGRES_PORT).toBe('5432');
|
|
1160
|
+
expect(secrets.NODE_ENV).toBe('development');
|
|
1161
|
+
});
|
|
1162
|
+
|
|
1163
|
+
it('should include redis service credentials', async () => {
|
|
1164
|
+
const secretsDir = join(testDir, '.gkm', 'secrets');
|
|
1165
|
+
mkdirSync(secretsDir, { recursive: true });
|
|
1166
|
+
const stageSecrets = {
|
|
1167
|
+
stage: 'development',
|
|
1168
|
+
createdAt: new Date().toISOString(),
|
|
1169
|
+
updatedAt: new Date().toISOString(),
|
|
1170
|
+
services: {
|
|
1171
|
+
redis: {
|
|
1172
|
+
password: 'redis123',
|
|
1173
|
+
host: 'localhost',
|
|
1174
|
+
port: 6379,
|
|
1175
|
+
},
|
|
1176
|
+
},
|
|
1177
|
+
urls: {},
|
|
1178
|
+
custom: {},
|
|
1179
|
+
};
|
|
1180
|
+
writeFileSync(
|
|
1181
|
+
join(secretsDir, 'development.json'),
|
|
1182
|
+
JSON.stringify(stageSecrets, null, 2),
|
|
1183
|
+
);
|
|
1184
|
+
|
|
1185
|
+
const secrets = await loadSecretsForApp(testDir);
|
|
1186
|
+
|
|
1187
|
+
expect(secrets.REDIS_PASSWORD).toBe('redis123');
|
|
1188
|
+
expect(secrets.REDIS_HOST).toBe('localhost');
|
|
1189
|
+
expect(secrets.REDIS_PORT).toBe('6379');
|
|
1190
|
+
});
|
|
1191
|
+
});
|
|
1192
|
+
});
|