create-absolutejs 0.10.3 → 0.11.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 (73) hide show
  1. package/dist/constants.d.ts +2 -2
  2. package/dist/constants.js +2 -2
  3. package/dist/data.d.ts +10 -10
  4. package/dist/data.js +88 -95
  5. package/dist/generators/angular/generateAngularPage.d.ts +7 -0
  6. package/dist/generators/angular/generateAngularPage.js +175 -0
  7. package/dist/generators/angular/scaffoldAngular.d.ts +2 -0
  8. package/dist/generators/angular/scaffoldAngular.js +34 -0
  9. package/dist/generators/configurations/generatePackageJson.js +26 -3
  10. package/dist/generators/configurations/scaffoldConfigurationFiles.js +26 -2
  11. package/dist/generators/db/dockerInitTemplates.d.ts +9 -9
  12. package/dist/generators/db/dockerInitTemplates.js +9 -9
  13. package/dist/generators/db/generateDatabaseTypes.js +5 -0
  14. package/dist/generators/db/generateDockerContainer.js +4 -2
  15. package/dist/generators/db/generateDrizzleSchema.js +16 -6
  16. package/dist/generators/db/handlerTemplates.d.ts +5 -0
  17. package/dist/generators/db/handlerTemplates.js +6 -0
  18. package/dist/generators/db/scaffoldDocker.js +42 -30
  19. package/dist/generators/html/generateHTMLPage.d.ts +1 -1
  20. package/dist/generators/html/generateHTMLPage.js +2 -2
  21. package/dist/generators/html/scaffoldHTML.d.ts +1 -1
  22. package/dist/generators/html/scaffoldHTML.js +2 -2
  23. package/dist/generators/htmx/generateHTMXPage.d.ts +1 -1
  24. package/dist/generators/htmx/generateHTMXPage.js +2 -2
  25. package/dist/generators/htmx/scaffoldHTMX.d.ts +1 -1
  26. package/dist/generators/htmx/scaffoldHTMX.js +2 -2
  27. package/dist/generators/project/computeFlags.d.ts +1 -0
  28. package/dist/generators/project/computeFlags.js +1 -0
  29. package/dist/generators/project/generateBuildBlock.d.ts +2 -1
  30. package/dist/generators/project/generateBuildBlock.js +11 -7
  31. package/dist/generators/project/generateDBBlock.js +6 -0
  32. package/dist/generators/project/generateImportsBlock.js +39 -27
  33. package/dist/generators/project/generateMarkupCSS.js +4 -0
  34. package/dist/generators/project/generateRoutesBlock.d.ts +1 -2
  35. package/dist/generators/project/generateRoutesBlock.js +28 -17
  36. package/dist/generators/project/generateServer.js +5 -10
  37. package/dist/generators/project/scaffoldFrontends.js +20 -1
  38. package/dist/generators/react/generateReactComponents.d.ts +2 -2
  39. package/dist/generators/react/generateReactComponents.js +33 -33
  40. package/dist/generators/react/scaffoldReact.d.ts +1 -1
  41. package/dist/generators/react/scaffoldReact.js +2 -2
  42. package/dist/generators/svelte/generateSveltePage.d.ts +1 -1
  43. package/dist/generators/svelte/generateSveltePage.js +20 -2
  44. package/dist/generators/svelte/scaffoldSvelte.d.ts +1 -1
  45. package/dist/generators/svelte/scaffoldSvelte.js +2 -2
  46. package/dist/generators/vue/generateVuePage.d.ts +1 -1
  47. package/dist/generators/vue/generateVuePage.js +20 -2
  48. package/dist/generators/vue/scaffoldVue.d.ts +1 -1
  49. package/dist/generators/vue/scaffoldVue.js +2 -2
  50. package/dist/questions/databaseEngine.d.ts +1 -1
  51. package/dist/questions/frontendDirectoryConfigurations.d.ts +1 -1
  52. package/dist/questions/frontends.d.ts +1 -1
  53. package/dist/questions/frontends.js +3 -3
  54. package/dist/scaffold.js +14 -2
  55. package/dist/templates/assets/svg/angular.svg +18 -0
  56. package/dist/templates/configurations/tsconfig.example.json +12 -12
  57. package/dist/templates/react/components/App.tsx +2 -2
  58. package/dist/templates/react/components/Head.tsx +7 -7
  59. package/dist/templates/react/components/OAuthLink.tsx +2 -2
  60. package/dist/templates/styles/colors.ts +6 -8
  61. package/dist/templates/styles/reset.css +15 -0
  62. package/dist/templates/svelte/components/Counter.svelte +4 -0
  63. package/dist/templates/vue/components/CountButton.vue +1 -1
  64. package/dist/typeGuards.d.ts +6 -6
  65. package/dist/typeGuards.js +6 -6
  66. package/dist/types.d.ts +1 -0
  67. package/dist/utils/checkDockerInstalled.d.ts +4 -4
  68. package/dist/utils/checkDockerInstalled.js +78 -71
  69. package/dist/utils/parseCommandLineOptions.js +13 -16
  70. package/dist/versions.d.ts +37 -29
  71. package/dist/versions.js +48 -39
  72. package/package.json +10 -9
  73. /package/dist/templates/configurations/{eslint.config.mjs → eslint.config.example.mjs} +0 -0
