@noormdev/sdk 1.0.0-alpha.32 → 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 +319 -194
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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,
|
|
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
|
-
|
|
15037
|
-
"
|
|
15038
|
-
|
|
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
|
-
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
|
|
15046
|
-
|
|
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,
|
|
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);
|