hazo_env 0.2.0 → 0.4.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 (43) hide show
  1. package/CHANGE_LOG.md +47 -0
  2. package/README.md +83 -17
  3. package/SETUP_CHECKLIST.md +32 -0
  4. package/config/hazo_env_config.ini.sample +16 -0
  5. package/dist/cli.js +21 -7
  6. package/dist/doctor.d.ts.map +1 -1
  7. package/dist/doctor.js +168 -3
  8. package/dist/env.server.d.ts +7 -1
  9. package/dist/env.server.d.ts.map +1 -1
  10. package/dist/env.server.js +25 -2
  11. package/dist/index.client.d.ts +6 -2
  12. package/dist/index.client.d.ts.map +1 -1
  13. package/dist/index.client.js +15 -9
  14. package/dist/index.d.ts +5 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +5 -2
  17. package/dist/migrate/db.d.ts +3 -0
  18. package/dist/migrate/db.d.ts.map +1 -1
  19. package/dist/migrate/db.js +6 -1
  20. package/dist/migrate/db.postgrest.d.ts +4 -0
  21. package/dist/migrate/db.postgrest.d.ts.map +1 -0
  22. package/dist/migrate/db.postgrest.js +93 -0
  23. package/dist/migrate/files.d.ts.map +1 -1
  24. package/dist/migrate/files.js +2 -4
  25. package/dist/migrate/progress.d.ts +5 -0
  26. package/dist/migrate/progress.d.ts.map +1 -0
  27. package/dist/migrate/progress.js +24 -0
  28. package/dist/migrate/run.d.ts.map +1 -1
  29. package/dist/migrate/run.js +60 -25
  30. package/dist/migrate/snapshot.d.ts.map +1 -1
  31. package/dist/migrate/snapshot.js +3 -0
  32. package/dist/migrate/verify.d.ts +1 -0
  33. package/dist/migrate/verify.d.ts.map +1 -1
  34. package/dist/migrate/verify.js +120 -30
  35. package/dist/resolve/files.d.ts +6 -0
  36. package/dist/resolve/files.d.ts.map +1 -1
  37. package/dist/resolve/files.js +23 -0
  38. package/dist/resolve/migrate.d.ts +3 -0
  39. package/dist/resolve/migrate.d.ts.map +1 -0
  40. package/dist/resolve/migrate.js +29 -0
  41. package/dist/types/index.d.ts +13 -0
  42. package/dist/types/index.d.ts.map +1 -1
  43. package/package.json +9 -9
@@ -1,51 +1,141 @@
1
1
  // hazo_env/src/migrate/verify.ts — post-migration file verification
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
+ import { optional_import } from 'hazo_core';
4
5
  function resolveEnvFilesRoot(env, dataRoot) {
5
6
  return path.join(dataRoot, env, 'files');
6
7
  }
