@adlas/create-app 1.0.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.
Files changed (79) hide show
  1. package/README.md +476 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +39 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/figma.d.ts +16 -0
  7. package/dist/commands/figma.d.ts.map +1 -0
  8. package/dist/commands/figma.js +172 -0
  9. package/dist/commands/figma.js.map +1 -0
  10. package/dist/commands/index.d.ts +5 -0
  11. package/dist/commands/index.d.ts.map +1 -0
  12. package/dist/commands/index.js +5 -0
  13. package/dist/commands/index.js.map +1 -0
  14. package/dist/commands/init.d.ts +8 -0
  15. package/dist/commands/init.d.ts.map +1 -0
  16. package/dist/commands/init.js +1471 -0
  17. package/dist/commands/init.js.map +1 -0
  18. package/dist/commands/swagger.d.ts +16 -0
  19. package/dist/commands/swagger.d.ts.map +1 -0
  20. package/dist/commands/swagger.js +404 -0
  21. package/dist/commands/swagger.js.map +1 -0
  22. package/dist/commands/update.d.ts +15 -0
  23. package/dist/commands/update.d.ts.map +1 -0
  24. package/dist/commands/update.js +93 -0
  25. package/dist/commands/update.js.map +1 -0
  26. package/package.json +63 -0
  27. package/templates/.vscode/extensions.json +9 -0
  28. package/templates/.vscode/launch.json +26 -0
  29. package/templates/.vscode/settings.json +67 -0
  30. package/templates/.vscode/tasks.json +21 -0
  31. package/templates/boilerplate/config/fonts.ts +10 -0
  32. package/templates/boilerplate/config/navigationUrls.ts +47 -0
  33. package/templates/boilerplate/config/site.ts +96 -0
  34. package/templates/boilerplate/libs/I18n.ts +15 -0
  35. package/templates/boilerplate/libs/I18nNavigation.ts +5 -0
  36. package/templates/boilerplate/libs/I18nRouting.ts +9 -0
  37. package/templates/boilerplate/libs/env.ts +21 -0
  38. package/templates/boilerplate/libs/react-query/ReactQueryProvider.tsx +21 -0
  39. package/templates/boilerplate/libs/react-query/index.ts +2 -0
  40. package/templates/boilerplate/libs/react-query/queryClient.ts +62 -0
  41. package/templates/boilerplate/libs/react-query/queryKeys.ts +5 -0
  42. package/templates/boilerplate/public/images/index.ts +1 -0
  43. package/templates/boilerplate/reset.d.ts +2 -0
  44. package/templates/boilerplate/styles/globals.css +308 -0
  45. package/templates/boilerplate/types/i18n.ts +10 -0
  46. package/templates/boilerplate/types/locale.ts +8 -0
  47. package/templates/boilerplate/utils/file/fileConfig.ts +123 -0
  48. package/templates/boilerplate/utils/file/fileValidation.ts +78 -0
  49. package/templates/boilerplate/utils/file/imageCompression.ts +182 -0
  50. package/templates/boilerplate/utils/file/index.ts +3 -0
  51. package/templates/boilerplate/utils/helpers.ts +55 -0
  52. package/templates/boilerplate/validations/auth.validation.ts +92 -0
  53. package/templates/boilerplate/validations/commonValidations.ts +258 -0
  54. package/templates/boilerplate/validations/zodErrorMap.ts +101 -0
  55. package/templates/configs/.env.example +8 -0
  56. package/templates/configs/.prettierignore +23 -0
  57. package/templates/configs/.prettierrc.cjs +26 -0
  58. package/templates/configs/.prettierrc.icons.cjs +11 -0
  59. package/templates/configs/Dockerfile +6 -0
  60. package/templates/configs/commitlint.config.ts +8 -0
  61. package/templates/configs/eslint.config.mjs +119 -0
  62. package/templates/configs/knip.config.ts +32 -0
  63. package/templates/configs/lefthook.yml +42 -0
  64. package/templates/configs/lint-staged.config.js +8 -0
  65. package/templates/configs/next.config.template.ts +77 -0
  66. package/templates/configs/next.config.ts +43 -0
  67. package/templates/configs/package.json +75 -0
  68. package/templates/configs/postcss.config.mjs +15 -0
  69. package/templates/configs/svgr.config.mjs +129 -0
  70. package/templates/configs/tsconfig.json +75 -0
  71. package/templates/docs/AI_QUICK_REFERENCE.md +379 -0
  72. package/templates/docs/ARCHITECTURE_PATTERNS.md +927 -0
  73. package/templates/docs/DOCUMENTATION_INDEX.md +411 -0
  74. package/templates/docs/FIGMA_TO_CODE_GUIDE.md +768 -0
  75. package/templates/docs/IMPLEMENTATION_GUIDE.md +892 -0
  76. package/templates/docs/PROJECT_OVERVIEW.md +302 -0
  77. package/templates/docs/REFACTOR_PROGRESS.md +1113 -0
  78. package/templates/docs/SHADCN_TO_HEROUI_MIGRATION.md +1375 -0
  79. package/templates/docs/UI_COMPONENTS_GUIDE.md +893 -0
