@askdb/core 1.0.0-beta.45 → 1.0.0-beta.46

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 (85) hide show
  1. package/README.md +15 -13
  2. package/dist/ask.d.ts +15 -7
  3. package/dist/ask.d.ts.map +1 -1
  4. package/dist/ask.js +29 -5
  5. package/dist/ask.js.map +1 -1
  6. package/dist/enrichment/prompt.d.ts.map +1 -1
  7. package/dist/enrichment/prompt.js +6 -4
  8. package/dist/enrichment/prompt.js.map +1 -1
  9. package/dist/enrichment/types.d.ts +13 -12
  10. package/dist/enrichment/types.d.ts.map +1 -1
  11. package/dist/errors.d.ts +30 -6
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js.map +1 -1
  14. package/dist/index.d.ts +3 -3
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +3 -3
  17. package/dist/index.js.map +1 -1
  18. package/dist/logging/askdb-logger.d.ts +2 -0
  19. package/dist/logging/askdb-logger.d.ts.map +1 -1
  20. package/dist/logging/create-askdb-logger.d.ts.map +1 -1
  21. package/dist/logging/create-askdb-logger.js +3 -0
  22. package/dist/logging/create-askdb-logger.js.map +1 -1
  23. package/dist/logging/log-events.d.ts +8 -0
  24. package/dist/logging/log-events.d.ts.map +1 -1
  25. package/dist/logging/log-events.js +8 -0
  26. package/dist/logging/log-events.js.map +1 -1
  27. package/dist/schema/normalize.d.ts +0 -2
  28. package/dist/schema/normalize.d.ts.map +1 -1
  29. package/dist/schema/normalize.js +0 -4
  30. package/dist/schema/normalize.js.map +1 -1
  31. package/dist/schema/v2/index.d.ts +3 -2
  32. package/dist/schema/v2/index.d.ts.map +1 -1
  33. package/dist/schema/v2/index.js +3 -2
  34. package/dist/schema/v2/index.js.map +1 -1
  35. package/dist/schema/v2/loader.d.ts +24 -6
  36. package/dist/schema/v2/loader.d.ts.map +1 -1
  37. package/dist/schema/v2/loader.js +164 -100
  38. package/dist/schema/v2/loader.js.map +1 -1
  39. package/dist/schema/v2/save-file.d.ts +56 -0
  40. package/dist/schema/v2/save-file.d.ts.map +1 -0
  41. package/dist/schema/v2/save-file.js +138 -0
  42. package/dist/schema/v2/save-file.js.map +1 -0
  43. package/dist/schema/v2/tenant-policy-loader.d.ts +1 -10
  44. package/dist/schema/v2/tenant-policy-loader.d.ts.map +1 -1
  45. package/dist/schema/v2/tenant-policy-loader.js +65 -51
  46. package/dist/schema/v2/tenant-policy-loader.js.map +1 -1
  47. package/dist/schema/v2/tenant-policy.d.ts +5 -0
  48. package/dist/schema/v2/tenant-policy.d.ts.map +1 -1
  49. package/dist/schema/v2/tenant-policy.js +26 -0
  50. package/dist/schema/v2/tenant-policy.js.map +1 -1
  51. package/dist/sql/bind.d.ts +11 -4
  52. package/dist/sql/bind.d.ts.map +1 -1
  53. package/dist/sql/bind.js +5 -8
  54. package/dist/sql/bind.js.map +1 -1
  55. package/dist/sql/dialect-spec.d.ts +1 -0
  56. package/dist/sql/dialect-spec.d.ts.map +1 -1
  57. package/dist/sql/dialect-spec.js +2 -1
  58. package/dist/sql/dialect-spec.js.map +1 -1
  59. package/dist/sql/guardrail-decide.d.ts +4 -2
  60. package/dist/sql/guardrail-decide.d.ts.map +1 -1
  61. package/dist/sql/guardrail-decide.js.map +1 -1
  62. package/dist/sql/prompt-identifiers.d.ts +9 -0
  63. package/dist/sql/prompt-identifiers.d.ts.map +1 -1
  64. package/dist/sql/prompt-identifiers.js +22 -3
  65. package/dist/sql/prompt-identifiers.js.map +1 -1
  66. package/dist/sql/prompt.d.ts.map +1 -1
  67. package/dist/sql/prompt.js +3 -1
  68. package/dist/sql/prompt.js.map +1 -1
  69. package/dist/sql/rebind.d.ts +34 -7
  70. package/dist/sql/rebind.d.ts.map +1 -1
  71. package/dist/sql/rebind.js +50 -10
  72. package/dist/sql/rebind.js.map +1 -1
  73. package/dist/sql/tenant-placeholders.d.ts +26 -11
  74. package/dist/sql/tenant-placeholders.d.ts.map +1 -1
  75. package/dist/sql/tenant-placeholders.js +50 -25
  76. package/dist/sql/tenant-placeholders.js.map +1 -1
  77. package/dist/sql/tenant-policy-warnings.d.ts +8 -0
  78. package/dist/sql/tenant-policy-warnings.d.ts.map +1 -0
  79. package/dist/sql/tenant-policy-warnings.js +21 -0
  80. package/dist/sql/tenant-policy-warnings.js.map +1 -0
  81. package/dist/sql/validate.d.ts +15 -3
  82. package/dist/sql/validate.d.ts.map +1 -1
  83. package/dist/sql/validate.js +107 -8
  84. package/dist/sql/validate.js.map +1 -1
  85. package/package.json +2 -2
