@nextsparkjs/core 0.1.0-beta.21 → 0.1.0-beta.23
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/lib/api/entity/generic-handler.d.ts.map +1 -1
- package/dist/lib/api/entity/generic-handler.js +8 -94
- package/dist/styles/classes.json +1 -1
- package/package.json +1 -1
- package/templates/contents/themes/starter/tests/cypress/support/e2e.ts +36 -4
- package/templates/contents/themes/starter/tests/cypress.config.ts +18 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAqSvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"generic-handler.d.ts","sourceRoot":"","sources":["../../../../src/lib/api/entity/generic-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAqSvD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA4ZnF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAsSrF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CA+JpJ;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAoStJ;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAqGtJ;AAED;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAElE"}
|
|
@@ -178,7 +178,7 @@ async function validateTeamContextWithBypass(request, authResult, userId) {
|
|
|
178
178
|
return { valid: true, teamId };
|
|
179
179
|
}
|
|
180
180
|
async function handleGenericList(request) {
|
|
181
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
181
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
182
182
|
try {
|
|
183
183
|
const resolution = await resolveEntityFromUrl(request.nextUrl.pathname);
|
|
184
184
|
if (!resolution.isValidEntity || !resolution.entityConfig) {
|
|
@@ -398,7 +398,7 @@ async function handleGenericList(request) {
|
|
|
398
398
|
}
|
|
399
399
|
const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";
|
|
400
400
|
query = `
|
|
401
|
-
SELECT ${fields}
|
|
401
|
+
SELECT ${fields}, COUNT(*) OVER() as total_count
|
|
402
402
|
FROM "${tableName}" t
|
|
403
403
|
${whereClause}
|
|
404
404
|
ORDER BY t."createdAt" DESC
|
|
@@ -406,98 +406,12 @@ async function handleGenericList(request) {
|
|
|
406
406
|
`;
|
|
407
407
|
queryParams.push(pagination.limit, pagination.offset);
|
|
408
408
|
}
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
if (teamId && !skipUserFilter) {
|
|
415
|
-
countWhereConditions.push(`"teamId" = $${countParamIndex++}`);
|
|
416
|
-
countParams.push(teamId);
|
|
417
|
-
}
|
|
418
|
-
if (userId && !((_h = entityConfig.access) == null ? void 0 : _h.shared) && !skipUserFilter) {
|
|
419
|
-
countWhereConditions.push(`"userId" = $${countParamIndex++}`);
|
|
420
|
-
countParams.push(userId);
|
|
421
|
-
}
|
|
422
|
-
if (searchParam && searchParam.trim() !== "") {
|
|
423
|
-
const searchTerm = searchParam.trim();
|
|
424
|
-
const hasName = entityConfig.fields.some((f) => f.name === "name");
|
|
425
|
-
const hasTitle = entityConfig.fields.some((f) => f.name === "title");
|
|
426
|
-
const hasSlug = entityConfig.fields.some((f) => f.name === "slug");
|
|
427
|
-
const hasContent = entityConfig.fields.some((f) => f.name === "content");
|
|
428
|
-
if (hasName || hasTitle || hasSlug || hasContent) {
|
|
429
|
-
const searchConditions = [];
|
|
430
|
-
if (hasName) {
|
|
431
|
-
searchConditions.push(`name ILIKE $${countParamIndex}`);
|
|
432
|
-
}
|
|
433
|
-
if (hasTitle) {
|
|
434
|
-
searchConditions.push(`title ILIKE $${countParamIndex}`);
|
|
435
|
-
}
|
|
436
|
-
if (hasSlug) {
|
|
437
|
-
searchConditions.push(`slug ILIKE $${countParamIndex}`);
|
|
438
|
-
}
|
|
439
|
-
if (hasContent) {
|
|
440
|
-
searchConditions.push(`content ILIKE $${countParamIndex}`);
|
|
441
|
-
}
|
|
442
|
-
countWhereConditions.push(`(${searchConditions.join(" OR ")})`);
|
|
443
|
-
countParams.push(`%${searchTerm}%`);
|
|
444
|
-
countParamIndex++;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
if (dateFieldName && (fromDate || toDate)) {
|
|
448
|
-
const field = entityConfig.fields.find((f) => f.name === dateFieldName);
|
|
449
|
-
if (field && (field.type === "datetime" || field.type === "date")) {
|
|
450
|
-
if (fromDate) {
|
|
451
|
-
countWhereConditions.push(`"${dateFieldName}" >= $${countParamIndex++}`);
|
|
452
|
-
countParams.push(fromDate);
|
|
453
|
-
}
|
|
454
|
-
if (toDate) {
|
|
455
|
-
countWhereConditions.push(`"${dateFieldName}" <= $${countParamIndex++}`);
|
|
456
|
-
countParams.push(toDate);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
Object.entries(customFilters).forEach(([key, values]) => {
|
|
461
|
-
const field = entityConfig.fields.find((f) => f.name === key);
|
|
462
|
-
if (field && values.length > 0) {
|
|
463
|
-
const columnName = `"${key}"`;
|
|
464
|
-
if (field.type === "relation-multi" || key === "socialPlatformId") {
|
|
465
|
-
const orConditions = values.map(() => {
|
|
466
|
-
const condition = `${columnName}::jsonb @> $${countParamIndex++}::jsonb`;
|
|
467
|
-
return condition;
|
|
468
|
-
});
|
|
469
|
-
values.forEach((value) => {
|
|
470
|
-
countParams.push(JSON.stringify([value]));
|
|
471
|
-
});
|
|
472
|
-
countWhereConditions.push(`(${orConditions.join(" OR ")})`);
|
|
473
|
-
} else {
|
|
474
|
-
const orConditions = values.map(() => {
|
|
475
|
-
const condition = `${columnName} = $${countParamIndex++}`;
|
|
476
|
-
return condition;
|
|
477
|
-
});
|
|
478
|
-
values.forEach((value) => {
|
|
479
|
-
countParams.push(value);
|
|
480
|
-
});
|
|
481
|
-
countWhereConditions.push(`(${orConditions.join(" OR ")})`);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
409
|
+
const rawData = await queryWithRLS(query, queryParams, userId);
|
|
410
|
+
const total = rawData.length > 0 ? Number(rawData[0].total_count) || 0 : 0;
|
|
411
|
+
const data = rawData.map((row) => {
|
|
412
|
+
const { total_count, ...rest } = row;
|
|
413
|
+
return rest;
|
|
484
414
|
});
|
|
485
|
-
if (taxonomyFilter == null ? void 0 : taxonomyFilter.taxonomyId) {
|
|
486
|
-
countWhereConditions.push(`EXISTS (
|
|
487
|
-
SELECT 1 FROM entity_taxonomy_relations etr
|
|
488
|
-
WHERE etr."entityId" = id::text
|
|
489
|
-
AND etr."entityType" = '${entityConfig.slug}'
|
|
490
|
-
AND etr."taxonomyId" = $${countParamIndex++}
|
|
491
|
-
)`);
|
|
492
|
-
countParams.push(taxonomyFilter.taxonomyId);
|
|
493
|
-
}
|
|
494
|
-
const countWhereClause = countWhereConditions.length > 0 ? `WHERE ${countWhereConditions.join(" AND ")}` : "";
|
|
495
|
-
totalResult = await queryWithRLS(
|
|
496
|
-
`SELECT COUNT(*) as count FROM "${tableName}" ${countWhereClause}`,
|
|
497
|
-
countParams,
|
|
498
|
-
userId
|
|
499
|
-
);
|
|
500
|
-
const total = ((_i = totalResult[0]) == null ? void 0 : _i.count) || 0;
|
|
501
415
|
const paginationMeta = createPaginationMeta(pagination.page, pagination.limit, total);
|
|
502
416
|
let dataWithMeta = data;
|
|
503
417
|
if (metaParams.includeMetadata && userId) {
|
|
@@ -520,7 +434,7 @@ async function handleGenericList(request) {
|
|
|
520
434
|
);
|
|
521
435
|
}
|
|
522
436
|
let dataWithTaxonomies = dataWithChild;
|
|
523
|
-
if ((
|
|
437
|
+
if ((_h = entityConfig.taxonomies) == null ? void 0 : _h.enabled) {
|
|
524
438
|
dataWithTaxonomies = await includeTaxonomiesInData(
|
|
525
439
|
entityConfig,
|
|
526
440
|
dataWithChild,
|
package/dist/styles/classes.json
CHANGED
package/package.json
CHANGED
|
@@ -5,17 +5,49 @@
|
|
|
5
5
|
* Use it to load plugins, add global hooks, and import commands.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
// Testing Library for better element queries
|
|
9
|
+
import '@testing-library/cypress/add-commands'
|
|
10
|
+
|
|
11
|
+
// Import @cypress/grep for test filtering by tags
|
|
12
|
+
import registerCypressGrep from '@cypress/grep'
|
|
13
|
+
registerCypressGrep()
|
|
14
|
+
|
|
8
15
|
// Import custom commands
|
|
9
16
|
import './commands'
|
|
10
17
|
|
|
11
18
|
// Import documentation commands (optional - for demo videos)
|
|
19
|
+
// Requires cypress-slow-down: pnpm add -D cypress-slow-down
|
|
12
20
|
// import './doc-commands'
|
|
13
21
|
|
|
14
|
-
//
|
|
15
|
-
// from application errors that don't affect test assertions
|
|
22
|
+
// Global error handling
|
|
16
23
|
Cypress.on('uncaught:exception', (err) => {
|
|
17
|
-
//
|
|
18
|
-
|
|
24
|
+
// Ignore React hydration errors
|
|
25
|
+
if (err.message.includes('Hydration')) {
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
// Ignore ResizeObserver errors
|
|
29
|
+
if (err.message.includes('ResizeObserver')) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
// Log other errors but don't fail tests
|
|
19
33
|
console.error('Uncaught exception:', err.message)
|
|
20
34
|
return false
|
|
21
35
|
})
|
|
36
|
+
|
|
37
|
+
// Global before hook
|
|
38
|
+
beforeEach(() => {
|
|
39
|
+
cy.clearCookies()
|
|
40
|
+
cy.clearLocalStorage()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// Type declarations for @cypress/grep
|
|
44
|
+
declare global {
|
|
45
|
+
namespace Cypress {
|
|
46
|
+
interface SuiteConfigOverrides {
|
|
47
|
+
tags?: string | string[]
|
|
48
|
+
}
|
|
49
|
+
interface TestConfigOverrides {
|
|
50
|
+
tags?: string | string[]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cypress Configuration for Starter Theme
|
|
3
3
|
*
|
|
4
|
-
* This config is
|
|
5
|
-
* Run with:
|
|
4
|
+
* This config is self-contained for npm projects created with `nextspark init`.
|
|
5
|
+
* Run with: pnpm cy:open
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { defineConfig } from 'cypress'
|
|
9
9
|
import path from 'path'
|
|
10
10
|
import fs from 'fs'
|
|
11
|
+
import { fileURLToPath } from 'url'
|
|
12
|
+
|
|
13
|
+
// ESM-compatible __dirname
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
15
|
+
const __dirname = path.dirname(__filename)
|
|
11
16
|
|
|
12
17
|
// Paths relative to this config file
|
|
13
18
|
const themeRoot = path.resolve(__dirname, '..')
|
|
@@ -18,24 +23,21 @@ const narrationsOutputDir = path.join(__dirname, 'cypress/videos/narrations')
|
|
|
18
23
|
import dotenv from 'dotenv'
|
|
19
24
|
dotenv.config({ path: path.join(projectRoot, '.env') })
|
|
20
25
|
|
|
21
|
-
// Server port (from .env or default
|
|
22
|
-
const port = process.env.PORT ||
|
|
26
|
+
// Server port (from .env or default 3000)
|
|
27
|
+
const port = process.env.PORT || 3000
|
|
23
28
|
|
|
24
29
|
export default defineConfig({
|
|
25
30
|
e2e: {
|
|
26
31
|
// Base URL for the application
|
|
27
32
|
baseUrl: `http://localhost:${port}`,
|
|
28
33
|
|
|
29
|
-
// Spec patterns:
|
|
34
|
+
// Spec patterns: theme tests only
|
|
30
35
|
specPattern: [
|
|
31
|
-
// Core tests (always included)
|
|
32
|
-
path.join(projectRoot, 'core/tests/cypress/e2e/core/**/*.cy.{js,ts}'),
|
|
33
|
-
// Theme-specific tests
|
|
34
36
|
path.join(__dirname, 'cypress/e2e/**/*.cy.{js,ts}'),
|
|
35
37
|
],
|
|
36
38
|
|
|
37
|
-
// Support file (
|
|
38
|
-
supportFile: path.join(
|
|
39
|
+
// Support file (theme-local)
|
|
40
|
+
supportFile: path.join(__dirname, 'cypress/support/e2e.ts'),
|
|
39
41
|
|
|
40
42
|
// Fixtures folder (theme-specific)
|
|
41
43
|
fixturesFolder: path.join(__dirname, 'cypress/fixtures'),
|
|
@@ -96,15 +98,16 @@ export default defineConfig({
|
|
|
96
98
|
grepOmitFiltered: true,
|
|
97
99
|
},
|
|
98
100
|
|
|
99
|
-
setupNodeEvents(on, config) {
|
|
101
|
+
async setupNodeEvents(on, config) {
|
|
100
102
|
// Allure plugin setup (allure-cypress)
|
|
101
|
-
const { allureCypress } =
|
|
103
|
+
const { allureCypress } = await import('allure-cypress/reporter')
|
|
102
104
|
allureCypress(on, config, {
|
|
103
105
|
resultsDir: path.join(__dirname, 'cypress/allure-results'),
|
|
104
106
|
})
|
|
105
107
|
|
|
106
108
|
// @cypress/grep plugin for test filtering by tags
|
|
107
|
-
|
|
109
|
+
const grepPlugin = await import('@cypress/grep/src/plugin.js')
|
|
110
|
+
;(grepPlugin.default || grepPlugin)(config)
|
|
108
111
|
|
|
109
112
|
// Documentation video tasks
|
|
110
113
|
on('task', {
|
|
@@ -127,7 +130,7 @@ export default defineConfig({
|
|
|
127
130
|
const filepath = path.join(narrationsOutputDir, filename)
|
|
128
131
|
|
|
129
132
|
fs.writeFileSync(filepath, JSON.stringify(narrations, null, 2))
|
|
130
|
-
console.log(
|
|
133
|
+
console.log(`📝 Narrations saved to: ${filepath}`)
|
|
131
134
|
|
|
132
135
|
return null
|
|
133
136
|
},
|
|
@@ -136,7 +139,7 @@ export default defineConfig({
|
|
|
136
139
|
* Add narration entry (called per narration)
|
|
137
140
|
*/
|
|
138
141
|
addNarration(narration: unknown) {
|
|
139
|
-
console.log('Narration:', narration)
|
|
142
|
+
console.log('🎙️ Narration:', narration)
|
|
140
143
|
return null
|
|
141
144
|
},
|
|
142
145
|
})
|