@igniter-js/cli 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/dist/index.d.ts +2 -0
- package/dist/index.js +358 -0
- package/dist/templates/components.json.hbs +21 -0
- package/dist/templates/copilot.instructions.hbs +117 -0
- package/dist/templates/docker-compose.hbs +15 -0
- package/dist/templates/env.hbs +33 -0
- package/dist/templates/eslintrc.hbs +3 -0
- package/dist/templates/feature.controller.hbs +83 -0
- package/dist/templates/feature.index.hbs +5 -0
- package/dist/templates/feature.interface.hbs +71 -0
- package/dist/templates/feature.procedure.hbs +76 -0
- package/dist/templates/globals.hbs +198 -0
- package/dist/templates/igniter.client.hbs +21 -0
- package/dist/templates/igniter.context.hbs +23 -0
- package/dist/templates/igniter.hbs +8 -0
- package/dist/templates/igniter.router.hbs +29 -0
- package/dist/templates/layout.hbs +54 -0
- package/dist/templates/page.hbs +313 -0
- package/dist/templates/prisma.hbs +9 -0
- package/dist/templates/readme.hbs +136 -0
- package/dist/templates/vitest.config.hbs +11 -0
- package/dist/utils/analyze.d.ts +17 -0
- package/dist/utils/analyze.js +187 -0
- package/dist/utils/consts.d.ts +26 -0
- package/dist/utils/consts.js +34 -0
- package/dist/utils/handlebars-helpers.d.ts +1 -0
- package/dist/utils/handlebars-helpers.js +43 -0
- package/dist/utils/helpers.d.ts +12 -0
- package/dist/utils/helpers.js +102 -0
- package/dist/utils/prisma-schema-parser.d.ts +59 -0
- package/dist/utils/prisma-schema-parser.js +197 -0
- package/dist/utils/template-handler.d.ts +6 -0
- package/dist/utils/template-handler.js +33 -0
- package/package.json +73 -0
- package/readme.md +143 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Represents a {{pascalCase name}} entity.
|
|
4
|
+
*/
|
|
5
|
+
export interface {{pascalCase name}} {
|
|
6
|
+
{{#each fields}}
|
|
7
|
+
{{#if isRelation}}
|
|
8
|
+
{{#if isList}}
|
|
9
|
+
/** Array of IDs representing the related {{name}} entities */
|
|
10
|
+
{{name}}Ids: string[];
|
|
11
|
+
{{else}}
|
|
12
|
+
/** ID of the related {{name}} entity */
|
|
13
|
+
{{name}}Id: string;
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{else}}
|
|
16
|
+
/** {{pascalCase name}}'s {{name}} property */
|
|
17
|
+
{{name}}{{#if isOptional}}?{{/if}}: {{lowerCase type}};
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{/each}}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Data transfer object for creating a new {{pascalCase name}}.
|
|
24
|
+
*/
|
|
25
|
+
export interface Create{{pascalCase name}}DTO {
|
|
26
|
+
{{#each fields}}
|
|
27
|
+
{{#if isRelation}}
|
|
28
|
+
{{#if isList}}
|
|
29
|
+
/** Array of IDs for the {{name}} relationships to be created */
|
|
30
|
+
{{name}}Ids: string[];
|
|
31
|
+
{{else}}
|
|
32
|
+
/** ID for the {{name}} relationship to be created */
|
|
33
|
+
{{name}}Id: string;
|
|
34
|
+
{{/if}}
|
|
35
|
+
{{else}}
|
|
36
|
+
/** {{name}} value for the new {{pascalCase name}} */
|
|
37
|
+
{{name}}{{#if isOptional}}?{{/if}}: {{lowerCase type}};
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{/each}}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Data transfer object for updating an existing {{pascalCase name}}.
|
|
44
|
+
*/
|
|
45
|
+
export interface Update{{pascalCase name}}DTO {
|
|
46
|
+
{{#each fields}}
|
|
47
|
+
{{#if isRelation}}
|
|
48
|
+
{{#if isList}}
|
|
49
|
+
/** Array of IDs for the {{name}} relationships to be updated */
|
|
50
|
+
{{name}}Ids?: string[];
|
|
51
|
+
{{else}}
|
|
52
|
+
/** ID for the {{name}} relationship to be updated */
|
|
53
|
+
{{name}}Id?: string;
|
|
54
|
+
{{/if}}
|
|
55
|
+
{{else}}
|
|
56
|
+
/** Updated {{name}} value */
|
|
57
|
+
{{name}}?: {{lowerCase type}};
|
|
58
|
+
{{/if}}
|
|
59
|
+
{{/each}}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Query parameters for fetching {{pascalCase name}} entities
|
|
64
|
+
*/
|
|
65
|
+
export interface {{pascalCase name}}QueryParams {
|
|
66
|
+
page?: number;
|
|
67
|
+
limit?: number;
|
|
68
|
+
sortBy?: string;
|
|
69
|
+
sortOrder?: 'asc' | 'desc';
|
|
70
|
+
search?: string;
|
|
71
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
import { igniter } from "@/igniter";
|
|
3
|
+
import type { {{pascalCase name}}, Create{{pascalCase name}}DTO, Update{{pascalCase name}}DTO, {{pascalCase name}}QueryParams } from "../{{kebabCase name}}.interface";
|
|
4
|
+
|
|
5
|
+
export const {{pascalCase name}}FeatureProcedure = igniter.procedure({
|
|
6
|
+
name: "{{pascalCase name}}FeatureProcedure",
|
|
7
|
+
handler: async (_, { context }) => {
|
|
8
|
+
return {
|
|
9
|
+
{{camelCase name}}: {
|
|
10
|
+
findMany: async (query: {{pascalCase name}}QueryParams): Promise<{{pascalCase name}}[]> => {
|
|
11
|
+
return context.providers.database.{{camelCase name}}.findMany({
|
|
12
|
+
where: query.search ? {
|
|
13
|
+
OR: [
|
|
14
|
+
{{#each fields}}
|
|
15
|
+
{{#unless isRelation}}
|
|
16
|
+
{ {{name}}: { contains: query.search } },
|
|
17
|
+
{{/unless}}
|
|
18
|
+
{{/each}}
|
|
19
|
+
]
|
|
20
|
+
} : undefined,
|
|
21
|
+
skip: query.page ? (query.page - 1) * (query.limit || 10) : undefined,
|
|
22
|
+
take: query.limit,
|
|
23
|
+
orderBy: query.sortBy ? {
|
|
24
|
+
[query.sortBy]: query.sortOrder || 'asc'
|
|
25
|
+
} : undefined
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
findOne: async (params: { id: string }): Promise<{{pascalCase name}} | null> => {
|
|
30
|
+
return context.providers.database.{{camelCase name}}.findUnique({
|
|
31
|
+
where: {
|
|
32
|
+
id: params.id
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
create: async (input: Create{{pascalCase name}}DTO): Promise<{{pascalCase name}}> => {
|
|
38
|
+
return context.providers.database.{{camelCase name}}.create({
|
|
39
|
+
data: {
|
|
40
|
+
id: randomUUID(),
|
|
41
|
+
{{#each fields}}
|
|
42
|
+
{{name}}: input.{{name}},
|
|
43
|
+
{{/each}}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
update: async (params: { id: string } & Update{{pascalCase name}}DTO): Promise<{{pascalCase name}}> => {
|
|
49
|
+
const {{camelCase name}} = await context.providers.database.{{camelCase name}}.findUnique({
|
|
50
|
+
where: { id: params.id }
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!{{camelCase name}}) throw new Error("{{pascalCase name}} not found");
|
|
54
|
+
|
|
55
|
+
return context.providers.database.{{camelCase name}}.update({
|
|
56
|
+
where: { id: params.id },
|
|
57
|
+
data: {
|
|
58
|
+
{{#each fields}}
|
|
59
|
+
{{name}}: params.{{name}},
|
|
60
|
+
{{/each}}
|
|
61
|
+
updatedAt: new Date()
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
delete: async (params: { id: string }): Promise<{ id: string }> => {
|
|
67
|
+
await context.providers.database.{{camelCase name}}.delete({
|
|
68
|
+
where: { id: params.id }
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
return { id: params.id };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
|
|
3
|
+
@plugin "tailwindcss-animate";
|
|
4
|
+
@custom-variant dark (&:is(.dark *));
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
--card: oklch(1 0 0);
|
|
8
|
+
--card-foreground: oklch(0.145 0 0);
|
|
9
|
+
--popover: oklch(1 0 0);
|
|
10
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
11
|
+
--primary: oklch(0.205 0 0);
|
|
12
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
13
|
+
--secondary: oklch(0.97 0 0);
|
|
14
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
15
|
+
--muted: oklch(0.97 0 0);
|
|
16
|
+
--muted-foreground: oklch(0.556 0 0);
|
|
17
|
+
--accent: oklch(0.97 0 0);
|
|
18
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
19
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
20
|
+
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
21
|
+
--border: oklch(0.922 0 0);
|
|
22
|
+
--input: oklch(0.922 0 0);
|
|
23
|
+
--ring: oklch(0.87 0 0);
|
|
24
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
25
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
26
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
27
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
28
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
29
|
+
--radius: 0.625rem;
|
|
30
|
+
--sidebar: oklch(0.985 0 0);
|
|
31
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
32
|
+
--sidebar-primary: oklch(0.205 0 0);
|
|
33
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
34
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
35
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
36
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
37
|
+
--sidebar-ring: oklch(0.87 0 0);
|
|
38
|
+
--background: oklch(1 0 0);
|
|
39
|
+
--foreground: oklch(0.145 0 0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.dark {
|
|
43
|
+
--background: oklch(0.145 0 0);
|
|
44
|
+
--foreground: oklch(0.985 0 0);
|
|
45
|
+
--card: oklch(0.145 0 0);
|
|
46
|
+
--card-foreground: oklch(0.985 0 0);
|
|
47
|
+
--popover: oklch(0.145 0 0);
|
|
48
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
49
|
+
--primary: oklch(0.985 0 0);
|
|
50
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
51
|
+
--secondary: oklch(0.269 0 0);
|
|
52
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
53
|
+
--muted: oklch(0.269 0 0);
|
|
54
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
55
|
+
--accent: oklch(0.269 0 0);
|
|
56
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
57
|
+
--destructive: oklch(0.396 0.141 25.723);
|
|
58
|
+
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
59
|
+
--border: oklch(0.269 0 0);
|
|
60
|
+
--input: oklch(0.269 0 0);
|
|
61
|
+
--ring: oklch(0.439 0 0);
|
|
62
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
63
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
64
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
65
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
66
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
67
|
+
--sidebar: oklch(0.205 0 0);
|
|
68
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
69
|
+
--sidebar-primary: oklch(0.488 0.243 264.376);
|
|
70
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
71
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
72
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
73
|
+
--sidebar-border: oklch(0.269 0 0);
|
|
74
|
+
--sidebar-ring: oklch(0.439 0 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.theme-login-one {
|
|
78
|
+
--primary: #ce2a2d;
|
|
79
|
+
--primary-foreground: #fff;
|
|
80
|
+
--ring: #ce2a2d9c;
|
|
81
|
+
--radius: 0rem;
|
|
82
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
83
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
84
|
+
--radius-lg: var(--radius);
|
|
85
|
+
|
|
86
|
+
font-family: var(--font-sans);
|
|
87
|
+
|
|
88
|
+
a {
|
|
89
|
+
color: var(--primary);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
[data-slot="card"] {
|
|
93
|
+
border-radius: 0rem;
|
|
94
|
+
box-shadow: none;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.theme-login-two {
|
|
99
|
+
--primary: #035fa8;
|
|
100
|
+
--primary-foreground: #fff;
|
|
101
|
+
--ring: #035fa89c;
|
|
102
|
+
font-family: var(--font-serif);
|
|
103
|
+
|
|
104
|
+
a {
|
|
105
|
+
color: var(--primary);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.theme-login-three {
|
|
110
|
+
--primary: #22c55e;
|
|
111
|
+
--primary-foreground: #000;
|
|
112
|
+
--ring: #22c55e;
|
|
113
|
+
--radius: 1.5rem;
|
|
114
|
+
|
|
115
|
+
font-family: var(--font-manrope);
|
|
116
|
+
|
|
117
|
+
a {
|
|
118
|
+
color: var(--primary);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[data-slot="card"] {
|
|
122
|
+
@apply shadow-xl;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[data-slot="input"] {
|
|
126
|
+
@apply dark:bg-input;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@theme inline {
|
|
131
|
+
--font-sans: var(--font-sans);
|
|
132
|
+
--font-mono: var(--font-mono);
|
|
133
|
+
--color-background: var(--background);
|
|
134
|
+
--color-foreground: var(--foreground);
|
|
135
|
+
--color-card: var(--card);
|
|
136
|
+
--color-card-foreground: var(--card-foreground);
|
|
137
|
+
--color-popover: var(--popover);
|
|
138
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
139
|
+
--color-primary: var(--primary);
|
|
140
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
141
|
+
--color-secondary: var(--secondary);
|
|
142
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
143
|
+
--color-muted: var(--muted);
|
|
144
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
145
|
+
--color-accent: var(--accent);
|
|
146
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
147
|
+
--color-destructive: var(--destructive);
|
|
148
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
149
|
+
--color-border: var(--border);
|
|
150
|
+
--color-input: var(--input);
|
|
151
|
+
--color-ring: var(--ring);
|
|
152
|
+
--color-chart-1: var(--chart-1);
|
|
153
|
+
--color-chart-2: var(--chart-2);
|
|
154
|
+
--color-chart-3: var(--chart-3);
|
|
155
|
+
--color-chart-4: var(--chart-4);
|
|
156
|
+
--color-chart-5: var(--chart-5);
|
|
157
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
158
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
159
|
+
--radius-lg: var(--radius);
|
|
160
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
161
|
+
--color-sidebar: var(--sidebar);
|
|
162
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
163
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
164
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
165
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
166
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
167
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
168
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
169
|
+
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
170
|
+
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
171
|
+
|
|
172
|
+
@keyframes accordion-down {
|
|
173
|
+
from {
|
|
174
|
+
height: 0;
|
|
175
|
+
}
|
|
176
|
+
to {
|
|
177
|
+
height: var(--radix-accordion-content-height);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@keyframes accordion-up {
|
|
182
|
+
from {
|
|
183
|
+
height: var(--radix-accordion-content-height);
|
|
184
|
+
}
|
|
185
|
+
to {
|
|
186
|
+
height: 0;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@layer base {
|
|
192
|
+
* {
|
|
193
|
+
@apply border-border outline-ring/50;
|
|
194
|
+
}
|
|
195
|
+
body {
|
|
196
|
+
@apply bg-background text-foreground;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AppRouter } from './igniter.router';
|
|
2
|
+
import { createIgniterClient, useIgniterQueryClient } from '@igniter-js/core/client'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Client for Igniter
|
|
6
|
+
*
|
|
7
|
+
* This client is used to fetch data on the client-side
|
|
8
|
+
* It uses the createIgniterClient function to create a client instance
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export const api = createIgniterClient(AppRouter);
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Query client for Igniter
|
|
16
|
+
*
|
|
17
|
+
* This client provides access to the Igniter query functions
|
|
18
|
+
* and handles data fetching with respect to the application router.
|
|
19
|
+
* It will enable the necessary hooks for query management.
|
|
20
|
+
*/
|
|
21
|
+
export const useQueryClient = useIgniterQueryClient<typeof AppRouter>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { prisma } from "@/core/providers/prisma";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description Create the context of the application
|
|
5
|
+
*
|
|
6
|
+
* @returns {Object} The application context containing providers
|
|
7
|
+
*/
|
|
8
|
+
export const createIgniterAppContext = () => {
|
|
9
|
+
return {
|
|
10
|
+
providers: {
|
|
11
|
+
database: prisma
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @description The context of the application
|
|
18
|
+
*
|
|
19
|
+
* @type {Object} context The context object containing providers
|
|
20
|
+
* @property {Object} providers The providers used in the application
|
|
21
|
+
* @property {Object} providers.database The Prisma database provider
|
|
22
|
+
*/
|
|
23
|
+
export type IgniterAppContext = Awaited<ReturnType<typeof createIgniterAppContext>>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Igniter } from "@igniter-js/core";
|
|
2
|
+
import type { IgniterAppContext } from "./igniter.context";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description Initialize the Igniter Router instance for application routing
|
|
6
|
+
* @type {IgniterRouter<IgniterAppContext>}
|
|
7
|
+
*/
|
|
8
|
+
export const igniter = Igniter.context<IgniterAppContext>().create()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { igniter } from "./igniter";
|
|
2
|
+
import { createIgniterAppContext } from "./igniter.context";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description Initialize the Igniter Router with controllers and context
|
|
6
|
+
* @param {Object} config Router configuration object
|
|
7
|
+
* @param {string} config.baseURL Base URL for the API endpoints
|
|
8
|
+
* @param {string} config.basePATH Base path prefix for all routes
|
|
9
|
+
* @param {Function} config.context Function to create context for each request
|
|
10
|
+
* @param {Object} config.controllers Object containing controller definitions
|
|
11
|
+
* @returns {Router} Initialized Igniter Router instance
|
|
12
|
+
* @example
|
|
13
|
+
* const router = appRouter({
|
|
14
|
+
* baseURL: 'http://api.example.com',
|
|
15
|
+
* basePATH: '/v1',
|
|
16
|
+
* context: createContext,
|
|
17
|
+
* controllers: {
|
|
18
|
+
* users: UsersController
|
|
19
|
+
* }
|
|
20
|
+
* })
|
|
21
|
+
*/
|
|
22
|
+
export const AppRouter = igniter.router({
|
|
23
|
+
baseURL: process.env.IGNITER_APP_URL,
|
|
24
|
+
basePATH: process.env.IGNITER_APP_BASE_PATH,
|
|
25
|
+
context: createIgniterAppContext,
|
|
26
|
+
controllers: {
|
|
27
|
+
// add your controllers here
|
|
28
|
+
}
|
|
29
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import localFont from "next/font/local";
|
|
2
|
+
|
|
3
|
+
import { type Metadata } from "next";
|
|
4
|
+
import { Toaster } from 'sonner'
|
|
5
|
+
import { IgniterProvider } from '@igniter-js/core/client'
|
|
6
|
+
|
|
7
|
+
import "./globals.css";
|
|
8
|
+
|
|
9
|
+
const geistSans = localFont({
|
|
10
|
+
src: "./fonts/GeistVF.woff",
|
|
11
|
+
variable: "--font-geist-sans",
|
|
12
|
+
weight: "100 900",
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const geistMono = localFont({
|
|
16
|
+
src: "./fonts/GeistMonoVF.woff",
|
|
17
|
+
variable: "--font-geist-mono",
|
|
18
|
+
weight: "100 900",
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export const metadata: Metadata = {
|
|
22
|
+
title: "Igniter Framework",
|
|
23
|
+
description: "A modern framework optimized for AI-powered development, featuring built-in best practices and type safety for rapid web applications",
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Root layout component that wraps the entire application
|
|
28
|
+
* Business Rule: We need to await connection() to ensure proper request-time behavior in Next.js 15
|
|
29
|
+
* @param children - React components to be rendered inside the layout
|
|
30
|
+
*/
|
|
31
|
+
export default async function RootLayout({
|
|
32
|
+
children,
|
|
33
|
+
}: Readonly<{
|
|
34
|
+
children: React.ReactNode;
|
|
35
|
+
}>) {
|
|
36
|
+
return (
|
|
37
|
+
<html lang="pt-BR" suppressHydrationWarning>
|
|
38
|
+
<body className="antialiased">
|
|
39
|
+
<ThemeProvider
|
|
40
|
+
attribute="class"
|
|
41
|
+
defaultTheme="system"
|
|
42
|
+
enableSystem
|
|
43
|
+
disableTransitionOnChange
|
|
44
|
+
forcedTheme='light'
|
|
45
|
+
>
|
|
46
|
+
<IgniterProvider>
|
|
47
|
+
<Toaster position="top-center" />
|
|
48
|
+
{children}
|
|
49
|
+
</IgniterProvider>
|
|
50
|
+
</ThemeProvider>
|
|
51
|
+
</body>
|
|
52
|
+
</html>
|
|
53
|
+
);
|
|
54
|
+
}
|