@@ -7,6 +7,8 @@
7
7
  export type AskDbLogger = {
8
8
  info(context: Record<string, unknown>, message: string): void;
9
9
  error(context: Record<string, unknown>, message: string): void;
10
+ /** Optional — a problem the host should fix that doesn't stop the run. Without it, `info` is used. */
11
+ warn?(context: Record<string, unknown>, message: string): void;
10
12
  /** Optional — used for prompt redaction notices without leaking sensitive identifiers. */
11
13
  debug?(context: Record<string, unknown>, message: string): void;
12
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"askdb-logger.d.ts","sourceRoot":"","sources":["../../src/logging/askdb-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,0FAA0F;IAC1F,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjE,CAAC"}
1
+ {"version":3,"file":"askdb-logger.d.ts","sourceRoot":"","sources":["../../src/logging/askdb-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9D,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,sGAAsG;IACtG,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/D,0FAA0F;IAC1F,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"create-askdb-logger.d.ts","sourceRoot":"","sources":["../../src/logging/create-askdb-logger.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,6CAA6C;AAC7C,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC;AAEjD,MAAM,MAAM,wBAAwB,GAAG;IACrC,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAgBF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CA8BhF"}
1
+ {"version":3,"file":"create-askdb-logger.d.ts","sourceRoot":"","sources":["../../src/logging/create-askdb-logger.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,6CAA6C;AAC7C,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC;AAEjD,MAAM,MAAM,wBAAwB,GAAG;IACrC,mDAAmD;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAmBF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,WAAW,CA8BhF"}
@@ -9,6 +9,9 @@ function wrapPinoAsAskDbLogger(pinoLogger) {
9
9
  error(context, message) {
10
10
  pinoLogger.error(context, message);
11
11
  },
12
+ warn(context, message) {
13
+ pinoLogger.warn(context, message);
14
+ },
12
15
  debug(context, message) {
13
16
  pinoLogger.debug(context, message);
14
17
  },
@@ -1 +1 @@
1
- {"version":3,"file":"create-askdb-logger.js","sourceRoot":"","sources":["../../src/logging/create-askdb-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAuBxB,SAAS,qBAAqB,CAAC,UAAsB;IACnD,OAAO;QACL,IAAI,CAAC,OAAgC,EAAE,OAAe;YACpD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,OAAgC,EAAE,OAAe;YACrD,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QACD,KAAK,CAAC,OAAgC,EAAE,OAAe;YACrD,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACvD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC;IAC1C,MAAM,YAAY,GAA6B,EAAE,CAAC;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,IAAI,GACR,YAAY,CAAC,MAAM,KAAK,CAAC;QACvB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE;QAClB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnE,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACzF,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC"}
1
+ {"version":3,"file":"create-askdb-logger.js","sourceRoot":"","sources":["../../src/logging/create-askdb-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAuBxB,SAAS,qBAAqB,CAAC,UAAsB;IACnD,OAAO;QACL,IAAI,CAAC,OAAgC,EAAE,OAAe;YACpD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,OAAgC,EAAE,OAAe;YACrD,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,CAAC,OAAgC,EAAE,OAAe;YACpD,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,OAAgC,EAAE,OAAe;YACrD,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAiC;IACjE,MAAM,KAAK,GAAkB,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAC;IACvD,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,OAAO,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC;IAC1C,MAAM,YAAY,GAA6B,EAAE,CAAC;IAClD,IAAI,QAAQ,EAAE,CAAC;QACb,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACtB,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,qBAAqB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,IAAI,GACR,YAAY,CAAC,MAAM,KAAK,CAAC;QACvB,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE;QAClB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAEnE,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IACzF,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC"}
@@ -31,6 +31,14 @@ export declare const AskDbLogEvent: {
31
31
  readonly TenantScopeValidated: "askdb.tenant.scope_validated";
32
32
  /** Tenant scope validation failed. Includes `reason`. */
33
33
  readonly TenantScopeRejected: "askdb.tenant.scope_rejected";
34
+ /**
35
+ * The loaded tenant policy doesn't fully match `schema.json` (ADR 0023). Logged at
36
+ * `warn` level, once per loaded schema, by the first `ask()` that receives it.
37
+ * Includes `enforcement`, `warningCount` and `warnings`: schema artifact metadata only
38
+ * (table and column IDs, and a polymorphic `mapping` key from the policy), never query
39
+ * text or row values.
40
+ */
41
+ readonly TenantPolicyWarnings: "askdb.tenant.policy_warnings";
34
42
  /**
35
43
  * Generated (or replayed) SQL was found to reference identifiers marked
36
44
  * `sensitive` in the schema artifact. Emitted by `ask()` in both `warn` and
@@ -1 +1 @@
1
- {"version":3,"file":"log-events.d.ts","sourceRoot":"","sources":["../../src/logging/log-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;IAIxB,kFAAkF;;;;IAIlF,yFAAyF;;IAEzF,4GAA4G;;IAE5G,yEAAyE;;IAEzE;;;OAGG;;IAEH;;;;OAIG;;IAEH,mFAAmF;;IAEnF,yDAAyD;;IAEzD;;;;;OAKG;;IAEH,yCAAyC;;IAEzC,iFAAiF;;IAEjF;;;;OAIG;;CAEK,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC"}
1
+ {"version":3,"file":"log-events.d.ts","sourceRoot":"","sources":["../../src/logging/log-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;IAIxB,kFAAkF;;;;IAIlF,yFAAyF;;IAEzF,4GAA4G;;IAE5G,yEAAyE;;IAEzE;;;OAGG;;IAEH;;;;OAIG;;IAEH,mFAAmF;;IAEnF,yDAAyD;;IAEzD;;;;;;OAMG;;IAEH;;;;;OAKG;;IAEH,yCAAyC;;IAEzC,iFAAiF;;IAEjF;;;;OAIG;;CAEK,CAAC;AAEX,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC"}
@@ -31,6 +31,14 @@ export const AskDbLogEvent = {
31
31
  TenantScopeValidated: "askdb.tenant.scope_validated",
32
32
  /** Tenant scope validation failed. Includes `reason`. */
33
33
  TenantScopeRejected: "askdb.tenant.scope_rejected",
34
+ /**
35
+ * The loaded tenant policy doesn't fully match `schema.json` (ADR 0023). Logged at
36
+ * `warn` level, once per loaded schema, by the first `ask()` that receives it.
37
+ * Includes `enforcement`, `warningCount` and `warnings`: schema artifact metadata only
38
+ * (table and column IDs, and a polymorphic `mapping` key from the policy), never query
39
+ * text or row values.
40
+ */
41
+ TenantPolicyWarnings: "askdb.tenant.policy_warnings",
34
42
  /**
35
43
  * Generated (or replayed) SQL was found to reference identifiers marked
36
44
  * `sensitive` in the schema artifact. Emitted by `ask()` in both `warn` and
@@ -1 +1 @@
1
- {"version":3,"file":"log-events.js","sourceRoot":"","sources":["../../src/logging/log-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,iBAAiB;IAC3B,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,kFAAkF;IAClF,YAAY,EAAE,qBAAqB;IACnC,qBAAqB,EAAE,+BAA+B;IACtD,wBAAwB,EAAE,kCAAkC;IAC5D,yFAAyF;IACzF,uBAAuB,EAAE,iCAAiC;IAC1D,4GAA4G;IAC5G,gCAAgC,EAAE,2CAA2C;IAC7E,yEAAyE;IACzE,cAAc,EAAE,uBAAuB;IACvC;;;OAGG;IACH,qBAAqB,EAAE,+BAA+B;IACtD;;;;OAIG;IACH,wBAAwB,EAAE,kCAAkC;IAC5D,mFAAmF;IACnF,oBAAoB,EAAE,8BAA8B;IACpD,yDAAyD;IACzD,mBAAmB,EAAE,6BAA6B;IAClD;;;;;OAKG;IACH,2BAA2B,EAAE,sCAAsC;IACnE,yCAAyC;IACzC,qBAAqB,EAAE,+BAA+B;IACtD,iFAAiF;IACjF,qBAAqB,EAAE,+BAA+B;IACtD;;;;OAIG;IACH,qBAAqB,EAAE,8BAA8B;CAC7C,CAAC"}
1
+ {"version":3,"file":"log-events.js","sourceRoot":"","sources":["../../src/logging/log-events.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,QAAQ,EAAE,iBAAiB;IAC3B,MAAM,EAAE,eAAe;IACvB,QAAQ,EAAE,iBAAiB;IAC3B,kFAAkF;IAClF,YAAY,EAAE,qBAAqB;IACnC,qBAAqB,EAAE,+BAA+B;IACtD,wBAAwB,EAAE,kCAAkC;IAC5D,yFAAyF;IACzF,uBAAuB,EAAE,iCAAiC;IAC1D,4GAA4G;IAC5G,gCAAgC,EAAE,2CAA2C;IAC7E,yEAAyE;IACzE,cAAc,EAAE,uBAAuB;IACvC;;;OAGG;IACH,qBAAqB,EAAE,+BAA+B;IACtD;;;;OAIG;IACH,wBAAwB,EAAE,kCAAkC;IAC5D,mFAAmF;IACnF,oBAAoB,EAAE,8BAA8B;IACpD,yDAAyD;IACzD,mBAAmB,EAAE,6BAA6B;IAClD;;;;;;OAMG;IACH,oBAAoB,EAAE,8BAA8B;IACpD;;;;;OAKG;IACH,2BAA2B,EAAE,sCAAsC;IACnE,yCAAyC;IACzC,qBAAqB,EAAE,+BAA+B;IACtD,iFAAiF;IACjF,qBAAqB,EAAE,+BAA+B;IACtD;;;;OAIG;IACH,qBAAqB,EAAE,8BAA8B;CAC7C,CAAC"}
@@ -44,6 +44,4 @@ export declare function formatSchemaForNlToSql(schema: NormalizedSchema, options
44
44
  ddl: string;
45
45
  stats: NlToSqlSchemaFormatStats;
46
46
  };
47
- /** Same DDL as {@link formatSchemaForNlToSql} with default options (sensitive names included, tagged). */
48
- export declare function formatSchemaForPrompt(schema: NormalizedSchema, options?: FormatNlToSqlOptions): string;
49
47
  //# sourceMappingURL=normalize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/schema/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB,CAc9E;AAED,kDAAkD;AAClD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5C,CAAC;AAEF,+HAA+H;AAC/H,MAAM,MAAM,wBAAwB,GAAG;IACrC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,0EAA0E;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,uBAAuB,EAAE,MAAM,CAAC;IAChC,4GAA4G;IAC5G,0BAA0B,EAAE,MAAM,CAAC;IACnC,yEAAyE;IACzE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAmBF;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,oBAAyB,GACjC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,wBAAwB,CAAC;CACjC,CAwDA;AAED,0GAA0G;AAC1G,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAEtG"}
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/schema/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,gBAAgB,CAc9E;AAED,kDAAkD;AAClD,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;OAGG;IACH,kCAAkC,CAAC,EAAE,OAAO,CAAC;IAC7C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5C,CAAC;AAEF,+HAA+H;AAC/H,MAAM,MAAM,wBAAwB,GAAG;IACrC,kCAAkC,EAAE,OAAO,CAAC;IAC5C,0EAA0E;IAC1E,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qEAAqE;IACrE,uBAAuB,EAAE,MAAM,CAAC;IAChC,4GAA4G;IAC5G,0BAA0B,EAAE,MAAM,CAAC;IACnC,yEAAyE;IACzE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAmBF;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,GAAE,oBAAyB,GACjC;IACD,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,wBAAwB,CAAC;CACjC,CAwDA"}
@@ -84,8 +84,4 @@ export function formatSchemaForNlToSql(schema, options = {}) {
84
84
  },
85
85
  };
86
86
  }
87
- /** Same DDL as {@link formatSchemaForNlToSql} with default options (sensitive names included, tagged). */
88
- export function formatSchemaForPrompt(schema, options) {
89
- return formatSchemaForNlToSql(schema, options).ddl;
90
- }
91
87
  //# sourceMappingURL=normalize.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/schema/normalize.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/schema/normalize.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
- export { loadSchema, loadSchemaFromJson } from "./loader.js";
1
+ export { loadSchema, loadSchemaFromJson, readSchemaDirectory } from "./loader.js";
2
2
  export type { BundledSchemaV2 } from "./loader.js";
3
3
  export { parseTableMarkdown, parseConceptsMarkdown } from "./parser.js";
4
4
  export { writeTableMarkdown, writeConceptsMarkdown, writeTenantPolicyMarkdown } from "./writer.js";
5
+ export { saveSchemaFile } from "./save-file.js";
5
6
  export { formatSchemaV2ForNlToSql } from "./format.js";
6
7
  export { v2SchemaJsonSchema, v2TableSchema, v2ColumnSchema } from "./physical.js";
7
8
  export type { V2SchemaJson, V2Table, V2Column } from "./physical.js";
@@ -9,7 +10,7 @@ export { v2TableFrontmatterSchema, v2ColumnFrontmatterSchema, v2ConceptsFrontmat
9
10
  export type { V2TableFrontmatter, V2ColumnFrontmatter, V2ConceptsFrontmatter, V2Concept, ParsedTableMarkdown, ParsedConceptsMarkdown, RecognizedH2Section, } from "./describable.js";
10
11
  export type { NormalizedSchemaV2, NormalizedV2Table, NormalizedV2Column, SchemaV2Warning, } from "./normalized.js";
11
12
  export { parseTenantPolicyMarkdown, normalizeTenantPolicy } from "./tenant-policy-loader.js";
12
- export { tenantPolicyFrontmatterSchema, tenantRootSchema, hierarchyEdgeSchema, scopedTableSchema, polymorphicTableSchema, enforcementModeSchema, tenantScopeSchema, tenantAccessSchema, TENANT_POLICY_H2_SECTIONS, } from "./tenant-policy.js";
13
+ export { tenantPolicyFrontmatterSchema, tenantRootSchema, hierarchyEdgeSchema, scopedTableSchema, polymorphicTableSchema, enforcementModeSchema, formatTenantPolicyWarning, tenantScopeSchema, tenantAccessSchema, TENANT_POLICY_H2_SECTIONS, } from "./tenant-policy.js";
13
14
  export type { TenantPolicyFrontmatter, TenantRoot, HierarchyEdge, ScopedTable, ScopeThrough, PolymorphicTable, EnforcementMode, TenantScope, TenantAccess, TenantAccessIds, TenantAccessSubtree, TenantAccessMultiRoot, TenantAccessGlobal, TenantScopeContext, ParsedTenantPolicyMarkdown, NormalizedTenantPolicy, TenantPolicyWarning, TableCoverageEntry, TableTenantClassification, TenantPolicyH2Section, } from "./tenant-policy.js";
14
15
  export { createMentionMatcher, findMentionedNames, sensitiveMentionNames, type MentionMatcher, type MentionName, } from "./mentions.js";
15
16
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/schema/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7D,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,EACf,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,SAAS,EACT,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,UAAU,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/schema/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,EACf,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,SAAS,EACT,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,uBAAuB,EACvB,UAAU,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,GACtB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,eAAe,CAAC"}
@@ -1,10 +1,11 @@
1
- export { loadSchema, loadSchemaFromJson } from "./loader.js";
1
+ export { loadSchema, loadSchemaFromJson, readSchemaDirectory } from "./loader.js";
2
2
  export { parseTableMarkdown, parseConceptsMarkdown } from "./parser.js";
3
3
  export { writeTableMarkdown, writeConceptsMarkdown, writeTenantPolicyMarkdown } from "./writer.js";
4
+ export { saveSchemaFile } from "./save-file.js";
4
5
  export { formatSchemaV2ForNlToSql } from "./format.js";
5
6
  export { v2SchemaJsonSchema, v2TableSchema, v2ColumnSchema } from "./physical.js";
6
7
  export { v2TableFrontmatterSchema, v2ColumnFrontmatterSchema, v2ConceptsFrontmatterSchema, v2ConceptSchema, RECOGNIZED_H2_SECTIONS, } from "./describable.js";
7
8
  export { parseTenantPolicyMarkdown, normalizeTenantPolicy } from "./tenant-policy-loader.js";
8
- export { tenantPolicyFrontmatterSchema, tenantRootSchema, hierarchyEdgeSchema, scopedTableSchema, polymorphicTableSchema, enforcementModeSchema, tenantScopeSchema, tenantAccessSchema, TENANT_POLICY_H2_SECTIONS, } from "./tenant-policy.js";
9
+ export { tenantPolicyFrontmatterSchema, tenantRootSchema, hierarchyEdgeSchema, scopedTableSchema, polymorphicTableSchema, enforcementModeSchema, formatTenantPolicyWarning, tenantScopeSchema, tenantAccessSchema, TENANT_POLICY_H2_SECTIONS, } from "./tenant-policy.js";
9
10
  export { createMentionMatcher, findMentionedNames, sensitiveMentionNames, } from "./mentions.js";
10
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/schema/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,EACf,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAgB1B,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAwB5B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,GAGtB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/schema/v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElF,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAElF,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,EACf,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAgB1B,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,oBAAoB,CAAC;AAwB5B,OAAO,EACL,oBAAoB,EACpB,kBAAkB,EAClB,qBAAqB,GAGtB,MAAM,eAAe,CAAC"}
@@ -40,13 +40,31 @@ export declare function loadSchemaFromJson(raw: string): NormalizedSchemaV2;
40
40
  * sibling `tables/*.md`, `concepts.md`, and `tenant-policy.md`
41
41
  *
42
42
  * Any other JSON file is treated as a standalone physical layer, unless its
43
- * directory also holds `tenant-policy.md`, `tables/` or `concepts.md`: loading it
44
- * alone would ignore them, so that throws `SchemaParseError`. To load only the
45
- * physical layer of such a file, pass its content to `loadSchemaFromJson()`.
43
+ * directory also holds `tenant-policy.md`, `tables/` or `concepts.md`, in any case:
44
+ * loading it alone would ignore them, so that throws `SchemaParseError`. To load only
45
+ * the physical layer of such a file, pass its content to `loadSchemaFromJson()`.
46
46
  *
47
- * Optional sibling files may be absent, but a present file that cannot be read
48
- * or parsed (e.g. malformed YAML front-matter in `tenant-policy.md`) throws
49
- * `SchemaParseError` — a broken tenant policy never silently disables tenancy.
47
+ * A directory is read by {@link readSchemaDirectory}, so a file name the loader looks
48
+ * up must be spelled exactly (`Tenant-Policy.md` throws on every OS). Optional sibling
49
+ * files may be absent, but a present file that cannot be read or parsed (e.g.
50
+ * malformed YAML front-matter in `tenant-policy.md`) throws `SchemaParseError` — a
51
+ * broken tenant policy never silently disables tenancy.
50
52
  */
51
53
  export declare function loadSchema(path: string): NormalizedSchemaV2;
54
+ /**
55
+ * Read a Schema v2 directory into its bundle form, the single file `askdb bundle`
56
+ * writes. Loading the result with `loadSchemaFromJson()` gives the same schema as
57
+ * `loadSchema(dir)`, which reads the directory through this function too.
58
+ *
59
+ * Every name it looks up must be spelled exactly: `schema.json`, `tenant-policy.md`,
60
+ * `concepts.md`, `tables/`, and the `.md` extension in `tables/`. A file that matches
61
+ * one only when case is ignored (`Tenant-Policy.md`, `tables/orders.MD`) throws
62
+ * `SchemaParseError` on every OS. Where file names are case-sensitive (Linux) it would
63
+ * otherwise be skipped, and a skipped `tenant-policy.md` turns tenant enforcement off.
64
+ *
65
+ * An optional file counts as absent only when the directory doesn't list it. A listed
66
+ * file that can't be read throws `SchemaParseError`, so does a `schema.json` that is
67
+ * missing or invalid. The file contents are returned unparsed, except `schema.json`.
68
+ */
69
+ export declare function readSchemaDirectory(dir: string): BundledSchemaV2;
52
70
  //# sourceMappingURL=loader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/schema/v2/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,iBAAiB,CAAC;AAezB;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,IAAI,CAAC;IACd,qBAAqB;IACrB,QAAQ,EAAE,YAAY,CAAC;IACvB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAYlE;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAqC3D"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/schema/v2/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,KAAK,EACV,kBAAkB,EAInB,MAAM,iBAAiB,CAAC;AAezB;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,IAAI,CAAC;IACd,qBAAqB;IACrB,QAAQ,EAAE,YAAY,CAAC;IACvB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,CAYlE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAqC3D;AAmCD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAEhE"}
@@ -35,13 +35,15 @@ export function loadSchemaFromJson(raw) {
35
35
  * sibling `tables/*.md`, `concepts.md`, and `tenant-policy.md`
36
36
  *
37
37
  * Any other JSON file is treated as a standalone physical layer, unless its
38
- * directory also holds `tenant-policy.md`, `tables/` or `concepts.md`: loading it
39
- * alone would ignore them, so that throws `SchemaParseError`. To load only the
40
- * physical layer of such a file, pass its content to `loadSchemaFromJson()`.
38
+ * directory also holds `tenant-policy.md`, `tables/` or `concepts.md`, in any case:
39
+ * loading it alone would ignore them, so that throws `SchemaParseError`. To load only
40
+ * the physical layer of such a file, pass its content to `loadSchemaFromJson()`.
41
41
  *
42
- * Optional sibling files may be absent, but a present file that cannot be read
43
- * or parsed (e.g. malformed YAML front-matter in `tenant-policy.md`) throws
44
- * `SchemaParseError` — a broken tenant policy never silently disables tenancy.
42
+ * A directory is read by {@link readSchemaDirectory}, so a file name the loader looks
43
+ * up must be spelled exactly (`Tenant-Policy.md` throws on every OS). Optional sibling
44
+ * files may be absent, but a present file that cannot be read or parsed (e.g.
45
+ * malformed YAML front-matter in `tenant-policy.md`) throws `SchemaParseError` — a
46
+ * broken tenant policy never silently disables tenancy.
45
47
  */
46
48
  export function loadSchema(path) {
47
49
  const resolved = resolve(path);
@@ -81,7 +83,7 @@ export function loadSchema(path) {
81
83
  * Every optional file the directory loader reads beside `schema.json`, by the exact
82
84
  * name it reads, keyed by the `BundledSchemaV2` field that carries it. `satisfies`
83
85
  * stops a new bundle field from compiling until it is named here, so the directory
84
- * loader, the bundle loader and `assertNotInSchemaDirectory` share one list.
86
+ * read, the bundle loader and `assertNotInSchemaDirectory` share one list.
85
87
  */
86
88
  const SCHEMA_DIRECTORY_FILES = {
87
89
  tenantPolicy: "tenant-policy.md",
@@ -92,11 +94,14 @@ const SCHEMA_DIRECTORY_FILES = {
92
94
  * A standalone JSON file must not sit beside schema-directory files. Loading it
93
95
  * alone would ignore them, so `cp schema.json prod-schema.json` would silently drop
94
96
  * the tenant policy (and with it `ask()`'s tenant scope) and every `tables/*.md`
95
- * `sensitive: true`. Fail closed instead and say how to load it.
97
+ * `sensitive: true`. Fail closed instead and say how to load it. A sibling counts in
98
+ * any case: a wrong-case `Tenant-Policy.md` is still a schema file the load would ignore.
96
99
  */
97
100
  function assertNotInSchemaDirectory(filePath) {
98
- const dir = dirname(filePath);
99
- const present = Object.values(SCHEMA_DIRECTORY_FILES).filter((name) => pathExists(join(dir, name)));
101
+ const siblingKeys = new Set(Object.values(SCHEMA_DIRECTORY_FILES).map(caseKey));
102
+ const present = readRequiredDir(dirname(filePath))
103
+ .filter((entry) => siblingKeys.has(caseKey(entry)))
104
+ .sort();
100
105
  if (present.length === 0)
101
106
  return;
102
107
  throw new SchemaParseError(`Refusing to load ${filePath} as a standalone physical layer: its directory also holds ` +
@@ -104,97 +109,155 @@ function assertNotInSchemaDirectory(filePath) {
104
109
  `tenant-policy.md turns tenant enforcement off). Pass the directory, rename the file ` +
105
110
  `to schema.json, or pass its content to loadSchemaFromJson() to load only the physical layer.`);
106
111
  }
107
- function loadFromDirectory(dir, schemaJsonPath = join(dir, "schema.json")) {
108
- let raw;
109
- try {
110
- raw = readFileSync(schemaJsonPath, "utf8");
111
- }
112
- catch {
112
+ /**
113
+ * Read a Schema v2 directory into its bundle form, the single file `askdb bundle`
114
+ * writes. Loading the result with `loadSchemaFromJson()` gives the same schema as
115
+ * `loadSchema(dir)`, which reads the directory through this function too.
116
+ *
117
+ * Every name it looks up must be spelled exactly: `schema.json`, `tenant-policy.md`,
118
+ * `concepts.md`, `tables/`, and the `.md` extension in `tables/`. A file that matches
119
+ * one only when case is ignored (`Tenant-Policy.md`, `tables/orders.MD`) throws
120
+ * `SchemaParseError` on every OS. Where file names are case-sensitive (Linux) it would
121
+ * otherwise be skipped, and a skipped `tenant-policy.md` turns tenant enforcement off.
122
+ *
123
+ * An optional file counts as absent only when the directory doesn't list it. A listed
124
+ * file that can't be read throws `SchemaParseError`, so does a `schema.json` that is
125
+ * missing or invalid. The file contents are returned unparsed, except `schema.json`.
126
+ */
127
+ export function readSchemaDirectory(dir) {
128
+ return readDirectory(resolve(dir));
129
+ }
130
+ const SCHEMA_JSON = "schema.json";
131
+ /**
132
+ * {@link readSchemaDirectory}, reading the physical layer from `schemaJsonPath` when
133
+ * the caller named that file (`loadSchema("<dir>/Schema.json")`). That name is the
134
+ * caller's, so it is read as given and only the names this function looks up itself
135
+ * are checked.
136
+ */
137
+ function readDirectory(dir, schemaJsonPath) {
138
+ const entries = readRequiredDir(dir);
139
+ const listed = new Set(entries);
140
+ const tables = SCHEMA_DIRECTORY_FILES.tables;
141
+ const tableDir = join(dir, tables);
142
+ // Sorted so warning order is deterministic (readdir order is filesystem-dependent)
143
+ // and matches the bundle loader, which sorts its `tables` keys the same way.
144
+ const tableEntries = listed.has(tables) ? readRequiredDir(tableDir).sort() : [];
145
+ assertExactNames(dir, entries, tableEntries, schemaJsonPath === undefined);
146
+ if (schemaJsonPath === undefined && !listed.has(SCHEMA_JSON)) {
113
147
  throw new SchemaParseError(`No schema.json found in directory: ${dir}`);
114
148
  }
149
+ const physicalPath = schemaJsonPath ?? join(dir, SCHEMA_JSON);
115
150
  let parsed;
116
151
  try {
117
- parsed = JSON.parse(raw);
152
+ parsed = JSON.parse(readRequiredFile(physicalPath));
118
153
  }
119
- catch {
120
- throw new SchemaParseError(`Failed to parse schema.json in ${dir}`);
121
- }
122
- const physical = parsePhysicalLayer(parsed, schemaJsonPath);
123
- // The describable files below are optional, but only *absence* (ENOENT) is
124
- // tolerated. Any other read or parse failure is fatal: silently skipping a
125
- // broken tenant-policy.md would load the schema with tenant enforcement off.
126
- // Load optional tables/*.md
127
- const tableDir = join(dir, SCHEMA_DIRECTORY_FILES.tables);
128
- const tableMarkdowns = {};
129
- // Sorted so warning order is deterministic (readdir order is filesystem-dependent)
130
- // and matches the bundle loader, which sorts its `tables` keys the same way.
131
- const entries = (readOptionalDir(tableDir) ?? []).sort();
132
- for (const entry of entries) {
133
- if (!entry.endsWith(".md"))
134
- continue;
135
- const filePath = join(tableDir, entry);
136
- const content = readRequiredFile(filePath);
137
- const parsed = parseOrWrap(filePath, () => parseTableMarkdown(content, filePath));
138
- addTableMarkdown(tableMarkdowns, { tableFile: `tables/${entry}`, parsed }, dir);
154
+ catch (e) {
155
+ if (e instanceof SchemaParseError)
156
+ throw e;
157
+ throw new SchemaParseError(`Failed to parse schema.json in ${dir}`, e);
139
158
  }
140
- // Load optional concepts.md
141
- let concepts;
142
- const conceptsPath = join(dir, SCHEMA_DIRECTORY_FILES.concepts);
143
- const conceptsContent = readOptionalFile(conceptsPath);
144
- if (conceptsContent !== undefined) {
145
- concepts = parseOrWrap(conceptsPath, () => parseConceptsMarkdown(conceptsContent, conceptsPath)).frontmatter;
159
+ const physical = parsePhysicalLayer(parsed, physicalPath);
160
+ const tableFiles = {};
161
+ for (const entry of tableEntries) {
162
+ if (entry.endsWith(".md"))
163
+ tableFiles[entry] = readRequiredFile(join(tableDir, entry));
146
164
  }
147
- // Load optional tenant-policy.md
148
- let tenantPolicy;
149
- const policyPath = join(dir, SCHEMA_DIRECTORY_FILES.tenantPolicy);
150
- const policyContent = readOptionalFile(policyPath);
151
- if (policyContent !== undefined) {
152
- tenantPolicy = parseOrWrap(policyPath, () => {
153
- const parsed = parseTenantPolicyMarkdown(policyContent, policyPath);
154
- const physicalTableIds = new Set(physical.tables.map((t) => t.id));
155
- const physicalColumnIds = new Set(physical.tables.flatMap((t) => t.columns.map((c) => c.id)));
156
- return normalizeTenantPolicy(parsed, physicalTableIds, physicalColumnIds);
157
- });
165
+ const bundle = { bundled: true, physical, tables: tableFiles };
166
+ for (const key of ["concepts", "tenantPolicy"]) {
167
+ const name = SCHEMA_DIRECTORY_FILES[key];
168
+ if (listed.has(name))
169
+ bundle[key] = readRequiredFile(join(dir, name));
158
170
  }
159
- return buildNormalized(physical, tableMarkdowns, concepts, [], tenantPolicy);
171
+ return bundle;
160
172
  }
161
- function isMissingPathError(e) {
162
- return (typeof e === "object" && e !== null && e.code === "ENOENT");
173
+ /**
174
+ * The key two names share when a case-insensitive filesystem stores them as one file.
175
+ * It is ADR 0013's key, checked there against Unicode full case folding: APFS folds
176
+ * `tableſ` (long s) to `tables`, which `toLowerCase()` alone misses.
177
+ */
178
+ function caseKey(name) {
179
+ return name.normalize("NFC").toLowerCase().toUpperCase().toLowerCase();
163
180
  }
164
- function errorMessage(e) {
165
- return e instanceof Error ? e.message : String(e);
181
+ /** A `tables/` entry's name with its extension lowercased: `users.MD` → `users.md`. */
182
+ function tableFileKey(entry) {
183
+ return entry.slice(0, -3) + entry.slice(-3).toLowerCase();
166
184
  }
167
- /** Read an optional file: `undefined` when it does not exist, `SchemaParseError` on any other failure. */
168
- function readOptionalFile(path) {
169
- try {
170
- return readFileSync(path, "utf8");
171
- }
172
- catch (e) {
173
- if (isMissingPathError(e))
174
- return undefined;
175
- throw new SchemaParseError(`Failed to read ${path}: ${errorMessage(e)}`, e);
185
+ /**
186
+ * Throw when a directory entry matches a name the loader looks up only when case is
187
+ * ignored. Where file names are case-sensitive (Linux), the loader would skip that
188
+ * file; on macOS and Windows the same directory loads. Checking on every OS makes a
189
+ * directory fail on a laptop the way it would fail open in production. One error
190
+ * names every problem, including the files in a wrong-case `Tables/`, so the user
191
+ * fixes them in one pass.
192
+ */
193
+ function assertExactNames(dir, entries, tableEntries, checkSchemaJson) {
194
+ const tables = SCHEMA_DIRECTORY_FILES.tables;
195
+ const names = [...(checkSchemaJson ? [SCHEMA_JSON] : []), ...Object.values(SCHEMA_DIRECTORY_FILES)];
196
+ const problems = spellingProblems(entries, names, caseKey, "");
197
+ // A lone wrong-case `Tables/` is listed too, so its files are named in this error.
198
+ const tablesSpellings = entries.filter((entry) => caseKey(entry) === tables);
199
+ const wrongCaseTables = tablesSpellings.length === 1 && tablesSpellings[0] !== tables
200
+ ? listOrEmpty(join(dir, tablesSpellings[0])).sort()
201
+ : [];
202
+ const files = [...tableEntries, ...wrongCaseTables];
203
+ const mdNames = [
204
+ ...new Set(files.map(tableFileKey).filter((key) => key.endsWith(".md"))),
205
+ ];
206
+ problems.push(...spellingProblems(files, mdNames, tableFileKey, `${tables}/`));
207
+ if (problems.length === 0)
208
+ return;
209
+ throw new SchemaParseError(`Schema directory ${dir} has a file name in the wrong case: ${problems.join("; ")}. ` +
210
+ `The loader reads these names exactly. Where file names are case-sensitive (Linux) it ` +
211
+ `would skip the file, and a skipped tenant-policy.md turns tenant enforcement off, so it ` +
212
+ `refuses on every OS.`);
213
+ }
214
+ /**
215
+ * For each name, the entries that spell it differently under `key`: one wrong spelling
216
+ * is a rename. Two or more spellings can coexist only where names are case-sensitive,
217
+ * and renaming one onto the other would overwrite a file or move a directory inside
218
+ * the other, so the problem says to keep one instead.
219
+ */
220
+ function spellingProblems(entries, names, key, prefix) {
221
+ const problems = [];
222
+ for (const name of names) {
223
+ const spellings = entries.filter((entry) => key(entry) === key(name)).sort();
224
+ if (spellings.length === 0 || (spellings.length === 1 && spellings[0] === name))
225
+ continue;
226
+ problems.push(spellings.length === 1
227
+ ? `rename ${prefix}${spellings[0]} to ${prefix}${name}`
228
+ : `keep one of ${spellings.map((s) => prefix + s).join(", ")}, named ${prefix}${name}`);
176
229
  }
230
+ return problems;
177
231
  }
178
- /** Whether a path exists: `false` only when it does not (ENOENT), `SchemaParseError` on any other failure. */
179
- function pathExists(path) {
232
+ /** List a directory whose contents only add detail to an error: `[]` if it can't be listed. */
233
+ function listOrEmpty(path) {
180
234
  try {
181
- statSync(path);
182
- return true;
235
+ return readdirSync(path);
183
236
  }
184
- catch (e) {
185
- if (isMissingPathError(e))
186
- return false;
187
- throw new SchemaParseError(`Failed to read ${path}: ${errorMessage(e)}`, e);
237
+ catch {
238
+ return [];
188
239
  }
189
240
  }
190
- /** List an optional directory: `undefined` when it does not exist, `SchemaParseError` on any other failure. */
191
- function readOptionalDir(path) {
241
+ function loadFromDirectory(dir, schemaJsonPath) {
242
+ const files = readDirectory(dir, schemaJsonPath);
243
+ // Errors name the file on disk.
244
+ return loadFromFiles(files, files.physical, (file) => join(dir, file), dir);
245
+ }
246
+ function loadFromBundle(bundle, filePath) {
247
+ const physical = parsePhysicalLayer(bundle.physical, filePath);
248
+ // Errors name the bundled file and the bundle that holds it: the user has the
249
+ // bundle on disk, not a tenant-policy.md or concepts.md.
250
+ return loadFromFiles(bundle, physical, (file) => `${file} (in ${filePath})`, filePath);
251
+ }
252
+ function errorMessage(e) {
253
+ return e instanceof Error ? e.message : String(e);
254
+ }
255
+ /** List a directory the loader needs: `SchemaParseError` on any failure. */
256
+ function readRequiredDir(path) {
192
257
  try {
193
258
  return readdirSync(path);
194
259
  }
195
260
  catch (e) {
196
- if (isMissingPathError(e))
197
- return undefined;
198
261
  throw new SchemaParseError(`Failed to read directory ${path}: ${errorMessage(e)}`, e);
199
262
  }
200
263
  }
@@ -222,33 +285,34 @@ function parseOrWrap(path, fn) {
222
285
  throw new SchemaParseError(`Failed to parse ${path}: ${errorMessage(e)}`, e);
223
286
  }
224
287
  }
225
- function loadFromBundle(bundle, filePath) {
226
- const physical = parsePhysicalLayer(bundle.physical, filePath);
288
+ /**
289
+ * Parse a schema's files, read from a directory or carried in a bundle, against its
290
+ * validated physical layer. `fileLabel` turns a file's path in the schema directory
291
+ * (`tables/orders.md`, `tenant-policy.md`) into the name errors use.
292
+ */
293
+ function loadFromFiles(files, physical, fileLabel, schemaPath) {
227
294
  const tableMarkdowns = {};
228
- // Errors name the bundled file and the bundle that holds it: the user has the
229
- // bundle on disk, not a tenant-policy.md or concepts.md.
230
- const inBundle = (file) => `${file} (in ${filePath})`;
231
- // Bundle keys are the `tables/` filenames (see `bundleSchemaDirectory` in
232
- // @askdb/enrich), so warnings name the same path the directory loader would.
233
- // Sorted like the directory loader's entries, so both report warnings in one order.
234
- for (const [filename, content] of Object.entries(bundle.tables).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
235
- const tableFile = `tables/${filename}`;
236
- const parsed = parseOrWrap(inBundle(tableFile), () => parseTableMarkdown(content, inBundle(tableFile)));
237
- addTableMarkdown(tableMarkdowns, { tableFile, parsed }, filePath);
238
- }
239
- // Mirror the directory loader: only an *absent* key means "no file". A present
240
- // value — including an empty string — is parsed and must be valid, so an empty
241
- // or corrupt tenantPolicy can never silently disable tenant enforcement.
295
+ // `tables` keys are the `tables/` filenames, so warnings name the file as it sits in
296
+ // the directory. Sorted so both forms report warnings in one order.
297
+ for (const [filename, content] of Object.entries(files.tables).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0)) {
298
+ const tableFile = `${SCHEMA_DIRECTORY_FILES.tables}/${filename}`;
299
+ const label = fileLabel(tableFile);
300
+ const parsed = parseOrWrap(label, () => parseTableMarkdown(content, label));
301
+ addTableMarkdown(tableMarkdowns, { tableFile, parsed }, schemaPath);
302
+ }
303
+ // Only an *absent* file (or bundle key) means "no file". A present value —
304
+ // including an empty string — is parsed and must be valid, so an empty or corrupt
305
+ // tenant policy can never silently disable tenant enforcement.
242
306
  let concepts;
243
- const conceptsContent = bundledFileContent(bundle, "concepts", filePath);
307
+ const conceptsContent = bundledFileContent(files, "concepts", schemaPath);
244
308
  if (conceptsContent !== undefined) {
245
- const conceptsFile = inBundle(SCHEMA_DIRECTORY_FILES.concepts);
309
+ const conceptsFile = fileLabel(SCHEMA_DIRECTORY_FILES.concepts);
246
310
  concepts = parseOrWrap(conceptsFile, () => parseConceptsMarkdown(conceptsContent, conceptsFile)).frontmatter;
247
311
  }
248
312
  let tenantPolicy;
249
- const policyContent = bundledFileContent(bundle, "tenantPolicy", filePath);
313
+ const policyContent = bundledFileContent(files, "tenantPolicy", schemaPath);
250
314
  if (policyContent !== undefined) {
251
- const policyFile = inBundle(SCHEMA_DIRECTORY_FILES.tenantPolicy);
315
+ const policyFile = fileLabel(SCHEMA_DIRECTORY_FILES.tenantPolicy);
252
316
  tenantPolicy = parseOrWrap(policyFile, () => {
253
317
  const parsed = parseTenantPolicyMarkdown(policyContent, policyFile);
254
318
  const physicalTableIds = new Set(physical.tables.map((t) => t.id));