@@ -0,0 +1,3 @@
1
+ export * from './fileConfig';
2
+ export * from './fileValidation';
3
+ export * from './imageCompression';
@@ -0,0 +1,55 @@
1
+ import { siteConfig } from '@/config/site';
2
+
3
+ export const isBrowser = (): boolean => typeof window !== 'undefined';
4
+
5
+ export const isServer = (): boolean => typeof window === 'undefined';
6
+
7
+ export const formatPrice = (
8
+ price: string | number,
9
+ locale: string = siteConfig.locales[1] as string,
10
+ ) => {
11
+ const priceNum = typeof price === 'string' ? Number.parseFloat(price) : price;
12
+
13
+ if (locale === siteConfig.locales[1]) {
14
+ const formatted = new Intl.NumberFormat('de-DE', {
15
+ style: 'currency',
16
+ currency: 'EUR',
17
+ minimumFractionDigits: 2,
18
+ maximumFractionDigits: 2,
19
+ }).format(priceNum);
20
+ return formatted;
21
+ }
22
+
23
+ const formatted = new Intl.NumberFormat('en-US', {
24
+ minimumFractionDigits: 2,
25
+ maximumFractionDigits: 2,
26
+ }).format(priceNum);
27
+ return `${formatted} €`;
28
+ };
29
+
30
+ export const formatLabel = (str: string) => {
31
+ return str
32
+ .split('-')
33
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
34
+ .join(' ');
35
+ };
36
+ // Format date
37
+ export const formatDate = (dateString: string, locale: string) => {
38
+ // Return empty string if dateString is empty or invalid
39
+ if (!dateString || dateString.trim() === '') {
40
+ return '';
41
+ }
42
+
43
+ const date = new Date(dateString);
44
+
45
+ // Check if date is invalid
46
+ if (Number.isNaN(date.getTime())) {
47
+ return '';
48
+ }
49
+
50
+ return new Intl.DateTimeFormat(locale === siteConfig.locales[0] ? 'en-US' : 'de-DE', {
51
+ year: 'numeric',
52
+ month: 'long',
53
+ day: 'numeric',
54
+ }).format(date);
55
+ };
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+
3
+ import {
4
+ confirmPasswordValidationI18n,
5
+ emailValidationI18n,
6
+ firstNameValidationI18n,
7
+ lastNameValidationI18n,
8
+ passwordValidationI18n,
9
+ } from './commonValidations';
10
+
11
+ // ==================== Authentication Validation Schemas with i18n ====================
12
+
13
+ /**
14
+ * Login validation schema with i18n support
15
+ */
16
+ export const LoginValidationI18n = z.object({
17
+ email: emailValidationI18n,
18
+ password: passwordValidationI18n,
19
+ });
20
+
21
+ /**
22
+ * Register person validation schema with i18n support
23
+ */
24
+ const _RegisterPersonValidationI18n = z
25
+ .object({
26
+ firstName: firstNameValidationI18n,
27
+ lastName: lastNameValidationI18n,
28
+ email: emailValidationI18n,
29
+ password: passwordValidationI18n,
30
+ confirmPassword: confirmPasswordValidationI18n,
31
+ })
32
+ .refine(data => data.password === data.confirmPassword, {
33
+ path: ['confirmPassword'],
34
+ message: 'Validations.Auth.passwordsDoNotMatch',
35
+ });
36
+
37
+ /**
38
+ * Basic info validation schema with i18n support
39
+ * Used for the first step of registration
40
+ */
41
+ export const PersonBasicInfoValidationI18n = z.object({
42
+ firstName: firstNameValidationI18n,
43
+ lastName: lastNameValidationI18n,
44
+ email: emailValidationI18n,
45
+ });
46
+
47
+ /**
48
+ * Password step validation schema with i18n support
49
+ * Used for the second step of registration
50
+ */
51
+ export const PersonPasswordValidationI18n = z
52
+ .object({
53
+ password: passwordValidationI18n,
54
+ confirmPassword: confirmPasswordValidationI18n,
55
+ })
56
+ .refine(data => data.password === data.confirmPassword, {
57
+ path: ['confirmPassword'],
58
+ message: 'Validations.Auth.passwordsDoNotMatch',
59
+ });
60
+
61
+ /**
62
+ * Forgot password request validation schema with i18n support
63
+ */
64
+ export const ForgotPasswordRequestValidationI18n = z.object({
65
+ email: emailValidationI18n,
66
+ });
67
+
68
+ /**
69
+ * Reset password validation schema with i18n support
70
+ */
71
+ export const ResetPasswordValidationI18n = z
72
+ .object({
73
+ email: emailValidationI18n,
74
+ token: z.string().min(1, { message: 'Validations.Auth.tokenRequired' }),
75
+ password: passwordValidationI18n,
76
+ confirmPassword: confirmPasswordValidationI18n,
77
+ })
78
+ .refine(data => data.password === data.confirmPassword, {
79
+ path: ['confirmPassword'],
80
+ message: 'Validations.Auth.passwordsDoNotMatch',
81
+ });
82
+
83
+ // ==================== Type Exports ====================
84
+
85
+ export type LoginValidationI18nType = z.infer<typeof LoginValidationI18n>;
86
+ export type RegisterPersonValidationI18nType = z.infer<typeof _RegisterPersonValidationI18n>;
87
+ export type PersonBasicInfoValidationI18nType = z.infer<typeof PersonBasicInfoValidationI18n>;
88
+ export type PersonPasswordValidationI18nType = z.infer<typeof PersonPasswordValidationI18n>;
89
+ export type ForgotPasswordRequestValidationI18nType = z.infer<
90
+ typeof ForgotPasswordRequestValidationI18n
91
+ >;
92
+ export type ResetPasswordValidationI18nType = z.infer<typeof ResetPasswordValidationI18n>;
@@ -0,0 +1,258 @@
1
+ import type { useTranslations } from 'next-intl';
2
+
3
+ import { z } from 'zod';
4
+
5
+ import type { FileValidationError } from '@/components/ui';
6
+
7
+ // ==================== Types ====================
8
+
9
+ /**
10
+ * Type for field validation (used by Form component)
11
+ */
12
+ export type FormFieldValidation = {
13
+ required?: boolean;
14
+ pattern?: RegExp;
15
+ min?: number;
16
+ max?: number;
17
+ minLength?: number;
18
+ maxLength?: number;
19
+ validate?: (value: unknown) => boolean | string;
20
+ };
21
+
22
+ // ==================== Common Validation Schemas with i18n ====================
23
+
24
+ /**
25
+ * Email validation with i18n support
26
+ */
27
+ export const emailValidationI18n = z
28
+ .string()
29
+ .min(1, { message: 'Validations.required' })
30
+ .toLowerCase()
31
+ .regex(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/, {
32
+ message: 'Validations.email',
33
+ });
34
+
35
+ /**
36
+ * Password validation with i18n support
37
+ * Must match validatePasswordRequirements function
38
+ */
39
+ export const passwordValidationI18n = z
40
+ .string()
41
+ .min(8, { message: 'Validations.Auth.passwordMinLength' })
42
+ .max(50, { message: 'Validations.Auth.passwordMaxLength' })
43
+ .regex(/[A-Z]/, { message: 'Validations.Auth.passwordUppercase' })
44
+ .regex(/[a-z]/, { message: 'Validations.Auth.passwordLowercase' })
45
+ .regex(/\d/, { message: 'Validations.Auth.passwordNumber' })
46
+ .regex(/[@#$%]/, { message: 'Validations.Auth.passwordSpecialChar' })
47
+ .regex(/^[a-z0-9@#$%]*$/i, { message: 'Validations.Auth.passwordEnglishOnly' });
48
+
49
+ /**
50
+ * Confirm password validation with i18n support
51
+ */
52
+ export const confirmPasswordValidationI18n = z
53
+ .string()
54
+ .min(1, { message: 'Validations.Auth.confirmPasswordRequired' });
55
+
56
+ /**
57
+ * First name validation with i18n support
58
+ */
59
+ export const firstNameValidationI18n = z
60
+ .string()
61
+ .min(1, { message: 'Validations.required' })
62
+ .min(2, { message: 'Validations.minLength' })
63
+ .max(50, { message: 'Validations.maxLength' })
64
+ .regex(/^[a-z\s\-']+$/i, {
65
+ message: 'Validations.invalidFormat',
66
+ });
67
+
68
+ /**
69
+ * Last name validation with i18n support
70
+ */
71
+ export const lastNameValidationI18n = z
72
+ .string()
73
+ .min(1, { message: 'Validations.required' })
74
+ .min(2, { message: 'Validations.minLength' })
75
+ .max(50, { message: 'Validations.maxLength' })
76
+ .regex(/^[a-z\s\-']+$/i, {
77
+ message: 'Validations.invalidFormat',
78
+ });
79
+
80
+ /**
81
+ * Phone number validation with i18n support
82
+ */
83
+ export const phoneValidationI18n = z
84
+ .string()
85
+ .min(1, { message: 'Validations.required' })
86
+ .regex(/^\+?[\d\s\-()]+$/, {
87
+ message: 'Validations.invalidFormat',
88
+ })
89
+ .min(10, { message: 'Validations.minLength' })
90
+ .max(20, { message: 'Validations.maxLength' });
91
+
92
+ /**
93
+ * Street address validation with i18n support
94
+ */
95
+ export const streetAddressValidationI18n = z
96
+ .string()
97
+ .min(1, { message: 'Validations.required' })
98
+ .min(5, { message: 'Validations.minLength' })
99
+ .max(200, { message: 'Validations.maxLength' });
100
+
101
+ /**
102
+ * City validation with i18n support
103
+ */
104
+ export const cityValidationI18n = z
105
+ .string()
106
+ .min(1, { message: 'Validations.required' })
107
+ .min(2, { message: 'Validations.minLength' })
108
+ .max(100, { message: 'Validations.maxLength' });
109
+
110
+ /**
111
+ * Postal code validation with i18n support
112
+ */
113
+ export const postalCodeValidationI18n = z
114
+ .string()
115
+ .min(1, { message: 'Validations.required' })
116
+ .regex(/^[\dA-Z\s\-]+$/i, {
117
+ message: 'Validations.invalidFormat',
118
+ });
119
+
120
+ /**
121
+ * Country code validation with i18n support
122
+ */
123
+ export const countryCodeValidationI18n = z
124
+ .string()
125
+ .min(1, { message: 'Validations.required' })
126
+ .length(2, { message: 'Validations.invalidFormat' });
127
+
128
+ /**
129
+ * State/Province validation with i18n support
130
+ */
131
+ export const stateProvinceValidationI18n = z
132
+ .string()
133
+ .max(100, { message: 'Validations.maxLength' })
134
+ .optional();
135
+
136
+ /**
137
+ * Gender validation with i18n support (optional)
138
+ */
139
+ export const genderValidationI18n = z
140
+ .enum(['male', 'female', 'diverse'], {
141
+ message: 'Validations.required',
142
+ })
143
+ .optional();
144
+
145
+ /**
146
+ * Birthday validation with i18n support (optional)
147
+ */
148
+ export const birthdayValidationI18n = z
149
+ .string()
150
+ .refine(
151
+ val => {
152
+ if (!val) {
153
+ return true;
154
+ }
155
+ const date = new Date(val);
156
+ if (Number.isNaN(date.getTime())) {
157
+ return false;
158
+ }
159
+
160
+ const today = new Date();
161
+ const minDate = new Date();
162
+ minDate.setFullYear(today.getFullYear() - 120);
163
+
164
+ return date >= minDate && date <= today;
165
+ },
166
+ { message: 'Validations.invalidDate' },
167
+ )
168
+ .optional();
169
+
170
+ // ==================== Utility Functions ====================
171
+
172
+ /**
173
+ * Makes any validation optional (allows empty string or undefined)
174
+ */
175
+ export function optional<T extends z.ZodTypeAny>(schema: T) {
176
+ return schema.optional().or(z.literal(''));
177
+ }
178
+
179
+ /**
180
+ * Type guard for file validation errors
181
+ */
182
+ const isFileValidationError = (value: unknown): value is FileValidationError => {
183
+ return (
184
+ typeof value === 'object' &&
185
+ value !== null &&
186
+ 'isValidationError' in value &&
187
+ value.isValidationError === true
188
+ );
189
+ };
190
+
191
+ /**
192
+ * Valid file input types for validation
193
+ */
194
+ type FileInput = File | string | FileValidationError | null | undefined;
195
+
196
+ /**
197
+ * Creates a file validation schema with i18n support
198
+ * @param required - Whether the file is required
199
+ */
200
+ export const createFileValidation = (required = false) =>
201
+ z.custom<FileInput>().superRefine((value, ctx) => {
202
+ // Handle validation error objects
203
+ if (isFileValidationError(value)) {
204
+ ctx.addIssue({
205
+ code: 'custom',
206
+ message: value.errorMessage,
207
+ });
208
+ return;
209
+ }
210
+
211
+ // If required, reject null/undefined/empty string
212
+ if (required && !value) {
213
+ ctx.addIssue({
214
+ code: 'custom',
215
+ message: 'Validations.File.required',
216
+ });
217
+ return;
218
+ }
219
+
220
+ // If value is a string (URL), it's valid - this happens after upload
221
+ if (typeof value === 'string' && value.length > 0) {
222
+ return;
223
+ }
224
+
225
+ // If value exists but is not a File instance or valid string, reject it
226
+ if (value && !(value instanceof File) && typeof value !== 'string') {
227
+ ctx.addIssue({
228
+ code: 'custom',
229
+ message: 'Validations.File.invalidType',
230
+ });
231
+ }
232
+ });
233
+
234
+ /**
235
+ * Password requirement type for validation feedback
236
+ */
237
+ type PasswordRequirement = {
238
+ text: string;
239
+ isValid: boolean;
240
+ };
241
+
242
+ /**
243
+ * Validates password requirements and returns validation results
244
+ * Used for real-time password strength feedback
245
+ */
246
+ export const validatePasswordRequirements = (
247
+ password: string,
248
+ t: ReturnType<typeof useTranslations>,
249
+ ): PasswordRequirement[] => {
250
+ return [
251
+ { text: t('minLength'), isValid: password.length >= 8 },
252
+ { text: t('maxLength'), isValid: password.length > 0 && password.length <= 50 },
253
+ { text: t('uppercase'), isValid: /[A-Z]/.test(password) },
254
+ { text: t('number'), isValid: /\d/.test(password) },
255
+ { text: t('specialChar'), isValid: /[@#$%]/.test(password) },
256
+ { text: t('englishOnly'), isValid: password.length > 0 && /^[a-z0-9@#$%]*$/i.test(password) },
257
+ ];
258
+ };
@@ -0,0 +1,101 @@
1
+ import type { z } from 'zod';
2
+
3
+ /**
4
+ * Translation function type - simplified to accept any params
5
+ */
6
+ type TranslationFn = (key: string, params?: Record<string, unknown>) => string;
7
+
8
+ /**
9
+ * Custom Zod error metadata for i18n
10
+ */
11
+ export type ZodErrorMetadata = {
12
+ translationKey?: string;
13
+ params?: Record<string, string | number>;
14
+ };
15
+
16
+ /**
17
+ * Extract parameter types from ZodErrorMap
18
+ */
19
+ type ZodErrorMapParams = Parameters<z.ZodErrorMap>;
20
+ type ZodIssueType = ZodErrorMapParams[0];
21
+
22
+ /**
23
+ * Extended issue type with all possible properties and custom metadata
24
+ */
25
+ type ZodIssueWithMetadata = {
26
+ code: string;
27
+ path: (string | number)[];
28
+ message?: string;
29
+ received?: string;
30
+ expected?: string;
31
+ validation?: string;
32
+ minimum?: number;
33
+ maximum?: number;
34
+ type?: string;
35
+ params?: ZodErrorMetadata;
36
+ };
37
+
38
+ /**
39
+ * Creates a custom Zod error map for i18n translation
40
+ * This replaces the pipe format with a clean, type-safe approach
41
+ */
42
+ export const createZodErrorMap = (t: TranslationFn): z.ZodErrorMap => {
43
+ return ((issue: ZodIssueType) => {
44
+ const typedIssue = issue as ZodIssueWithMetadata;
45
+ // Get custom metadata if provided
46
+ const metadata = typedIssue.params;
47
+ const translationKey = metadata?.translationKey;
48
+ const params = metadata?.params;
49
+
50
+ // If custom translation key is provided, use it
51
+ if (translationKey) {
52
+ return {
53
+ message: params ? t(translationKey, params) : t(translationKey),
54
+ };
55
+ }
56
+
57
+ // Handle different Zod issue types with default translations
58
+ switch (typedIssue.code) {
59
+ case 'invalid_type':
60
+ if (typedIssue.received === 'undefined' || typedIssue.received === 'null') {
61
+ return { message: t('Validations.required') };
62
+ }
63
+ return { message: t('Validations.invalidFormat') };
64
+
65
+ case 'invalid_string':
66
+ if (typedIssue.validation === 'email') {
67
+ return { message: t('Validations.email') };
68
+ }
69
+ if (typedIssue.validation === 'regex') {
70
+ return { message: t('Validations.invalidFormat') };
71
+ }
72
+ return { message: t('Validations.invalidFormat') };
73
+
74
+ case 'too_small':
75
+ if (typedIssue.type === 'string') {
76
+ if (typedIssue.minimum === 1) {
77
+ return { message: t('Validations.required') };
78
+ }
79
+ return {
80
+ message: t('Validations.minLength', { min: typedIssue.minimum as number }),
81
+ };
82
+ }
83
+ return { message: t('Validations.invalidFormat') };
84
+
85
+ case 'too_big':
86
+ if (typedIssue.type === 'string') {
87
+ return {
88
+ message: t('Validations.maxLength', { max: typedIssue.maximum as number }),
89
+ };
90
+ }
91
+ return { message: t('Validations.invalidFormat') };
92
+
93
+ case 'custom':
94
+ // For custom validations, the message is already set
95
+ return { message: typedIssue.message ?? t('Validations.invalidFormat') };
96
+
97
+ default:
98
+ return { message: t('Validations.invalidFormat') };
99
+ }
100
+ }) as z.ZodErrorMap;
101
+ };
@@ -0,0 +1,8 @@
1
+ # Public Site URL
2
+ NEXT_PUBLIC_API_URL=
3
+
4
+ # Sentry Token
5
+ SENTRY_AUTH_TOKEN=
6
+
7
+ # Node Environment
8
+ NODE_ENV=development
@@ -0,0 +1,23 @@
1
+ # Dependencies
2
+ node_modules
3
+ .pnp
4
+ .pnp.js
5
+
6
+ # Build outputs
7
+ .next
8
+ out
9
+ dist
10
+ build
11
+
12
+ # Logs
13
+ *.log
14
+
15
+ # Package manager
16
+ pnpm-lock.yaml
17
+ package-lock.json
18
+ yarn.lock
19
+
20
+ # Ignore markdown and YAML files (if you want ESLint to handle them)
21
+ *.md
22
+ *.yml
23
+ *.yaml
@@ -0,0 +1,26 @@
1
+ module.exports = {
2
+ printWidth: 100,
3
+ singleQuote: true,
4
+ semi: true,
5
+ trailingComma: 'all',
6
+ tabWidth: 2,
7
+ useTabs: false,
8
+ arrowParens: 'avoid',
9
+ plugins: ['prettier-plugin-tailwindcss'],
10
+ overrides: [
11
+ {
12
+ files: 'src/components/icons/**/*.{ts,tsx}',
13
+ options: {
14
+ plugins: [],
15
+ printWidth: 100,
16
+ },
17
+ },
18
+ {
19
+ // Disable Tailwind plugin for JS/TS/JSX/TSX (ESLint handles it)
20
+ files: '**/*.{js,jsx,ts,tsx}',
21
+ options: {
22
+ plugins: [],
23
+ },
24
+ },
25
+ ],
26
+ };
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ printWidth: 80,
3
+ singleQuote: true,
4
+ semi: true,
5
+ trailingComma: 'all',
6
+ tabWidth: 2,
7
+ useTabs: false,
8
+ arrowParens: 'avoid',
9
+ singleAttributePerLine: true,
10
+ plugins: [],
11
+ };
@@ -0,0 +1,6 @@
1
+ FROM node:20-bullseye AS base
2
+ WORKDIR /app
3
+
4
+ RUN npm install -g pnpm
5
+
6
+ COPY package.json pnpm-lock.yaml ./ .npmrc ./
@@ -0,0 +1,8 @@
1
+ import type { UserConfig } from '@commitlint/types';
2
+
3
+ const Configuration: UserConfig = {
4
+ extends: ['@commitlint/config-conventional'],
5
+ ignores: [message => message.startsWith('chore: bump')], // Ignore dependabot commits
6
+ };
7
+
8
+ export default Configuration;