create-absolutejs 0.10.3 → 0.12.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/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/data.d.ts +10 -10
- package/dist/data.js +88 -95
- package/dist/generators/angular/generateAngularPage.d.ts +11 -0
- package/dist/generators/angular/generateAngularPage.js +174 -0
- package/dist/generators/angular/scaffoldAngular.d.ts +2 -0
- package/dist/generators/angular/scaffoldAngular.js +38 -0
- package/dist/generators/configurations/generatePackageJson.js +28 -3
- package/dist/generators/configurations/scaffoldConfigurationFiles.js +26 -2
- package/dist/generators/db/dockerInitTemplates.d.ts +9 -9
- package/dist/generators/db/dockerInitTemplates.js +9 -9
- package/dist/generators/db/generateDatabaseTypes.js +5 -0
- package/dist/generators/db/generateDockerContainer.js +4 -2
- package/dist/generators/db/generateDrizzleSchema.js +16 -6
- package/dist/generators/db/handlerTemplates.d.ts +5 -0
- package/dist/generators/db/handlerTemplates.js +6 -0
- package/dist/generators/db/scaffoldDocker.js +42 -30
- package/dist/generators/html/generateHTMLPage.d.ts +1 -1
- package/dist/generators/html/generateHTMLPage.js +3 -3
- package/dist/generators/html/scaffoldHTML.d.ts +1 -1
- package/dist/generators/html/scaffoldHTML.js +4 -6
- package/dist/generators/htmx/generateHTMXPage.d.ts +1 -1
- package/dist/generators/htmx/generateHTMXPage.js +3 -3
- package/dist/generators/htmx/scaffoldHTMX.d.ts +1 -1
- package/dist/generators/htmx/scaffoldHTMX.js +4 -6
- package/dist/generators/project/computeFlags.d.ts +1 -0
- package/dist/generators/project/computeFlags.js +1 -0
- package/dist/generators/project/generateBuildBlock.d.ts +2 -1
- package/dist/generators/project/generateBuildBlock.js +12 -7
- package/dist/generators/project/generateDBBlock.js +6 -0
- package/dist/generators/project/generateImportsBlock.d.ts +1 -2
- package/dist/generators/project/generateImportsBlock.js +48 -50
- package/dist/generators/project/generateMarkupCSS.d.ts +1 -1
- package/dist/generators/project/generateMarkupCSS.js +5 -1
- package/dist/generators/project/generateRoutesBlock.d.ts +1 -4
- package/dist/generators/project/generateRoutesBlock.js +44 -38
- package/dist/generators/project/generateServer.js +5 -12
- package/dist/generators/project/scaffoldFrontends.js +40 -4
- package/dist/generators/react/generateReactComponents.d.ts +2 -2
- package/dist/generators/react/generateReactComponents.js +33 -33
- package/dist/generators/react/scaffoldReact.d.ts +1 -1
- package/dist/generators/react/scaffoldReact.js +4 -6
- package/dist/generators/svelte/generateSveltePage.d.ts +1 -1
- package/dist/generators/svelte/generateSveltePage.js +20 -2
- package/dist/generators/svelte/scaffoldSvelte.d.ts +1 -1
- package/dist/generators/svelte/scaffoldSvelte.js +4 -6
- package/dist/generators/vue/generateVuePage.d.ts +1 -1
- package/dist/generators/vue/generateVuePage.js +2 -229
- package/dist/generators/vue/scaffoldVue.d.ts +1 -1
- package/dist/generators/vue/scaffoldVue.js +6 -2
- package/dist/questions/databaseEngine.d.ts +1 -1
- package/dist/questions/frontendDirectoryConfigurations.d.ts +1 -1
- package/dist/questions/frontends.d.ts +1 -1
- package/dist/questions/frontends.js +3 -3
- package/dist/scaffold.js +14 -2
- package/dist/templates/assets/svg/angular.svg +18 -0
- package/dist/templates/configurations/tsconfig.example.json +12 -12
- package/dist/templates/react/components/App.tsx +2 -2
- package/dist/templates/react/components/Head.tsx +7 -7
- package/dist/templates/react/components/OAuthLink.tsx +2 -2
- package/dist/templates/styles/colors.ts +6 -8
- package/dist/templates/styles/reset.css +15 -0
- package/dist/templates/svelte/components/Counter.svelte +4 -0
- package/dist/templates/vue/components/CountButton.vue +1 -1
- package/dist/typeGuards.d.ts +6 -6
- package/dist/typeGuards.js +6 -6
- package/dist/types.d.ts +3 -0
- package/dist/utils/checkDockerInstalled.d.ts +4 -4
- package/dist/utils/checkDockerInstalled.js +78 -71
- package/dist/utils/parseCommandLineOptions.js +13 -16
- package/dist/versions.d.ts +38 -29
- package/dist/versions.js +49 -39
- package/package.json +10 -9
- /package/dist/templates/configurations/{eslint.config.mjs → eslint.config.example.mjs} +0 -0
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
package/dist/data.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { FrontendLabels, AvailableDependency } from './types';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const absoluteAuthPlugin: AvailableDependency;
|
|
3
3
|
export declare const availableAuthProviders: readonly ["abs", "none"];
|
|
4
|
-
export declare const
|
|
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
|
|
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
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
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
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
{
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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,11 @@
|
|
|
1
|
+
import { Frontend } from '../../types';
|
|
2
|
+
export declare const generateAngularPage: (_frontends: Frontend[]) => string;
|
|
3
|
+
export declare const generateAngularPageHtml: () => string;
|
|
4
|
+
export declare const generateAppComponent: (isSingleFrontend: boolean) => string;
|
|
5
|
+
export declare const generateAppComponentCss: () => string;
|
|
6
|
+
export declare const generateAppComponentHtml: (frontends: Frontend[], editBasePath: string) => string;
|
|
7
|
+
export declare const generateCounterComponent: (isSingleFrontend: boolean) => string;
|
|
8
|
+
export declare const generateCounterComponentHtml: () => string;
|
|
9
|
+
export declare const generateCounterComponentCss: () => string;
|
|
10
|
+
export declare const generateDropdownComponent: (_frontends: Frontend[]) => string;
|
|
11
|
+
export declare const generateDropdownComponentHtml: (frontends: Frontend[]) => string;
|
|
@@ -0,0 +1,174 @@
|
|
|
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 { defineAngularPage } from '@absolutejs/absolute/angular';
|
|
6
|
+
import { DropdownComponent } from '../components/dropdown.component';
|
|
7
|
+
import { AppComponent } from '../components/app.component';
|
|
8
|
+
|
|
9
|
+
export const INITIAL_COUNT = new InjectionToken<number>('INITIAL_COUNT');
|
|
10
|
+
|
|
11
|
+
type AngularPageProps = {
|
|
12
|
+
initialCount: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
imports: [CommonModule, DropdownComponent, AppComponent],
|
|
17
|
+
selector: 'angular-page',
|
|
18
|
+
standalone: true,
|
|
19
|
+
templateUrl: '../templates/angular-example.html'
|
|
20
|
+
})
|
|
21
|
+
export class AngularExampleComponent {
|
|
22
|
+
initialCount: number = 0;
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
const initialCountToken = inject(INITIAL_COUNT, { optional: true });
|
|
26
|
+
this.initialCount = initialCountToken ?? 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const page = defineAngularPage<AngularPageProps>({
|
|
31
|
+
component: AngularExampleComponent
|
|
32
|
+
});
|
|
33
|
+
`;
|
|
34
|
+
export const generateAngularPageHtml = () => `<header>
|
|
35
|
+
<a href="/">AbsoluteJS</a>
|
|
36
|
+
<app-dropdown></app-dropdown>
|
|
37
|
+
</header>
|
|
38
|
+
<app-root [initialCount]="initialCount"></app-root>
|
|
39
|
+
`;
|
|
40
|
+
export const generateAppComponent = (isSingleFrontend) => `import { Component, Input, ViewEncapsulation } from '@angular/core';
|
|
41
|
+
import { CommonModule } from '@angular/common';
|
|
42
|
+
import { CounterComponent } from './counter.component';
|
|
43
|
+
|
|
44
|
+
@Component({
|
|
45
|
+
selector: 'app-root',
|
|
46
|
+
standalone: true,
|
|
47
|
+
imports: [CommonModule, CounterComponent],
|
|
48
|
+
templateUrl: '../templates/app.component.html',
|
|
49
|
+
styleUrl: '${isSingleFrontend ? '../' : '../../'}styles/app.component.css',
|
|
50
|
+
encapsulation: ViewEncapsulation.None
|
|
51
|
+
})
|
|
52
|
+
export class AppComponent {
|
|
53
|
+
@Input() initialCount: number = 0;
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
export const generateAppComponentCss = () => ``;
|
|
57
|
+
export const generateAppComponentHtml = (frontends, editBasePath) => {
|
|
58
|
+
const exploreBlock = frontends.length > 1
|
|
59
|
+
? `\n\t<p style="margin-top: 2rem">\n\t\tExplore the other pages to see multiple frameworks running\n\t\ttogether.\n\t</p>`
|
|
60
|
+
: '';
|
|
61
|
+
return `<main>
|
|
62
|
+
<nav>
|
|
63
|
+
<a href="https://absolutejs.com" target="_blank">
|
|
64
|
+
<img
|
|
65
|
+
class="logo"
|
|
66
|
+
src="/assets/png/absolutejs-temp.png"
|
|
67
|
+
alt="AbsoluteJS Logo"
|
|
68
|
+
/>
|
|
69
|
+
</a>
|
|
70
|
+
<a href="https://angular.dev/">
|
|
71
|
+
<img
|
|
72
|
+
class="logo angular"
|
|
73
|
+
src="/assets/svg/angular.svg"
|
|
74
|
+
alt="Angular Logo"
|
|
75
|
+
/>
|
|
76
|
+
</a>
|
|
77
|
+
</nav>
|
|
78
|
+
<h1>AbsoluteJS + Angular</h1>
|
|
79
|
+
<app-counter [initialCount]="initialCount"></app-counter>
|
|
80
|
+
<p>
|
|
81
|
+
Edit <code>${editBasePath}/pages/angular-example.ts</code> and save to
|
|
82
|
+
test HMR.
|
|
83
|
+
</p>${exploreBlock}
|
|
84
|
+
<p style="color: #777; font-size: 1rem; margin-top: 2rem">
|
|
85
|
+
Click on the AbsoluteJS and Angular logos to learn more.
|
|
86
|
+
</p>
|
|
87
|
+
</main>
|
|
88
|
+
`;
|
|
89
|
+
};
|
|
90
|
+
export const generateCounterComponent = (isSingleFrontend) => `import { Component, Input } from '@angular/core';
|
|
91
|
+
import { CommonModule } from '@angular/common';
|
|
92
|
+
|
|
93
|
+
@Component({
|
|
94
|
+
selector: 'app-counter',
|
|
95
|
+
standalone: true,
|
|
96
|
+
imports: [CommonModule],
|
|
97
|
+
templateUrl: '../templates/counter.component.html',
|
|
98
|
+
styleUrl: '${isSingleFrontend ? '../' : '../../'}styles/counter.component.css'
|
|
99
|
+
})
|
|
100
|
+
export class CounterComponent {
|
|
101
|
+
@Input() initialCount: number = 0;
|
|
102
|
+
count: number = 0;
|
|
103
|
+
|
|
104
|
+
ngOnInit() {
|
|
105
|
+
this.count = this.initialCount;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
increment() {
|
|
109
|
+
this.count++;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
export const generateCounterComponentHtml = () => `<button (click)="increment()">
|
|
114
|
+
count is <span class="counter-value">{{ count }}</span>
|
|
115
|
+
</button>
|
|
116
|
+
`;
|
|
117
|
+
export const generateCounterComponentCss = () => `button {
|
|
118
|
+
background-color: #1a1a1a;
|
|
119
|
+
border: 1px solid transparent;
|
|
120
|
+
border-radius: 0.5rem;
|
|
121
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
122
|
+
cursor: pointer;
|
|
123
|
+
font-family: inherit;
|
|
124
|
+
font-size: 1.1rem;
|
|
125
|
+
font-weight: 500;
|
|
126
|
+
margin: 2rem 0;
|
|
127
|
+
padding: 0.6rem 1.2rem;
|
|
128
|
+
transition: border-color 0.25s;
|
|
129
|
+
}
|
|
130
|
+
button:hover {
|
|
131
|
+
border-color: #dd0031;
|
|
132
|
+
}
|
|
133
|
+
button:focus,
|
|
134
|
+
button:focus-visible {
|
|
135
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@media (prefers-color-scheme: light) {
|
|
139
|
+
button {
|
|
140
|
+
background-color: #ffffff;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
`;
|
|
144
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
145
|
+
export const generateDropdownComponent = (_frontends) => {
|
|
146
|
+
return `import { Component } from '@angular/core';
|
|
147
|
+
import { CommonModule } from '@angular/common';
|
|
148
|
+
|
|
149
|
+
@Component({
|
|
150
|
+
selector: 'app-dropdown',
|
|
151
|
+
standalone: true,
|
|
152
|
+
imports: [CommonModule],
|
|
153
|
+
templateUrl: '../templates/dropdown.component.html'
|
|
154
|
+
})
|
|
155
|
+
export class DropdownComponent {
|
|
156
|
+
isOpen = false;
|
|
157
|
+
}
|
|
158
|
+
`;
|
|
159
|
+
};
|
|
160
|
+
export const generateDropdownComponentHtml = (frontends) => {
|
|
161
|
+
const navLinks = frontends.map(formatNavLink).join('\n\t\t');
|
|
162
|
+
return `<details
|
|
163
|
+
class="dropdown"
|
|
164
|
+
[attr.open]="isOpen ? '' : null"
|
|
165
|
+
(mouseenter)="isOpen = true"
|
|
166
|
+
(mouseleave)="isOpen = false"
|
|
167
|
+
>
|
|
168
|
+
<summary>Pages</summary>
|
|
169
|
+
<nav class="menu">
|
|
170
|
+
${navLinks}
|
|
171
|
+
</nav>
|
|
172
|
+
</details>
|
|
173
|
+
`;
|
|
174
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { copyFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { generateMarkupCSS } from '../project/generateMarkupCSS';
|
|
4
|
+
import { generateAngularPage, generateAngularPageHtml, generateAppComponent, generateAppComponentCss, generateAppComponentHtml, generateCounterComponent, generateCounterComponentCss, generateCounterComponentHtml, generateDropdownComponent, generateDropdownComponentHtml } from './generateAngularPage';
|
|
5
|
+
export const scaffoldAngular = ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory, stylesDirectory, stylesIndexesDirectory }) => {
|
|
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 templatesDir = join(targetDirectory, 'templates');
|
|
12
|
+
mkdirSync(templatesDir, { recursive: true });
|
|
13
|
+
writeFileSync(join(pagesDirectory, 'angular-example.ts'), generateAngularPage(frontends), 'utf-8');
|
|
14
|
+
writeFileSync(join(templatesDir, 'angular-example.html'), generateAngularPageHtml(), 'utf-8');
|
|
15
|
+
writeFileSync(join(componentsDirectory, 'dropdown.component.ts'), generateDropdownComponent(frontends), 'utf-8');
|
|
16
|
+
writeFileSync(join(templatesDir, 'dropdown.component.html'), generateDropdownComponentHtml(frontends), 'utf-8');
|
|
17
|
+
writeFileSync(join(componentsDirectory, 'app.component.ts'), generateAppComponent(isSingleFrontend), 'utf-8');
|
|
18
|
+
writeFileSync(join(templatesDir, 'app.component.html'), generateAppComponentHtml(frontends, editBasePath), 'utf-8');
|
|
19
|
+
writeFileSync(join(stylesDirectory, 'app.component.css'), generateAppComponentCss(), 'utf-8');
|
|
20
|
+
writeFileSync(join(componentsDirectory, 'counter.component.ts'), generateCounterComponent(isSingleFrontend), 'utf-8');
|
|
21
|
+
writeFileSync(join(templatesDir, 'counter.component.html'), generateCounterComponentHtml(), 'utf-8');
|
|
22
|
+
writeFileSync(join(stylesDirectory, 'counter.component.css'), generateCounterComponentCss(), 'utf-8');
|
|
23
|
+
const angularCSS = generateMarkupCSS('angular', '#dd0031');
|
|
24
|
+
const customElementCSS = `
|
|
25
|
+
/* Flex wrappers for Angular custom elements */
|
|
26
|
+
angular-page {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex: 1;
|
|
29
|
+
flex-direction: column;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
app-root {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex: 1;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
}`;
|
|
37
|
+
writeFileSync(join(stylesIndexesDirectory, 'angular-example.css'), angularCSS + customElementCSS, 'utf-8');
|
|
38
|
+
};
|
|
@@ -46,12 +46,22 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
|
|
|
46
46
|
if (flags.requiresReact) {
|
|
47
47
|
packageNames.add('react');
|
|
48
48
|
packageNames.add('react-dom');
|
|
49
|
+
packageNames.add('react-refresh');
|
|
49
50
|
packageNames.add('@types/react');
|
|
50
51
|
}
|
|
51
52
|
if (flags.requiresReact && codeQualityTool === 'eslint+prettier') {
|
|
52
53
|
for (const dep of eslintReactDependencies)
|
|
53
54
|
packageNames.add(dep.value);
|
|
54
55
|
}
|
|
56
|
+
if (flags.requiresAngular) {
|
|
57
|
+
packageNames.add('@angular/common');
|
|
58
|
+
packageNames.add('@angular/compiler');
|
|
59
|
+
packageNames.add('@angular/compiler-cli');
|
|
60
|
+
packageNames.add('@angular/core');
|
|
61
|
+
packageNames.add('@angular/platform-browser');
|
|
62
|
+
packageNames.add('@angular/platform-server');
|
|
63
|
+
packageNames.add('@angular/ssr');
|
|
64
|
+
}
|
|
55
65
|
if (flags.requiresSvelte)
|
|
56
66
|
packageNames.add('svelte');
|
|
57
67
|
if (flags.requiresSvelte && codeQualityTool === 'eslint+prettier')
|
|
@@ -133,12 +143,27 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
|
|
|
133
143
|
dependencies['react'] = resolveVersion('react', versions['react']);
|
|
134
144
|
dependencies['react-dom'] = resolveVersion('react-dom', versions['react-dom']);
|
|
135
145
|
devDependencies['@types/react'] = resolveVersion('@types/react', versions['@types/react']);
|
|
146
|
+
devDependencies['react-refresh'] = resolveVersion('react-refresh', versions['react-refresh']);
|
|
136
147
|
}
|
|
137
148
|
if (flags.requiresReact && codeQualityTool === 'eslint+prettier') {
|
|
138
149
|
eslintReactDependencies.forEach((dep) => {
|
|
139
150
|
devDependencies[dep.value] = resolveVersion(dep.value, dep.latestVersion);
|
|
140
151
|
});
|
|
141
152
|
}
|
|
153
|
+
if (flags.requiresAngular) {
|
|
154
|
+
const angularPackages = [
|
|
155
|
+
'@angular/common',
|
|
156
|
+
'@angular/compiler',
|
|
157
|
+
'@angular/compiler-cli',
|
|
158
|
+
'@angular/core',
|
|
159
|
+
'@angular/platform-browser',
|
|
160
|
+
'@angular/platform-server',
|
|
161
|
+
'@angular/ssr'
|
|
162
|
+
];
|
|
163
|
+
angularPackages.forEach((pkg) => {
|
|
164
|
+
dependencies[pkg] = resolveVersion(pkg, versions[pkg]);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
142
167
|
if (flags.requiresSvelte) {
|
|
143
168
|
dependencies['svelte'] = resolveVersion('svelte', versions['svelte']);
|
|
144
169
|
}
|
|
@@ -168,9 +193,9 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
|
|
|
168
193
|
if (latest)
|
|
169
194
|
s.stop(green('Package versions resolved'));
|
|
170
195
|
const scripts = {
|
|
171
|
-
dev: '
|
|
172
|
-
format: `
|
|
173
|
-
lint: '
|
|
196
|
+
dev: 'absolute dev',
|
|
197
|
+
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' : ''}}"`,
|
|
198
|
+
lint: 'absolute eslint',
|
|
174
199
|
test: 'echo "Error: no test specified" && exit 1',
|
|
175
200
|
typecheck: 'bun run tsc --noEmit'
|
|
176
201
|
};
|
|
@@ -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
|
-
|
|
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
|
+
};
|