@noormdev/sdk 1.0.0-alpha.33 → 1.0.0-alpha.34

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/index.js CHANGED
@@ -2,7 +2,7 @@ import { createRequire } from 'module';
2
2
  import { processFile, DtReader, isTemplate, FORMAT_VERSION, DT_EXTENSIONS, encryptWithPassphrase, ENCODED_TYPES } from './chunk-5AYPF5D5.js';
3
3
  import './chunk-UOFJT5PY.js';
4
4
  import { initializeVault, getVaultStatus, setVaultSecret, getVaultSecret, getAllVaultSecrets, listVaultSecretKeys, deleteVaultSecret, vaultSecretExists, getVaultKey, noormDb, getNoormTables, encryptVaultKey } from './chunk-DE3NJ22A.js';
5
- import { makeNestedConfig, gigabytes, observer, attempt, retry, clone, merge, attemptSync, ObserverRelay } from './chunk-DLQES4PM.js';
5
+ import { makeNestedConfig, gigabytes, observer, attempt, retry, attemptSync, clone, merge, ObserverRelay } from './chunk-DLQES4PM.js';
6
6
  import { dist_default } from './chunk-TBRUDUBQ.js';
7
7
  import { require_dist } from './chunk-YJBKNUTP.js';
8
8
  import { __commonJS, __export, __toESM } from './chunk-D2XW2UOP.js';
