vouchington-tooling 0.32.0 → 0.34.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 (208) hide show
  1. package/README.md +219 -1
  2. package/dist/api-contract-discovery/index.d.mts +4 -1
  3. package/dist/api-contract-discovery/index.mjs +1 -0
  4. package/dist/api-contract-discovery/protocol-analysis-cache.d.mts +21 -0
  5. package/dist/api-contract-discovery/protocol-analysis-cache.mjs +7 -0
  6. package/dist/api-contract-discovery/protocol-callback-invocation.d.mts +2 -1
  7. package/dist/api-contract-discovery/protocol-callback-invocation.mjs +12 -4
  8. package/dist/api-contract-discovery/protocol-callback-values.d.mts +2 -1
  9. package/dist/api-contract-discovery/protocol-callback-values.mjs +3 -3
  10. package/dist/api-contract-discovery/protocol-execution-path.d.mts +2 -1
  11. package/dist/api-contract-discovery/protocol-execution-path.mjs +2 -2
  12. package/dist/api-contract-discovery/protocol-http-association.mjs +8 -0
  13. package/dist/api-contract-discovery/protocol-http-context-callers.d.mts +2 -1
  14. package/dist/api-contract-discovery/protocol-http-context-callers.mjs +13 -7
  15. package/dist/api-contract-discovery/protocol-http-context-escapes.d.mts +3 -0
  16. package/dist/api-contract-discovery/protocol-http-context-escapes.mjs +95 -0
  17. package/dist/api-contract-discovery/protocol-http-context.d.mts +1 -2
  18. package/dist/api-contract-discovery/protocol-http-context.mjs +6 -29
  19. package/dist/api-contract-discovery/protocol-http-method-access.d.mts +9 -0
  20. package/dist/api-contract-discovery/protocol-http-method-access.mjs +34 -0
  21. package/dist/api-contract-discovery/protocol-http-reflect.d.mts +5 -0
  22. package/dist/api-contract-discovery/protocol-http-reflect.mjs +45 -0
  23. package/dist/api-contract-discovery/protocol-http-response-mutations.d.mts +3 -0
  24. package/dist/api-contract-discovery/protocol-http-response-mutations.mjs +31 -0
  25. package/dist/api-contract-discovery/protocol-platform-callbacks.d.mts +2 -0
  26. package/dist/api-contract-discovery/protocol-platform-callbacks.mjs +4 -0
  27. package/dist/api-contract-discovery/protocol-sse-raw-writes.mjs +36 -7
  28. package/dist/api-contract-discovery/protocol-sse-write-helpers.d.mts +1 -0
  29. package/dist/api-contract-discovery/protocol-sse-write-helpers.mjs +21 -5
  30. package/dist/api-contract-discovery/protocol-sse-write-mutations.d.mts +1 -1
  31. package/dist/api-contract-discovery/protocol-sse-write-mutations.mjs +8 -2
  32. package/dist/api-contract-discovery/query-contract-extraction.mjs +20 -3
  33. package/dist/api-contract-discovery/query-contract-literals.d.mts +5 -0
  34. package/dist/api-contract-discovery/query-contract-literals.mjs +29 -0
  35. package/dist/api-contract-discovery/registered-route-binding-writes.d.mts +2 -1
  36. package/dist/api-contract-discovery/registered-route-binding-writes.mjs +20 -11
  37. package/dist/api-contract-discovery/registered-route-handler-analysis.d.mts +7 -1
  38. package/dist/api-contract-discovery/registered-route-handler-analysis.mjs +27 -26
  39. package/dist/api-contract-discovery/registered-route-handler-helpers.d.mts +3 -0
  40. package/dist/api-contract-discovery/registered-route-handler-helpers.mjs +16 -0
  41. package/dist/api-contract-discovery/request-validation-callbacks.d.mts +9 -0
  42. package/dist/api-contract-discovery/request-validation-callbacks.mjs +27 -0
  43. package/dist/api-contract-discovery/request-validation-checker.d.mts +7 -0
  44. package/dist/api-contract-discovery/request-validation-checker.mjs +25 -0
  45. package/dist/api-contract-discovery/request-validation-conditional.d.mts +6 -0
  46. package/dist/api-contract-discovery/request-validation-conditional.mjs +31 -0
  47. package/dist/api-contract-discovery/request-validation-factory-calls.d.mts +11 -0
  48. package/dist/api-contract-discovery/request-validation-factory-calls.mjs +23 -0
  49. package/dist/api-contract-discovery/request-validation-facts.d.mts +16 -0
  50. package/dist/api-contract-discovery/request-validation-facts.mjs +64 -0
  51. package/dist/api-contract-discovery/request-validation-follow.d.mts +24 -0
  52. package/dist/api-contract-discovery/request-validation-follow.mjs +38 -0
  53. package/dist/api-contract-discovery/request-validation-handler-state.d.mts +8 -0
  54. package/dist/api-contract-discovery/request-validation-handler-state.mjs +35 -0
  55. package/dist/api-contract-discovery/request-validation-input.d.mts +12 -0
  56. package/dist/api-contract-discovery/request-validation-input.mjs +43 -0
  57. package/dist/api-contract-discovery/request-validation-keys.d.mts +25 -0
  58. package/dist/api-contract-discovery/request-validation-keys.mjs +119 -0
  59. package/dist/api-contract-discovery/request-validation-match.d.mts +11 -0
  60. package/dist/api-contract-discovery/request-validation-match.mjs +47 -0
  61. package/dist/api-contract-discovery/request-validation-mutation.d.mts +7 -0
  62. package/dist/api-contract-discovery/request-validation-mutation.mjs +80 -0
  63. package/dist/api-contract-discovery/request-validation-origin.d.mts +20 -0
  64. package/dist/api-contract-discovery/request-validation-origin.mjs +71 -0
  65. package/dist/api-contract-discovery/request-validation-reads.d.mts +13 -0
  66. package/dist/api-contract-discovery/request-validation-reads.mjs +88 -0
  67. package/dist/api-contract-discovery/request-validation-registration.d.mts +9 -0
  68. package/dist/api-contract-discovery/request-validation-registration.mjs +32 -0
  69. package/dist/api-contract-discovery/request-validation-report.d.mts +3 -0
  70. package/dist/api-contract-discovery/request-validation-report.mjs +21 -0
  71. package/dist/api-contract-discovery/request-validation-request-origin.d.mts +5 -0
  72. package/dist/api-contract-discovery/request-validation-request-origin.mjs +13 -0
  73. package/dist/api-contract-discovery/request-validation-select.d.mts +9 -0
  74. package/dist/api-contract-discovery/request-validation-select.mjs +36 -0
  75. package/dist/api-contract-discovery/request-validation-sites.d.mts +9 -0
  76. package/dist/api-contract-discovery/request-validation-sites.mjs +77 -0
  77. package/dist/api-contract-discovery/request-validation-state-key.d.mts +13 -0
  78. package/dist/api-contract-discovery/request-validation-state-key.mjs +30 -0
  79. package/dist/api-contract-discovery/request-validation-trace-helpers.d.mts +14 -0
  80. package/dist/api-contract-discovery/request-validation-trace-helpers.mjs +80 -0
  81. package/dist/api-contract-discovery/request-validation-trace-select.d.mts +23 -0
  82. package/dist/api-contract-discovery/request-validation-trace-select.mjs +45 -0
  83. package/dist/api-contract-discovery/request-validation-trace.d.mts +8 -0
  84. package/dist/api-contract-discovery/request-validation-trace.mjs +130 -0
  85. package/dist/api-contract-discovery/request-validation-types.d.mts +84 -0
  86. package/dist/api-contract-discovery/request-validation-types.mjs +1 -0
  87. package/dist/api-contract-discovery/request-validation-walker.d.mts +26 -0
  88. package/dist/api-contract-discovery/request-validation-walker.mjs +143 -0
  89. package/dist/api-contract-discovery/request-validation.test-helpers.d.mts +39 -0
  90. package/dist/api-contract-discovery/request-validation.test-helpers.mjs +108 -0
  91. package/dist/api-contract-discovery/response-contract-attribution-facts.d.mts +2 -0
  92. package/dist/api-contract-discovery/response-contract-attribution-facts.mjs +18 -0
  93. package/dist/api-contract-discovery/response-contract-attribution.d.mts +3 -0
  94. package/dist/api-contract-discovery/response-contract-attribution.mjs +23 -0
  95. package/dist/api-contract-discovery/response-contract-call-classification.d.mts +3 -0
  96. package/dist/api-contract-discovery/response-contract-call-classification.mjs +37 -0
  97. package/dist/api-contract-discovery/response-contract-error-branch.d.mts +1 -1
  98. package/dist/api-contract-discovery/response-contract-error-branch.mjs +109 -6
  99. package/dist/api-contract-discovery/response-contract-handler-bindings.d.mts +3 -0
  100. package/dist/api-contract-discovery/response-contract-handler-bindings.mjs +126 -0
  101. package/dist/api-contract-discovery/response-contract-handler-calls.d.mts +3 -0
  102. package/dist/api-contract-discovery/response-contract-handler-calls.mjs +81 -0
  103. package/dist/api-contract-discovery/response-contract-implicit-variants.d.mts +2 -0
  104. package/dist/api-contract-discovery/response-contract-implicit-variants.mjs +6 -0
  105. package/dist/api-contract-discovery/response-contract-implicit.d.mts +2 -1
  106. package/dist/api-contract-discovery/response-contract-implicit.mjs +9 -17
  107. package/dist/api-contract-discovery/response-contract-lenient.d.mts +18 -0
  108. package/dist/api-contract-discovery/response-contract-object-symbols.d.mts +3 -0
  109. package/dist/api-contract-discovery/response-contract-object-symbols.mjs +80 -0
  110. package/dist/api-contract-discovery/response-contract-property-mutations.d.mts +5 -0
  111. package/dist/api-contract-discovery/response-contract-property-mutations.mjs +84 -0
  112. package/dist/api-contract-discovery/response-contract-registration.d.mts +1 -1
  113. package/dist/api-contract-discovery/response-contract-registration.mjs +7 -3
  114. package/dist/api-contract-discovery/response-contract-registry.mjs +43 -8
  115. package/dist/api-contract-discovery/response-contract-route-analysis.d.mts +3 -4
  116. package/dist/api-contract-discovery/response-contract-route-analysis.mjs +4 -101
  117. package/dist/api-contract-discovery/response-contract-route-syntax.d.mts +7 -0
  118. package/dist/api-contract-discovery/response-contract-route-syntax.mjs +41 -0
  119. package/dist/api-contract-discovery/response-contract-symbols.d.mts +5 -0
  120. package/dist/api-contract-discovery/response-contract-symbols.mjs +82 -0
  121. package/dist/basic-auth-doc-sync/index.d.mts +3 -0
  122. package/dist/basic-auth-doc-sync/index.mjs +2 -0
  123. package/dist/basic-auth-doc-sync/methods.d.mts +1 -0
  124. package/dist/basic-auth-doc-sync/methods.mjs +4 -0
  125. package/dist/basic-auth-doc-sync/runbook.d.mts +5 -0
  126. package/dist/basic-auth-doc-sync/runbook.mjs +59 -0
  127. package/dist/basic-auth-doc-sync/source.d.mts +2 -0
  128. package/dist/basic-auth-doc-sync/source.mjs +71 -0
  129. package/dist/compiler-build/index.d.mts +2 -0
  130. package/dist/compiler-build/index.mjs +1 -0
  131. package/dist/compiler-build/program-configuration.d.mts +9 -0
  132. package/dist/compiler-build/program-configuration.mjs +28 -0
  133. package/dist/compiler-build/program-types.d.mts +29 -0
  134. package/dist/compiler-build/program-types.mjs +1 -0
  135. package/dist/compiler-build/program.d.mts +7 -0
  136. package/dist/compiler-build/program.mjs +78 -0
  137. package/dist/contract-schema/index.d.mts +4 -0
  138. package/dist/contract-schema/index.mjs +2 -0
  139. package/dist/contract-schema/type-query-api.d.mts +44 -0
  140. package/dist/contract-schema/type-query-api.mjs +10 -0
  141. package/dist/contract-schema/type-query-call.d.mts +16 -0
  142. package/dist/contract-schema/type-query-call.mjs +52 -0
  143. package/dist/contract-schema/type-query-export.d.mts +10 -0
  144. package/dist/contract-schema/type-query-export.mjs +91 -0
  145. package/dist/contract-schema/type-query.d.mts +22 -0
  146. package/dist/contract-schema/type-query.mjs +39 -0
  147. package/dist/finite-enum-ripple/ast.d.mts +9 -0
  148. package/dist/finite-enum-ripple/ast.mjs +94 -0
  149. package/dist/finite-enum-ripple/check.d.mts +3 -0
  150. package/dist/finite-enum-ripple/check.mjs +62 -0
  151. package/dist/finite-enum-ripple/compare.d.mts +20 -0
  152. package/dist/finite-enum-ripple/compare.mjs +90 -0
  153. package/dist/finite-enum-ripple/component-paths.d.mts +8 -0
  154. package/dist/finite-enum-ripple/component-paths.mjs +30 -0
  155. package/dist/finite-enum-ripple/configured-object-mutations.d.mts +1 -0
  156. package/dist/finite-enum-ripple/configured-object-mutations.mjs +78 -0
  157. package/dist/finite-enum-ripple/create-page-jsx.d.mts +3 -0
  158. package/dist/finite-enum-ripple/create-page-jsx.mjs +28 -0
  159. package/dist/finite-enum-ripple/create-page-literals.d.mts +2 -0
  160. package/dist/finite-enum-ripple/create-page-literals.mjs +83 -0
  161. package/dist/finite-enum-ripple/create-page-object-visitor.d.mts +2 -0
  162. package/dist/finite-enum-ripple/create-page-object-visitor.mjs +57 -0
  163. package/dist/finite-enum-ripple/create-page-properties.d.mts +4 -0
  164. package/dist/finite-enum-ripple/create-page-properties.mjs +35 -0
  165. package/dist/finite-enum-ripple/index.d.mts +2 -0
  166. package/dist/finite-enum-ripple/index.mjs +1 -0
  167. package/dist/finite-enum-ripple/model.d.mts +74 -0
  168. package/dist/finite-enum-ripple/model.mjs +1 -0
  169. package/dist/finite-enum-ripple/parser-support.d.mts +11 -0
  170. package/dist/finite-enum-ripple/parser-support.mjs +86 -0
  171. package/dist/finite-enum-ripple/parsers.d.mts +32 -0
  172. package/dist/finite-enum-ripple/parsers.mjs +113 -0
  173. package/dist/finite-enum-ripple/pattern-captures.d.mts +2 -0
  174. package/dist/finite-enum-ripple/pattern-captures.mjs +45 -0
  175. package/dist/finite-enum-ripple/structured-route-check.d.mts +3 -0
  176. package/dist/finite-enum-ripple/structured-route-check.mjs +94 -0
  177. package/dist/finite-enum-ripple/types.d.mts +2 -0
  178. package/dist/finite-enum-ripple/types.mjs +60 -0
  179. package/dist/finite-enum-ripple/union-factory-check.d.mts +2 -0
  180. package/dist/finite-enum-ripple/union-factory-check.mjs +34 -0
  181. package/dist/finite-enum-ripple/union-types.d.mts +2 -0
  182. package/dist/finite-enum-ripple/union-types.mjs +129 -0
  183. package/dist/markdown/content-facts.d.mts +6 -0
  184. package/dist/markdown/content-facts.mjs +18 -0
  185. package/dist/markdown/html-blocks.d.mts +5 -0
  186. package/dist/markdown/html-blocks.mjs +51 -0
  187. package/dist/markdown/index.d.mts +4 -1
  188. package/dist/markdown/index.mjs +3 -0
  189. package/dist/markdown/tasks.d.mts +2 -0
  190. package/dist/markdown/tasks.mjs +10 -0
  191. package/dist/markdown/types.d.mts +27 -0
  192. package/dist/openapi-document/build-openapi-query.mjs +1 -1
  193. package/dist/openapi-document/openapi-types.d.mts +1 -1
  194. package/dist/openapi-document/query-types.d.mts +8 -2
  195. package/dist/post-publication-inventory/index.d.mts +5 -0
  196. package/dist/post-publication-inventory/index.mjs +2 -0
  197. package/dist/post-publication-inventory/readers/sql-executors.d.mts +3 -0
  198. package/dist/post-publication-inventory/readers/sql-executors.mjs +32 -0
  199. package/dist/post-publication-inventory/readers/sql-source.d.mts +7 -0
  200. package/dist/post-publication-inventory/readers/sql-source.mjs +87 -0
  201. package/dist/post-publication-inventory/readers/sql-template.d.mts +12 -0
  202. package/dist/post-publication-inventory/readers/sql-template.mjs +119 -0
  203. package/dist/post-publication-inventory/writers/source.d.mts +9 -0
  204. package/dist/post-publication-inventory/writers/source.mjs +128 -0
  205. package/dist/post-publication-inventory/writers/types.d.mts +19 -0
  206. package/dist/post-publication-inventory/writers/types.mjs +1 -0
  207. package/docs/basic-auth-doc-sync.md +37 -0
  208. package/package.json +24 -3
