@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.
@@ -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,CAygBnF;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"}
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, _i, _j;
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 data = await queryWithRLS(query, queryParams, userId);
410
- let totalResult;
411
- const countWhereConditions = [];
412
- const countParams = [];
413
- let countParamIndex = 1;
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 ((_j = entityConfig.taxonomies) == null ? void 0 : _j.enabled) {
437
+ if ((_h = entityConfig.taxonomies) == null ? void 0 : _h.enabled) {
524
438
  dataWithTaxonomies = await includeTaxonomiesInData(
525
439
  entityConfig,
526
440
  dataWithChild,
@@ -1,5 +1,5 @@
1
1
  {
2
- "generated": "2026-01-07T18:41:28.152Z",
2
+ "generated": "2026-01-07T18:45:02.841Z",
3
3
  "totalClasses": 999,
4
4
  "classes": [
5
5
  "''",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/core",
3
- "version": "0.1.0-beta.21",
3
+ "version": "0.1.0-beta.23",
4
4
  "description": "NextSpark - The complete SaaS framework for Next.js",
5
5
  "license": "MIT",
6
6
  "author": "NextSpark <hello@nextspark.dev>",
@@ -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
- // Disable uncaught exception handling to prevent test failures
15
- // from application errors that don't affect test assertions
22
+ // Global error handling
16
23
  Cypress.on('uncaught:exception', (err) => {
17
- // Returning false here prevents Cypress from failing the test
18
- // You may want to be more selective about which errors to ignore
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 theme-specific and used by scripts/cy.mjs.
5
- * Run with: NEXT_PUBLIC_ACTIVE_THEME=starter pnpm cy:open
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 5173)
22
- const port = process.env.PORT || 5173
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: core tests + theme tests
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 (shared across themes)
38
- supportFile: path.join(projectRoot, 'core/tests/cypress/support/e2e.ts'),
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 } = require('allure-cypress/reporter')
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
- require('@cypress/grep/src/plugin')(config)
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(`Narrations saved to: ${filepath}`)
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
  })