@@ -10,7 +10,7 @@ import { constants, existsSync, readFileSync, mkdirSync, writeFileSync, createWr
10
10
  import path, { join, dirname, resolve } from 'path';
11
11
  import { homedir, availableParallelism, userInfo } from 'os';
12
12
  import { stat, mkdir, writeFile, unlink, rename, rm, readdir, readFile, access } from 'fs/promises';
13
- import { createHash, createDecipheriv, randomBytes, createCipheriv, randomUUID, hkdfSync } from 'crypto';
13
+ import { createHash, createPrivateKey, createPublicKey, createDecipheriv, randomBytes, createCipheriv, randomUUID, hkdfSync } from 'crypto';
14
14
  import { execSync } from 'child_process';
15
15
  import { sql } from 'kysely';
16
16
  import { Worker, parentPort, workerData } from 'worker_threads';
@@ -304,6 +304,9 @@ var PRIVATE_KEY_PATH = join(NOORM_HOME, "identity.key");
304
304
  var PUBLIC_KEY_PATH = join(NOORM_HOME, "identity.pub");
305
305
  var IDENTITY_METADATA_PATH = join(NOORM_HOME, "identity.json");
306
306
  async function loadIdentityMetadata() {
307
+ if (identityOverride) {
308
+ return identityOverride;
309
+ }
307
310
  const [content, err] = await attempt(
308
311
  () => readFile(IDENTITY_METADATA_PATH, { encoding: "utf8" })
309
312
  );
@@ -320,6 +323,9 @@ async function loadIdentityMetadata() {
320
323
  return parsed;
321
324
  }
322
325
  async function loadPrivateKey() {
326
+ if (keyOverride) {
327
+ return keyOverride;
328
+ }
323
329
  const [content, err] = await attempt(() => readFile(PRIVATE_KEY_PATH, { encoding: "utf8" }));
324
330
  if (err) {
325
331
  if (err.code === "ENOENT") {
@@ -339,6 +345,34 @@ async function loadPublicKey() {
339
345
  }
340
346
  return content.trim();
341
347
  }
348
+ function isValidKeyHex(hex4) {
349
+ if (!/^[0-9a-f]+$/i.test(hex4)) {
350
+ return false;
351
+ }
352
+ const validLengths = [88, 96];
353
+ return validLengths.includes(hex4.length);
354
+ }
355
+ var keyOverride = null;
356
+ function setKeyOverride(key) {
357
+ keyOverride = key;
358
+ }
359
+ var identityOverride = null;
360
+ function setIdentityOverride(identity) {
361
+ identityOverride = identity;
362
+ }
363
+ function derivePublicKeyFromPrivate(privateKeyHex) {
364
+ const privateKeyObj = createPrivateKey({
365
+ key: Buffer.from(privateKeyHex, "hex"),
366
+ format: "der",
367
+ type: "pkcs8"
368
+ });
369
+ const publicKeyObj = createPublicKey(privateKeyObj);
370
+ const publicKeyDer = publicKeyObj.export({
371
+ type: "spki",
372
+ format: "der"
373
+ });
374
+ return publicKeyDer.toString("hex");
375
+ }
342
376
  function deriveStateKey(privateKey) {
343
377
  const privateKeyBuffer = Buffer.from(privateKey, "hex");
344
378
  return Buffer.from(
@@ -14866,199 +14900,26 @@ function getEffectiveBuildPaths(buildInclude, buildExclude, rules, config2) {
14866
14900
 
14867
14901
  // src/core/settings/manager.ts
14868
14902
  var import_yaml = __toESM(require_dist(), 1);
14869
-
14870
- // src/core/config/schema.ts
14871
- var DialectSchema2 = external_exports.enum(["postgres", "mysql", "sqlite", "mssql"]);
14872
- var ConfigNameSchema = external_exports.string().min(1, "Config name is required").regex(
14873
- /^[a-z0-9_-]+$/i,
14874
- "Config name must contain only letters, numbers, hyphens, and underscores"
14875
- );
14876
- var PortSchema2 = external_exports.number().int().min(1, "Port must be at least 1").max(65535, "Port must be at most 65535");
14877
- var PoolSchema = external_exports.object({
14878
- min: external_exports.number().int().min(0).optional(),
14879
- max: external_exports.number().int().min(1).optional()
14880
- });
14881
- var SSLSchema = external_exports.union([
14882
- external_exports.boolean(),
14883
- external_exports.object({
14884
- rejectUnauthorized: external_exports.boolean().optional(),
14885
- ca: external_exports.string().optional(),
14886
- cert: external_exports.string().optional(),
14887
- key: external_exports.string().optional()
14888
- })
14889
- ]);
14890
- var ConnectionSchema = external_exports.object({
14891
- dialect: DialectSchema2,
14892
- host: external_exports.string().optional(),
14893
- port: PortSchema2.optional(),
14894
- database: external_exports.string().min(1, "Database name is required"),
14895
- filename: external_exports.string().optional(),
14896
- user: external_exports.string().optional(),
14897
- password: external_exports.string().optional(),
14898
- ssl: SSLSchema.optional(),
14899
- pool: PoolSchema.optional()
14900
- }).refine((conn) => conn.dialect === "sqlite" || conn.host, {
14901
- message: "Host is required for non-SQLite databases",
14902
- path: ["host"]
14903
- });
14904
- var ConfigSchema = external_exports.object({
14905
- name: ConfigNameSchema,
14906
- type: external_exports.enum(["local", "remote"]).default("local"),
14907
- isTest: external_exports.boolean().default(false),
14908
- protected: external_exports.boolean().default(false),
14909
- connection: ConnectionSchema,
14910
- identity: external_exports.string().optional()
14911
- });
14912
- var PartialConnectionSchema = external_exports.object({
14913
- dialect: DialectSchema2.optional(),
14914
- host: external_exports.string().optional(),
14915
- port: PortSchema2.optional(),
14916
- database: external_exports.string().optional(),
14917
- filename: external_exports.string().optional(),
14918
- user: external_exports.string().optional(),
14919
- password: external_exports.string().optional(),
14920
- ssl: SSLSchema.optional(),
14921
- pool: PoolSchema.optional()
14922
- });
14923
- external_exports.object({
14924
- name: external_exports.string().regex(/^[a-z0-9_-]+$/i).optional(),
14925
- type: external_exports.enum(["local", "remote"]).optional(),
14926
- isTest: external_exports.boolean().optional(),
14927
- protected: external_exports.boolean().optional(),
14928
- connection: PartialConnectionSchema.optional(),
14929
- identity: external_exports.string().optional()
14930
- });
14931
- ConfigSchema.extend({
14932
- name: ConfigNameSchema.optional()
14933
- });
14934
- var ConfigValidationError = class extends Error {
14935
- constructor(message, field, issues) {
14936
- super(message);
14937
- this.field = field;
14938
- this.issues = issues;
14939
- this.name = "ConfigValidationError";
14940
- }
14941
- };
14942
- function parseConfig(config2) {
14943
- const result = ConfigSchema.safeParse(config2);
14944
- if (!result.success) {
14945
- const firstIssue = result.error.issues[0];
14946
- throw new ConfigValidationError(
14947
- firstIssue?.message ?? "Validation failed",
14948
- firstIssue?.path.join(".") || "unknown",
14949
- result.error.issues
14950
- );
14951
- }
14952
- return result.data;
14953
- }
14954
-
14955
- // src/core/environment.ts
14956
- function getEnvConfigName() {
14957
- return process.env["NOORM_CONFIG"];
14958
- }
14959
-
14960
- // src/core/config/resolver.ts
14961
- var SettingsProvider = class {
14962
- #manager;
14963
- constructor(manager) {
14964
- this.#manager = manager;
14965
- }
14966
- /** Get a stage by name */
14967
- getStage(name) {
14968
- return this.#manager.getStage(name) ?? null;
14969
- }
14970
- /** Get stage that matches a config name (for auto-linking) */
14971
- findStageForConfig(configName) {
14972
- return this.#manager.getStage(configName) ?? null;
14973
- }
14974
- };
14975
- var DEFAULTS = {
14976
- type: "local",
14977
- isTest: false,
14978
- protected: false,
14979
- connection: {
14980
- host: "localhost",
14981
- pool: { min: 0, max: 10 }
14982
- },
14983
- log: {
14984
- level: "info"
14985
- }
14986
- };
14987
- function resolveConfig(state, options = {}) {
14988
- const configName = options.name ?? getEnvConfigName() ?? state.getActiveConfigName();
14989
- if (!configName) {
14990
- const envConfig2 = getEnvConfig();
14991
- if (envConfig2.connection?.dialect && envConfig2.connection?.database) {
14992
- return resolveFromEnvOnly(envConfig2, options.flags, options.stage, options.settings);
14993
- }
14994
- return null;
14995
- }
14996
- const stored = state.getConfig(configName);
14997
- if (!stored) {
14998
- throw new Error(`Config "${configName}" not found`);
14999
- }
15000
- const stageDefaults = getStageDefaults(configName, options.stage, options.settings);
15001
- const envConfig = getEnvConfig();
15002
- let merged = clone(DEFAULTS);
15003
- if (stageDefaults) {
15004
- merged = merge(merged, stageDefaults);
15005
- }
15006
- merged = merge(merged, stored);
15007
- merged = merge(merged, envConfig);
15008
- merged = merge(merged, options.flags ?? {});
15009
- return parseConfig(merged);
15010
- }
15011
- function getStageDefaults(configName, stageName, settings) {
15012
- if (!settings) return null;
15013
- if (stageName) return settings.getStage(stageName)?.defaults ?? null;
15014
- return settings.findStageForConfig(configName)?.defaults ?? null;
15015
- }
15016
- function resolveFromEnvOnly(envConfig, flags, stageName, settings) {
15017
- const name = envConfig.name ?? flags?.name ?? "__env__";
15018
- const stageDefaults = getStageDefaults(name, stageName, settings);
15019
- let merged = clone(DEFAULTS);
15020
- if (stageDefaults) {
15021
- merged = merge(merged, stageDefaults);
15022
- }
15023
- merged = merge(merged, envConfig);
15024
- merged = merge(merged, flags ?? {});
15025
- if (!merged.name) {
15026
- merged.name = "__env__";
15027
- }
15028
- return parseConfig(merged);
15029
- }
15030
-
15031
- // src/core/config/index.ts
15032
- var META_ENV_VARS = /* @__PURE__ */ new Set([
14903
+ var META_SETTINGS_ENV_VARS = /* @__PURE__ */ new Set([
15033
14904
  "NOORM_CONFIG",
15034
- // Config selection
15035
14905
  "NOORM_YES",
15036
- // Skip confirmations
15037
- "NOORM_JSON"
15038
- // JSON output mode
14906
+ "NOORM_JSON",
14907
+ "NOORM_HEADLESS",
14908
+ "NOORM_DEBUG",
14909
+ "NOORM_DEV",
14910
+ "NOORM_CI_CONFIG_NAME",
14911
+ "NOORM_LOGGER_DEBUG",
14912
+ "NOORM_IDENTITY"
15039
14913
  ]);
15040
- var VALID_DIALECTS = ["postgres", "mysql", "sqlite", "mssql"];
15041
- var { allConfigs, getConfig } = makeNestedConfig(process.env, {
15042
- filter: (key) => key.startsWith("NOORM_") && !META_ENV_VARS.has(key),
15043
- stripPrefix: "NOORM_",
15044
- forceAllCapToLower: true,
15045
- memoizeOpts: false,
15046
- skipConversion: (key) => key.toLowerCase().includes("password")
15047
- });
15048
- function getEnvConfig() {
15049
- const config2 = allConfigs();
15050
- if (config2.connection?.dialect) {
15051
- const result = DialectSchema2.safeParse(config2.connection.dialect);
15052
- if (!result.success) {
15053
- throw new Error(
15054
- `Invalid NOORM_CONNECTION_DIALECT: must be one of ${VALID_DIALECTS.join(", ")}`
15055
- );
15056
- }
15057
- }
15058
- return config2;
14914
+ function allSettingsEnv() {
14915
+ const { allConfigs: allConfigs2 } = makeNestedConfig(process.env, {
14916
+ filter: (key) => key.startsWith("NOORM_") && !META_SETTINGS_ENV_VARS.has(key) && !key.startsWith("NOORM_IDENTITY_") && !key.startsWith("NOORM_CONNECTION_"),
14917
+ stripPrefix: "NOORM_",
14918
+ forceAllCapToLower: true,
14919
+ memoizeOpts: false
14920
+ });
14921
+ return allConfigs2();
15059
14922
  }
15060
-
15061
- // src/core/settings/manager.ts
15062
14923
  var SettingsManager = class {
15063
14924
  #projectRoot;
15064
14925
  #settingsDir;
@@ -15134,7 +14995,7 @@ var SettingsManager = class {
15134
14995
  }
15135
14996
  fromFile = true;
15136
14997
  }
15137
- this.#settings = merge(this.#settings, allConfigs());
14998
+ this.#settings = merge(this.#settings, allSettingsEnv());
15138
14999
  this.#loaded = true;
15139
15000
  observer.emit("settings:loaded", {
15140
15001
  path: this.settingsFilePath,
@@ -15718,6 +15579,13 @@ function formatIdentity(identity) {
15718
15579
  }
15719
15580
  return identity.name;
15720
15581
  }
15582
+ function computeIdentityHash(input) {
15583
+ if (!input.email || !input.name || !input.machine || false) {
15584
+ throw new Error("All fields required for identity hash: email, name, machine, os");
15585
+ }
15586
+ const hashInput = [input.email, input.name, input.machine, input.os].join("\0");
15587
+ return createHash("sha256").update(hashInput, "utf8").digest("hex");
15588
+ }
15721
15589
 
15722
15590
  // src/core/identity/factory.ts
15723
15591
  async function loadExistingIdentity() {
@@ -16638,6 +16506,11 @@ function createDialectQuoting(opts) {
16638
16506
  return { quote: quote5, qualifiedName: qualifiedName4 };
16639
16507
  }
16640
16508
 
16509
+ // src/core/environment.ts
16510
+ function getEnvConfigName() {
16511
+ return process.env["NOORM_CONFIG"];
16512
+ }
16513
+
16641
16514
  // src/core/logger/logger.ts
16642
16515
  __toESM(require_dayjs_min(), 1);
16643
16516
 
@@ -16765,6 +16638,50 @@ async function registerIdentity(db, identity, dialect) {
16765
16638
  return { ok: true, registered: true };
16766
16639
  }
16767
16640
 
16641
+ // src/core/identity/env.ts
16642
+ var CI_ENV_VARS = {
16643
+ privateKey: "NOORM_IDENTITY_PRIVATE_KEY",
16644
+ name: "NOORM_IDENTITY_NAME",
16645
+ email: "NOORM_IDENTITY_EMAIL"
16646
+ };
16647
+ function loadIdentityFromEnv() {
16648
+ const rawKey = process.env[CI_ENV_VARS.privateKey];
16649
+ const rawName = process.env[CI_ENV_VARS.name];
16650
+ const rawEmail = process.env[CI_ENV_VARS.email];
16651
+ if (!rawKey || !rawName || !rawEmail) {
16652
+ return null;
16653
+ }
16654
+ const privateKey = rawKey.trim();
16655
+ const name = rawName.trim();
16656
+ const email3 = rawEmail.trim();
16657
+ if (!name || !email3) {
16658
+ return null;
16659
+ }
16660
+ if (!isValidKeyHex(privateKey)) {
16661
+ return null;
16662
+ }
16663
+ const [publicKey, deriveErr] = attemptSync(() => derivePublicKeyFromPrivate(privateKey));
16664
+ if (deriveErr || !publicKey) {
16665
+ return null;
16666
+ }
16667
+ const identityHash = computeIdentityHash({
16668
+ email: email3,
16669
+ name,
16670
+ machine: publicKey,
16671
+ os: "env"
16672
+ });
16673
+ const identity = {
16674
+ identityHash,
16675
+ name,
16676
+ email: email3,
16677
+ publicKey,
16678
+ machine: "ci",
16679
+ os: "env",
16680
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
16681
+ };
16682
+ return { identity, privateKey, source: "env" };
16683
+ }
16684
+
16768
16685
  // src/core/identity/index.ts
16769
16686
  var cachedIdentity = null;
16770
16687
  function resolveIdentity2(options = {}) {
@@ -16791,6 +16708,205 @@ async function waitForIdentityToLoad(db, dialect) {
16791
16708
  });
16792
16709
  }
16793
16710
 
16711
+ // src/core/config/schema.ts
16712
+ var DialectSchema2 = external_exports.enum(["postgres", "mysql", "sqlite", "mssql"]);
16713
+ var ConfigNameSchema = external_exports.string().min(1, "Config name is required").regex(
16714
+ /^[a-z0-9_-]+$/i,
16715
+ "Config name must contain only letters, numbers, hyphens, and underscores"
16716
+ );
16717
+ var PortSchema2 = external_exports.number().int().min(1, "Port must be at least 1").max(65535, "Port must be at most 65535");
16718
+ var PoolSchema = external_exports.object({
16719
+ min: external_exports.number().int().min(0).optional(),
16720
+ max: external_exports.number().int().min(1).optional()
16721
+ });
16722
+ var SSLSchema = external_exports.union([
16723
+ external_exports.boolean(),
16724
+ external_exports.object({
16725
+ rejectUnauthorized: external_exports.boolean().optional(),
16726
+ ca: external_exports.string().optional(),
16727
+ cert: external_exports.string().optional(),
16728
+ key: external_exports.string().optional()
16729
+ })
16730
+ ]);
16731
+ var ConnectionSchema = external_exports.object({
16732
+ dialect: DialectSchema2,
16733
+ host: external_exports.string().optional(),
16734
+ port: PortSchema2.optional(),
16735
+ database: external_exports.string().min(1, "Database name is required"),
16736
+ filename: external_exports.string().optional(),
16737
+ user: external_exports.string().optional(),
16738
+ password: external_exports.string().optional(),
16739
+ ssl: SSLSchema.optional(),
16740
+ pool: PoolSchema.optional()
16741
+ }).refine((conn) => conn.dialect === "sqlite" || conn.host, {
16742
+ message: "Host is required for non-SQLite databases",
16743
+ path: ["host"]
16744
+ });
16745
+ var ConfigSchema = external_exports.object({
16746
+ name: ConfigNameSchema,
16747
+ type: external_exports.enum(["local", "remote"]).default("local"),
16748
+ isTest: external_exports.boolean().default(false),
16749
+ protected: external_exports.boolean().default(false),
16750
+ connection: ConnectionSchema,
16751
+ identity: external_exports.string().optional()
16752
+ });
16753
+ var PartialConnectionSchema = external_exports.object({
16754
+ dialect: DialectSchema2.optional(),
16755
+ host: external_exports.string().optional(),
16756
+ port: PortSchema2.optional(),
16757
+ database: external_exports.string().optional(),
16758
+ filename: external_exports.string().optional(),
16759
+ user: external_exports.string().optional(),
16760
+ password: external_exports.string().optional(),
16761
+ ssl: SSLSchema.optional(),
16762
+ pool: PoolSchema.optional()
16763
+ });
16764
+ external_exports.object({
16765
+ name: external_exports.string().regex(/^[a-z0-9_-]+$/i).optional(),
16766
+ type: external_exports.enum(["local", "remote"]).optional(),
16767
+ isTest: external_exports.boolean().optional(),
16768
+ protected: external_exports.boolean().optional(),
16769
+ connection: PartialConnectionSchema.optional(),
16770
+ identity: external_exports.string().optional()
16771
+ });
16772
+ ConfigSchema.extend({
16773
+ name: ConfigNameSchema.optional()
16774
+ });
16775
+ var ConfigValidationError = class extends Error {
16776
+ constructor(message, field, issues) {
16777
+ super(message);
16778
+ this.field = field;
16779
+ this.issues = issues;
16780
+ this.name = "ConfigValidationError";
16781
+ }
16782
+ };
16783
+ function parseConfig(config2) {
16784
+ const result = ConfigSchema.safeParse(config2);
16785
+ if (!result.success) {
16786
+ const firstIssue = result.error.issues[0];
16787
+ throw new ConfigValidationError(
16788
+ firstIssue?.message ?? "Validation failed",
16789
+ firstIssue?.path.join(".") || "unknown",
16790
+ result.error.issues
16791
+ );
16792
+ }
16793
+ return result.data;
16794
+ }
16795
+
16796
+ // src/core/config/index.ts
16797
+ var META_ENV_VARS = /* @__PURE__ */ new Set([
16798
+ "NOORM_CONFIG",
16799
+ // Config selection
16800
+ "NOORM_YES",
16801
+ // Skip confirmations
16802
+ "NOORM_JSON",
16803
+ // JSON output mode
16804
+ "NOORM_HEADLESS",
16805
+ // Headless mode detection
16806
+ "NOORM_DEBUG",
16807
+ // Debug logging
16808
+ "NOORM_DEV",
16809
+ // Dev mode detection
16810
+ "NOORM_CI_CONFIG_NAME",
16811
+ // ci init config name override
16812
+ "NOORM_LOGGER_DEBUG"
16813
+ // Logger-internal debug
16814
+ ]);
16815
+ var NON_CONFIG_ENV_PREFIXES = [
16816
+ "NOORM_IDENTITY_"
16817
+ ];
16818
+ var VALID_DIALECTS = ["postgres", "mysql", "sqlite", "mssql"];
16819
+ var { allConfigs, getConfig } = makeNestedConfig(process.env, {
16820
+ filter: (key) => key.startsWith("NOORM_") && !META_ENV_VARS.has(key) && !NON_CONFIG_ENV_PREFIXES.some((prefix) => key.startsWith(prefix)),
16821
+ stripPrefix: "NOORM_",
16822
+ forceAllCapToLower: true,
16823
+ memoizeOpts: false,
16824
+ skipConversion: (key) => key.toLowerCase().includes("password")
16825
+ });
16826
+ function getEnvConfig() {
16827
+ const config2 = allConfigs();
16828
+ if (config2.connection?.dialect) {
16829
+ const result = DialectSchema2.safeParse(config2.connection.dialect);
16830
+ if (!result.success) {
16831
+ throw new Error(
16832
+ `Invalid NOORM_CONNECTION_DIALECT: must be one of ${VALID_DIALECTS.join(", ")}`
16833
+ );
16834
+ }
16835
+ }
16836
+ return config2;
16837
+ }
16838
+
16839
+ // src/core/config/resolver.ts
16840
+ var SettingsProvider = class {
16841
+ #manager;
16842
+ constructor(manager) {
16843
+ this.#manager = manager;
16844
+ }
16845
+ /** Get a stage by name */
16846
+ getStage(name) {
16847
+ return this.#manager.getStage(name) ?? null;
16848
+ }
16849
+ /** Get stage that matches a config name (for auto-linking) */
16850
+ findStageForConfig(configName) {
16851
+ return this.#manager.getStage(configName) ?? null;
16852
+ }
16853
+ };
16854
+ var DEFAULTS = {
16855
+ type: "local",
16856
+ isTest: false,
16857
+ protected: false,
16858
+ connection: {
16859
+ host: "localhost",
16860
+ pool: { min: 0, max: 10 }
16861
+ },
16862
+ log: {
16863
+ level: "info"
16864
+ }
16865
+ };
16866
+ function resolveConfig(state, options = {}) {
16867
+ const configName = options.name ?? getEnvConfigName() ?? state.getActiveConfigName();
16868
+ if (!configName) {
16869
+ const envConfig2 = getEnvConfig();
16870
+ if (envConfig2.connection?.dialect && envConfig2.connection?.database) {
16871
+ return resolveFromEnvOnly(envConfig2, options.flags, options.stage, options.settings);
16872
+ }
16873
+ return null;
16874
+ }
16875
+ const stored = state.getConfig(configName);
16876
+ if (!stored) {
16877
+ throw new Error(`Config "${configName}" not found`);
16878
+ }
16879
+ const stageDefaults = getStageDefaults(configName, options.stage, options.settings);
16880
+ const envConfig = getEnvConfig();
16881
+ let merged = clone(DEFAULTS);
16882
+ if (stageDefaults) {
16883
+ merged = merge(merged, stageDefaults);
16884
+ }
16885
+ merged = merge(merged, stored);
16886
+ merged = merge(merged, envConfig);
16887
+ merged = merge(merged, options.flags ?? {});
16888
+ return parseConfig(merged);
16889
+ }
16890
+ function getStageDefaults(configName, stageName, settings) {
16891
+ if (!settings) return null;
16892
+ if (stageName) return settings.getStage(stageName)?.defaults ?? null;
16893
+ return settings.findStageForConfig(configName)?.defaults ?? null;
16894
+ }
16895
+ function resolveFromEnvOnly(envConfig, flags, stageName, settings) {
16896
+ const name = envConfig.name ?? flags?.name ?? "__env__";
16897
+ const stageDefaults = getStageDefaults(name, stageName, settings);
16898
+ let merged = clone(DEFAULTS);
16899
+ if (stageDefaults) {
16900
+ merged = merge(merged, stageDefaults);
16901
+ }
16902
+ merged = merge(merged, envConfig);
16903
+ merged = merge(merged, flags ?? {});
16904
+ if (!merged.name) {
16905
+ merged.name = "__env__";
16906
+ }
16907
+ return parseConfig(merged);
16908
+ }
16909
+
16794
16910
  // src/sdk/tvp.ts
16795
16911
  var MSSQL_PARAM_LIMIT = 2100;
16796
16912
  function tvp(typeName, rows) {
@@ -19119,7 +19235,7 @@ async function executeChange(context, change, options = {}) {
19119
19235
  const [, lockErr] = await attempt(
19120
19236
  () => lockManager.acquire(context.db, context.configName, identity, {
19121
19237
  reason: `Change: ${change.name}`,
19122
- dialect: context.dialect
19238
+ dialect: context.dialect ?? "postgres"
19123
19239
  })
19124
19240
  );
19125
19241
  if (lockErr) {
@@ -19191,7 +19307,7 @@ async function revertChange(context, change, options = {}) {
19191
19307
  const [, lockErr] = await attempt(
19192
19308
  () => lockManager.acquire(context.db, context.configName, identity, {
19193
19309
  reason: `Revert: ${change.name}`,
19194
- dialect: context.dialect
19310
+ dialect: context.dialect ?? "postgres"
19195
19311
  })
19196
19312
  );
19197
19313
  if (lockErr) {
@@ -20266,8 +20382,12 @@ var ChangesNamespace = class {
20266
20382
  }
20267
20383
  #createChangeContext() {
20268
20384
  const state = getStateManager(this.#state.projectRoot);
20385
+ if (!this.#state.connection) {
20386
+ throw new Error("Not connected. Call connect() first.");
20387
+ }
20269
20388
  return {
20270
20389
  db: this.#kysely,
20390
+ dialect: this.#state.connection.dialect,
20271
20391
  configName: this.#state.config.name,
20272
20392
  identity: this.#state.identity,
20273
20393
  projectRoot: this.#state.projectRoot,
@@ -27874,6 +27994,11 @@ function toSettingsProvider(manager) {
27874
27994
  }
27875
27995
  async function createContext(options = {}) {
27876
27996
  const projectRoot = options.projectRoot ?? process.cwd();
27997
+ const envIdentity = loadIdentityFromEnv();
27998
+ if (envIdentity) {
27999
+ setKeyOverride(envIdentity.privateKey);
28000
+ setIdentityOverride(envIdentity.identity);
28001
+ }
27877
28002
  await initState(projectRoot);
27878
28003
  const state = getStateManager(projectRoot);
27879
28004
  const settingsManager = getSettingsManager(projectRoot);