@@ -0,0 +1,87 @@
1
+ import ts from '../../contract-schema/typescript-api.mjs';
2
+ import { terminalSqlExecutorBindings } from './sql-executors.mjs';
3
+ import { identifierName, staticComputedPropertyName, staticSqlTemplateText, unparenthesized, walk, } from './sql-template.mjs';
4
+ /**
5
+ * Collect static SQL fragments returned, exported, or passed to configured executors.
6
+ * Interpolations become numbered placeholders; local append chains are reassembled.
7
+ * This preserves name-based collection heuristics, not binding or control-flow proof.
8
+ */
9
+ export function extractStaticSqlTemplateQuasis(content, options) {
10
+ // TypeScript's source-file parser recovers from syntax errors. Reject those first,
11
+ // preserving the previous strict parser's failure contract instead of trusting recovery.
12
+ const result = ts.transpileModule(content, {
13
+ fileName: 'reader.mts',
14
+ reportDiagnostics: true,
15
+ compilerOptions: { target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.ESNext },
16
+ });
17
+ if (result.diagnostics?.length)
18
+ throw new SyntaxError(ts.flattenDiagnosticMessageText(result.diagnostics[0].messageText, '\n'));
19
+ const ast = ts.createSourceFile('reader.mts', content, ts.ScriptTarget.Latest, true);
20
+ const executors = terminalSqlExecutorBindings(ast, options);
21
+ const statements = new Map();
22
+ const consumed = new Set();
23
+ const direct = [];
24
+ walk(ast, (node) => {
25
+ if (!ts.isVariableDeclaration(node))
26
+ return;
27
+ const binding = identifierName(node.name);
28
+ const text = staticSqlTemplateText(node.initializer, options);
29
+ if (binding && text)
30
+ statements.set(binding, { text, offset: node.getStart(ast) });
31
+ });
32
+ walk(ast, (node) => {
33
+ if (ts.isVariableStatement(node) &&
34
+ node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) {
35
+ for (const declaration of node.declarationList.declarations) {
36
+ const binding = identifierName(declaration.name);
37
+ if (binding)
38
+ consumed.add(binding);
39
+ }
40
+ }
41
+ if (ts.isReturnStatement(node) && node.expression) {
42
+ const binding = identifierName(node.expression);
43
+ if (binding)
44
+ consumed.add(binding);
45
+ const text = staticSqlTemplateText(node.expression, options);
46
+ if (text)
47
+ direct.push(text);
48
+ return;
49
+ }
50
+ if (!ts.isCallExpression(node))
51
+ return;
52
+ const callee = unparenthesized(node.expression);
53
+ if (!ts.isIdentifier(callee) || !executors.has(callee.text))
54
+ return;
55
+ for (const argument of node.arguments) {
56
+ const binding = identifierName(argument);
57
+ if (binding)
58
+ consumed.add(binding);
59
+ const text = staticSqlTemplateText(argument, options);
60
+ if (text)
61
+ direct.push(text);
62
+ }
63
+ });
64
+ walk(ast, (node) => {
65
+ if (!ts.isCallExpression(node))
66
+ return;
67
+ const callee = unparenthesized(node.expression);
68
+ if (!ts.isPropertyAccessExpression(callee) && !ts.isElementAccessExpression(callee))
69
+ return;
70
+ const method = ts.isPropertyAccessExpression(callee)
71
+ ? callee.name.text
72
+ : callee.argumentExpression
73
+ ? staticComputedPropertyName(callee.argumentExpression)
74
+ : undefined;
75
+ if (method !== options.appendMethod)
76
+ return;
77
+ const receiver = identifierName(callee.expression);
78
+ const statement = receiver ? statements.get(receiver) : undefined;
79
+ const appended = staticSqlTemplateText(node.arguments[0], options);
80
+ if (statement && appended && node.getStart(ast) > statement.offset)
81
+ statement.text += appended;
82
+ });
83
+ return [
84
+ ...direct,
85
+ ...[...statements].flatMap(([binding, statement]) => consumed.has(binding) ? [statement.text] : []),
86
+ ];
87
+ }
@@ -0,0 +1,12 @@
1
+ import ts from '../../contract-schema/typescript-api.mts';
2
+ export interface ReaderSqlTemplateOptions {
3
+ readonly templateTag: string;
4
+ readonly appendMethod: string;
5
+ readonly executorImports: ReadonlyMap<string, ReadonlySet<string>>;
6
+ readonly placeholderPrefix: string;
7
+ }
8
+ export declare function identifierName(node: ts.Node): string | undefined;
9
+ export declare function staticComputedPropertyName(node: ts.Node): string | undefined;
10
+ export declare function unparenthesized(node: ts.Node): ts.Node;
11
+ export declare function staticSqlTemplateText(node: ts.Node | undefined, options: ReaderSqlTemplateOptions): string | undefined;
12
+ export declare function walk(root: ts.Node, visit: (node: ts.Node) => void): void;
@@ -0,0 +1,119 @@
1
+ import ts from '../../contract-schema/typescript-api.mjs';
2
+ export function identifierName(node) {
3
+ node = unparenthesized(node);
4
+ return ts.isIdentifier(node) ? node.text : undefined;
5
+ }
6
+ export function staticComputedPropertyName(node) {
7
+ node = unparenthesized(node);
8
+ return ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)
9
+ ? node.text
10
+ : undefined;
11
+ }
12
+ export function unparenthesized(node) {
13
+ while (ts.isParenthesizedExpression(node))
14
+ node = node.expression;
15
+ return node;
16
+ }
17
+ export function staticSqlTemplateText(node, options) {
18
+ if (!node)
19
+ return undefined;
20
+ node = unparenthesized(node);
21
+ if (ts.isTaggedTemplateExpression(node)) {
22
+ if (identifierName(node.tag) !== options.templateTag)
23
+ return undefined;
24
+ node = node.template;
25
+ }
26
+ if (ts.isNoSubstitutionTemplateLiteral(node))
27
+ return rawQuasi(node);
28
+ if (!ts.isTemplateExpression(node))
29
+ return undefined;
30
+ return [
31
+ rawQuasi(node.head),
32
+ ...node.templateSpans.map((span, index) => `${options.placeholderPrefix}${index + 1}${rawQuasi(span.literal)}`),
33
+ ].join('');
34
+ }
35
+ function rawQuasi(node) {
36
+ const closingWidth = ts.isTemplateHead(node) || ts.isTemplateMiddle(node) ? 2 : 1;
37
+ return node.getText().slice(1, -closingWidth);
38
+ }
39
+ export function walk(root, visit) {
40
+ visit(root);
41
+ // Retain the existing analyzer's alternate-before-consequent branch order.
42
+ // Concatenated fragment order is observable even though this is not execution analysis.
43
+ if (ts.isIfStatement(root)) {
44
+ if (root.elseStatement)
45
+ walk(root.elseStatement, visit);
46
+ walk(root.thenStatement, visit);
47
+ walk(root.expression, visit);
48
+ return;
49
+ }
50
+ if (ts.isConditionalExpression(root)) {
51
+ walk(root.whenFalse, visit);
52
+ walk(root.whenTrue, visit);
53
+ walk(root.condition, visit);
54
+ return;
55
+ }
56
+ if (ts.isCallExpression(root)) {
57
+ for (const argument of root.arguments)
58
+ walk(argument, visit);
59
+ walk(root.expression, visit);
60
+ for (const typeArgument of root.typeArguments ?? [])
61
+ walk(typeArgument, visit);
62
+ return;
63
+ }
64
+ if (ts.isFunctionDeclaration(root) ||
65
+ ts.isFunctionExpression(root) ||
66
+ ts.isArrowFunction(root) ||
67
+ ts.isMethodDeclaration(root) ||
68
+ ts.isConstructorDeclaration(root) ||
69
+ ts.isGetAccessorDeclaration(root) ||
70
+ ts.isSetAccessorDeclaration(root)) {
71
+ for (const modifier of root.modifiers ?? [])
72
+ if (ts.isDecorator(modifier))
73
+ walk(modifier, visit);
74
+ if (ts.isMethodDeclaration(root) ||
75
+ ts.isGetAccessorDeclaration(root) ||
76
+ ts.isSetAccessorDeclaration(root))
77
+ walk(root.name, visit);
78
+ if (root.body)
79
+ walk(root.body, visit);
80
+ for (const parameter of root.parameters)
81
+ walk(parameter, visit);
82
+ return;
83
+ }
84
+ if (ts.isForStatement(root)) {
85
+ walk(root.statement, visit);
86
+ for (const header of [root.initializer, root.condition, root.incrementor]) {
87
+ if (header)
88
+ walk(header, visit);
89
+ }
90
+ return;
91
+ }
92
+ if (ts.isWhileStatement(root) || ts.isForInStatement(root) || ts.isForOfStatement(root)) {
93
+ walk(root.statement, visit);
94
+ if (ts.isForInStatement(root) || ts.isForOfStatement(root))
95
+ walk(root.initializer, visit);
96
+ walk(root.expression, visit);
97
+ return;
98
+ }
99
+ if (ts.isTryStatement(root)) {
100
+ walk(root.tryBlock, visit);
101
+ if (root.finallyBlock)
102
+ walk(root.finallyBlock, visit);
103
+ if (root.catchClause)
104
+ walk(root.catchClause, visit);
105
+ return;
106
+ }
107
+ if (ts.isSwitchStatement(root)) {
108
+ walk(root.caseBlock, visit);
109
+ walk(root.expression, visit);
110
+ return;
111
+ }
112
+ if (ts.isCaseClause(root)) {
113
+ for (const statement of root.statements)
114
+ walk(statement, visit);
115
+ walk(root.expression, visit);
116
+ return;
117
+ }
118
+ ts.forEachChild(root, (node) => walk(node, visit));
119
+ }
@@ -0,0 +1,9 @@
1
+ import type { PostPublicationWriterSourceOptions } from './types.mts';
2
+ export type PostPublicationWriterSourceAnalysis = {
3
+ readonly callsApprovedCaptureHelper: boolean;
4
+ readonly optsOutOfPublicationCapture: boolean;
5
+ readonly writesConfigEntityTable: boolean;
6
+ readonly writesGeneratedRelationTable: boolean;
7
+ readonly writesEligibilityTable: boolean;
8
+ };
9
+ export declare function analyzePostPublicationWriterSource(source: string, path: string, options: PostPublicationWriterSourceOptions): PostPublicationWriterSourceAnalysis;
@@ -0,0 +1,128 @@
1
+ import ts from '../../contract-schema/typescript-api.mjs';
2
+ const DML = /\b(?:INSERT\s+INTO|UPDATE(?:\s+ONLY)?|DELETE\s+FROM)\b/i;
3
+ const DML_PREFIX = /\b(?:INSERT\s+INTO|UPDATE(?:\s+ONLY)?|DELETE\s+FROM)\s*$/i;
4
+ export function analyzePostPublicationWriterSource(source, path, options) {
5
+ const captureBindings = new Set();
6
+ const invokedIdentifiers = new Set();
7
+ const relationTableBindings = new Set();
8
+ let optsOutOfPublicationCapture = false;
9
+ let hasConfigEntityTable = false;
10
+ let hasDmlPrefix = false;
11
+ let buildsRelationInsert = false;
12
+ let appendsRelationTable = false;
13
+ let writesEligibilityTable = false;
14
+ const ast = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
15
+ function visit(node) {
16
+ if (ts.isImportDeclaration(node))
17
+ collectCaptureBindings(node, captureBindings, options);
18
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
19
+ invokedIdentifiers.add(node.expression.text);
20
+ buildsRelationInsert ||= node.expression.text === options.insertBuilder;
21
+ hasConfigEntityTable ||= isConfigEntityTableAssertion(node, options);
22
+ }
23
+ if (ts.isPropertyAssignment(node) &&
24
+ (ts.isIdentifier(node.name) || ts.isStringLiteral(node.name)) &&
25
+ node.name.text === options.captureOption &&
26
+ node.initializer.kind === ts.SyntaxKind.FalseKeyword)
27
+ optsOutOfPublicationCapture = true;
28
+ if (ts.isVariableDeclaration(node) &&
29
+ ts.isIdentifier(node.name) &&
30
+ isEntityRelationElectionTableIdentifier(node.initializer, options))
31
+ relationTableBindings.add(node.name.text);
32
+ if (ts.isCallExpression(node) && isRelationTableAppend(node, relationTableBindings, options))
33
+ appendsRelationTable = true;
34
+ if (isSqlTextNode(node)) {
35
+ const text = sqlText(node);
36
+ if (!ts.isStringLiteral(node))
37
+ hasDmlPrefix ||= DML_PREFIX.test(text);
38
+ if (DML.test(text)) {
39
+ const table = writtenTableName(text);
40
+ writesEligibilityTable ||=
41
+ options.eligibilityTables.has(table ?? '') ||
42
+ (ts.isTemplateExpression(node) && dynamicEligibilityTable(node, options));
43
+ }
44
+ }
45
+ ts.forEachChild(node, visit);
46
+ }
47
+ visit(ast);
48
+ return {
49
+ callsApprovedCaptureHelper: [...captureBindings].some((binding) => invokedIdentifiers.has(binding)),
50
+ optsOutOfPublicationCapture,
51
+ writesConfigEntityTable: hasConfigEntityTable && hasDmlPrefix,
52
+ writesGeneratedRelationTable: buildsRelationInsert || (appendsRelationTable && hasDmlPrefix),
53
+ writesEligibilityTable,
54
+ };
55
+ }
56
+ function collectCaptureBindings(node, bindings, options) {
57
+ if (!ts.isStringLiteral(node.moduleSpecifier) ||
58
+ !options.captureModules.has(node.moduleSpecifier.text))
59
+ return;
60
+ const namedBindings = node.importClause?.namedBindings;
61
+ if (!namedBindings || !ts.isNamedImports(namedBindings))
62
+ return;
63
+ for (const binding of namedBindings.elements) {
64
+ const importedName = binding.propertyName?.text ?? binding.name.text;
65
+ if (options.captureSymbols.has(importedName))
66
+ bindings.add(binding.name.text);
67
+ }
68
+ }
69
+ function isConfigEntityTableAssertion(node, options) {
70
+ return (ts.isIdentifier(node.expression) &&
71
+ node.expression.text === options.identifierAssertion &&
72
+ isConfigEntityTable(node.arguments[0], options));
73
+ }
74
+ function isRelationTableAppend(node, bindings, options) {
75
+ if (!ts.isPropertyAccessExpression(node.expression) ||
76
+ node.expression.name.text !== options.appendMethod)
77
+ return false;
78
+ const argument = node.arguments[0];
79
+ return (!!argument &&
80
+ (isRelationTableName(argument, options) ||
81
+ (ts.isIdentifier(argument) && bindings.has(argument.text))));
82
+ }
83
+ function isEntityRelationElectionTableIdentifier(initializer, options) {
84
+ return Boolean(initializer &&
85
+ ts.isCallExpression(initializer) &&
86
+ ts.isIdentifier(initializer.expression) &&
87
+ initializer.expression.text === options.identifierAssertion &&
88
+ initializer.arguments.some((argument) => ts.isIdentifier(argument) && argument.text === options.relationElectionAllowlist));
89
+ }
90
+ function isConfigEntityTable(node, options) {
91
+ return Boolean(node &&
92
+ ts.isPropertyAccessExpression(node) &&
93
+ node.name.text === options.entityTable.property &&
94
+ ts.isIdentifier(node.expression) &&
95
+ node.expression.text === options.entityTable.receiver);
96
+ }
97
+ function isRelationTableName(node, options) {
98
+ return Boolean(node &&
99
+ ts.isPropertyAccessExpression(node) &&
100
+ node.name.text === options.relationTable.property &&
101
+ ts.isIdentifier(node.expression) &&
102
+ node.expression.text === options.relationTable.receiver);
103
+ }
104
+ function isSqlTextNode(node) {
105
+ return (ts.isNoSubstitutionTemplateLiteral(node) ||
106
+ ts.isTemplateExpression(node) ||
107
+ ts.isStringLiteral(node));
108
+ }
109
+ function sqlText(node) {
110
+ if (ts.isStringLiteral(node))
111
+ return node.text;
112
+ return ts.isNoSubstitutionTemplateLiteral(node)
113
+ ? node.text
114
+ : [node.head.text, ...node.templateSpans.map((span) => span.literal.text)].join('');
115
+ }
116
+ function writtenTableName(text) {
117
+ return /\b(?:INSERT\s+INTO|UPDATE(?:\s+ONLY)?|DELETE\s+FROM)\s+(?:(?:"?[\w$]+"?\.)?"?)([\w$]+)"?/i
118
+ .exec(text)?.[1]
119
+ ?.toLowerCase();
120
+ }
121
+ function dynamicEligibilityTable(node, options) {
122
+ if (!/\b(?:INSERT\s+INTO|UPDATE(?:\s+ONLY)?|DELETE\s+FROM)\s+(?:(?:"?[\w$]+"?\.)?)$/i.test(node.head.text))
123
+ return false;
124
+ const expression = node.templateSpans[0]?.expression;
125
+ return (expression !== undefined &&
126
+ ts.isStringLiteral(expression) &&
127
+ options.eligibilityTables.has(expression.text));
128
+ }
@@ -0,0 +1,19 @@
1
+ /** All repository-specific names are explicit; SQL recognition preserves the inventory heuristic. */
2
+ export interface PostPublicationWriterSourceOptions {
3
+ captureModules: ReadonlySet<string>;
4
+ captureSymbols: ReadonlySet<string>;
5
+ eligibilityTables: ReadonlySet<string>;
6
+ captureOption: string;
7
+ insertBuilder: string;
8
+ identifierAssertion: string;
9
+ entityTable: {
10
+ receiver: string;
11
+ property: string;
12
+ };
13
+ relationTable: {
14
+ receiver: string;
15
+ property: string;
16
+ };
17
+ relationElectionAllowlist: string;
18
+ appendMethod: string;
19
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ # Basic Auth exemption facts
2
+
3
+ Import from `vouchington-tooling/basic-auth-doc-sync`. TypeScript source parsing uses
4
+ the optional `@typescript/typescript6` dependency. Markdown-only callers can import
5
+ `findRunbookExemptRoutes` from `vouchington-tooling/basic-auth-doc-sync/runbook`
6
+ without installing that optional compiler.
7
+
8
+ - `findBasicAuthExemptPaths(source, variableName)` returns the literal strings in a
9
+ top-level `const` initialized with `new Set([...])`.
10
+ - `findBasicAuthExemptMethodsByPath(source, variableName)` returns a map of literal
11
+ paths to literal uppercase HTTP method tokens from `new Map([[path, new Set([...])]])`.
12
+ - `findRunbookExemptRoutes(markdown, heading)` reads the first GFM table following
13
+ the configured real GFM level-three heading (case insensitive), stopping at the
14
+ next same-or-higher-level heading. Duplicate `Path` or `Methods` columns are rejected. Columns are named `Path`
15
+ and `Methods`; paths and comma-separated method tokens must be inline code.
16
+
17
+ All functions return `null` for absent or unsupported declarations/tables. Source
18
+ collections must be nonempty and contain only nonempty string literals or static
19
+ templates; dynamic expressions are rejected. Literal order and duplicate methods
20
+ or documentation rows are preserved for caller validation; repeated map keys follow
21
+ Map replacement semantics. The runbook reader accepts short table separators and CRLF.
22
+
23
+ Callers own symbol names, route inventory, document locations, comparisons, and
24
+ diagnostics. These functions return data without exposing AST nodes.
25
+
26
+ ## Source provenance
27
+
28
+ The fact readers were extracted from `vouchington/vouchington` at
29
+ `99a0948e4e3cc0c5b9791062df6e9de37e4cf3f1`:
30
+
31
+ - `static-code-analysis/targeted-guardrails/basic-auth-doc-sync-parsers.mts`
32
+ - `static-code-analysis/targeted-guardrails/basic-auth-doc-sync.test.mts`
33
+ - `static-code-analysis/targeted-guardrails/basic-auth-doc-sync-parser-edge.test.mts`
34
+
35
+ The original parser and its characterization tests informed the extraction. The
36
+ first extraction commit misspelled the edge-test basename in its provenance body;
37
+ the paths above are the authoritative source list.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vouchington-tooling",
3
- "version": "0.32.0",
3
+ "version": "0.34.0",
4
4
  "description": "Vouchington CLI and extractable tooling libraries.",
5
5
  "homepage": "https://github.com/vouchington/vouchington-tooling/tree/main/packages/vouchington-tooling#readme",
6
6
  "bugs": {
@@ -331,7 +331,27 @@
331
331
  "import": "./dist/gh-api-shell-quoting/index.mjs",
332
332
  "default": "./dist/gh-api-shell-quoting/index.mjs"
333
333
  },
334
- "./package.json": "./package.json"
334
+ "./package.json": "./package.json",
335
+ "./basic-auth-doc-sync": {
336
+ "types": "./dist/basic-auth-doc-sync/index.d.mts",
337
+ "import": "./dist/basic-auth-doc-sync/index.mjs",
338
+ "default": "./dist/basic-auth-doc-sync/index.mjs"
339
+ },
340
+ "./basic-auth-doc-sync/runbook": {
341
+ "types": "./dist/basic-auth-doc-sync/runbook.d.mts",
342
+ "import": "./dist/basic-auth-doc-sync/runbook.mjs",
343
+ "default": "./dist/basic-auth-doc-sync/runbook.mjs"
344
+ },
345
+ "./finite-enum-ripple": {
346
+ "types": "./dist/finite-enum-ripple/index.d.mts",
347
+ "import": "./dist/finite-enum-ripple/index.mjs",
348
+ "default": "./dist/finite-enum-ripple/index.mjs"
349
+ },
350
+ "./post-publication-inventory": {
351
+ "types": "./dist/post-publication-inventory/index.d.mts",
352
+ "import": "./dist/post-publication-inventory/index.mjs",
353
+ "default": "./dist/post-publication-inventory/index.mjs"
354
+ }
335
355
  },
336
356
  "publishConfig": {
337
357
  "access": "public"
@@ -359,7 +379,8 @@
359
379
  "@types/picomatch": "^4.0.3",
360
380
  "@types/spdx-expression-parse": "4.0.0",
361
381
  "agent-blackboard": "^0.6.0",
362
- "smol-toml": "1.9.0"
382
+ "smol-toml": "1.9.0",
383
+ "typescript5": "npm:typescript@5.9.3"
363
384
  },
364
385
  "peerDependencies": {
365
386
  "@modelcontextprotocol/sdk": "^1.31.0",