@@ -1,4 +1,4 @@
1
- export declare const UNFOUND_INDEX = -1;
2
1
  export declare const DEFAULT_ARG_LENGTH = 2;
3
- export declare const TWO_THIRDS: number;
4
2
  export declare const HOURS_IN_DAY = 24;
3
+ export declare const TWO_THIRDS: number;
4
+ export declare const UNFOUND_INDEX = -1;
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export const UNFOUND_INDEX = -1;
2
1
  export const DEFAULT_ARG_LENGTH = 2;
3
- export const TWO_THIRDS = 2 / 3;
4
2
  export const HOURS_IN_DAY = 24;
3
+ export const TWO_THIRDS = 2 / 3;
4
+ export const UNFOUND_INDEX = -1;
package/dist/data.d.ts CHANGED
@@ -1,18 +1,18 @@
1
1
  import type { FrontendLabels, AvailableDependency } from './types';
2
- export declare const availableFrontends: readonly ["react", "html", "svelte", "vue", "htmx"];
2
+ export declare const absoluteAuthPlugin: AvailableDependency;
3
3
  export declare const availableAuthProviders: readonly ["abs", "none"];
4
- export declare const availableDrizzleDialects: readonly ["gel", "mysql", "postgresql", "sqlite", "singlestore", "mariadb"];
5
- export declare const availablePrismaDialects: readonly ["mysql", "postgresql", "sqlite", "mongodb", "mariadb", "cockroachdb", "mssql"];
4
+ export declare const availableCodeQualityTools: readonly ["eslint+prettier", "biome"];
6
5
  export declare const availableDatabaseEngines: readonly ["postgresql", "mysql", "sqlite", "mongodb", "mariadb", "gel", "singlestore", "cockroachdb", "mssql", "none"];
6
+ export declare const availableDatabaseHosts: readonly ["neon", "planetscale", "turso", "none"];
7
7
  export declare const availableDirectoryConfigurations: readonly ["default", "custom"];
8
+ export declare const availableDrizzleDialects: readonly ["gel", "mariadb", "mssql", "mysql", "postgresql", "singlestore", "sqlite"];
9
+ export declare const availableFrontends: readonly ["react", "html", "svelte", "vue", "htmx", "angular"];
8
10
  export declare const availableORMs: readonly ["drizzle", "prisma", "none"];
9
- export declare const availableDatabaseHosts: readonly ["neon", "planetscale", "turso", "none"];
10
- export declare const availableCodeQualityTools: readonly ["eslint+prettier", "biome"];
11
- export declare const frontendLabels: FrontendLabels;
12
11
  export declare const availablePlugins: AvailableDependency[];
13
- export declare const absoluteAuthPlugin: AvailableDependency;
14
- export declare const scopedStatePlugin: AvailableDependency;
15
- export declare const eslintAndPrettierDependencies: AvailableDependency[];
16
- export declare const eslintReactDependencies: AvailableDependency[];
12
+ export declare const availablePrismaDialects: readonly ["mysql", "postgresql", "sqlite", "mongodb", "mariadb", "cockroachdb", "mssql"];
17
13
  export declare const defaultDependencies: AvailableDependency[];
18
14
  export declare const defaultPlugins: AvailableDependency[];
15
+ export declare const eslintAndPrettierDependencies: AvailableDependency[];
16
+ export declare const eslintReactDependencies: AvailableDependency[];
17
+ export declare const frontendLabels: FrontendLabels;
18
+ export declare const scopedStatePlugin: AvailableDependency;
package/dist/data.js CHANGED
@@ -1,31 +1,20 @@
1
- import { cyan, green, magenta } from 'picocolors';
1
+ import { cyan, green, magenta, red } from 'picocolors';
2
2
  import { versions } from './versions';
