@newcms/query-engine 0.1.0 → 0.2.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/dist/index.cjs +351 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{types.d.ts → index.d.cts} +41 -10
- package/dist/index.d.ts +150 -3
- package/dist/index.js +329 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/query-engine.d.ts +0 -30
- package/dist/query-engine.d.ts.map +0 -1
- package/dist/query-engine.js +0 -346
- package/dist/query-engine.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,2 +1,330 @@
|
|
|
1
|
-
|
|
1
|
+
// src/query-engine.ts
|
|
2
|
+
import { eq, and, or, desc, asc, sql, inArray, like, gt, lt, notInArray } from "drizzle-orm";
|
|
3
|
+
import {
|
|
4
|
+
posts,
|
|
5
|
+
postmeta,
|
|
6
|
+
termRelationships,
|
|
7
|
+
termTaxonomy,
|
|
8
|
+
terms
|
|
9
|
+
} from "@newcms/database";
|
|
10
|
+
var DEFAULT_PER_PAGE = 10;
|
|
11
|
+
var QueryEngine = class {
|
|
12
|
+
constructor(db) {
|
|
13
|
+
this.db = db;
|
|
14
|
+
}
|
|
15
|
+
db;
|
|
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
|
+
const [countResult] = await this.db.select({ count: sql`count(DISTINCT ${posts.id})::int` }).from(posts).leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql`false`).leftJoin(
|
|
26
|
+
termRelationships,
|
|
27
|
+
this.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql`false`
|
|
28
|
+
).where(conditions.length > 0 ? and(...conditions) : void 0);
|
|
29
|
+
const total = countResult.count;
|
|
30
|
+
const totalPages = perPage > 0 ? Math.ceil(total / perPage) : total > 0 ? 1 : 0;
|
|
31
|
+
let query = this.db.selectDistinct({
|
|
32
|
+
id: posts.id,
|
|
33
|
+
postAuthor: posts.postAuthor,
|
|
34
|
+
postDate: posts.postDate,
|
|
35
|
+
postDateGmt: posts.postDateGmt,
|
|
36
|
+
postContent: posts.postContent,
|
|
37
|
+
postTitle: posts.postTitle,
|
|
38
|
+
postExcerpt: posts.postExcerpt,
|
|
39
|
+
postStatus: posts.postStatus,
|
|
40
|
+
commentStatus: posts.commentStatus,
|
|
41
|
+
pingStatus: posts.pingStatus,
|
|
42
|
+
postPassword: posts.postPassword,
|
|
43
|
+
postName: posts.postName,
|
|
44
|
+
toPing: posts.toPing,
|
|
45
|
+
pinged: posts.pinged,
|
|
46
|
+
postModified: posts.postModified,
|
|
47
|
+
postModifiedGmt: posts.postModifiedGmt,
|
|
48
|
+
postContentFiltered: posts.postContentFiltered,
|
|
49
|
+
postParent: posts.postParent,
|
|
50
|
+
guid: posts.guid,
|
|
51
|
+
menuOrder: posts.menuOrder,
|
|
52
|
+
postType: posts.postType,
|
|
53
|
+
postMimeType: posts.postMimeType,
|
|
54
|
+
commentCount: posts.commentCount
|
|
55
|
+
}).from(posts).leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql`false`).leftJoin(
|
|
56
|
+
termRelationships,
|
|
57
|
+
this.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql`false`
|
|
58
|
+
).where(conditions.length > 0 ? and(...conditions) : void 0).orderBy(orderClause).$dynamic();
|
|
59
|
+
if (perPage > 0) {
|
|
60
|
+
query = query.limit(perPage).offset(offset);
|
|
61
|
+
}
|
|
62
|
+
const rows = await query;
|
|
63
|
+
const flags = this.buildFlags(params, rows.length, total);
|
|
64
|
+
return {
|
|
65
|
+
posts: rows,
|
|
66
|
+
total,
|
|
67
|
+
totalPages,
|
|
68
|
+
page,
|
|
69
|
+
perPage: perPage || total,
|
|
70
|
+
flags
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Shorthand: query a single post by ID.
|
|
75
|
+
*/
|
|
76
|
+
async querySingle(id, postType) {
|
|
77
|
+
return this.query({
|
|
78
|
+
include: [id],
|
|
79
|
+
postType: postType ?? "post",
|
|
80
|
+
postStatus: ["publish", "private", "draft"],
|
|
81
|
+
perPage: 1
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// ─── Private: condition builders ─────────────────────────────
|
|
85
|
+
buildConditions(params) {
|
|
86
|
+
const conditions = [];
|
|
87
|
+
const postType = params.postType ?? "post";
|
|
88
|
+
if (Array.isArray(postType)) {
|
|
89
|
+
conditions.push(inArray(posts.postType, postType));
|
|
90
|
+
} else {
|
|
91
|
+
conditions.push(eq(posts.postType, postType));
|
|
92
|
+
}
|
|
93
|
+
const status = params.postStatus ?? "publish";
|
|
94
|
+
if (Array.isArray(status)) {
|
|
95
|
+
conditions.push(inArray(posts.postStatus, status));
|
|
96
|
+
} else {
|
|
97
|
+
conditions.push(eq(posts.postStatus, status));
|
|
98
|
+
}
|
|
99
|
+
if (params.author !== void 0) {
|
|
100
|
+
if (Array.isArray(params.author)) {
|
|
101
|
+
conditions.push(inArray(posts.postAuthor, params.author));
|
|
102
|
+
} else {
|
|
103
|
+
conditions.push(eq(posts.postAuthor, params.author));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (params.include && params.include.length > 0) {
|
|
107
|
+
conditions.push(inArray(posts.id, params.include));
|
|
108
|
+
}
|
|
109
|
+
if (params.exclude && params.exclude.length > 0) {
|
|
110
|
+
conditions.push(notInArray(posts.id, params.exclude));
|
|
111
|
+
}
|
|
112
|
+
if (params.parent !== void 0) {
|
|
113
|
+
conditions.push(eq(posts.postParent, params.parent));
|
|
114
|
+
}
|
|
115
|
+
if (params.slug !== void 0) {
|
|
116
|
+
if (Array.isArray(params.slug)) {
|
|
117
|
+
conditions.push(inArray(posts.postName, params.slug));
|
|
118
|
+
} else {
|
|
119
|
+
conditions.push(eq(posts.postName, params.slug));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (params.search) {
|
|
123
|
+
const searchTerm = params.search.replace(/[^\w\s]/g, "").trim();
|
|
124
|
+
if (searchTerm) {
|
|
125
|
+
conditions.push(
|
|
126
|
+
or(
|
|
127
|
+
like(posts.postTitle, `%${searchTerm}%`),
|
|
128
|
+
like(posts.postContent, `%${searchTerm}%`)
|
|
129
|
+
)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (params.tax) {
|
|
134
|
+
const taxConditions = this.buildTaxConditions(params.tax);
|
|
135
|
+
if (taxConditions) {
|
|
136
|
+
conditions.push(taxConditions);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (params.meta) {
|
|
140
|
+
const metaConditions = this.buildMetaConditions(params.meta);
|
|
141
|
+
if (metaConditions) {
|
|
142
|
+
conditions.push(metaConditions);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (params.date) {
|
|
146
|
+
const dateConditions = this.buildDateConditions(params.date);
|
|
147
|
+
if (dateConditions) {
|
|
148
|
+
conditions.push(dateConditions);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return conditions;
|
|
152
|
+
}
|
|
153
|
+
buildTaxConditions(tax) {
|
|
154
|
+
const clauseConditions = tax.clauses.map((clause) => {
|
|
155
|
+
const subConditions = [];
|
|
156
|
+
if (clause.termIds && clause.termIds.length > 0) {
|
|
157
|
+
const ttIdSubquery = sql`${termRelationships.termTaxonomyId} IN (
|
|
158
|
+
SELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}
|
|
159
|
+
WHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}
|
|
160
|
+
AND ${termTaxonomy.termId} IN (${sql.join(clause.termIds.map((id) => sql`${id}`), sql`, `)})
|
|
161
|
+
)`;
|
|
162
|
+
if (clause.operator === "NOT IN") {
|
|
163
|
+
subConditions.push(sql`${posts.id} NOT IN (
|
|
164
|
+
SELECT ${termRelationships.objectId} FROM ${termRelationships}
|
|
165
|
+
WHERE ${ttIdSubquery}
|
|
166
|
+
)`);
|
|
167
|
+
} else {
|
|
168
|
+
subConditions.push(ttIdSubquery);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (clause.termSlugs && clause.termSlugs.length > 0) {
|
|
172
|
+
const ttIdSubquery = sql`${termRelationships.termTaxonomyId} IN (
|
|
173
|
+
SELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}
|
|
174
|
+
INNER JOIN ${terms} ON ${terms.termId} = ${termTaxonomy.termId}
|
|
175
|
+
WHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}
|
|
176
|
+
AND ${terms.slug} IN (${sql.join(clause.termSlugs.map((s) => sql`${s}`), sql`, `)})
|
|
177
|
+
)`;
|
|
178
|
+
if (clause.operator === "NOT IN") {
|
|
179
|
+
subConditions.push(sql`${posts.id} NOT IN (
|
|
180
|
+
SELECT ${termRelationships.objectId} FROM ${termRelationships}
|
|
181
|
+
WHERE ${ttIdSubquery}
|
|
182
|
+
)`);
|
|
183
|
+
} else {
|
|
184
|
+
subConditions.push(ttIdSubquery);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return subConditions.length > 0 ? and(...subConditions) : void 0;
|
|
188
|
+
}).filter(Boolean);
|
|
189
|
+
if (clauseConditions.length === 0) return void 0;
|
|
190
|
+
const relation = tax.relation ?? "AND";
|
|
191
|
+
if (relation === "OR") {
|
|
192
|
+
return or(...clauseConditions);
|
|
193
|
+
}
|
|
194
|
+
return and(...clauseConditions);
|
|
195
|
+
}
|
|
196
|
+
buildMetaConditions(meta) {
|
|
197
|
+
const clauseConditions = meta.clauses.map((clause) => {
|
|
198
|
+
if (clause.compare === "EXISTS") {
|
|
199
|
+
return sql`${posts.id} IN (
|
|
200
|
+
SELECT ${postmeta.postId} FROM ${postmeta}
|
|
201
|
+
WHERE ${postmeta.metaKey} = ${clause.key}
|
|
202
|
+
)`;
|
|
203
|
+
}
|
|
204
|
+
if (clause.compare === "NOT EXISTS") {
|
|
205
|
+
return sql`${posts.id} NOT IN (
|
|
206
|
+
SELECT ${postmeta.postId} FROM ${postmeta}
|
|
207
|
+
WHERE ${postmeta.metaKey} = ${clause.key}
|
|
208
|
+
)`;
|
|
209
|
+
}
|
|
210
|
+
const valueStr = String(clause.value ?? "");
|
|
211
|
+
const compare = clause.compare ?? "=";
|
|
212
|
+
const castCol = clause.type === "NUMERIC" ? sql`CAST(${postmeta.metaValue} AS NUMERIC)` : postmeta.metaValue;
|
|
213
|
+
const compareValue = clause.type === "NUMERIC" ? sql`CAST(${valueStr} AS NUMERIC)` : sql`${valueStr}`;
|
|
214
|
+
let condition;
|
|
215
|
+
switch (compare) {
|
|
216
|
+
case "=":
|
|
217
|
+
condition = sql`${castCol} = ${compareValue}`;
|
|
218
|
+
break;
|
|
219
|
+
case "!=":
|
|
220
|
+
condition = sql`${castCol} != ${compareValue}`;
|
|
221
|
+
break;
|
|
222
|
+
case ">":
|
|
223
|
+
condition = sql`${castCol} > ${compareValue}`;
|
|
224
|
+
break;
|
|
225
|
+
case "<":
|
|
226
|
+
condition = sql`${castCol} < ${compareValue}`;
|
|
227
|
+
break;
|
|
228
|
+
case ">=":
|
|
229
|
+
condition = sql`${castCol} >= ${compareValue}`;
|
|
230
|
+
break;
|
|
231
|
+
case "<=":
|
|
232
|
+
condition = sql`${castCol} <= ${compareValue}`;
|
|
233
|
+
break;
|
|
234
|
+
case "LIKE":
|
|
235
|
+
condition = sql`${postmeta.metaValue} LIKE ${valueStr}`;
|
|
236
|
+
break;
|
|
237
|
+
case "NOT LIKE":
|
|
238
|
+
condition = sql`${postmeta.metaValue} NOT LIKE ${valueStr}`;
|
|
239
|
+
break;
|
|
240
|
+
default:
|
|
241
|
+
condition = sql`${castCol} = ${compareValue}`;
|
|
242
|
+
}
|
|
243
|
+
return sql`${posts.id} IN (
|
|
244
|
+
SELECT ${postmeta.postId} FROM ${postmeta}
|
|
245
|
+
WHERE ${postmeta.metaKey} = ${clause.key} AND ${condition}
|
|
246
|
+
)`;
|
|
247
|
+
}).filter(Boolean);
|
|
248
|
+
if (clauseConditions.length === 0) return void 0;
|
|
249
|
+
const relation = meta.relation ?? "AND";
|
|
250
|
+
if (relation === "OR") {
|
|
251
|
+
return or(...clauseConditions);
|
|
252
|
+
}
|
|
253
|
+
return and(...clauseConditions);
|
|
254
|
+
}
|
|
255
|
+
buildDateConditions(date) {
|
|
256
|
+
const clauseConditions = date.clauses.map((clause) => {
|
|
257
|
+
const col = clause.column === "post_modified" ? posts.postModified : posts.postDate;
|
|
258
|
+
const conditions = [];
|
|
259
|
+
if (clause.year !== void 0) {
|
|
260
|
+
conditions.push(sql`EXTRACT(YEAR FROM ${col}) = ${clause.year}`);
|
|
261
|
+
}
|
|
262
|
+
if (clause.month !== void 0) {
|
|
263
|
+
conditions.push(sql`EXTRACT(MONTH FROM ${col}) = ${clause.month}`);
|
|
264
|
+
}
|
|
265
|
+
if (clause.day !== void 0) {
|
|
266
|
+
conditions.push(sql`EXTRACT(DAY FROM ${col}) = ${clause.day}`);
|
|
267
|
+
}
|
|
268
|
+
if (clause.after !== void 0) {
|
|
269
|
+
const afterDate = clause.after instanceof Date ? clause.after : new Date(clause.after);
|
|
270
|
+
conditions.push(gt(col, afterDate));
|
|
271
|
+
}
|
|
272
|
+
if (clause.before !== void 0) {
|
|
273
|
+
const beforeDate = clause.before instanceof Date ? clause.before : new Date(clause.before);
|
|
274
|
+
conditions.push(lt(col, beforeDate));
|
|
275
|
+
}
|
|
276
|
+
return conditions.length > 0 ? and(...conditions) : void 0;
|
|
277
|
+
}).filter(Boolean);
|
|
278
|
+
if (clauseConditions.length === 0) return void 0;
|
|
279
|
+
const relation = date.relation ?? "AND";
|
|
280
|
+
if (relation === "OR") {
|
|
281
|
+
return or(...clauseConditions);
|
|
282
|
+
}
|
|
283
|
+
return and(...clauseConditions);
|
|
284
|
+
}
|
|
285
|
+
// ─── Private: order by ───────────────────────────────────────
|
|
286
|
+
buildOrderBy(params) {
|
|
287
|
+
const direction = params.order === "asc" ? asc : desc;
|
|
288
|
+
switch (params.orderBy) {
|
|
289
|
+
case "title":
|
|
290
|
+
return direction(posts.postTitle);
|
|
291
|
+
case "name":
|
|
292
|
+
return direction(posts.postName);
|
|
293
|
+
case "modified":
|
|
294
|
+
return direction(posts.postModified);
|
|
295
|
+
case "id":
|
|
296
|
+
return direction(posts.id);
|
|
297
|
+
case "author":
|
|
298
|
+
return direction(posts.postAuthor);
|
|
299
|
+
case "menu_order":
|
|
300
|
+
return direction(posts.menuOrder);
|
|
301
|
+
case "date":
|
|
302
|
+
default:
|
|
303
|
+
return direction(posts.postDate);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// ─── Private: join detection ─────────────────────────────────
|
|
307
|
+
needsMetaJoin(params) {
|
|
308
|
+
return params.meta !== void 0 && params.meta.clauses.length > 0;
|
|
309
|
+
}
|
|
310
|
+
needsTaxJoin(params) {
|
|
311
|
+
return params.tax !== void 0 && params.tax.clauses.length > 0;
|
|
312
|
+
}
|
|
313
|
+
// ─── Private: query flags ────────────────────────────────────
|
|
314
|
+
buildFlags(params, resultCount, _total) {
|
|
315
|
+
const isSearch = Boolean(params.search);
|
|
316
|
+
const isSingle = (params.include?.length === 1 || params.slug !== void 0) && !Array.isArray(params.slug);
|
|
317
|
+
const isAuthor = params.author !== void 0;
|
|
318
|
+
const isTaxonomy = params.tax !== void 0;
|
|
319
|
+
const isDate = params.date !== void 0;
|
|
320
|
+
const isPage = params.postType === "page";
|
|
321
|
+
const is404 = resultCount === 0;
|
|
322
|
+
const isHome = !isSearch && !isSingle && !isAuthor && !isTaxonomy && !isDate && params.postType === "post";
|
|
323
|
+
const isArchive = !isSingle && (isAuthor || isTaxonomy || isDate);
|
|
324
|
+
return { isSingle, isArchive, isSearch, is404, isHome, isPage, isAuthor, isTaxonomy, isDate };
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
export {
|
|
328
|
+
QueryEngine
|
|
329
|
+
};
|
|
2
330
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"sources":["../src/query-engine.ts"],"sourcesContent":["import { eq, and, or, desc, asc, sql, inArray, like, gt, lt, notInArray } from 'drizzle-orm';\nimport {\n\tposts,\n\tpostmeta,\n\ttermRelationships,\n\ttermTaxonomy,\n\tterms,\n} from '@newcms/database';\nimport type { Database } from '@newcms/database';\nimport type {\n\tQueryParams,\n\tQueryResult,\n\tQueryFlags,\n\tTaxQuery,\n\tMetaQuery,\n\tDateQuery,\n} from './types';\n\nconst DEFAULT_PER_PAGE = 10;\n\n/**\n * Declarative query engine for content.\n *\n * Accepts a `QueryParams` object and builds a type-safe SQL query\n * via Drizzle ORM. Supports taxonomy sub-queries, meta sub-queries,\n * date filters, full-text search, and pagination.\n */\nexport class QueryEngine {\n\tconstructor(private db: Database) {}\n\n\t/**\n\t * Execute a content query.\n\t */\n\tasync query(params: QueryParams = {}): Promise<QueryResult> {\n\t\tconst perPage = params.perPage === -1 ? 0 : (params.perPage ?? DEFAULT_PER_PAGE);\n\t\tconst page = params.page ?? 1;\n\t\tconst offset = perPage > 0 ? (page - 1) * perPage : 0;\n\n\t\tconst conditions = this.buildConditions(params);\n\t\tconst orderClause = this.buildOrderBy(params);\n\n\t\t// Count total\n\t\tconst [countResult] = await this.db\n\t\t\t.select({ count: sql<number>`count(DISTINCT ${posts.id})::int` })\n\t\t\t.from(posts)\n\t\t\t.leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql`false`)\n\t\t\t.leftJoin(\n\t\t\t\ttermRelationships,\n\t\t\t\tthis.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql`false`,\n\t\t\t)\n\t\t\t.where(conditions.length > 0 ? and(...conditions) : undefined);\n\n\t\tconst total = countResult.count;\n\t\tconst totalPages = perPage > 0 ? Math.ceil(total / perPage) : (total > 0 ? 1 : 0);\n\n\t\t// Fetch posts\n\t\tlet query = this.db\n\t\t\t.selectDistinct({\n\t\t\t\tid: posts.id,\n\t\t\t\tpostAuthor: posts.postAuthor,\n\t\t\t\tpostDate: posts.postDate,\n\t\t\t\tpostDateGmt: posts.postDateGmt,\n\t\t\t\tpostContent: posts.postContent,\n\t\t\t\tpostTitle: posts.postTitle,\n\t\t\t\tpostExcerpt: posts.postExcerpt,\n\t\t\t\tpostStatus: posts.postStatus,\n\t\t\t\tcommentStatus: posts.commentStatus,\n\t\t\t\tpingStatus: posts.pingStatus,\n\t\t\t\tpostPassword: posts.postPassword,\n\t\t\t\tpostName: posts.postName,\n\t\t\t\ttoPing: posts.toPing,\n\t\t\t\tpinged: posts.pinged,\n\t\t\t\tpostModified: posts.postModified,\n\t\t\t\tpostModifiedGmt: posts.postModifiedGmt,\n\t\t\t\tpostContentFiltered: posts.postContentFiltered,\n\t\t\t\tpostParent: posts.postParent,\n\t\t\t\tguid: posts.guid,\n\t\t\t\tmenuOrder: posts.menuOrder,\n\t\t\t\tpostType: posts.postType,\n\t\t\t\tpostMimeType: posts.postMimeType,\n\t\t\t\tcommentCount: posts.commentCount,\n\t\t\t})\n\t\t\t.from(posts)\n\t\t\t.leftJoin(postmeta, this.needsMetaJoin(params) ? eq(posts.id, postmeta.postId) : sql`false`)\n\t\t\t.leftJoin(\n\t\t\t\ttermRelationships,\n\t\t\t\tthis.needsTaxJoin(params) ? eq(posts.id, termRelationships.objectId) : sql`false`,\n\t\t\t)\n\t\t\t.where(conditions.length > 0 ? and(...conditions) : undefined)\n\t\t\t.orderBy(orderClause)\n\t\t\t.$dynamic();\n\n\t\tif (perPage > 0) {\n\t\t\tquery = query.limit(perPage).offset(offset);\n\t\t}\n\n\t\tconst rows = await query;\n\n\t\tconst flags = this.buildFlags(params, rows.length, total);\n\n\t\treturn {\n\t\t\tposts: rows,\n\t\t\ttotal,\n\t\t\ttotalPages,\n\t\t\tpage,\n\t\t\tperPage: perPage || total,\n\t\t\tflags,\n\t\t};\n\t}\n\n\t/**\n\t * Shorthand: query a single post by ID.\n\t */\n\tasync querySingle(id: number, postType?: string): Promise<QueryResult> {\n\t\treturn this.query({\n\t\t\tinclude: [id],\n\t\t\tpostType: postType ?? 'post',\n\t\t\tpostStatus: ['publish', 'private', 'draft'],\n\t\t\tperPage: 1,\n\t\t});\n\t}\n\n\t// ─── Private: condition builders ─────────────────────────────\n\n\tprivate buildConditions(params: QueryParams): ReturnType<typeof eq>[] {\n\t\tconst conditions: ReturnType<typeof eq>[] = [];\n\n\t\t// Post type\n\t\tconst postType = params.postType ?? 'post';\n\t\tif (Array.isArray(postType)) {\n\t\t\tconditions.push(inArray(posts.postType, postType));\n\t\t} else {\n\t\t\tconditions.push(eq(posts.postType, postType));\n\t\t}\n\n\t\t// Post status\n\t\tconst status = params.postStatus ?? 'publish';\n\t\tif (Array.isArray(status)) {\n\t\t\tconditions.push(inArray(posts.postStatus, status));\n\t\t} else {\n\t\t\tconditions.push(eq(posts.postStatus, status));\n\t\t}\n\n\t\t// Author\n\t\tif (params.author !== undefined) {\n\t\t\tif (Array.isArray(params.author)) {\n\t\t\t\tconditions.push(inArray(posts.postAuthor, params.author));\n\t\t\t} else {\n\t\t\t\tconditions.push(eq(posts.postAuthor, params.author));\n\t\t\t}\n\t\t}\n\n\t\t// Include/exclude IDs\n\t\tif (params.include && params.include.length > 0) {\n\t\t\tconditions.push(inArray(posts.id, params.include));\n\t\t}\n\t\tif (params.exclude && params.exclude.length > 0) {\n\t\t\tconditions.push(notInArray(posts.id, params.exclude));\n\t\t}\n\n\t\t// Parent\n\t\tif (params.parent !== undefined) {\n\t\t\tconditions.push(eq(posts.postParent, params.parent));\n\t\t}\n\n\t\t// Slug\n\t\tif (params.slug !== undefined) {\n\t\t\tif (Array.isArray(params.slug)) {\n\t\t\t\tconditions.push(inArray(posts.postName, params.slug));\n\t\t\t} else {\n\t\t\t\tconditions.push(eq(posts.postName, params.slug));\n\t\t\t}\n\t\t}\n\n\t\t// Search (full-text)\n\t\tif (params.search) {\n\t\t\tconst searchTerm = params.search.replace(/[^\\w\\s]/g, '').trim();\n\t\t\tif (searchTerm) {\n\t\t\t\tconditions.push(\n\t\t\t\t\tor(\n\t\t\t\t\t\tlike(posts.postTitle, `%${searchTerm}%`),\n\t\t\t\t\t\tlike(posts.postContent, `%${searchTerm}%`),\n\t\t\t\t\t)!,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Taxonomy sub-query\n\t\tif (params.tax) {\n\t\t\tconst taxConditions = this.buildTaxConditions(params.tax);\n\t\t\tif (taxConditions) {\n\t\t\t\tconditions.push(taxConditions);\n\t\t\t}\n\t\t}\n\n\t\t// Meta sub-query\n\t\tif (params.meta) {\n\t\t\tconst metaConditions = this.buildMetaConditions(params.meta);\n\t\t\tif (metaConditions) {\n\t\t\t\tconditions.push(metaConditions);\n\t\t\t}\n\t\t}\n\n\t\t// Date sub-query\n\t\tif (params.date) {\n\t\t\tconst dateConditions = this.buildDateConditions(params.date);\n\t\t\tif (dateConditions) {\n\t\t\t\tconditions.push(dateConditions);\n\t\t\t}\n\t\t}\n\n\t\treturn conditions;\n\t}\n\n\tprivate buildTaxConditions(tax: TaxQuery): ReturnType<typeof eq> | undefined {\n\t\tconst clauseConditions = tax.clauses.map((clause) => {\n\t\t\tconst subConditions: ReturnType<typeof eq>[] = [];\n\n\t\t\tif (clause.termIds && clause.termIds.length > 0) {\n\t\t\t\t// Sub-select to find term_taxonomy_ids for these term IDs\n\t\t\t\tconst ttIdSubquery = sql`${termRelationships.termTaxonomyId} IN (\n\t\t\t\t\tSELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}\n\t\t\t\t\tWHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}\n\t\t\t\t\tAND ${termTaxonomy.termId} IN (${sql.join(clause.termIds.map((id) => sql`${id}`), sql`, `)})\n\t\t\t\t)`;\n\n\t\t\t\tif (clause.operator === 'NOT IN') {\n\t\t\t\t\tsubConditions.push(sql`${posts.id} NOT IN (\n\t\t\t\t\t\tSELECT ${termRelationships.objectId} FROM ${termRelationships}\n\t\t\t\t\t\tWHERE ${ttIdSubquery}\n\t\t\t\t\t)`);\n\t\t\t\t} else {\n\t\t\t\t\tsubConditions.push(ttIdSubquery);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (clause.termSlugs && clause.termSlugs.length > 0) {\n\t\t\t\tconst ttIdSubquery = sql`${termRelationships.termTaxonomyId} IN (\n\t\t\t\t\tSELECT ${termTaxonomy.termTaxonomyId} FROM ${termTaxonomy}\n\t\t\t\t\tINNER JOIN ${terms} ON ${terms.termId} = ${termTaxonomy.termId}\n\t\t\t\t\tWHERE ${termTaxonomy.taxonomy} = ${clause.taxonomy}\n\t\t\t\t\tAND ${terms.slug} IN (${sql.join(clause.termSlugs.map((s) => sql`${s}`), sql`, `)})\n\t\t\t\t)`;\n\n\t\t\t\tif (clause.operator === 'NOT IN') {\n\t\t\t\t\tsubConditions.push(sql`${posts.id} NOT IN (\n\t\t\t\t\t\tSELECT ${termRelationships.objectId} FROM ${termRelationships}\n\t\t\t\t\t\tWHERE ${ttIdSubquery}\n\t\t\t\t\t)`);\n\t\t\t\t} else {\n\t\t\t\t\tsubConditions.push(ttIdSubquery);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn subConditions.length > 0 ? and(...subConditions) : undefined;\n\t\t}).filter(Boolean);\n\n\t\tif (clauseConditions.length === 0) return undefined;\n\n\t\tconst relation = tax.relation ?? 'AND';\n\t\tif (relation === 'OR') {\n\t\t\treturn or(...clauseConditions)!;\n\t\t}\n\t\treturn and(...clauseConditions)!;\n\t}\n\n\tprivate buildMetaConditions(meta: MetaQuery): ReturnType<typeof eq> | undefined {\n\t\tconst clauseConditions = meta.clauses.map((clause) => {\n\t\t\tif (clause.compare === 'EXISTS') {\n\t\t\t\treturn sql`${posts.id} IN (\n\t\t\t\t\tSELECT ${postmeta.postId} FROM ${postmeta}\n\t\t\t\t\tWHERE ${postmeta.metaKey} = ${clause.key}\n\t\t\t\t)`;\n\t\t\t}\n\t\t\tif (clause.compare === 'NOT EXISTS') {\n\t\t\t\treturn sql`${posts.id} NOT IN (\n\t\t\t\t\tSELECT ${postmeta.postId} FROM ${postmeta}\n\t\t\t\t\tWHERE ${postmeta.metaKey} = ${clause.key}\n\t\t\t\t)`;\n\t\t\t}\n\n\t\t\tconst valueStr = String(clause.value ?? '');\n\t\t\tconst compare = clause.compare ?? '=';\n\t\t\tconst castCol = clause.type === 'NUMERIC'\n\t\t\t\t? sql`CAST(${postmeta.metaValue} AS NUMERIC)`\n\t\t\t\t: postmeta.metaValue;\n\n\t\t\tconst compareValue = clause.type === 'NUMERIC'\n\t\t\t\t? sql`CAST(${valueStr} AS NUMERIC)`\n\t\t\t\t: sql`${valueStr}`;\n\n\t\t\tlet condition;\n\t\t\tswitch (compare) {\n\t\t\t\tcase '=': condition = sql`${castCol} = ${compareValue}`; break;\n\t\t\t\tcase '!=': condition = sql`${castCol} != ${compareValue}`; break;\n\t\t\t\tcase '>': condition = sql`${castCol} > ${compareValue}`; break;\n\t\t\t\tcase '<': condition = sql`${castCol} < ${compareValue}`; break;\n\t\t\t\tcase '>=': condition = sql`${castCol} >= ${compareValue}`; break;\n\t\t\t\tcase '<=': condition = sql`${castCol} <= ${compareValue}`; break;\n\t\t\t\tcase 'LIKE': condition = sql`${postmeta.metaValue} LIKE ${valueStr}`; break;\n\t\t\t\tcase 'NOT LIKE': condition = sql`${postmeta.metaValue} NOT LIKE ${valueStr}`; break;\n\t\t\t\tdefault: condition = sql`${castCol} = ${compareValue}`;\n\t\t\t}\n\n\t\t\treturn sql`${posts.id} IN (\n\t\t\t\tSELECT ${postmeta.postId} FROM ${postmeta}\n\t\t\t\tWHERE ${postmeta.metaKey} = ${clause.key} AND ${condition}\n\t\t\t)`;\n\t\t}).filter(Boolean);\n\n\t\tif (clauseConditions.length === 0) return undefined;\n\n\t\tconst relation = meta.relation ?? 'AND';\n\t\tif (relation === 'OR') {\n\t\t\treturn or(...clauseConditions)!;\n\t\t}\n\t\treturn and(...clauseConditions)!;\n\t}\n\n\tprivate buildDateConditions(date: DateQuery): ReturnType<typeof eq> | undefined {\n\t\tconst clauseConditions = date.clauses.map((clause) => {\n\t\t\tconst col = clause.column === 'post_modified' ? posts.postModified : posts.postDate;\n\t\t\tconst conditions: ReturnType<typeof eq>[] = [];\n\n\t\t\tif (clause.year !== undefined) {\n\t\t\t\tconditions.push(sql`EXTRACT(YEAR FROM ${col}) = ${clause.year}`);\n\t\t\t}\n\t\t\tif (clause.month !== undefined) {\n\t\t\t\tconditions.push(sql`EXTRACT(MONTH FROM ${col}) = ${clause.month}`);\n\t\t\t}\n\t\t\tif (clause.day !== undefined) {\n\t\t\t\tconditions.push(sql`EXTRACT(DAY FROM ${col}) = ${clause.day}`);\n\t\t\t}\n\t\t\tif (clause.after !== undefined) {\n\t\t\t\tconst afterDate = clause.after instanceof Date ? clause.after : new Date(clause.after);\n\t\t\t\tconditions.push(gt(col, afterDate));\n\t\t\t}\n\t\t\tif (clause.before !== undefined) {\n\t\t\t\tconst beforeDate = clause.before instanceof Date ? clause.before : new Date(clause.before);\n\t\t\t\tconditions.push(lt(col, beforeDate));\n\t\t\t}\n\n\t\t\treturn conditions.length > 0 ? and(...conditions) : undefined;\n\t\t}).filter(Boolean);\n\n\t\tif (clauseConditions.length === 0) return undefined;\n\n\t\tconst relation = date.relation ?? 'AND';\n\t\tif (relation === 'OR') {\n\t\t\treturn or(...clauseConditions)!;\n\t\t}\n\t\treturn and(...clauseConditions)!;\n\t}\n\n\t// ─── Private: order by ───────────────────────────────────────\n\n\tprivate buildOrderBy(params: QueryParams) {\n\t\tconst direction = params.order === 'asc' ? asc : desc;\n\t\tswitch (params.orderBy) {\n\t\t\tcase 'title': return direction(posts.postTitle);\n\t\t\tcase 'name': return direction(posts.postName);\n\t\t\tcase 'modified': return direction(posts.postModified);\n\t\t\tcase 'id': return direction(posts.id);\n\t\t\tcase 'author': return direction(posts.postAuthor);\n\t\t\tcase 'menu_order': return direction(posts.menuOrder);\n\t\t\tcase 'date':\n\t\t\tdefault: return direction(posts.postDate);\n\t\t}\n\t}\n\n\t// ─── Private: join detection ─────────────────────────────────\n\n\tprivate needsMetaJoin(params: QueryParams): boolean {\n\t\treturn params.meta !== undefined && params.meta.clauses.length > 0;\n\t}\n\n\tprivate needsTaxJoin(params: QueryParams): boolean {\n\t\treturn params.tax !== undefined && params.tax.clauses.length > 0;\n\t}\n\n\t// ─── Private: query flags ────────────────────────────────────\n\n\tprivate buildFlags(params: QueryParams, resultCount: number, _total: number): QueryFlags {\n\t\tconst isSearch = Boolean(params.search);\n\t\tconst isSingle = (params.include?.length === 1 || params.slug !== undefined) && !Array.isArray(params.slug);\n\t\tconst isAuthor = params.author !== undefined;\n\t\tconst isTaxonomy = params.tax !== undefined;\n\t\tconst isDate = params.date !== undefined;\n\t\tconst isPage = params.postType === 'page';\n\t\tconst is404 = resultCount === 0;\n\t\tconst isHome = !isSearch && !isSingle && !isAuthor && !isTaxonomy && !isDate && params.postType === 'post';\n\t\tconst isArchive = !isSingle && (isAuthor || isTaxonomy || isDate);\n\n\t\treturn { isSingle, isArchive, isSearch, is404, isHome, isPage, isAuthor, isTaxonomy, isDate };\n\t}\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newcms/query-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Declarative query engine for NewCMS — type-safe content queries with taxonomy, meta, and date sub-queries",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -16,10 +16,13 @@
|
|
|
16
16
|
"postgres",
|
|
17
17
|
"newcms"
|
|
18
18
|
],
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.js",
|
|
19
21
|
"exports": {
|
|
20
22
|
".": {
|
|
21
23
|
"types": "./dist/index.d.ts",
|
|
22
|
-
"import": "./dist/index.js"
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"require": "./dist/index.cjs"
|
|
23
26
|
}
|
|
24
27
|
},
|
|
25
28
|
"files": [
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
"README.md"
|
|
28
31
|
],
|
|
29
32
|
"dependencies": {
|
|
30
|
-
"drizzle-orm": "^0.
|
|
33
|
+
"drizzle-orm": "^0.45.2",
|
|
31
34
|
"postgres": "^3.4.7"
|
|
32
35
|
},
|
|
33
36
|
"peerDependencies": {
|
|
@@ -36,14 +39,15 @@
|
|
|
36
39
|
"devDependencies": {
|
|
37
40
|
"@types/node": "^22.15.3",
|
|
38
41
|
"dotenv": "^16.5.0",
|
|
42
|
+
"tsup": "^8.5.1",
|
|
39
43
|
"typescript": "^5.9.3",
|
|
40
44
|
"vitest": "^3.2.4",
|
|
41
|
-
"@newcms/
|
|
42
|
-
"@newcms/
|
|
45
|
+
"@newcms/database": "0.2.0",
|
|
46
|
+
"@newcms/config": "0.0.1"
|
|
43
47
|
},
|
|
44
48
|
"scripts": {
|
|
45
|
-
"build": "
|
|
46
|
-
"dev": "
|
|
49
|
+
"build": "tsup",
|
|
50
|
+
"dev": "tsup --watch",
|
|
47
51
|
"typecheck": "tsc --noEmit",
|
|
48
52
|
"test": "vitest run",
|
|
49
53
|
"test:watch": "vitest",
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
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/query-engine.d.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|