create-velox-app 0.6.103 → 0.6.105
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/CHANGELOG.md +12 -0
- package/dist/templates/auth.js +0 -4
- package/dist/templates/placeholders.js +40 -34
- package/package.json +1 -1
- package/src/templates/source/web/main.tsx +12 -4
- package/src/templates/source/web/routes/__root.tsx +1 -0
- package/src/templates/source/web/routes/users.tsx +8 -1
- package/src/templates/source/api/routes.auth.ts +0 -41
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# create-velox-app
|
|
2
2
|
|
|
3
|
+
## 0.6.105
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fix(create): resolve JSX conditional marker artifacts and add auth route guard & some socumentation updates
|
|
8
|
+
|
|
9
|
+
## 0.6.104
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- feat(client): smart convention-based route inference, eliminate routes.ts
|
|
14
|
+
|
|
3
15
|
## 0.6.103
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/dist/templates/auth.js
CHANGED
|
@@ -50,9 +50,6 @@ function generateIndexTs() {
|
|
|
50
50
|
function generateRouterTs() {
|
|
51
51
|
return compileTemplate('api/router.auth.ts', AUTH_CONFIG);
|
|
52
52
|
}
|
|
53
|
-
function generateRoutesTs() {
|
|
54
|
-
return compileTemplate('api/routes.auth.ts', AUTH_CONFIG);
|
|
55
|
-
}
|
|
56
53
|
function generateConfigDatabase(config) {
|
|
57
54
|
return compileTemplate('api/config/database.ts', config);
|
|
58
55
|
}
|
|
@@ -96,7 +93,6 @@ export function generateAuthTemplate(config) {
|
|
|
96
93
|
{ path: 'apps/api/prisma/schema.prisma', content: generatePrismaSchema(config) },
|
|
97
94
|
// API Source files
|
|
98
95
|
{ path: 'apps/api/src/router.ts', content: generateRouterTs() },
|
|
99
|
-
{ path: 'apps/api/src/routes.ts', content: generateRoutesTs() },
|
|
100
96
|
{ path: 'apps/api/src/index.ts', content: generateIndexTs() },
|
|
101
97
|
{ path: 'apps/api/src/config/app.ts', content: generateConfigApp(config) },
|
|
102
98
|
{ path: 'apps/api/src/config/auth.ts', content: generateAuthConfig() },
|
|
@@ -310,90 +310,96 @@ export function processConditionals(content, config) {
|
|
|
310
310
|
const { template, database } = config;
|
|
311
311
|
// =========================================================================
|
|
312
312
|
// Template conditionals
|
|
313
|
+
//
|
|
314
|
+
// IMPORTANT: JSX patterns must be processed BEFORE non-JSX patterns.
|
|
315
|
+
// Non-JSX markers (/* @if auth */) are substrings of JSX markers
|
|
316
|
+
// ({/* @if auth */}). Processing non-JSX first would partially strip
|
|
317
|
+
// JSX markers, leaving orphaned {} in the output.
|
|
313
318
|
// =========================================================================
|
|
314
|
-
// Process auth conditionals
|
|
319
|
+
// Process auth conditionals
|
|
315
320
|
if (template === 'auth') {
|
|
316
|
-
// Keep auth content but remove markers
|
|
317
|
-
result = result.replaceAll(CONDITIONALS.AUTH_START, '');
|
|
318
|
-
result = result.replaceAll(CONDITIONALS.AUTH_END, '');
|
|
321
|
+
// Keep auth content but remove markers (JSX first, then non-JSX)
|
|
319
322
|
result = result.replaceAll(CONDITIONALS.JSX_AUTH_START, '');
|
|
320
323
|
result = result.replaceAll(CONDITIONALS.JSX_AUTH_END, '');
|
|
324
|
+
result = result.replaceAll(CONDITIONALS.AUTH_START, '');
|
|
325
|
+
result = result.replaceAll(CONDITIONALS.AUTH_END, '');
|
|
321
326
|
}
|
|
322
327
|
else {
|
|
323
|
-
// Remove entire auth blocks (
|
|
324
|
-
result = result.replace(AUTH_BLOCK_PATTERN, '');
|
|
328
|
+
// Remove entire auth blocks (JSX first, then non-JSX)
|
|
325
329
|
result = result.replace(JSX_AUTH_BLOCK_PATTERN, '');
|
|
330
|
+
result = result.replace(AUTH_BLOCK_PATTERN, '');
|
|
326
331
|
}
|
|
327
|
-
// Process default conditionals
|
|
332
|
+
// Process default conditionals
|
|
328
333
|
// Note: 'rsc' template uses default-style content (no auth)
|
|
329
334
|
// 'trpc' template has its own @if trpc blocks for tRPC-specific configuration
|
|
330
335
|
if (template === 'spa' || template === 'rsc') {
|
|
331
|
-
// Keep default content but remove markers
|
|
332
|
-
result = result.replaceAll(CONDITIONALS.DEFAULT_START, '');
|
|
333
|
-
result = result.replaceAll(CONDITIONALS.DEFAULT_END, '');
|
|
336
|
+
// Keep default content but remove markers (JSX first, then non-JSX)
|
|
334
337
|
result = result.replaceAll(CONDITIONALS.JSX_DEFAULT_START, '');
|
|
335
338
|
result = result.replaceAll(CONDITIONALS.JSX_DEFAULT_END, '');
|
|
339
|
+
result = result.replaceAll(CONDITIONALS.DEFAULT_START, '');
|
|
340
|
+
result = result.replaceAll(CONDITIONALS.DEFAULT_END, '');
|
|
336
341
|
}
|
|
337
342
|
else {
|
|
338
|
-
// Remove entire default blocks (
|
|
339
|
-
result = result.replace(DEFAULT_BLOCK_PATTERN, '');
|
|
343
|
+
// Remove entire default blocks (JSX first, then non-JSX)
|
|
340
344
|
result = result.replace(JSX_DEFAULT_BLOCK_PATTERN, '');
|
|
345
|
+
result = result.replace(DEFAULT_BLOCK_PATTERN, '');
|
|
341
346
|
}
|
|
342
|
-
// Process trpc conditionals
|
|
347
|
+
// Process trpc conditionals
|
|
343
348
|
if (template === 'trpc') {
|
|
344
|
-
// Keep trpc content but remove markers
|
|
345
|
-
result = result.replaceAll(CONDITIONALS.TRPC_START, '');
|
|
346
|
-
result = result.replaceAll(CONDITIONALS.TRPC_END, '');
|
|
349
|
+
// Keep trpc content but remove markers (JSX first, then non-JSX)
|
|
347
350
|
result = result.replaceAll(CONDITIONALS.JSX_TRPC_START, '');
|
|
348
351
|
result = result.replaceAll(CONDITIONALS.JSX_TRPC_END, '');
|
|
352
|
+
result = result.replaceAll(CONDITIONALS.TRPC_START, '');
|
|
353
|
+
result = result.replaceAll(CONDITIONALS.TRPC_END, '');
|
|
349
354
|
}
|
|
350
355
|
else {
|
|
351
|
-
// Remove entire trpc blocks (
|
|
352
|
-
result = result.replace(TRPC_BLOCK_PATTERN, '');
|
|
356
|
+
// Remove entire trpc blocks (JSX first, then non-JSX)
|
|
353
357
|
result = result.replace(JSX_TRPC_BLOCK_PATTERN, '');
|
|
358
|
+
result = result.replace(TRPC_BLOCK_PATTERN, '');
|
|
354
359
|
}
|
|
355
|
-
// Process rest conditionals
|
|
360
|
+
// Process rest conditionals
|
|
356
361
|
// REST mode applies to all templates except trpc (spa, auth, rsc)
|
|
357
362
|
if (template !== 'trpc') {
|
|
358
|
-
// Keep rest content but remove markers
|
|
359
|
-
result = result.replaceAll(CONDITIONALS.REST_START, '');
|
|
360
|
-
result = result.replaceAll(CONDITIONALS.REST_END, '');
|
|
363
|
+
// Keep rest content but remove markers (JSX first, then non-JSX)
|
|
361
364
|
result = result.replaceAll(CONDITIONALS.JSX_REST_START, '');
|
|
362
365
|
result = result.replaceAll(CONDITIONALS.JSX_REST_END, '');
|
|
366
|
+
result = result.replaceAll(CONDITIONALS.REST_START, '');
|
|
367
|
+
result = result.replaceAll(CONDITIONALS.REST_END, '');
|
|
363
368
|
}
|
|
364
369
|
else {
|
|
365
|
-
// Remove entire rest blocks (
|
|
366
|
-
result = result.replace(REST_BLOCK_PATTERN, '');
|
|
370
|
+
// Remove entire rest blocks (JSX first, then non-JSX)
|
|
367
371
|
result = result.replace(JSX_REST_BLOCK_PATTERN, '');
|
|
372
|
+
result = result.replace(REST_BLOCK_PATTERN, '');
|
|
368
373
|
}
|
|
369
374
|
// =========================================================================
|
|
370
375
|
// Database conditionals
|
|
371
376
|
// =========================================================================
|
|
372
377
|
// Process sqlite conditionals
|
|
373
378
|
if (database === 'sqlite') {
|
|
374
|
-
// Keep sqlite content but remove markers
|
|
375
|
-
result = result.replaceAll(CONDITIONALS.SQLITE_START, '');
|
|
376
|
-
result = result.replaceAll(CONDITIONALS.SQLITE_END, '');
|
|
377
379
|
result = result.replaceAll(CONDITIONALS.JSX_SQLITE_START, '');
|
|
378
380
|
result = result.replaceAll(CONDITIONALS.JSX_SQLITE_END, '');
|
|
381
|
+
result = result.replaceAll(CONDITIONALS.SQLITE_START, '');
|
|
382
|
+
result = result.replaceAll(CONDITIONALS.SQLITE_END, '');
|
|
379
383
|
}
|
|
380
384
|
else {
|
|
381
|
-
// Remove entire sqlite blocks
|
|
382
|
-
result = result.replace(SQLITE_BLOCK_PATTERN, '');
|
|
383
385
|
result = result.replace(JSX_SQLITE_BLOCK_PATTERN, '');
|
|
386
|
+
result = result.replace(SQLITE_BLOCK_PATTERN, '');
|
|
384
387
|
}
|
|
385
388
|
// Process postgresql conditionals
|
|
386
389
|
if (database === 'postgresql') {
|
|
387
|
-
// Keep postgresql content but remove markers
|
|
388
|
-
result = result.replaceAll(CONDITIONALS.POSTGRESQL_START, '');
|
|
389
|
-
result = result.replaceAll(CONDITIONALS.POSTGRESQL_END, '');
|
|
390
390
|
result = result.replaceAll(CONDITIONALS.JSX_POSTGRESQL_START, '');
|
|
391
391
|
result = result.replaceAll(CONDITIONALS.JSX_POSTGRESQL_END, '');
|
|
392
|
+
result = result.replaceAll(CONDITIONALS.POSTGRESQL_START, '');
|
|
393
|
+
result = result.replaceAll(CONDITIONALS.POSTGRESQL_END, '');
|
|
392
394
|
}
|
|
393
395
|
else {
|
|
394
|
-
// Remove entire postgresql blocks
|
|
395
|
-
result = result.replace(POSTGRESQL_BLOCK_PATTERN, '');
|
|
396
396
|
result = result.replace(JSX_POSTGRESQL_BLOCK_PATTERN, '');
|
|
397
|
+
result = result.replace(POSTGRESQL_BLOCK_PATTERN, '');
|
|
397
398
|
}
|
|
399
|
+
// =========================================================================
|
|
400
|
+
// Cleanup: remove trailing whitespace and collapse consecutive blank lines
|
|
401
|
+
// =========================================================================
|
|
402
|
+
result = result.replace(/[ \t]+$/gm, '');
|
|
403
|
+
result = result.replace(/\n{3,}/g, '\n\n');
|
|
398
404
|
return result;
|
|
399
405
|
}
|
package/package.json
CHANGED
|
@@ -8,10 +8,8 @@ import './styles/global.css';
|
|
|
8
8
|
|
|
9
9
|
// Import router type (type-only import is erased at compile time)
|
|
10
10
|
import type { AppRouter } from '../../api/src/router.js';
|
|
11
|
-
/* @if auth */
|
|
12
|
-
// Import routes from browser-safe routes file (no server-side code)
|
|
13
|
-
import { routes } from '../../api/src/routes.js';
|
|
14
11
|
|
|
12
|
+
/* @if auth */
|
|
15
13
|
/* @endif auth */
|
|
16
14
|
|
|
17
15
|
// Create router with route tree
|
|
@@ -82,7 +80,17 @@ createRoot(rootElement).render(
|
|
|
82
80
|
config={{
|
|
83
81
|
baseUrl: '/api',
|
|
84
82
|
headers: getAuthHeaders,
|
|
85
|
-
|
|
83
|
+
// Routes are inferred from procedure naming conventions.
|
|
84
|
+
// Manually add routes for procedures with .rest() overrides:
|
|
85
|
+
routes: {
|
|
86
|
+
auth: {
|
|
87
|
+
createAccount: { method: 'POST', path: '/auth/register', kind: 'mutation' },
|
|
88
|
+
createSession: { method: 'POST', path: '/auth/login', kind: 'mutation' },
|
|
89
|
+
createRefresh: { method: 'POST', path: '/auth/refresh', kind: 'mutation' },
|
|
90
|
+
deleteSession: { method: 'POST', path: '/auth/logout', kind: 'mutation' },
|
|
91
|
+
getMe: { method: 'GET', path: '/auth/me', kind: 'query' },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
86
94
|
onUnauthorized: handleUnauthorized,
|
|
87
95
|
}}
|
|
88
96
|
>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Data is guaranteed to be available when the component renders.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
8
|
+
import { createFileRoute, notFound } from '@tanstack/react-router';
|
|
9
9
|
import { Suspense } from 'react';
|
|
10
10
|
import { ErrorBoundary } from 'react-error-boundary';
|
|
11
11
|
|
|
@@ -14,6 +14,13 @@ import { api } from '@/api';
|
|
|
14
14
|
|
|
15
15
|
export const Route = createFileRoute('/users')({
|
|
16
16
|
component: UsersPage,
|
|
17
|
+
/* @if auth */
|
|
18
|
+
beforeLoad: () => {
|
|
19
|
+
if (!localStorage.getItem('token')) {
|
|
20
|
+
throw notFound();
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
/* @endif auth */
|
|
17
24
|
});
|
|
18
25
|
|
|
19
26
|
function UsersPage() {
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser-Safe Route Definitions
|
|
3
|
-
*
|
|
4
|
-
* This file exports route metadata that can be safely imported by frontend code.
|
|
5
|
-
* It does NOT import any server-side modules like procedures or database clients.
|
|
6
|
-
*
|
|
7
|
-
* IMPORTANT: Keep this file browser-safe - no Node.js imports or side effects.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { RouteMap } from '@veloxts/velox';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Route mappings for the VeloxTS client
|
|
14
|
-
*
|
|
15
|
-
* Maps namespace -> procedure -> { method, path, kind }
|
|
16
|
-
* These must match the actual procedure definitions in ./procedures/
|
|
17
|
-
*/
|
|
18
|
-
export const routes: RouteMap = {
|
|
19
|
-
health: {
|
|
20
|
-
getHealth: { method: 'GET', path: '/health', kind: 'query' },
|
|
21
|
-
},
|
|
22
|
-
auth: {
|
|
23
|
-
createAccount: { method: 'POST', path: '/auth/register', kind: 'mutation' },
|
|
24
|
-
createSession: { method: 'POST', path: '/auth/login', kind: 'mutation' },
|
|
25
|
-
createRefresh: { method: 'POST', path: '/auth/refresh', kind: 'mutation' },
|
|
26
|
-
deleteSession: { method: 'POST', path: '/auth/logout', kind: 'mutation' },
|
|
27
|
-
getMe: { method: 'GET', path: '/auth/me', kind: 'query' },
|
|
28
|
-
},
|
|
29
|
-
users: {
|
|
30
|
-
listUsers: { method: 'GET', path: '/users', kind: 'query' },
|
|
31
|
-
getUser: { method: 'GET', path: '/users/:id', kind: 'query' },
|
|
32
|
-
createUser: { method: 'POST', path: '/users', kind: 'mutation' },
|
|
33
|
-
updateUser: { method: 'PUT', path: '/users/:id', kind: 'mutation' },
|
|
34
|
-
patchUser: { method: 'PATCH', path: '/users/:id', kind: 'mutation' },
|
|
35
|
-
deleteUser: { method: 'DELETE', path: '/users/:id', kind: 'mutation' },
|
|
36
|
-
},
|
|
37
|
-
profiles: {
|
|
38
|
-
getProfile: { method: 'GET', path: '/profiles/:id', kind: 'query' },
|
|
39
|
-
getFullProfile: { method: 'GET', path: '/profiles/:id/full', kind: 'query' },
|
|
40
|
-
},
|
|
41
|
-
};
|