3
- export const availableFrontends = [
4
- 'react',
5
- 'html',
6
- 'svelte',
7
- // 'angular',
8
- 'vue',
9
- 'htmx'
10
- ];
3
+ export const absoluteAuthPlugin = {
4
+ imports: [
5
+ {
6
+ config: {
7
+ providersConfiguration: {}
8
+ },
9
+ isPlugin: true,
10
+ packageName: 'absoluteAuth'
11
+ }
12
+ ],
13
+ latestVersion: versions['@absolutejs/auth'],
14
+ value: '@absolutejs/auth'
15
+ };
11
16
  export const availableAuthProviders = ['abs', 'none'];
12
- export const availableDrizzleDialects = [
13
- 'gel',
14
- 'mysql',
15
- 'postgresql',
16
- 'sqlite',
17
- 'singlestore',
18
- 'mariadb'
19
- ];
20
- export const availablePrismaDialects = [
21
- 'mysql',
22
- 'postgresql',
23
- 'sqlite',
24
- 'mongodb',
25
- 'mariadb',
26
- 'cockroachdb',
27
- 'mssql'
28
- ];
17
+ export const availableCodeQualityTools = ['eslint+prettier', 'biome'];
29
18
  export const availableDatabaseEngines = [
30
19
  'postgresql',
31
20
  'mysql',
@@ -38,25 +27,31 @@ export const availableDatabaseEngines = [
38
27
  'mssql',
39
28
  'none'
40
29
  ];
41
- export const availableDirectoryConfigurations = ['default', 'custom'];
42
- export const availableORMs = ['drizzle', 'prisma', 'none'];
43
30
  export const availableDatabaseHosts = [
44
31
  'neon',
45
32
  'planetscale',
46
33
  'turso',
47
34
  'none'
48
35
  ];
49
- export const availableCodeQualityTools = ['eslint+prettier', 'biome'];
50
- /* eslint-disable absolute/sort-keys-fixable */
51
- export const frontendLabels = {
52
- react: cyan('React'),
53
- html: 'HTML',
54
- htmx: 'HTMX',
55
- svelte: magenta('Svelte'),
56
- vue: green('Vue')
57
- // angular: red('Angular'),
58
- };
59
- /* eslint-enable absolute/sort-keys-fixable */
36
+ export const availableDirectoryConfigurations = ['default', 'custom'];
37
+ export const availableDrizzleDialects = [
38
+ 'gel',
39
+ 'mariadb',
40
+ 'mssql',
41
+ 'mysql',
42
+ 'postgresql',
43
+ 'singlestore',
44
+ 'sqlite'
45
+ ];
46
+ export const availableFrontends = [
47
+ 'react',
48
+ 'html',
49
+ 'svelte',
50
+ 'vue',
51
+ 'htmx',
52
+ 'angular'
53
+ ];
54
+ export const availableORMs = ['drizzle', 'prisma', 'none'];
60
55
  export const availablePlugins = [
61
56
  {
62
57
  imports: [{ config: null, isPlugin: true, packageName: 'cors' }],
@@ -77,30 +72,41 @@ export const availablePlugins = [
77
72
  value: 'elysia-rate-limit'
78
73
  }
79
74
  ];
80
- export const absoluteAuthPlugin = {
81
- imports: [
82
- {
83
- config: {
84
- providersConfiguration: {}
85
- },
86
- isPlugin: true,
87
- packageName: 'absoluteAuth'
88
- }
89
- ],
90
- latestVersion: versions['@absolutejs/auth'],
91
- value: '@absolutejs/auth'
92
- };
93
- export const scopedStatePlugin = {
94
- imports: [
95
- {
96
- config: { count: { value: 0 } },
97
- isPlugin: true,
98
- packageName: 'scopedState'
99
- }
100
- ],
101
- latestVersion: versions['elysia-scoped-state'],
102
- value: 'elysia-scoped-state'
103
- };
75
+ export const availablePrismaDialects = [
76
+ 'mysql',
77
+ 'postgresql',
78
+ 'sqlite',
79
+ 'mongodb',
80
+ 'mariadb',
81
+ 'cockroachdb',
82
+ 'mssql'
83
+ ];
84
+ export const defaultDependencies = [
85
+ {
86
+ imports: [{ isPlugin: false, packageName: 'Elysia' }],
87
+ latestVersion: versions['elysia'],
88
+ value: 'elysia'
89
+ }
90
+ ];
91
+ export const defaultPlugins = [
92
+ {
93
+ imports: [
94
+ { isPlugin: false, packageName: 'asset' },
95
+ { isPlugin: true, packageName: 'networking' },
96
+ { isPlugin: false, packageName: 'prepare' }
97
+ ],
98
+ latestVersion: versions['@absolutejs/absolute'],
99
+ value: '@absolutejs/absolute'
100
+ },
101
+ {
102
+ latestVersion: versions['@elysiajs/eden'],
103
+ value: '@elysiajs/eden'
104
+ },
105
+ {
106
+ latestVersion: versions['@elysiajs/static'],
107
+ value: '@elysiajs/static'
108
+ }
109
+ ];
104
110
  export const eslintAndPrettierDependencies = [
105
111
  {
106
112
  latestVersion: versions['@eslint/compat'],
@@ -173,35 +179,22 @@ export const eslintReactDependencies = [
173
179
  value: 'zod-validation-error'
174
180
  }
175
181
  ];
176
- export const defaultDependencies = [
177
- {
178
- imports: [{ isPlugin: false, packageName: 'Elysia' }],
179
- latestVersion: versions['elysia'],
180
- value: 'elysia'
181
- }
182
- ];
183
- export const defaultPlugins = [
184
- {
185
- imports: [
186
- { isPlugin: false, packageName: 'BuildConfig' },
187
- { isPlugin: false, packageName: 'asset' },
188
- { isPlugin: false, packageName: 'build' },
189
- { isPlugin: false, packageName: 'devBuild' },
190
- { isPlugin: false, packageName: 'hmr' },
191
- { isPlugin: true, packageName: 'networking' }
192
- ],
193
- latestVersion: versions['@absolutejs/absolute'],
194
- value: '@absolutejs/absolute'
195
- },
196
- {
197
- imports: [
198
- {
199
- config: { assets: './build', prefix: '' },
200
- isPlugin: true,
201
- packageName: 'staticPlugin'
202
- }
203
- ],
204
- latestVersion: versions['@elysiajs/static'],
205
- value: '@elysiajs/static'
206
- }
207
- ];
182
+ export const frontendLabels = {
183
+ angular: red('Angular'),
184
+ html: 'HTML',
185
+ htmx: 'HTMX',
186
+ react: cyan('React'),
187
+ svelte: magenta('Svelte'),
188
+ vue: green('Vue')
189
+ };
190
+ export const scopedStatePlugin = {
191
+ imports: [
192
+ {
193
+ config: { count: { value: 0 } },
194
+ isPlugin: true,
195
+ packageName: 'scopedState'
196
+ }
197
+ ],
198
+ latestVersion: versions['elysia-scoped-state'],
199
+ value: 'elysia-scoped-state'
200
+ };
@@ -0,0 +1,7 @@
1
+ import { Frontend } from '../../types';
2
+ export declare const generateAngularPage: (_frontends: Frontend[]) => string;
3
+ export declare const generateAppComponent: () => string;
4
+ export declare const generateAppComponentCss: () => string;
5
+ export declare const generateAppComponentHtml: (frontends: Frontend[], editBasePath: string) => string;
6
+ export declare const generateCounterComponent: () => string;
7
+ export declare const generateDropdownComponent: (frontends: Frontend[]) => string;
@@ -0,0 +1,175 @@
1
+ import { formatNavLink } from '../../utils/formatNavLink';
2
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
+ export const generateAngularPage = (_frontends) => `import { Component, inject, InjectionToken } from '@angular/core';
4
+ import { CommonModule } from '@angular/common';
5
+ import { DropdownComponent } from '../components/dropdown.component';
6
+ import { AppComponent } from '../components/app.component';
7
+
8
+ export const INITIAL_COUNT = new InjectionToken<number>('INITIAL_COUNT');
9
+
10
+ type AngularPageProps = {
11
+ initialCount: number;
12
+ };
13
+
14
+ @Component({
15
+ selector: 'angular-page',
16
+ standalone: true,
17
+ imports: [CommonModule, DropdownComponent, AppComponent],
18
+ template: \`
19
+ <header>
20
+ <a href="/">AbsoluteJS</a>
21
+ <app-dropdown></app-dropdown>
22
+ </header>
23
+ <app-root [initialCount]="initialCount"></app-root>
24
+ \`
25
+ })
26
+ export class AngularExampleComponent {
27
+ initialCount: number = 0;
28
+
29
+ constructor() {
30
+ const initialCountToken = inject(INITIAL_COUNT, { optional: true });
31
+ this.initialCount = initialCountToken ?? 0;
32
+ }
33
+ }
34
+
35
+ export const factory = (props: AngularPageProps) => {
36
+ const component = new AngularExampleComponent();
37
+ component.initialCount = props.initialCount;
38
+ return component;
39
+ };
40
+ `;
41
+ export const generateAppComponent = () => `import { Component, Input, ViewEncapsulation } from '@angular/core';
42
+ import { CommonModule } from '@angular/common';
43
+ import { CounterComponent } from './counter.component';
44
+
45
+ @Component({
46
+ selector: 'app-root',
47
+ standalone: true,
48
+ imports: [CommonModule, CounterComponent],
49
+ templateUrl: './app.component.html',
50
+ styleUrls: ['./app.component.css'],
51
+ encapsulation: ViewEncapsulation.None
52
+ })
53
+ export class AppComponent {
54
+ @Input() initialCount: number = 0;
55
+ }
56
+ `;
57
+ export const generateAppComponentCss = () => ``;
58
+ export const generateAppComponentHtml = (frontends, editBasePath) => {
59
+ const exploreBlock = frontends.length > 1
60
+ ? `\n\t<p style="margin-top: 2rem">\n\t\tExplore the other pages to see multiple frameworks running\n\t\ttogether.\n\t</p>`
61
+ : '';
62
+ return `<main>
63
+ <nav>
64
+ <a href="https://absolutejs.com" target="_blank">
65
+ <img
66
+ class="logo"
67
+ src="/assets/png/absolutejs-temp.png"
68
+ alt="AbsoluteJS Logo"
69
+ />
70
+ </a>
71
+ <a href="https://angular.dev/">
72
+ <img
73
+ class="logo angular"
74
+ src="/assets/svg/angular.svg"
75
+ alt="Angular Logo"
76
+ />
77
+ </a>
78
+ </nav>
79
+ <h1>AbsoluteJS + Angular</h1>
80
+ <app-counter [initialCount]="initialCount"></app-counter>
81
+ <p>
82
+ Edit <code>${editBasePath}/pages/angular-example.ts</code> and save to
83
+ test HMR.
84
+ </p>${exploreBlock}
85
+ <p style="color: #777; font-size: 1rem; margin-top: 2rem">
86
+ Click on the AbsoluteJS and Angular logos to learn more.
87
+ </p>
88
+ </main>
89
+ `;
90
+ };
91
+ export const generateCounterComponent = () => `import { Component, Input } from '@angular/core';
92
+ import { CommonModule } from '@angular/common';
93
+
94
+ @Component({
95
+ selector: 'app-counter',
96
+ standalone: true,
97
+ imports: [CommonModule],
98
+ template: \`
99
+ <button (click)="increment()">
100
+ count is <span class="counter-value">{{ count }}</span>
101
+ </button>
102
+ \`,
103
+ styles: [
104
+ \`
105
+ button {
106
+ background-color: #1a1a1a;
107
+ border: 1px solid transparent;
108
+ border-radius: 0.5rem;
109
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
110
+ cursor: pointer;
111
+ font-family: inherit;
112
+ font-size: 1.1rem;
113
+ font-weight: 500;
114
+ margin: 2rem 0;
115
+ padding: 0.6rem 1.2rem;
116
+ transition: border-color 0.25s;
117
+ }
118
+ button:hover {
119
+ border-color: #dd0031;
120
+ }
121
+ button:focus,
122
+ button:focus-visible {
123
+ outline: 4px auto -webkit-focus-ring-color;
124
+ }
125
+
126
+ @media (prefers-color-scheme: light) {
127
+ button {
128
+ background-color: #ffffff;
129
+ }
130
+ }
131
+ \`
132
+ ]
133
+ })
134
+ export class CounterComponent {
135
+ @Input() initialCount: number = 0;
136
+ count: number = 0;
137
+
138
+ ngOnInit() {
139
+ this.count = this.initialCount;
140
+ }
141
+
142
+ increment() {
143
+ this.count++;
144
+ }
145
+ }
146
+ `;
147
+ export const generateDropdownComponent = (frontends) => {
148
+ const navLinks = frontends.map(formatNavLink).join('\n\t\t\t\t');
149
+ return `import { Component } from '@angular/core';
150
+ import { CommonModule } from '@angular/common';
151
+
152
+ @Component({
153
+ selector: 'app-dropdown',
154
+ standalone: true,
155
+ imports: [CommonModule],
156
+ template: \`
157
+ <details
158
+ class="dropdown"
159
+ [attr.open]="isOpen ? '' : null"
160
+ (mouseenter)="isOpen = true"
161
+ (mouseleave)="isOpen = false"
162
+ >
163
+ <summary>Pages</summary>
164
+ <nav class="menu">
165
+ ${navLinks}
166
+ </nav>
167
+ </details>
168
+ \`,
169
+ styles: []
170
+ })
171
+ export class DropdownComponent {
172
+ isOpen = false;
173
+ }
174
+ `;
175
+ };
@@ -0,0 +1,2 @@
1
+ import { ScaffoldFrontendProps } from '../../types';
2
+ export declare const scaffoldAngular: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }: ScaffoldFrontendProps) => void;
@@ -0,0 +1,34 @@
1
+ import { copyFileSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { generateMarkupCSS } from '../project/generateMarkupCSS';
4
+ import { generateAngularPage, generateAppComponent, generateAppComponentCss, generateAppComponentHtml, generateCounterComponent, generateDropdownComponent } from './generateAngularPage';
5
+ export const scaffoldAngular = ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }) => {
6
+ copyFileSync(join(templatesDirectory, 'assets', 'svg', 'angular.svg'), join(projectAssetsDirectory, 'svg', 'angular.svg'));
7
+ const componentsDirectory = join(targetDirectory, 'components');
8
+ mkdirSync(componentsDirectory, { recursive: true });
9
+ const pagesDirectory = join(targetDirectory, 'pages');
10
+ mkdirSync(pagesDirectory, { recursive: true });
11
+ const stylesDirectory = join(targetDirectory, 'styles');
12
+ mkdirSync(stylesDirectory, { recursive: true });
13
+ writeFileSync(join(pagesDirectory, 'angular-example.ts'), generateAngularPage(frontends), 'utf-8');
14
+ writeFileSync(join(componentsDirectory, 'dropdown.component.ts'), generateDropdownComponent(frontends), 'utf-8');
15
+ writeFileSync(join(componentsDirectory, 'app.component.ts'), generateAppComponent(), 'utf-8');
16
+ writeFileSync(join(componentsDirectory, 'app.component.html'), generateAppComponentHtml(frontends, editBasePath), 'utf-8');
17
+ writeFileSync(join(componentsDirectory, 'app.component.css'), generateAppComponentCss(), 'utf-8');
18
+ writeFileSync(join(componentsDirectory, 'counter.component.ts'), generateCounterComponent(), 'utf-8');
19
+ const angularCSS = generateMarkupCSS('angular', '#dd0031', isSingleFrontend);
20
+ const customElementCSS = `
21
+ /* Flex wrappers for Angular custom elements */
22
+ angular-page {
23
+ display: flex;
24
+ flex: 1;
25
+ flex-direction: column;
26
+ }
27
+
28
+ app-root {
29
+ display: flex;
30
+ flex: 1;
31
+ flex-direction: column;
32
+ }`;
33
+ writeFileSync(join(stylesDirectory, 'angular-example.css'), angularCSS + customElementCSS, 'utf-8');
34
+ };
@@ -52,6 +52,15 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
52
52
  for (const dep of eslintReactDependencies)