8
+ function walkDir(dir) {
9
+ if (!fs.existsSync(dir))
10
+ return [];
11
+ return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
12
+ const absPath = path.join(dir, entry.name);
13
+ if (entry.isDirectory())
14
+ return walkDir(absPath);
15
+ // Return relative to dir's parent so caller can strip filesRoot prefix
16
+ return [absPath];
17
+ });
18
+ }
19
+ function walkRelative(filesRoot) {
20
+ const abs = walkDir(filesRoot);
21
+ return abs.map((p) => p.slice(filesRoot.length + 1)); // strip filesRoot + sep
22
+ }
7
23
  export async function verifyFiles(env, dataRoot, opts = {}) {
8
- const { checkOrphans = true } = opts;
24
+ const { hash = 'sample', checkOrphans = true, adapter } = opts;
9
25
  const filesRoot = resolveEnvFilesRoot(env, dataRoot);
10
26
  const missing = [];
11
27
  const sizeMismatch = [];
12
28
  const hashMismatch = [];
13
29
  const orphans = [];
14
30
  let checked = 0;
15
- let sentinelOk = true;
16
- // Layer 1: check sentinel file (data root exists and is readable)
17
- if (!fs.existsSync(filesRoot)) {
18
- sentinelOk = false;
31
+ let hashed;
32
+ // Layer 1: sentinel — filesRoot must exist and be readable
33
+ const sentinelOk = fs.existsSync(filesRoot);
34
+ if (!sentinelOk) {
19
35
  return { ok: false, checked: 0, missing: [], sizeMismatch: [], hashMismatch: [], orphans: [], sentinelOk: false };
20
36
  }
21
- // Layer 2 & 3: walk all files
22
- function walkDir(dir, relBase) {
23
- if (!fs.existsSync(dir))
24
- return [];
25
- return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
26
- const relPath = path.join(relBase, entry.name);
27
- const absPath = path.join(dir, entry.name);
28
- if (entry.isDirectory())
29
- return walkDir(absPath, relPath);
30
- return [relPath];
31
- });
32
- }
33
- const diskFiles = walkDir(filesRoot, '');
34
- for (const relPath of diskFiles) {
37
+ // S3: Fallback detection — need both hazo_files module and an adapter
38
+ const hazoFiles = await optional_import('hazo_files');
39
+ if (!hazoFiles || !adapter) {
40
+ // Disk-only fallback
41
+ const diskFiles = walkRelative(filesRoot);
42
+ checked = diskFiles.length;
43
+ const skippedReason = 'no hazo_files tracking — size/hash/orphan skipped';
44
+ const ok = sentinelOk && missing.length === 0;
45
+ return { ok, checked, missing, sizeMismatch, hashMismatch, orphans, sentinelOk, skippedReason };
46
+ }
47
+ // Main path: adapter + hazo_files available
48
+ const connectMod = await optional_import('hazo_connect/server');
49
+ let rows = [];
50
+ let skippedReason;
51
+ try {
52
+ if (!connectMod)
53
+ throw new Error('hazo_connect not available');
54
+ const service = connectMod.createCrudService(adapter, 'hazo_files');
55
+ const all = await service.list();
56
+ rows = all.filter((r) => !r.storage_type || r.storage_type === 'local');
57
+ }
58
+ catch {
59
+ // Table not found or connect unavailable — disk-only fallback
60
+ const diskFiles = walkRelative(filesRoot);
61
+ checked = diskFiles.length;
62
+ skippedReason = 'hazo_files table not found — disk-only fallback';
63
+ const ok = sentinelOk && missing.length === 0;
64
+ return { ok, checked, missing, sizeMismatch, hashMismatch, orphans, sentinelOk, skippedReason };
65
+ }
66
+ // Normalize DB paths: strip leading slash if present
67
+ const normalizeDbPath = (p) => p.startsWith('/') ? p.slice(1) : p;
68
+ const dbPathSet = new Set(rows.map((r) => normalizeDbPath(r.file_path)));
69
+ // Track present rows for hash/size checks
70
+ const presentRows = [];
71
+ // L2 Existence
72
+ for (const row of rows) {
73
+ const relPath = normalizeDbPath(row.file_path);
35
74
  const absPath = path.join(filesRoot, relPath);
36
- try {
37
- fs.statSync(absPath); // existence + size (stat succeeds = file accessible)
38
- checked++;
75
+ if (!fs.existsSync(absPath)) {
76
+ missing.push(row.file_path);
77
+ }
78
+ else {
79
+ presentRows.push({ ...row, file_path: relPath });
39
80
  }
40
- catch {
41
- missing.push(relPath);
81
+ }
82
+ // L3 Size
83
+ for (const row of presentRows) {
84
+ const absPath = path.join(filesRoot, row.file_path);
85
+ const stat = fs.statSync(absPath);
86
+ if (row.file_size != null && stat.size !== row.file_size) {
87
+ sizeMismatch.push(row.file_path);
88
+ }
89
+ checked++;
90
+ }
91
+ // L4 Hash
92
+ if (hash !== 'none') {
93
+ let toHash;
94
+ if (hash === 'full') {
95
+ toHash = presentRows;
96
+ }
97
+ else {
98
+ // sample: 1% random (min 1) + top 10 by file_size DESC + top 10 by file_changed_at DESC
99
+ const n = Math.max(1, Math.floor(presentRows.length * 0.01));
100
+ const shuffled = [...presentRows].sort(() => Math.random() - 0.5).slice(0, n);
101
+ const bySize = [...presentRows]
102
+ .filter((r) => r.file_size != null)
103
+ .sort((a, b) => (b.file_size ?? 0) - (a.file_size ?? 0))
104
+ .slice(0, 10);
105
+ const byChanged = [...presentRows]
106
+ .filter((r) => r.file_changed_at != null)
107
+ .sort((a, b) => (b.file_changed_at ?? '') < (a.file_changed_at ?? '') ? -1 : 1)
108
+ .slice(0, 10);
109
+ // Deduplicate by file_path
110
+ const seen = new Set();
111
+ toHash = [];
112
+ for (const r of [...shuffled, ...bySize, ...byChanged]) {
113
+ if (!seen.has(r.file_path)) {
114
+ seen.add(r.file_path);
115
+ toHash.push(r);
116
+ }
117
+ }
118
+ }
119
+ hashed = 0;
120
+ for (const row of toHash) {
121
+ const absPath = path.join(filesRoot, row.file_path);
122
+ const buf = fs.readFileSync(absPath);
123
+ const computed = hazoFiles.computeFileHashSync(buf);
124
+ if (row.file_hash && computed !== row.file_hash) {
125
+ hashMismatch.push(row.file_path);
126
+ }
127
+ hashed++;
42
128
  }
43
129
  }
44
- // Layer 4: orphan check — files on disk with no corresponding DB tracking row
45
- // In Phase A, hazo_files integration is not wired; just verify directory is readable
46
- if (checkOrphans && !fs.existsSync(filesRoot)) {
47
- orphans.push(filesRoot);
130
+ // L5 Orphans
131
+ if (checkOrphans) {
132
+ const diskFiles = walkRelative(filesRoot);
133
+ for (const diskRel of diskFiles) {
134
+ if (!dbPathSet.has(diskRel)) {
135
+ orphans.push(diskRel);
136
+ }
137
+ }
48
138
  }
49
- const ok = missing.length === 0 && sizeMismatch.length === 0 && hashMismatch.length === 0;
50
- return { ok, checked, missing, sizeMismatch, hashMismatch, orphans, sentinelOk };
139
+ const ok = sentinelOk && missing.length === 0 && sizeMismatch.length === 0 && hashMismatch.length === 0;
140
+ return { ok, checked, missing, sizeMismatch, hashMismatch, orphans, sentinelOk, hashed, skippedReason };
51
141
  }
@@ -5,4 +5,10 @@ import type { FilesEnvConfig } from '../types/index.js';
5
5
  * Falls back to app_data if not configured.
6
6
  */
7
7
  export declare function resolveFilesConfig(appConfigPkg?: string): FilesEnvConfig;
8
+ /**
9
+ * Resolve the file storage root path for a specific environment.
10
+ * Checks [files.<env>] root in hazo_env_config.ini first;
11
+ * falls back to <dataRoot>/<env>/files convention if absent.
12
+ */
13
+ export declare function resolveFilesRoot(env: string): string;
8
14
  //# sourceMappingURL=files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/resolve/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAgBxD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,cAAc,CAoCxE"}
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../src/resolve/files.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAgBxD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,cAAc,CAoCxE;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAiBpD"}
@@ -51,3 +51,26 @@ export function resolveFilesConfig(appConfigPkg) {
51
51
  }
52
52
  return { provider: 'local', local };
53
53
  }
54
+ /**
55
+ * Resolve the file storage root path for a specific environment.
56
+ * Checks [files.<env>] root in hazo_env_config.ini first;
57
+ * falls back to <dataRoot>/<env>/files convention if absent.
58
+ */
59
+ export function resolveFilesRoot(env) {
60
+ const envConfig = tryLoadConfig('hazo_env');
61
+ // Check explicit per-env root: [files.<env>] root = /some/path
62
+ const filesSection = envConfig?.getSection(`files.${env}`);
63
+ const explicitRoot = filesSection?.['root'];
64
+ if (explicitRoot) {
65
+ return path.isAbsolute(explicitRoot)
66
+ ? explicitRoot
67
+ : path.resolve(process.cwd(), explicitRoot);
68
+ }
69
+ // Fall back to <dataRoot>/<env>/files convention
70
+ const dataSection = envConfig?.getSection('data');
71
+ const dataRoot = dataSection?.['root'] ?? DEFAULT_DATA_ROOT;
72
+ const resolvedDataRoot = path.isAbsolute(dataRoot)
73
+ ? dataRoot
74
+ : path.resolve(process.cwd(), dataRoot);
75
+ return path.join(resolvedDataRoot, env, 'files');
76
+ }
@@ -0,0 +1,3 @@
1
+ import type { MigrateConfig } from '../types/index.js';
2
+ export declare function resolveMigrateConfig(): MigrateConfig;
3
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/resolve/migrate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,wBAAgB,oBAAoB,IAAI,aAAa,CA2BpD"}
@@ -0,0 +1,29 @@
1
+ // hazo_env/src/resolve/migrate.ts — read [migrate] section from hazo_env_config.ini
2
+ import path from 'node:path';
3
+ import { HazoConfig } from 'hazo_config/server';
4
+ export function resolveMigrateConfig() {
5
+ try {
6
+ const filePath = path.resolve(process.cwd(), 'config', 'hazo_env_config.ini');
7
+ const config = new HazoConfig({ filePath });
8
+ const section = config.getSection('migrate');
9
+ if (!section)
10
+ return {};
11
+ const tables = section['tables']
12
+ ? section['tables'].split(',').map((t) => t.trim()).filter(Boolean)
13
+ : undefined;
14
+ const preserve = section['preserve']
15
+ ? section['preserve'].split(',').map((t) => t.trim()).filter(Boolean)
16
+ : undefined;
17
+ // Parse per-table pk overrides: keys like "pk.some_table = custom_col"
18
+ const pkOverrides = {};
19
+ for (const [k, v] of Object.entries(section)) {
20
+ if (k.startsWith('pk.') && typeof v === 'string') {
21
+ pkOverrides[k.slice(3)] = v.trim();
22
+ }
23
+ }
24
+ return { tables, preserve, ...(Object.keys(pkOverrides).length ? { pkOverrides } : {}) };
25
+ }
26
+ catch {
27
+ return {};
28
+ }
29
+ }
@@ -4,6 +4,8 @@ export type HazoEnv = 'dev' | 'test' | 'staging' | 'prod' | string;
4
4
  export type HazoEnvRole = 'development' | 'test' | 'staging' | 'production';
5
5
  /** The set of valid environment names for this app, from [env] pattern in INI */
6
6
  export type EnvPattern = string[];
7
+ /** Mapping of env name → broad role, for config-driven role resolution */
8
+ export type EnvRoleMap = Record<string, HazoEnvRole>;
7
9
  /** Hint about where an environment runs */
8
10
  export type HostHint = 'local' | 'remote' | 'unknown';
9
11
  /** DB configuration for a single environment (from [db.<env>] in INI) */
@@ -34,6 +36,7 @@ export interface EnvDescription {
34
36
  app: string;
35
37
  dataRoot: string;
36
38
  hostHint: HostHint;
39
+ roles?: EnvRoleMap;
37
40
  }
38
41
  /** Options for resolveConnectConfig */
39
42
  export interface ResolveConnectOptions {
@@ -62,6 +65,8 @@ export interface MigrationRequest {
62
65
  allowProdTarget?: boolean;
63
66
  confirmToken?: string;
64
67
  onProgress?: (p: MigrationProgress) => void;
68
+ jobId?: string;
69
+ progressDir?: string;
65
70
  }
66
71
  export interface MigrationResult {
67
72
  ok: boolean;
@@ -88,6 +93,14 @@ export interface VerifyReport {
88
93
  hashMismatch: string[];
89
94
  orphans: string[];
90
95
  sentinelOk: boolean;
96
+ hashed?: number;
97
+ skippedReason?: string;
98
+ }
99
+ /** Parsed [migrate] section from hazo_env_config.ini */
100
+ export interface MigrateConfig {
101
+ tables?: string[];
102
+ preserve?: string[];
103
+ pkOverrides?: Record<string, string>;
91
104
  }
92
105
  export type MaskTransform = (value: unknown, key: string, maskKey: string) => unknown;
93
106
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_env",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "Canonical environment resolver — typed env names, per-env DB/file/secret config, doctor and CLI for hazo apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,10 +38,10 @@
38
38
  "picocolors": "^1.1.1"
39
39
  },
40
40
  "peerDependencies": {
41
- "hazo_core": "^1.1.0",
42
- "hazo_config": "^2.1.10",
43
- "hazo_connect": "^3.4.1",
44
- "hazo_files": "^3.0.0",
41
+ "hazo_core": "^1.2.0",
42
+ "hazo_config": "^2.4.1",
43
+ "hazo_connect": "^3.9.0",
44
+ "hazo_files": "^3.1.1",
45
45
  "hazo_secure": "^1.2.0",
46
46
  "hazo_audit": "^2.1.0",
47
47
  "hazo_pdf": "^2.0.0",
@@ -84,10 +84,10 @@
84
84
  "@types/node": "^22.10.0",
85
85
  "@types/react": "^19.0.0",
86
86
  "@types/react-dom": "^19.0.0",
87
- "hazo_core": "^1.1.0",
88
- "hazo_config": "^2.1.10",
89
- "hazo_connect": "^3.4.1",
90
- "hazo_files": "^3.0.0",
87
+ "hazo_core": "^1.2.1",
88
+ "hazo_config": "^2.4.1",
89
+ "hazo_connect": "^3.9.0",
90
+ "hazo_files": "^3.1.1",
91
91
  "next": "^16.0.10",
92
92
  "react": "^19.0.0",
93
93
  "react-dom": "^19.0.0",