patram 0.1.1 → 0.3.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 (49) hide show
  1. package/lib/build-graph-identity.js +57 -24
  2. package/lib/build-graph.js +383 -17
  3. package/lib/build-graph.types.ts +5 -2
  4. package/lib/check-directive-metadata.js +516 -0
  5. package/lib/check-directive-value.js +282 -0
  6. package/lib/check-graph.js +24 -5
  7. package/lib/cli-help-metadata.js +580 -0
  8. package/lib/derived-summary.js +280 -0
  9. package/lib/directive-diagnostics.js +38 -0
  10. package/lib/directive-type-rules.js +133 -0
  11. package/lib/discover-fields.js +427 -0
  12. package/lib/discover-fields.types.ts +52 -0
  13. package/lib/format-derived-summary-row.js +9 -0
  14. package/lib/format-node-header.js +21 -0
  15. package/lib/format-output-item-block.js +22 -0
  16. package/lib/format-output-metadata.js +54 -0
  17. package/lib/layout-stored-queries.js +96 -2
  18. package/lib/load-patram-config.js +754 -18
  19. package/lib/load-patram-config.types.ts +128 -2
  20. package/lib/load-project-graph.js +4 -1
  21. package/lib/output-view.types.ts +29 -6
  22. package/lib/parse-cli-arguments-helpers.js +263 -90
  23. package/lib/parse-cli-arguments.js +160 -8
  24. package/lib/parse-cli-arguments.types.ts +49 -4
  25. package/lib/parse-where-clause.js +670 -209
  26. package/lib/parse-where-clause.types.ts +72 -0
  27. package/lib/patram-cli.js +180 -21
  28. package/lib/patram-config.js +31 -31
  29. package/lib/patram-config.types.ts +10 -4
  30. package/lib/patram.js +6 -0
  31. package/lib/query-graph.js +444 -113
  32. package/lib/query-inspection.js +798 -0
  33. package/lib/render-check-output.js +1 -1
  34. package/lib/render-cli-help.js +419 -0
  35. package/lib/render-field-discovery.js +148 -0
  36. package/lib/render-json-output.js +66 -14
  37. package/lib/render-output-view.js +272 -22
  38. package/lib/render-plain-output.js +31 -86
  39. package/lib/render-rich-output.js +34 -87
  40. package/lib/resolve-patram-graph-config.js +15 -9
  41. package/lib/resolve-where-clause.js +18 -3
  42. package/lib/show-document.js +51 -7
  43. package/lib/tagged-fenced-block-error.js +17 -0
  44. package/lib/tagged-fenced-block-markdown.js +111 -0
  45. package/lib/tagged-fenced-block-metadata.js +97 -0
  46. package/lib/tagged-fenced-block-parser.js +292 -0
  47. package/lib/tagged-fenced-blocks.js +100 -0
  48. package/lib/tagged-fenced-blocks.types.ts +38 -0
  49. package/package.json +12 -7
@@ -97,7 +97,7 @@ function createStoredQueryPhrases(where_clause) {
97
97
  }
98
98
 
99
99
  /**
100
- * @param {{ is_negated: boolean, term: { kind: 'field', field_name: 'id' | 'kind' | 'path' | 'status' | 'title', operator: '=' | '^=' | '~', value: string } | { kind: 'relation', relation_name: string } | { kind: 'relation_target', relation_name: string, target_id: string } }} clause
100
+ * @param {import('./parse-where-clause.types.ts').ParsedClause} clause
101
101
  * @param {boolean} should_prefix_and
102
102
  * @returns {StoredQuerySegment[]}
103
103
  */
@@ -121,10 +121,14 @@ function createClausePhrase(clause, should_prefix_and) {
121
121
  }
122
122
 
123
123
  /**
124
- * @param {{ kind: 'field', field_name: 'id' | 'kind' | 'path' | 'status' | 'title', operator: '=' | '^=' | '~', value: string } | { kind: 'relation', relation_name: string } | { kind: 'relation_target', relation_name: string, target_id: string }} term
124
+ * @param {import('./parse-where-clause.types.ts').ParsedTerm} term
125
125
  * @returns {StoredQuerySegment[]}
126
126
  */