53
53
  packageNames.add(dep.value);
54
54
  }
55
+ if (flags.requiresAngular) {
56
+ packageNames.add('@angular/common');
57
+ packageNames.add('@angular/compiler');
58
+ packageNames.add('@angular/compiler-cli');
59
+ packageNames.add('@angular/core');
60
+ packageNames.add('@angular/platform-browser');
61
+ packageNames.add('@angular/platform-server');
62
+ packageNames.add('@angular/ssr');
63
+ }
55
64
  if (flags.requiresSvelte)
56
65
  packageNames.add('svelte');
57
66
  if (flags.requiresSvelte && codeQualityTool === 'eslint+prettier')
@@ -139,6 +148,20 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
139
148
  devDependencies[dep.value] = resolveVersion(dep.value, dep.latestVersion);
140
149
  });
141
150
  }
151
+ if (flags.requiresAngular) {
152
+ const angularPackages = [
153
+ '@angular/common',
154
+ '@angular/compiler',
155
+ '@angular/compiler-cli',
156
+ '@angular/core',
157
+ '@angular/platform-browser',
158
+ '@angular/platform-server',
159
+ '@angular/ssr'
160
+ ];
161
+ angularPackages.forEach((pkg) => {
162
+ dependencies[pkg] = resolveVersion(pkg, versions[pkg]);
163
+ });
164
+ }
142
165
  if (flags.requiresSvelte) {
143
166
  dependencies['svelte'] = resolveVersion('svelte', versions['svelte']);
144
167
  }
