@newcms/query-engine 0.1.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.
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # @newcms/query-engine
2
+
3
+ Declarative, type-safe query engine for [NewCMS](https://github.com/durvs/newcms). Build complex content queries with taxonomy, meta, and date sub-queries — all compiled to efficient SQL via Drizzle ORM.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @newcms/query-engine @newcms/database
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { createConnection } from '@newcms/database';
15
+ import { QueryEngine } from '@newcms/query-engine';
16
+
17
+ const { db } = createConnection();
18
+ const engine = new QueryEngine(db);
19
+
20
+ // Get published posts, newest first
21
+ const result = await engine.query({
22
+ postType: 'post',
23
+ postStatus: 'publish',
24
+ perPage: 10,
25
+ page: 1,
26
+ });
27
+
28
+ console.log(result.posts); // Post[]
29
+ console.log(result.total); // Total matching posts
30
+ console.log(result.totalPages); // Total pages
31
+ console.log(result.flags); // { isHome, isSingle, isArchive, ... }
32
+ ```
33
+
34
+ ## Query Parameters
35
+
36
+ ```typescript
37
+ const result = await engine.query({
38
+ // Content type
39
+ postType: 'post', // string or string[]
40
+ postStatus: 'publish', // string or string[]
41
+
42
+ // Filters
43
+ author: 1, // number or number[]
44
+ search: 'hello world', // full-text search
45
+ slug: 'my-post', // string or string[]
46
+ parent: 0, // for hierarchical types
47
+ include: [1, 2, 3], // only these IDs
48
+ exclude: [4, 5], // not these IDs
49
+
50
+ // Pagination
51
+ perPage: 10, // -1 for all results
52
+ page: 1,
53
+
54
+ // Ordering
55
+ orderBy: 'date', // date | title | name | modified | id | author | menu_order
56
+ order: 'desc', // asc | desc
57
+ });
58
+ ```
59
+
60
+ ## Taxonomy Sub-Query
61
+
62
+ Filter posts by assigned terms:
63
+
64
+ ```typescript
65
+ const result = await engine.query({
66
+ tax: {
67
+ relation: 'AND', // all clauses must match
68
+ clauses: [
69
+ { taxonomy: 'category', termSlugs: ['news', 'tech'], operator: 'IN' },
70
+ { taxonomy: 'post_tag', termIds: [42], operator: 'IN' },
71
+ ],
72
+ },
73
+ });
74
+ ```
75
+
76
+ **Operators:**
77
+ - `IN` — post has any of the specified terms (default)
78
+ - `NOT IN` — post does NOT have any of the specified terms
79
+ - `AND` — post has ALL specified terms
80
+
81
+ ## Meta Sub-Query
82
+
83
+ Filter posts by metadata values:
84
+
85
+ ```typescript
86
+ const result = await engine.query({
87
+ meta: {
88
+ relation: 'AND',
89
+ clauses: [
90
+ { key: '_featured', compare: 'EXISTS' },
91
+ { key: 'rating', value: 4, compare: '>=', type: 'NUMERIC' },
92
+ { key: 'color', value: 'red', compare: '=' },
93
+ ],
94
+ },
95
+ });
96
+ ```
97
+
98
+ **Compare operators:** `=`, `!=`, `>`, `<`, `>=`, `<=`, `LIKE`, `NOT LIKE`, `IN`, `NOT IN`, `EXISTS`, `NOT EXISTS`
99
+
100
+ **Type casting:** `CHAR` (default), `NUMERIC`, `DATE`, `DATETIME`
101
+
102
+ ## Date Sub-Query
103
+
104
+ Filter posts by date:
105
+
106
+ ```typescript
107
+ const result = await engine.query({
108
+ date: {
109
+ relation: 'AND',
110
+ clauses: [
111
+ { year: 2026, month: 4 },
112
+ { after: '2026-01-01', before: '2026-12-31' },
113
+ { column: 'post_modified' }, // default: post_date
114
+ ],
115
+ },
116
+ });
117
+ ```
118
+
119
+ ## Query Flags
120
+
121
+ Every result includes flags indicating the query type:
122
+
123
+ ```typescript
124
+ result.flags.isHome // Default blog listing
125
+ result.flags.isSingle // Single post/page
126
+ result.flags.isArchive // Archive (author, taxonomy, date)
127
+ result.flags.isSearch // Search results
128
+ result.flags.is404 // No results found
129
+ result.flags.isPage // Page type query
130
+ result.flags.isAuthor // Author archive
131
+ result.flags.isTaxonomy // Taxonomy archive
132
+ result.flags.isDate // Date archive
133
+ ```
134
+
135
+ ## Single Post Query
136
+
137
+ ```typescript
138
+ const result = await engine.querySingle(42);
139
+ // Queries post ID 42 with status publish/private/draft
140
+ ```
141
+
142
+ ## License
143
+
144
+ GPL-2.0-or-later
@@ -0,0 +1,3 @@
1
+ export { QueryEngine } from './query-engine.js';
2
+ export type { QueryParams, QueryResult, QueryFlags, TaxQuery, TaxQueryClause, MetaQuery, MetaQueryClause, DateQuery, DateQueryClause, } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,QAAQ,EACR,cAAc,EACd,SAAS,EACT,eAAe,EACf,SAAS,EACT,eAAe,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { QueryEngine } from './query-engine.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Database } from '@newcms/database';
2
+ import type { QueryParams, QueryResult } from './types.js';
3
+ /**
4
+ * Declarative query engine for content.
5
+ *
6
+ * Accepts a `QueryParams` object and builds a type-safe SQL query
7
+ * via Drizzle ORM. Supports taxonomy sub-queries, meta sub-queries,
8
+ * date filters, full-text search, and pagination.
9
+ */
10
+ export declare class QueryEngine {
11
+ private db;
12
+ constructor(db: Database);
13
+ /**
14
+ * Execute a content query.
15
+ */
16
+ query(params?: QueryParams): Promise<QueryResult>;
17
+ /**
18
+ * Shorthand: query a single post by ID.
19
+ */
20
+ querySingle(id: number, postType?: string): Promise<QueryResult>;
21
+ private buildConditions;
22
+ private buildTaxConditions;
23
+ private buildMetaConditions;
24
+ private buildDateConditions;
25
+ private buildOrderBy;
26
+ private needsMetaJoin;
27
+ private needsTaxJoin;
28
+ private buildFlags;
29
+ }
30
+ //# sourceMappingURL=query-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-engine.d.ts","sourceRoot":"","sources":["../src/query-engine.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EACX,WAAW,EACX,WAAW,EAKX,MAAM,YAAY,CAAC;AAIpB;;;;;;GAMG;AACH,qBAAa,WAAW;IACX,OAAO,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ;IAEhC;;OAEG;IACG,KAAK,CAAC,MAAM,GAAE,WAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IA6E3D;;OAEG;IACG,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAWtE,OAAO,CAAC,eAAe;IA0FvB,OAAO,CAAC,kBAAkB;IAoD1B,OAAO,CAAC,mBAAmB;IAqD3B,OAAO,CAAC,mBAAmB;IAqC3B,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,UAAU;CAalB"}
@@ -0,0 +1,346 @@
1
+ import { eq, and, or, desc, asc, sql, inArray, like, gt, lt, notInArray } from 'drizzle-orm';
2
+ import { posts, postmeta, termRelationships, termTaxonomy, terms, } from '@newcms/database/schema';
3
+ const DEFAULT_PER_PAGE = 10;
4
+ /**
5
+ * Declarative query engine for content.
6
+ *
7
+ * Accepts a `QueryParams` object and builds a type-safe SQL query
8
+ * via Drizzle ORM. Supports taxonomy sub-queries, meta sub-queries,
9
+ * date filters, full-text search, and pagination.
10
+ */
11
+ export class QueryEngine {
12
+ db;
13
+ constructor(db) {
14
+ this.db = db;
15
+ }
16
+ /**
17
+ * Execute a content query.
18
+ */
19
+ async query(params = {}) {
20
+ const perPage = params.perPage === -1 ? 0 : (params.perPage ?? DEFAULT_PER_PAGE);
21
+ const page = params.page ?? 1;
22
+ const offset = perPage > 0 ? (page - 1) * perPage : 0;
23
+ const conditions = this.buildConditions(params);
24
+ const orderClause = this.buildOrderBy(params);
25
+ // Count total
26
+ const [countResult] = await this.db
27
+ .select({ count: sql `count(DISTINCT ${posts.id})::int` })
28
+ .from(posts)
29
+ .leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql `false`)
30
+ .leftJoin(termRelationships, this.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql `false`)
31
+ .where(conditions.length > 0 ? and(...conditions) : undefined);
32
+ const total = countResult.count;
33
+ const totalPages = perPage > 0 ? Math.ceil(total / perPage) : (total > 0 ? 1 : 0);
34
+ // Fetch posts
35
+ let query = this.db
36
+ .selectDistinct({
37
+ id: posts.id,
38
+ postAuthor: posts.postAuthor,
39
+ postDate: posts.postDate,
40
+ postDateGmt: posts.postDateGmt,
41
+ postContent: posts.postContent,
42
+ postTitle: posts.postTitle,
43
+ postExcerpt: posts.postExcerpt,
44
+ postStatus: posts.postStatus,
45
+ commentStatus: posts.commentStatus,
46
+ pingStatus: posts.pingStatus,
47
+ postPassword: posts.postPassword,
48
+ postName: posts.postName,
49
+ toPing: posts.toPing,
50
+ pinged: posts.pinged,
51
+ postModified: posts.postModified,
52
+ postModifiedGmt: posts.postModifiedGmt,
53
+ postContentFiltered: posts.postContentFiltered,
54
+ postParent: posts.postParent,
55
+ guid: posts.guid,
56
+ menuOrder: posts.menuOrder,
57
+ postType: posts.postType,
58
+ postMimeType: posts.postMimeType,
59
+ commentCount: posts.commentCount,
60
+ })
61
+ .from(posts)
62
+ .leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql `false`)
63
+ .leftJoin(termRelationships, this.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql `false`)
64
+ .where(conditions.length > 0 ? and(...conditions) : undefined)
65
+ .orderBy(orderClause)
66
+ .$dynamic();
67
+ if (perPage > 0) {
68
+ query = query.limit(perPage).offset(offset);
69
+ }
70
+ const rows = await query;
71
+ const flags = this.buildFlags(params, rows.length, total);
72
+ return {
73
+ posts: rows,
74
+ total,
75
+ totalPages,
76
+ page,
77
+ perPage: perPage || total,
78
+ flags,
79
+ };
80
+ }
81
+ /**
82
+ * Shorthand: query a single post by ID.
83
+ */
84
+ async querySingle(id, postType) {
85
+ return this.query({
86
+ include: [id],
87
+ postType: postType ?? 'post',
88
+ postStatus: ['publish', 'private', 'draft'],
89
+ perPage: 1,
90
+ });
91
+ }
92
+ // ─── Private: condition builders ─────────────────────────────
93
+ buildConditions(params) {
94
+ const conditions = [];
95
+ // Post type
96
+ const postType = params.postType ?? 'post';
97
+ if (Array.isArray(postType)) {
98
+ conditions.push(inArray(posts.postType, postType));
99
+ }
100
+ else {
101
+ conditions.push(eq(posts.postType, postType));
102
+ }
103
+ // Post status
104
+ const status = params.postStatus ?? 'publish';
105
+ if (Array.isArray(status)) {
106
+ conditions.push(inArray(posts.postStatus, status));
107
+ }
108
+ else {
109
+ conditions.push(eq(posts.postStatus, status));
110
+ }
111
+ // Author
112
+ if (params.author !== undefined) {
113
+ if (Array.isArray(params.author)) {
114
+ conditions.push(inArray(posts.postAuthor, params.author));
115
+ }
116
+ else {
117
+ conditions.push(eq(posts.postAuthor, params.author));
118
+ }
119
+ }
120
+ // Include/exclude IDs
121
+ if (params.include && params.include.length > 0) {
122
+ conditions.push(inArray(posts.id, params.include));
123
+ }
124
+ if (params.exclude && params.exclude.length > 0) {
125
+ conditions.push(notInArray(posts.id, params.exclude));
126
+ }
127
+ // Parent
128
+ if (params.parent !== undefined) {
129
+ conditions.push(eq(posts.postParent, params.parent));
130
+ }
131
+ // Slug
132
+ if (params.slug !== undefined) {
133
+ if (Array.isArray(params.slug)) {
134
+ conditions.push(inArray(posts.postName, params.slug));
135
+ }
136
+ else {
137
+ conditions.push(eq(posts.postName, params.slug));
138
+ }
139
+ }
140
+ // Search (full-text)
141
+ if (params.search) {
142
+ const searchTerm = params.search.replace(/[^\w\s]/g, '').trim();
143
+ if (searchTerm) {
144
+ conditions.push(or(like(posts.postTitle, `%${searchTerm}%`), like(posts.postContent, `%${searchTerm}%`)));
145
+ }
146
+ }
147
+ // Taxonomy sub-query
148
+ if (params.tax) {
149
+ const taxConditions = this.buildTaxConditions(params.tax);
150
+ if (taxConditions) {
151
+ conditions.push(taxConditions);
152
+ }
153
+ }
154
+ // Meta sub-query
155
+ if (params.meta) {
156
+ const metaConditions = this.buildMetaConditions(params.meta);
157
+ if (metaConditions) {
158
+ conditions.push(metaConditions);
159
+ }
160
+ }
161
+ // Date sub-query
162
+ if (params.date) {
163
+ const dateConditions = this.buildDateConditions(params.date);
164
+ if (dateConditions) {
165
+ conditions.push(dateConditions);
166
+ }
167
+ }
168
+ return conditions;
169
+ }
170
+ buildTaxConditions(tax) {
171
+ const clauseConditions = tax.clauses.map((clause) => {
172
+ const subConditions = [];
173
+ if (clause.termIds && clause.termIds.length > 0) {
174
+ // Sub-select to find term_taxonomy_ids for these term IDs
175
+ const ttIdSubquery = sql `${termRelationships.termTaxonomyId} IN (
176
+ SELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}
177
+ WHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}
178
+ AND ${termTaxonomy.termId} IN (${sql.join(clause.termIds.map((id) => sql `${id}`), sql `, `)})
179
+ )`;
180
+ if (clause.operator === 'NOT IN') {
181
+ subConditions.push(sql `${posts.id} NOT IN (
182
+ SELECT ${termRelationships.objectId} FROM ${termRelationships}
183
+ WHERE ${ttIdSubquery}
184
+ )`);
185
+ }
186
+ else {
187
+ subConditions.push(ttIdSubquery);
188
+ }
189
+ }
190
+ if (clause.termSlugs && clause.termSlugs.length > 0) {
191
+ const ttIdSubquery = sql `${termRelationships.termTaxonomyId} IN (
192
+ SELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}
193
+ INNER JOIN ${terms} ON ${terms.termId} = ${termTaxonomy.termId}
194
+ WHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}
195
+ AND ${terms.slug} IN (${sql.join(clause.termSlugs.map((s) => sql `${s}`), sql `, `)})
196
+ )`;
197
+ if (clause.operator === 'NOT IN') {
198
+ subConditions.push(sql `${posts.id} NOT IN (
199
+ SELECT ${termRelationships.objectId} FROM ${termRelationships}
200
+ WHERE ${ttIdSubquery}
201
+ )`);
202
+ }
203
+ else {
204
+ subConditions.push(ttIdSubquery);
205
+ }
206
+ }
207
+ return subConditions.length > 0 ? and(...subConditions) : undefined;
208
+ }).filter(Boolean);
209
+ if (clauseConditions.length === 0)
210
+ return undefined;
211
+ const relation = tax.relation ?? 'AND';
212
+ if (relation === 'OR') {
213
+ return or(...clauseConditions);
214
+ }
215
+ return and(...clauseConditions);
216
+ }
217
+ buildMetaConditions(meta) {
218
+ const clauseConditions = meta.clauses.map((clause) => {
219
+ if (clause.compare === 'EXISTS') {
220
+ return sql `${posts.id} IN (
221
+ SELECT ${postmeta.postId} FROM ${postmeta}
222
+ WHERE ${postmeta.metaKey} = ${clause.key}
223
+ )`;
224
+ }
225
+ if (clause.compare === 'NOT EXISTS') {
226
+ return sql `${posts.id} NOT IN (
227
+ SELECT ${postmeta.postId} FROM ${postmeta}
228
+ WHERE ${postmeta.metaKey} = ${clause.key}
229
+ )`;
230
+ }
231
+ const valueStr = String(clause.value ?? '');
232
+ const compare = clause.compare ?? '=';
233
+ const castCol = clause.type === 'NUMERIC'
234
+ ? sql `CAST(${postmeta.metaValue} AS NUMERIC)`
235
+ : postmeta.metaValue;
236
+ const compareValue = clause.type === 'NUMERIC'
237
+ ? sql `CAST(${valueStr} AS NUMERIC)`
238
+ : sql `${valueStr}`;
239
+ let condition;
240
+ switch (compare) {
241
+ case '=':
242
+ condition = sql `${castCol} = ${compareValue}`;
243
+ break;
244
+ case '!=':
245
+ condition = sql `${castCol} != ${compareValue}`;
246
+ break;
247
+ case '>':
248
+ condition = sql `${castCol} > ${compareValue}`;
249
+ break;
250
+ case '<':
251
+ condition = sql `${castCol} < ${compareValue}`;
252
+ break;
253
+ case '>=':
254
+ condition = sql `${castCol} >= ${compareValue}`;
255
+ break;
256
+ case '<=':
257
+ condition = sql `${castCol} <= ${compareValue}`;
258
+ break;
259
+ case 'LIKE':
260
+ condition = sql `${postmeta.metaValue} LIKE ${valueStr}`;
261
+ break;
262
+ case 'NOT LIKE':
263
+ condition = sql `${postmeta.metaValue} NOT LIKE ${valueStr}`;
264
+ break;
265
+ default: condition = sql `${castCol} = ${compareValue}`;
266
+ }
267
+ return sql `${posts.id} IN (
268
+ SELECT ${postmeta.postId} FROM ${postmeta}
269
+ WHERE ${postmeta.metaKey} = ${clause.key} AND ${condition}
270
+ )`;
271
+ }).filter(Boolean);
272
+ if (clauseConditions.length === 0)
273
+ return undefined;
274
+ const relation = meta.relation ?? 'AND';
275
+ if (relation === 'OR') {
276
+ return or(...clauseConditions);
277
+ }
278
+ return and(...clauseConditions);
279
+ }
280
+ buildDateConditions(date) {
281
+ const clauseConditions = date.clauses.map((clause) => {
282
+ const col = clause.column === 'post_modified' ? posts.postModified : posts.postDate;
283
+ const conditions = [];
284
+ if (clause.year !== undefined) {
285
+ conditions.push(sql `EXTRACT(YEAR FROM ${col}) = ${clause.year}`);
286
+ }
287
+ if (clause.month !== undefined) {
288
+ conditions.push(sql `EXTRACT(MONTH FROM ${col}) = ${clause.month}`);
289
+ }
290
+ if (clause.day !== undefined) {
291
+ conditions.push(sql `EXTRACT(DAY FROM ${col}) = ${clause.day}`);
292
+ }
293
+ if (clause.after !== undefined) {
294
+ const afterDate = clause.after instanceof Date ? clause.after : new Date(clause.after);
295
+ conditions.push(gt(col, afterDate));
296
+ }
297
+ if (clause.before !== undefined) {
298
+ const beforeDate = clause.before instanceof Date ? clause.before : new Date(clause.before);
299
+ conditions.push(lt(col, beforeDate));
300
+ }
301
+ return conditions.length > 0 ? and(...conditions) : undefined;
302
+ }).filter(Boolean);
303
+ if (clauseConditions.length === 0)
304
+ return undefined;
305
+ const relation = date.relation ?? 'AND';
306
+ if (relation === 'OR') {
307
+ return or(...clauseConditions);
308
+ }
309
+ return and(...clauseConditions);
310
+ }
311
+ // ─── Private: order by ───────────────────────────────────────
312
+ buildOrderBy(params) {
313
+ const direction = params.order === 'asc' ? asc : desc;
314
+ switch (params.orderBy) {
315
+ case 'title': return direction(posts.postTitle);
316
+ case 'name': return direction(posts.postName);
317
+ case 'modified': return direction(posts.postModified);
318
+ case 'id': return direction(posts.id);
319
+ case 'author': return direction(posts.postAuthor);
320
+ case 'menu_order': return direction(posts.menuOrder);
321
+ case 'date':
322
+ default: return direction(posts.postDate);
323
+ }
324
+ }
325
+ // ─── Private: join detection ─────────────────────────────────
326
+ needsMetaJoin(params) {
327
+ return params.meta !== undefined && params.meta.clauses.length > 0;
328
+ }
329
+ needsTaxJoin(params) {
330
+ return params.tax !== undefined && params.tax.clauses.length > 0;
331
+ }
332
+ // ─── Private: query flags ────────────────────────────────────
333
+ buildFlags(params, resultCount, _total) {
334
+ const isSearch = Boolean(params.search);
335
+ const isSingle = (params.include?.length === 1 || params.slug !== undefined) && !Array.isArray(params.slug);
336
+ const isAuthor = params.author !== undefined;
337
+ const isTaxonomy = params.tax !== undefined;
338
+ const isDate = params.date !== undefined;
339
+ const isPage = params.postType === 'page';
340
+ const is404 = resultCount === 0;
341
+ const isHome = !isSearch && !isSingle && !isAuthor && !isTaxonomy && !isDate && params.postType === 'post';
342
+ const isArchive = !isSingle && (isAuthor || isTaxonomy || isDate);
343
+ return { isSingle, isArchive, isSearch, is404, isHome, isPage, isAuthor, isTaxonomy, isDate };
344
+ }
345
+ }
346
+ //# sourceMappingURL=query-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-engine.js","sourceRoot":"","sources":["../src/query-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Parameters for a content query.
3
+ */
4
+ export interface QueryParams {
5
+ /** Post type(s) to query. Default: 'post' */
6
+ postType?: string | string[];
7
+ /** Post status(es). Default: 'publish' */
8
+ postStatus?: string | string[];
9
+ /** Filter by author ID(s) */
10
+ author?: number | number[];
11
+ /** Search term (full-text search) */
12
+ search?: string;
13
+ /** Number of results per page. Default: 10. Use -1 for all. */
14
+ perPage?: number;
15
+ /** Page number (1-based). Default: 1 */
16
+ page?: number;
17
+ /** Order by field. Default: 'date' */
18
+ orderBy?: 'date' | 'title' | 'name' | 'modified' | 'id' | 'author' | 'menu_order' | 'relevance';
19
+ /** Order direction. Default: 'desc' */
20
+ order?: 'asc' | 'desc';
21
+ /** Include only these post IDs */
22
+ include?: number[];
23
+ /** Exclude these post IDs */
24
+ exclude?: number[];
25
+ /** Filter by parent ID (for hierarchical types) */
26
+ parent?: number;
27
+ /** Filter by slug(s) */
28
+ slug?: string | string[];
29
+ /** Only sticky posts */
30
+ stickyOnly?: boolean;
31
+ /** Taxonomy sub-query */
32
+ tax?: TaxQuery;
33
+ /** Meta sub-query */
34
+ meta?: MetaQuery;
35
+ /** Date sub-query */
36
+ date?: DateQuery;
37
+ /** Specific fields to return (optimization) */
38
+ fields?: 'all' | 'ids';
39
+ }
40
+ /**
41
+ * Taxonomy sub-query — filter posts by term assignments.
42
+ */
43
+ export interface TaxQuery {
44
+ /** How to combine multiple clauses: AND = all must match, OR = any can match */
45
+ relation?: 'AND' | 'OR';
46
+ clauses: TaxQueryClause[];
47
+ }
48
+ export interface TaxQueryClause {
49
+ taxonomy: string;
50
+ /** Term IDs to match */
51
+ termIds?: number[];
52
+ /** Term slugs to match */
53
+ termSlugs?: string[];
54
+ /** Operator: IN = has any of these terms, NOT IN = doesn't have these */
55
+ operator?: 'IN' | 'NOT IN' | 'AND';
56
+ /** Include children of hierarchical terms */
57
+ includeChildren?: boolean;
58
+ }
59
+ /**
60
+ * Meta sub-query — filter posts by metadata values.
61
+ */
62
+ export interface MetaQuery {
63
+ relation?: 'AND' | 'OR';
64
+ clauses: MetaQueryClause[];
65
+ }
66
+ export interface MetaQueryClause {
67
+ key: string;
68
+ value?: string | number | boolean;
69
+ compare?: '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE' | 'NOT LIKE' | 'IN' | 'NOT IN' | 'EXISTS' | 'NOT EXISTS';
70
+ /** Cast type for comparison */
71
+ type?: 'CHAR' | 'NUMERIC' | 'DATE' | 'DATETIME';
72
+ }
73
+ /**
74
+ * Date sub-query — filter posts by date ranges.
75
+ */
76
+ export interface DateQuery {
77
+ relation?: 'AND' | 'OR';
78
+ clauses: DateQueryClause[];
79
+ }
80
+ export interface DateQueryClause {
81
+ year?: number;
82
+ month?: number;
83
+ day?: number;
84
+ after?: string | Date;
85
+ before?: string | Date;
86
+ column?: 'post_date' | 'post_modified';
87
+ }
88
+ /**
89
+ * Result of a content query.
90
+ */
91
+ export interface QueryResult<T = unknown> {
92
+ /** The matched posts */
93
+ posts: T[];
94
+ /** Total number of matching posts (ignoring pagination) */
95
+ total: number;
96
+ /** Total number of pages */
97
+ totalPages: number;
98
+ /** Current page */
99
+ page: number;
100
+ /** Posts per page */
101
+ perPage: number;
102
+ /** Query type flags */
103
+ flags: QueryFlags;
104
+ }
105
+ /**
106
+ * Flags indicating the type of query result.
107
+ */
108
+ export interface QueryFlags {
109
+ isSingle: boolean;
110
+ isArchive: boolean;
111
+ isSearch: boolean;
112
+ is404: boolean;
113
+ isHome: boolean;
114
+ isPage: boolean;
115
+ isAuthor: boolean;
116
+ isTaxonomy: boolean;
117
+ isDate: boolean;
118
+ }
119
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@newcms/query-engine",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Declarative query engine for NewCMS — type-safe content queries with taxonomy, meta, and date sub-queries",
6
+ "license": "GPL-2.0-or-later",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/durvs/newcms.git",
10
+ "directory": "packages/query-engine"
11
+ },
12
+ "keywords": [
13
+ "cms",
14
+ "query",
15
+ "drizzle",
16
+ "postgres",
17
+ "newcms"
18
+ ],
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md"
28
+ ],
29
+ "dependencies": {
30
+ "drizzle-orm": "^0.44.2",
31
+ "postgres": "^3.4.7"
32
+ },
33
+ "peerDependencies": {
34
+ "@newcms/database": ">=0.0.2"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.15.3",
38
+ "dotenv": "^16.5.0",
39
+ "typescript": "^5.9.3",
40
+ "vitest": "^3.2.4",
41
+ "@newcms/config": "0.0.1",
42
+ "@newcms/database": "0.1.0"
43
+ },
44
+ "scripts": {
45
+ "build": "tsc",
46
+ "dev": "tsc --watch",
47
+ "typecheck": "tsc --noEmit",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "lint": "echo 'lint ok'",
51
+ "clean": "rm -rf dist .turbo"
52
+ }
53
+ }