127
127
  function createTermSegments(term) {
128
+ if (term.kind === 'aggregate') {
129
+ return createAggregateSegments(term);
130
+ }
131
+
128
132
  if (term.kind === 'field') {
129
133
  return [
130
134
  { kind: 'field_name', text: term.field_name },
@@ -133,6 +137,10 @@ function createTermSegments(term) {
133
137
  ];
134
138
  }
135
139
 
140
+ if (term.kind === 'field_set') {
141
+ return createFieldSetSegments(term);
142
+ }
143
+
136
144
  if (term.kind === 'relation_target') {
137
145
  return [
138
146
  { kind: 'field_name', text: term.relation_name },
@@ -147,6 +155,92 @@ function createTermSegments(term) {
147
155
  ];
148
156
  }
149
157
 
158
+ /**
159
+ * @param {import('./parse-where-clause.types.ts').ParsedFieldSetTerm} term
160
+ * @returns {StoredQuerySegment[]}
161
+ */
162
+ function createFieldSetSegments(term) {
163
+ return [
164
+ { kind: 'field_name', text: term.field_name },
165
+ { kind: 'plain', text: ' ' },
166
+ { kind: 'operator', text: term.operator },
167
+ { kind: 'plain', text: ' ' },
168
+ { kind: 'operator', text: '[' },
169
+ ...createListSegments(term.values),
170
+ { kind: 'operator', text: ']' },
171
+ ];
172
+ }
173
+
174
+ /**
175
+ * @param {import('./parse-where-clause.types.ts').ParsedAggregateTerm} term
176
+ * @returns {StoredQuerySegment[]}
177
+ */
178
+ function createAggregateSegments(term) {
179
+ /** @type {StoredQuerySegment[]} */
180
+ const segments = [
181
+ { kind: 'field_name', text: term.aggregate_name },
182
+ { kind: 'operator', text: '(' },
183
+ ...createTraversalSegments(term.traversal),
184
+ { kind: 'operator', text: ', ' },
185
+ ...createNestedClauseSegments(term.clauses),
186
+ { kind: 'operator', text: ')' },
187
+ ];
188
+
189
+ if (term.aggregate_name === 'count') {
190
+ segments.push({ kind: 'plain', text: ' ' });
191
+ segments.push({ kind: 'operator', text: term.comparison ?? '=' });
192
+ segments.push({ kind: 'plain', text: ' ' });
193
+ segments.push({ kind: 'literal', text: String(term.value ?? 0) });
194
+ }
195
+
196
+ return segments;
197
+ }
198
+
199
+ /**
200
+ * @param {{ direction: 'in' | 'out', relation_name: string }} traversal
201
+ * @returns {StoredQuerySegment[]}
202
+ */
203
+ function createTraversalSegments(traversal) {
204
+ return [
205
+ { kind: 'field_name', text: traversal.direction },
206
+ { kind: 'operator', text: ':' },
207
+ { kind: 'field_name', text: traversal.relation_name },
208
+ ];
209
+ }
210
+
211
+ /**
212
+ * @param {import('./parse-where-clause.types.ts').ParsedClause[]} clauses
213
+ * @returns {StoredQuerySegment[]}
214
+ */
215
+ function createNestedClauseSegments(clauses) {
216
+ return clauses.flatMap((clause, clause_index) => {
217
+ const clause_phrase = createClausePhrase(clause, clause_index > 0);
218
+
219
+ if (clause_index === 0) {
220
+ return clause_phrase;
221
+ }
222
+
223
+ return [{ kind: 'plain', text: ' ' }, ...clause_phrase];
224
+ });
225
+ }
226
+
227
+ /**
228
+ * @param {string[]} values
229
+ * @returns {StoredQuerySegment[]}
230
+ */
231
+ function createListSegments(values) {
232
+ return values.flatMap((value, value_index) => {
233
+ if (value_index === 0) {
234
+ return [{ kind: 'literal', text: value }];
235
+ }
236
+
237
+ return [
238
+ { kind: 'operator', text: ', ' },
239
+ { kind: 'literal', text: value },
240
+ ];
241
+ });
242
+ }
243
+
150
244
  /**
151
245
  * @param {string} where_clause
152
246
  * @returns {StoredQuerySegment[][]}