@@ -168,9 +191,9 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
168
191
  if (latest)
169
192
  s.stop(green('Package versions resolved'));
170
193
  const scripts = {
171
- dev: 'absolutejs dev',
172
- format: `absolutejs prettier --write "./**/*.{js,ts,css,json,mjs,md${flags.requiresReact ? ',jsx,tsx' : ''}${flags.requiresSvelte ? ',svelte' : ''}${flags.requiresVue ? ',vue' : ''}${flags.requiresHtml || flags.requiresHtmx ? ',html' : ''}}"`,
173
- lint: 'absolutejs eslint',
194
+ dev: 'absolute dev',
195
+ format: `absolute prettier --write "./**/*.{js,ts,css,json,mjs,md${flags.requiresReact ? ',jsx,tsx' : ''}${flags.requiresSvelte ? ',svelte' : ''}${flags.requiresVue ? ',vue' : ''}${flags.requiresHtml || flags.requiresHtmx ? ',html' : ''}}"`,
196
+ lint: 'absolute eslint',
174
197
  test: 'echo "Error: no test specified" && exit 1',
175
198
  typecheck: 'bun run tsc --noEmit'
176
199
  };
@@ -1,11 +1,35 @@
1
- import { copyFileSync, writeFileSync } from 'fs';
1
+ import { copyFileSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { dim, yellow } from 'picocolors';
4
4
  import { generateEnv } from './generateEnv';
5
5
  import { generateEslintConfig } from './generateEslintConfig';
6
6
  import { generatePrettierrc } from './generatePrettierrc';
7
7
  export const scaffoldConfigurationFiles = ({ tailwind, templatesDirectory, databaseEngine, envVariables, databaseHost, codeQualityTool, frontends, initializeGitNow, projectName }) => {
8
- copyFileSync(join(templatesDirectory, 'configurations', 'tsconfig.example.json'), join(projectName, 'tsconfig.json'));
8
+ const hasAngular = frontends.includes('angular');
9
+ if (hasAngular) {
10
+ const templatePath = join(templatesDirectory, 'configurations', 'tsconfig.example.json');
11
+ const raw = readFileSync(templatePath, 'utf-8');
12
+ const stripped = raw
13
+ .replace(/\/\*[\s\S]*?\*\//g, '')
14
+ .replace(/\/\/[^\n]*/g, '')
15
+ .replace(/,\s*([}\]])/g, '$1');
16
+ const tsconfig = JSON.parse(stripped);
17
+ tsconfig.compilerOptions['emitDecoratorMetadata'] = true;
18
+ tsconfig.compilerOptions['experimentalDecorators'] = true;
19
+ tsconfig.compilerOptions['useDefineForClassFields'] = false;
20
+ const withAngular = {
21
+ angularCompilerOptions: {
22
+ enableI18nLegacyMessageIdFormat: false,
23
+ strictInjectionParameters: true,
24
+ strictTemplates: true
25
+ },
26
+ ...tsconfig
27
+ };
28
+ writeFileSync(join(projectName, 'tsconfig.json'), JSON.stringify(withAngular, null, '\t'));
29
+ }
30
+ else {
31
+ copyFileSync(join(templatesDirectory, 'configurations', 'tsconfig.example.json'), join(projectName, 'tsconfig.json'));
32
+ }
9
33
  if (tailwind) {
10
34
  copyFileSync(join(templatesDirectory, 'tailwind', 'postcss.config.ts'), join(projectName, 'postcss.config.ts'));
11
35
  copyFileSync(join(templatesDirectory, 'tailwind', 'tailwind.config.ts'), join(projectName, 'tailwind.config.ts'));
@@ -1,12 +1,3 @@
1
- export declare const userTables: {
2
- readonly cockroachdb: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT NOW(),\n metadata JSONB DEFAULT '{}'::jsonb\n);";
3
- readonly gel: "create type users {\n create required property auth_sub: str {\n create constraint exclusive;\n };\n\n create required property created_at: datetime {\n set default := datetime_current();\n };\n\n create required property metadata: json {\n set default := to_json('{}');\n };\n};";
4
- readonly mariadb: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT ('{}')\n);";
5
- readonly mssql: "IF OBJECT_ID('users','U') IS NULL\nBEGIN\n CREATE TABLE users (\n auth_sub NVARCHAR(255) PRIMARY KEY,\n created_at DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),\n metadata NVARCHAR(MAX) NULL\n );\nEND;";
6
- readonly mysql: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT (JSON_OBJECT())\n);";
7
- readonly postgresql: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT NOW(),\n metadata JSONB DEFAULT '{}'::jsonb\n);";
8
- readonly singlestore: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT ('{}')\n);";
9
- };
10
1
  export declare const countHistoryTables: {
11
2
  readonly cockroachdb: "CREATE SEQUENCE IF NOT EXISTS count_history_uid_seq START WITH 1 INCREMENT BY 1;\nCREATE TABLE IF NOT EXISTS count_history (\n uid BIGINT PRIMARY KEY DEFAULT nextval('count_history_uid_seq'),\n count INT NOT NULL,\n created_at TIMESTAMP NOT NULL DEFAULT NOW()\n);";
12
3
  readonly gel: "create scalar type CountHistoryUid extending sequence;\ncreate type count_history {\n create required property uid: CountHistoryUid {\n create constraint exclusive;\n set default := sequence_next(introspect CountHistoryUid);\n };\n\n create required property count: int16;\n\n create required property created_at: datetime {\n set default := datetime_current();\n };\n};";
@@ -50,3 +41,12 @@ export declare const initTemplates: {
50
41
  readonly wait: "until singlestore -u root -ppassword -e \"SELECT 1\" >/dev/null 2>&1; do sleep 1; done";
51
42
  };
52
43
  };
