@blogic-cz/agent-tools 0.14.3 → 0.14.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/package.json
CHANGED
package/src/db-tool/service.ts
CHANGED
|
@@ -76,6 +76,7 @@ export class DbService extends Context.Service<
|
|
|
76
76
|
const remotePort = dbConfig.remotePort ?? 5432;
|
|
77
77
|
|
|
78
78
|
const zshrcEnvCache = yield* Ref.make<Record<string, string> | null>(null);
|
|
79
|
+
const envTemplateRegex = /^\$\{([A-Za-z0-9_]+)\}$/;
|
|
79
80
|
|
|
80
81
|
const loadEnvFromZshrc = Effect.fn("DbService.loadEnvFromZshrc")(function* () {
|
|
81
82
|
const cached = yield* Ref.get(zshrcEnvCache);
|
|
@@ -141,6 +142,42 @@ export class DbService extends Context.Service<
|
|
|
141
142
|
return "";
|
|
142
143
|
});
|
|
143
144
|
|
|
145
|
+
const resolveConfigString = Effect.fn("DbService.resolveConfigString")(function* (
|
|
146
|
+
value: string,
|
|
147
|
+
env: string,
|
|
148
|
+
label: string,
|
|
149
|
+
zshrcEnv: Record<string, string>,
|
|
150
|
+
) {
|
|
151
|
+
const match = value.match(envTemplateRegex);
|
|
152
|
+
if (!match) return value;
|
|
153
|
+
|
|
154
|
+
const envVar = match[1];
|
|
155
|
+
const fromEnv = Bun.env[envVar];
|
|
156
|
+
if (fromEnv !== undefined) return fromEnv;
|
|
157
|
+
|
|
158
|
+
const fromZsh = zshrcEnv[envVar];
|
|
159
|
+
if (fromZsh !== undefined) return fromZsh;
|
|
160
|
+
|
|
161
|
+
return yield* new DbConnectionError({
|
|
162
|
+
message: `Environment variable ${envVar} (required for '${label}' config field) is not set in environment ${env}.`,
|
|
163
|
+
environment: env,
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const resolveDbConfig = Effect.fn("DbService.resolveDbConfig")(function* (
|
|
168
|
+
config: DbConfig,
|
|
169
|
+
env: string,
|
|
170
|
+
) {
|
|
171
|
+
const needsEnvResolution =
|
|
172
|
+
envTemplateRegex.test(config.user) || envTemplateRegex.test(config.database);
|
|
173
|
+
const zshrcEnv = needsEnvResolution ? yield* loadEnvFromZshrc() : {};
|
|
174
|
+
return {
|
|
175
|
+
...config,
|
|
176
|
+
user: yield* resolveConfigString(config.user, env, "user", zshrcEnv),
|
|
177
|
+
database: yield* resolveConfigString(config.database, env, "database", zshrcEnv),
|
|
178
|
+
};
|
|
179
|
+
});
|
|
180
|
+
|
|
144
181
|
const executeShellCommand = (command: ChildProcess.Command) =>
|
|
145
182
|
Effect.scoped(
|
|
146
183
|
Effect.gen(function* () {
|
|
@@ -183,6 +220,7 @@ export class DbService extends Context.Service<
|
|
|
183
220
|
dbConfig,
|
|
184
221
|
(command, _label) => executeShellCommand(command),
|
|
185
222
|
effect,
|
|
223
|
+
{ tryWithoutPrerequisites: true },
|
|
186
224
|
).pipe(
|
|
187
225
|
Effect.mapError((error) =>
|
|
188
226
|
isPrerequisiteRunError(error)
|
|
@@ -583,10 +621,11 @@ export class DbService extends Context.Service<
|
|
|
583
621
|
) {
|
|
584
622
|
const config = getConfigForEnv(env);
|
|
585
623
|
const startTimeMs = yield* Clock.currentTimeMillis;
|
|
586
|
-
const
|
|
624
|
+
const resolvedConfig = yield* resolveDbConfig(config, env);
|
|
625
|
+
const password = yield* resolvePassword(resolvedConfig, env);
|
|
587
626
|
const mutation = isMutationQuery(sql);
|
|
588
627
|
|
|
589
|
-
if (mutation && !
|
|
628
|
+
if (mutation && !resolvedConfig.allowMutations) {
|
|
590
629
|
return yield* new DbMutationBlockedError({
|
|
591
630
|
message:
|
|
592
631
|
"Mutation queries (UPDATE, INSERT, DELETE, etc.) are not allowed on this environment. Use a local environment for mutations.",
|
|
@@ -595,12 +634,12 @@ export class DbService extends Context.Service<
|
|
|
595
634
|
}
|
|
596
635
|
|
|
597
636
|
const queryEffect = mutation
|
|
598
|
-
? executeMutationQuery(
|
|
599
|
-
: executeSelectQuery(
|
|
637
|
+
? executeMutationQuery(resolvedConfig, sql, password, Number(startTimeMs))
|
|
638
|
+
: executeSelectQuery(resolvedConfig, sql, password, Number(startTimeMs), true);
|
|
600
639
|
|
|
601
640
|
return yield* runWithVpnPrerequisites(
|
|
602
|
-
|
|
603
|
-
runQueryWithOptionalTunnel(
|
|
641
|
+
resolvedConfig.port,
|
|
642
|
+
runQueryWithOptionalTunnel(resolvedConfig, queryEffect),
|
|
604
643
|
);
|
|
605
644
|
});
|
|
606
645
|
|
|
@@ -611,7 +650,8 @@ export class DbService extends Context.Service<
|
|
|
611
650
|
) {
|
|
612
651
|
const config = getConfigForEnv(env);
|
|
613
652
|
const startTimeMs = yield* Clock.currentTimeMillis;
|
|
614
|
-
const
|
|
653
|
+
const resolvedConfig = yield* resolveDbConfig(config, env);
|
|
654
|
+
const password = yield* resolvePassword(resolvedConfig, env);
|
|
615
655
|
|
|
616
656
|
if (mode === "columns" && !table) {
|
|
617
657
|
const endTime = yield* Clock.currentTimeMillis;
|
|
@@ -636,16 +676,26 @@ export class DbService extends Context.Service<
|
|
|
636
676
|
|
|
637
677
|
const queryEffect =
|
|
638
678
|
mode === "tables"
|
|
639
|
-
? executeSelectQuery(
|
|
679
|
+
? executeSelectQuery(resolvedConfig, getTableNames(), password, Number(startTimeMs))
|
|
640
680
|
: mode === "columns"
|
|
641
|
-
? executeSelectQuery(
|
|
681
|
+
? executeSelectQuery(
|
|
682
|
+
resolvedConfig,
|
|
683
|
+
getColumns(table ?? ""),
|
|
684
|
+
password,
|
|
685
|
+
Number(startTimeMs),
|
|
686
|
+
)
|
|
642
687
|
: mode === "relationships"
|
|
643
|
-
? executeSelectQuery(
|
|
644
|
-
|
|
688
|
+
? executeSelectQuery(
|
|
689
|
+
resolvedConfig,
|
|
690
|
+
getRelationships(),
|
|
691
|
+
password,
|
|
692
|
+
Number(startTimeMs),
|
|
693
|
+
)
|
|
694
|
+
: executeFullSchemaQuery(resolvedConfig, password, Number(startTimeMs));
|
|
645
695
|
|
|
646
696
|
const result = yield* runWithVpnPrerequisites(
|
|
647
|
-
|
|
648
|
-
runQueryWithOptionalTunnel(
|
|
697
|
+
resolvedConfig.port,
|
|
698
|
+
runQueryWithOptionalTunnel(resolvedConfig, queryEffect),
|
|
649
699
|
);
|
|
650
700
|
|
|
651
701
|
if (result.success) {
|
package/src/k8s-tool/service.ts
CHANGED
|
@@ -116,6 +116,7 @@ export const runWithProfilePrerequisites = <A, E, CommandError>(
|
|
|
116
116
|
profile: ProfilePrerequisites,
|
|
117
117
|
runCommand: PrerequisiteCommandRunner<CommandError>,
|
|
118
118
|
effect: Effect.Effect<A, E, never>,
|
|
119
|
+
options?: { tryWithoutPrerequisites?: boolean },
|
|
119
120
|
): Effect.Effect<A, E | PrerequisiteRunError, never> => {
|
|
120
121
|
const prerequisites = normalizeProfilePrerequisites(profile);
|
|
121
122
|
const vpnPrerequisites = prerequisites.filter((prerequisite) => prerequisite.type === "vpn");
|
|
@@ -125,6 +126,13 @@ export const runWithProfilePrerequisites = <A, E, CommandError>(
|
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
return Effect.gen(function* () {
|
|
129
|
+
if (options?.tryWithoutPrerequisites) {
|
|
130
|
+
const directResult = yield* effect.pipe(Effect.result);
|
|
131
|
+
if (Result.isSuccess(directResult)) {
|
|
132
|
+
return directResult.success;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
128
136
|
const startedDrivers: Array<{ driver: ResolvedVpnDriver; cooldownMs: number }> = [];
|
|
129
137
|
|
|
130
138
|
for (const prerequisite of vpnPrerequisites) {
|