44
+ export declare const userTables: {
45
+ readonly cockroachdb: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT NOW(),\n metadata JSONB DEFAULT '{}'::jsonb\n);";
46
+ readonly gel: "create type users {\n create required property auth_sub: str {\n create constraint exclusive;\n };\n\n create required property created_at: datetime {\n set default := datetime_current();\n };\n\n create required property metadata: json {\n set default := to_json('{}');\n };\n};";
47
+ readonly mariadb: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT ('{}')\n);";
48
+ readonly mssql: "IF OBJECT_ID('users','U') IS NULL\nBEGIN\n CREATE TABLE users (\n auth_sub NVARCHAR(255) PRIMARY KEY,\n created_at DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),\n metadata NVARCHAR(MAX) NULL\n );\nEND;";
49
+ readonly mysql: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT (JSON_OBJECT())\n);";
50
+ readonly postgresql: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT NOW(),\n metadata JSONB DEFAULT '{}'::jsonb\n);";
51
+ readonly singlestore: "CREATE TABLE IF NOT EXISTS users (\n auth_sub VARCHAR(255) PRIMARY KEY,\n created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,\n metadata JSON DEFAULT ('{}')\n);";
52
+ };
@@ -91,15 +91,6 @@ create type count_history {
91
91
  set default := datetime_current();
92
92
  };
93
93
  };`;
94
- export const userTables = {
95
- cockroachdb: cockroachdbUsers,
96
- gel: gelUsers,
97
- mariadb: mariadbUsers,
98
- mssql: mssqlUsers,
99
- mysql: mysqlUsers,
100
- postgresql: postgresqlUsers,
101
- singlestore: singlestoreUsers
102
- };
103
94
  export const countHistoryTables = {
104
95
  cockroachdb: cockroachdbCountHistory,
105
96
  gel: gelCountHistory,
@@ -143,3 +134,12 @@ export const initTemplates = {
143
134
  wait: 'until singlestore -u root -ppassword -e "SELECT 1" >/dev/null 2>&1; do sleep 1; done'
144
135
  }
145
136
  };
137
+ export const userTables = {
138
+ cockroachdb: cockroachdbUsers,
139
+ gel: gelUsers,
140
+ mariadb: mariadbUsers,
141
+ mssql: mssqlUsers,
142
+ mysql: mysqlUsers,
143
+ postgresql: postgresqlUsers,
144
+ singlestore: singlestoreUsers
145
+ };
@@ -34,6 +34,11 @@ export const generateDatabaseTypes = ({ databaseEngine, databaseHost, authOption
34
34
  dbTypeLine =
35
35
  'export type DatabaseType = Mysql2Database<SchemaType>;';
36
36
  break;
37
+ case 'mssql':
38
+ dbImport = `import { NodeMssqlDatabase } from 'drizzle-orm/node-mssql';`;
39
+ dbTypeLine =
40
+ 'export type DatabaseType = NodeMssqlDatabase<SchemaType>;';
41
+ break;
37
42
  case 'postgresql':
38
43
  dbImport = `import { BunSQLDatabase } from 'drizzle-orm/bun-sql';`;
39
44
  dbTypeLine =