create-absolutejs 0.11.0 → 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.
Files changed (32) hide show
  1. package/dist/generators/angular/generateAngularPage.d.ts +7 -3
  2. package/dist/generators/angular/generateAngularPage.js +67 -68
  3. package/dist/generators/angular/scaffoldAngular.d.ts +1 -1
  4. package/dist/generators/angular/scaffoldAngular.js +14 -10
  5. package/dist/generators/configurations/generatePackageJson.js +2 -0
  6. package/dist/generators/html/generateHTMLPage.d.ts +1 -1
  7. package/dist/generators/html/generateHTMLPage.js +2 -2
  8. package/dist/generators/html/scaffoldHTML.d.ts +1 -1
  9. package/dist/generators/html/scaffoldHTML.js +4 -6
  10. package/dist/generators/htmx/generateHTMXPage.js +1 -1
  11. package/dist/generators/htmx/scaffoldHTMX.d.ts +1 -1
  12. package/dist/generators/htmx/scaffoldHTMX.js +3 -5
  13. package/dist/generators/project/generateBuildBlock.js +1 -0
  14. package/dist/generators/project/generateImportsBlock.d.ts +1 -2
  15. package/dist/generators/project/generateImportsBlock.js +10 -24
  16. package/dist/generators/project/generateMarkupCSS.d.ts +1 -1
  17. package/dist/generators/project/generateMarkupCSS.js +1 -1
  18. package/dist/generators/project/generateRoutesBlock.d.ts +1 -3
  19. package/dist/generators/project/generateRoutesBlock.js +34 -39
  20. package/dist/generators/project/generateServer.js +0 -2
  21. package/dist/generators/project/scaffoldFrontends.js +20 -3
  22. package/dist/generators/react/scaffoldReact.d.ts +1 -1
  23. package/dist/generators/react/scaffoldReact.js +3 -5
  24. package/dist/generators/svelte/scaffoldSvelte.d.ts +1 -1
  25. package/dist/generators/svelte/scaffoldSvelte.js +3 -5
  26. package/dist/generators/vue/generateVuePage.js +0 -245
  27. package/dist/generators/vue/scaffoldVue.d.ts +1 -1
  28. package/dist/generators/vue/scaffoldVue.js +5 -1
  29. package/dist/types.d.ts +2 -0
  30. package/dist/versions.d.ts +9 -8
  31. package/dist/versions.js +9 -8
  32. package/package.json +2 -2
@@ -1,7 +1,11 @@
1
1
  import { Frontend } from '../../types';
2
2
  export declare const generateAngularPage: (_frontends: Frontend[]) => string;
3
- export declare const generateAppComponent: () => string;
3
+ export declare const generateAngularPageHtml: () => string;
4
+ export declare const generateAppComponent: (isSingleFrontend: boolean) => string;
4
5
  export declare const generateAppComponentCss: () => string;
5
6
  export declare const generateAppComponentHtml: (frontends: Frontend[], editBasePath: string) => string;
6
- export declare const generateCounterComponent: () => string;
7
- export declare const generateDropdownComponent: (frontends: Frontend[]) => 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;
@@ -2,6 +2,7 @@ import { formatNavLink } from '../../utils/formatNavLink';
2
2
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
3
  export const generateAngularPage = (_frontends) => `import { Component, inject, InjectionToken } from '@angular/core';
4
4
  import { CommonModule } from '@angular/common';
5
+ import { defineAngularPage } from '@absolutejs/absolute/angular';
5
6
  import { DropdownComponent } from '../components/dropdown.component';
6
7
  import { AppComponent } from '../components/app.component';
7
8
 
@@ -12,16 +13,10 @@ type AngularPageProps = {
12
13
  };
13
14
 
14
15
  @Component({
16
+ imports: [CommonModule, DropdownComponent, AppComponent],
15
17
  selector: 'angular-page',
16
18
  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
- \`
19
+ templateUrl: '../templates/angular-example.html'
25
20
  })
26
21
  export class AngularExampleComponent {
27
22
  initialCount: number = 0;
@@ -32,13 +27,17 @@ export class AngularExampleComponent {
32
27
  }
33
28
  }
34
29
 
35
- export const factory = (props: AngularPageProps) => {
36
- const component = new AngularExampleComponent();
37
- component.initialCount = props.initialCount;
38
- return component;
39
- };
30
+ export const page = defineAngularPage<AngularPageProps>({
31
+ component: AngularExampleComponent
32
+ });
40
33
  `;
41
- export const generateAppComponent = () => `import { Component, Input, ViewEncapsulation } from '@angular/core';
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';
42
41
  import { CommonModule } from '@angular/common';
43
42
  import { CounterComponent } from './counter.component';
44
43
 
@@ -46,8 +45,8 @@ import { CounterComponent } from './counter.component';
46
45
  selector: 'app-root',
47
46
  standalone: true,
48
47
  imports: [CommonModule, CounterComponent],
49
- templateUrl: './app.component.html',
50
- styleUrls: ['./app.component.css'],
48
+ templateUrl: '../templates/app.component.html',
49
+ styleUrl: '${isSingleFrontend ? '../' : '../../'}styles/app.component.css',
51
50
  encapsulation: ViewEncapsulation.None
52
51
  })
53
52
  export class AppComponent {
@@ -88,48 +87,15 @@ export const generateAppComponentHtml = (frontends, editBasePath) => {
88
87
  </main>
89
88
  `;
90
89
  };
91
- export const generateCounterComponent = () => `import { Component, Input } from '@angular/core';
90
+ export const generateCounterComponent = (isSingleFrontend) => `import { Component, Input } from '@angular/core';
92
91
  import { CommonModule } from '@angular/common';
93
92
 
94
93
  @Component({
95
94
  selector: 'app-counter',
96
95
  standalone: true,
97
96
  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
- ]
97
+ templateUrl: '../templates/counter.component.html',
98
+ styleUrl: '${isSingleFrontend ? '../' : '../../'}styles/counter.component.css'
133
99
  })
134
100
  export class CounterComponent {
135
101
  @Input() initialCount: number = 0;
@@ -144,8 +110,39 @@ export class CounterComponent {
144
110
  }
145
111
  }
146
112
  `;
147
- export const generateDropdownComponent = (frontends) => {
148
- const navLinks = frontends.map(formatNavLink).join('\n\t\t\t\t');
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) => {
149
146
  return `import { Component } from '@angular/core';
150
147
  import { CommonModule } from '@angular/common';
151
148
 
@@ -153,23 +150,25 @@ import { CommonModule } from '@angular/common';
153
150
  selector: 'app-dropdown',
154
151
  standalone: true,
155
152
  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: []
153
+ templateUrl: '../templates/dropdown.component.html'
170
154
  })
171
155
  export class DropdownComponent {
172
156
  isOpen = false;
173
157
  }
174
158
  `;
175
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
+ };
@@ -1,2 +1,2 @@
1
1
  import { ScaffoldFrontendProps } from '../../types';
2
- export declare const scaffoldAngular: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }: ScaffoldFrontendProps) => void;
2
+ export declare const scaffoldAngular: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory, stylesDirectory, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
@@ -1,22 +1,26 @@
1
1
  import { copyFileSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
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 }) => {
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
6
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'angular.svg'), join(projectAssetsDirectory, 'svg', 'angular.svg'));
7
7
  const componentsDirectory = join(targetDirectory, 'components');
8
8
  mkdirSync(componentsDirectory, { recursive: true });
9
9
  const pagesDirectory = join(targetDirectory, 'pages');
10
10
  mkdirSync(pagesDirectory, { recursive: true });
11
- const stylesDirectory = join(targetDirectory, 'styles');
12
- mkdirSync(stylesDirectory, { recursive: true });
11
+ const templatesDir = join(targetDirectory, 'templates');
12
+ mkdirSync(templatesDir, { recursive: true });
13
13
  writeFileSync(join(pagesDirectory, 'angular-example.ts'), generateAngularPage(frontends), 'utf-8');
14
+ writeFileSync(join(templatesDir, 'angular-example.html'), generateAngularPageHtml(), 'utf-8');
14
15
  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);
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');
20
24
  const customElementCSS = `
21
25
  /* Flex wrappers for Angular custom elements */
22
26
  angular-page {
@@ -30,5 +34,5 @@ app-root {
30
34
  flex: 1;
31
35
  flex-direction: column;
32
36
  }`;
33
- writeFileSync(join(stylesDirectory, 'angular-example.css'), angularCSS + customElementCSS, 'utf-8');
37
+ writeFileSync(join(stylesIndexesDirectory, 'angular-example.css'), angularCSS + customElementCSS, 'utf-8');
34
38
  };
@@ -46,6 +46,7 @@ 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') {
@@ -142,6 +143,7 @@ export const createPackageJson = async ({ projectName, authOption, plugins, data
142
143
  dependencies['react'] = resolveVersion('react', versions['react']);
143
144
  dependencies['react-dom'] = resolveVersion('react-dom', versions['react-dom']);
144
145
  devDependencies['@types/react'] = resolveVersion('@types/react', versions['@types/react']);
146
+ devDependencies['react-refresh'] = resolveVersion('react-refresh', versions['react-refresh']);
145
147
  }
146
148
  if (flags.requiresReact && codeQualityTool === 'eslint+prettier') {
147
149
  eslintReactDependencies.forEach((dep) => {
@@ -1,2 +1,2 @@
1
1
  import { CreateConfiguration, Frontend } from '../../types';
2
- export declare const generateHTMLPage: (frontends: Frontend[], useHTMLScripts: CreateConfiguration["useHTMLScripts"], editBasePath: string) => string;
2
+ export declare const generateHTMLPage: (frontends: Frontend[], useHTMLScripts: CreateConfiguration["useHTMLScripts"], editBasePath: string, isSingleFrontend: boolean) => string;
@@ -1,5 +1,5 @@
1
1
  import { formatNavLink } from '../../utils/formatNavLink';
2
- export const generateHTMLPage = (frontends, useHTMLScripts, editBasePath) => {
2
+ export const generateHTMLPage = (frontends, useHTMLScripts, editBasePath, isSingleFrontend) => {
3
3
  const navLinks = frontends.map(formatNavLink).join('\n\t\t\t');
4
4
  const initialCount = useHTMLScripts ? '0' : 'disabled';
5
5
  const scriptTagBlock = useHTMLScripts
@@ -15,7 +15,7 @@ export const generateHTMLPage = (frontends, useHTMLScripts, editBasePath) => {
15
15
  <link
16
16
  rel="stylesheet"
17
17
  type="text/css"
18
- href="../styles/html-example.css"
18
+ href="${isSingleFrontend ? '../../' : '../../../'}styles/indexes/html-example.css"
19
19
  />
20
20
  <link rel="icon" href="/assets/ico/favicon.ico" />
21
21
  </head>
@@ -2,5 +2,5 @@ import { ScaffoldFrontendProps } from '../../types';
2
2
  type ScaffoldHTMLProps = ScaffoldFrontendProps & {
3
3
  useHTMLScripts: boolean;
4
4
  };
5
- export declare const scaffoldHTML: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, useHTMLScripts, templatesDirectory, projectAssetsDirectory }: ScaffoldHTMLProps) => void;
5
+ export declare const scaffoldHTML: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, useHTMLScripts, templatesDirectory, projectAssetsDirectory, stylesIndexesDirectory }: ScaffoldHTMLProps) => void;
6
6
  export {};
@@ -2,9 +2,9 @@ import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { generateMarkupCSS } from '../project/generateMarkupCSS';
4
4
  import { generateHTMLPage } from './generateHTMLPage';
5
- export const scaffoldHTML = ({ editBasePath, isSingleFrontend, targetDirectory, frontends, useHTMLScripts, templatesDirectory, projectAssetsDirectory }) => {
5
+ export const scaffoldHTML = ({ editBasePath, isSingleFrontend, targetDirectory, frontends, useHTMLScripts, templatesDirectory, projectAssetsDirectory, stylesIndexesDirectory }) => {
6
6
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'HTML5_Badge.svg'), join(projectAssetsDirectory, 'svg', 'HTML5_Badge.svg'));
7
- const htmlPage = generateHTMLPage(frontends, useHTMLScripts, editBasePath);
7
+ const htmlPage = generateHTMLPage(frontends, useHTMLScripts, editBasePath, isSingleFrontend);
8
8
  const pagesDirectory = join(targetDirectory, 'pages');
9
9
  mkdirSync(pagesDirectory, { recursive: true });
10
10
  const htmlFilePath = join(pagesDirectory, 'HTMLExample.html');
@@ -13,9 +13,7 @@ export const scaffoldHTML = ({ editBasePath, isSingleFrontend, targetDirectory,
13
13
  cpSync(join(templatesDirectory, 'html', 'scripts'), scriptsDirectory, {
14
14
  recursive: true
15
15
  });
16
- const cssOutputDir = join(targetDirectory, 'styles');
17
- mkdirSync(cssOutputDir, { recursive: true });
18
- const cssOutputFile = join(cssOutputDir, 'html-example.css');
19
- const htmlCSS = generateMarkupCSS('html', '#e34f26', isSingleFrontend);
16
+ const cssOutputFile = join(stylesIndexesDirectory, 'html-example.css');
17
+ const htmlCSS = generateMarkupCSS('html', '#e34f26');
20
18
  writeFileSync(cssOutputFile, htmlCSS, 'utf-8');
21
19
  };
@@ -11,7 +11,7 @@ export const generateHTMXPage = (isSingle, frontends, editBasePath) => {
11
11
  <link
12
12
  rel="stylesheet"
13
13
  type="text/css"
14
- href="../styles/htmx-example.css"
14
+ href="${isSingle ? '../../' : '../../../'}styles/indexes/htmx-example.css"
15
15
  />
16
16
  <link rel="icon" href="/assets/ico/favicon.ico" />
17
17
  <script src="${isSingle ? '' : '/htmx'}/htmx.min.js"></script>
@@ -1,2 +1,2 @@
1
1
  import { ScaffoldFrontendProps } from '../../types';
2
- export declare const scaffoldHTMX: ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }: ScaffoldFrontendProps) => void;
2
+ export declare const scaffoldHTMX: ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
@@ -3,7 +3,7 @@ import { join } from 'path';
3
3
  import { Glob } from 'bun';
4
4
  import { generateMarkupCSS } from '../project/generateMarkupCSS';
5
5
  import { generateHTMXPage } from './generateHTMXPage';
6
- export const scaffoldHTMX = ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }) => {
6
+ export const scaffoldHTMX = ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend, stylesIndexesDirectory }) => {
7
7
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'htmx-logo-black.svg'), join(projectAssetsDirectory, 'svg', 'htmx-logo-black.svg'));
8
8
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'htmx-logo-white.svg'), join(projectAssetsDirectory, 'svg', 'htmx-logo-white.svg'));
9
9
  const glob = new Glob('htmx*.min.js');
@@ -20,9 +20,7 @@ export const scaffoldHTMX = ({ editBasePath, targetDirectory, templatesDirectory
20
20
  mkdirSync(pagesDirectory, { recursive: true });
21
21
  const htmxFilePath = join(pagesDirectory, 'HTMXExample.html');
22
22
  writeFileSync(htmxFilePath, htmxPage, 'utf-8');
23
- const cssOutputDir = join(targetDirectory, 'styles');
24
- mkdirSync(cssOutputDir, { recursive: true });
25
- const cssOutputFile = join(cssOutputDir, 'htmx-example.css');
26
- const htmxCSS = generateMarkupCSS('htmx', '#3465a4', isSingleFrontend);
23
+ const cssOutputFile = join(stylesIndexesDirectory, 'htmx-example.css');
24
+ const htmxCSS = generateMarkupCSS('htmx', '#3465a4');
27
25
  writeFileSync(cssOutputFile, htmxCSS, 'utf-8');
28
26
  };
@@ -6,6 +6,7 @@ export const generateBuildBlock = ({ assetsDirectory, backendDirectory, buildDir
6
6
  `buildDirectory: '${buildDirectory}'`,
7
7
  ...Object.entries(frontendDirectories).map(([f, dir]) => `${f}Directory: 'src/frontend${dir ? `/${dir}` : ''}'`),
8
8
  `publicDirectory: '${publicDirectory}'`,
9
+ `stylesConfig: 'src/styles/indexes'`,
9
10
  tailwind ? `tailwind: ${JSON.stringify(tailwind)}` : ''
10
11
  ]
11
12
  .filter(Boolean)
@@ -1,7 +1,6 @@
1
1
  import type { AvailableDependency, CreateConfiguration } from '../../types';
2
2
  import type { FrameworkFlags } from './computeFlags';
3
3
  type GenerateImportsBlockProps = {
4
- backendDirectory: string;
5
4
  deps: AvailableDependency[];
6
5
  flags: FrameworkFlags;
7
6
  orm: CreateConfiguration['orm'];
@@ -10,5 +9,5 @@ type GenerateImportsBlockProps = {
10
9
  databaseHost: CreateConfiguration['databaseHost'];
11
10
  frontendDirectories: CreateConfiguration['frontendDirectories'];
12
11
  };
13
- export declare const generateImportsBlock: ({ backendDirectory, deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }: GenerateImportsBlockProps) => string;
12
+ export declare const generateImportsBlock: ({ deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }: GenerateImportsBlockProps) => string;
14
13
  export {};
@@ -1,30 +1,20 @@
1
- import { mkdirSync, writeFileSync } from 'fs';
2
- import { join } from 'path';
3
1
  import { isDrizzleDialect } from '../../typeGuards';
4
- export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }) => {
2
+ export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }) => {
5
3
  const rawImports = [];
6
4
  const pushHandler = (cond, name, pkg = '@absolutejs/absolute') => cond && rawImports.push(`import { ${name} } from '${pkg}'`);
7
5
  pushHandler(flags.requiresAngular, 'handleAngularPageRequest', '@absolutejs/absolute/angular');
8
6
  pushHandler(flags.requiresAngular, 'generateHeadElement');
9
7
  pushHandler(flags.requiresHtml, 'handleHTMLPageRequest');
10
- pushHandler(flags.requiresReact, 'handleReactPageRequest');
8
+ pushHandler(flags.requiresReact, 'handleReactPageRequest', '@absolutejs/absolute/react');
11
9
  pushHandler(flags.requiresSvelte, 'handleSveltePageRequest', '@absolutejs/absolute/svelte');
12
10
  pushHandler(flags.requiresVue, 'handleVuePageRequest', '@absolutejs/absolute/vue');
13
11
  pushHandler(flags.requiresVue, 'generateHeadElement');
14
12
  pushHandler(flags.requiresHtmx, 'handleHTMXPageRequest');
15
- const nonFrameworkOnly = (flags.requiresHtml || flags.requiresHtmx) &&
16
- !flags.requiresAngular &&
17
- !flags.requiresReact &&
18
- !flags.requiresSvelte &&
19
- !flags.requiresVue;
20
13
  for (const dependency of deps) {
21
14
  const importsList = dependency.imports ?? [];
22
- const relevantImports = nonFrameworkOnly
23
- ? importsList.filter((imp) => imp.packageName !== 'asset')
24
- : importsList;
25
- if (relevantImports.length === 0)
15
+ if (importsList.length === 0)
26
16
  continue;
27
- rawImports.push(`import { ${relevantImports
17
+ rawImports.push(`import { ${importsList
28
18
  .map((imp) => imp.packageName)
29
19
  .sort()
30
20
  .join(', ')} } from '${dependency.value}'`);
@@ -33,12 +23,15 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
33
23
  const reactDir = frontendDirectories.react;
34
24
  const svelteDir = frontendDirectories.svelte;
35
25
  const vueDir = frontendDirectories.vue;
26
+ const angularDir = frontendDirectories.angular;
36
27
  if (flags.requiresReact && reactDir !== undefined)
37
28
  rawImports.push(`import { ReactExample } from '${buildExamplePath(reactDir, 'ReactExample')}'`);
38
29
  if (flags.requiresSvelte && svelteDir !== undefined)
39
- rawImports.push(`import SvelteExample from '${buildExamplePath(svelteDir, 'SvelteExample.svelte')}'`);
40
- if (flags.requiresVue && !flags.requiresSvelte && vueDir !== undefined)
41
- rawImports.push(`import VueExample from '${buildExamplePath(vueDir, 'VueExample.vue')}'`);
30
+ rawImports.push(`import type SvelteExample from '${buildExamplePath(svelteDir, 'SvelteExample.svelte')}'`);
31
+ if (flags.requiresVue && vueDir !== undefined)
32
+ rawImports.push(`import type VueExample from '${buildExamplePath(vueDir, 'VueExample.vue')}'`);
33
+ if (flags.requiresAngular && angularDir !== undefined)
34
+ rawImports.push(`import type * as AngularExamplePage from '${buildExamplePath(angularDir, 'angular-example')}'`);
42
35
  const connectorImports = {
43
36
  neon: [`import { neon } from '@neondatabase/serverless'`],
44
37
  planetscale: [`import { Client } from '@planetscale/database'`],
@@ -187,13 +180,6 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
187
180
  rawImports.push(`import { absoluteAuthConfig } from './utils/absoluteAuthConfig'`, `import { t } from 'elysia'`, `import { authProviderOption, providers, userSessionIdTypebox, getStatus } from '@absolutejs/auth'`);
188
181
  if (hasDatabase && (authOption === undefined || authOption === 'none'))
189
182
  rawImports.push(`import { getCountHistory, createCountHistory } from './handlers/countHistoryHandlers'`, `import { t } from 'elysia'`);
190
- if (flags.requiresVue && flags.requiresSvelte) {
191
- const utilsDir = join(backendDirectory, 'utils');
192
- mkdirSync(utilsDir, { recursive: true });
193
- const vuePathForUtils = `../../frontend${vueDir ? `/${vueDir}` : ''}/pages/VueExample.vue`;
194
- writeFileSync(join(utilsDir, 'vueImporter.ts'), `import VueExample from "${vuePathForUtils}"\n\nexport const vueImports = { VueExample } as const\n`);
195
- rawImports.push(`import { vueImports } from './utils/vueImporter'`);
196
- }
197
183
  const importMap = new Map();
198
184
  for (const stmt of rawImports) {
199
185
  const match = stmt.match(/^import\s+(.+)\s+from\s+['"](.+)['"];?/);
@@ -1,2 +1,2 @@
1
1
  import { Frontend } from '../../types';
2
- export declare const generateMarkupCSS: (frontend: Frontend, color: string, isSingleFrontend: boolean) => string;
2
+ export declare const generateMarkupCSS: (frontend: Frontend, color: string) => string;
@@ -1,4 +1,4 @@
1
- export const generateMarkupCSS = (frontend, color, isSingleFrontend) => `@import url('${isSingleFrontend ? '../styles/reset.css' : '../../styles/reset.css'}');
1
+ export const generateMarkupCSS = (frontend, color) => `@import url('../reset.css');
2
2
 
3
3
  header {
4
4
  align-items: center;
@@ -1,10 +1,8 @@
1
1
  import type { AuthOption, CreateConfiguration, FrontendDirectories } from '../../types';
2
- import type { FrameworkFlags } from './computeFlags';
3
2
  type GenerateRoutesBlockProps = {
4
3
  databaseEngine: CreateConfiguration['databaseEngine'];
5
- flags: FrameworkFlags;
6
4
  frontendDirectories: FrontendDirectories;
7
5
  authOption: AuthOption;
8
6
  };
9
- export declare const generateRoutesBlock: ({ databaseEngine, flags, frontendDirectories, authOption }: GenerateRoutesBlockProps) => string;
7
+ export declare const generateRoutesBlock: ({ databaseEngine, frontendDirectories, authOption }: GenerateRoutesBlockProps) => string;
10
8
  export {};
@@ -1,5 +1,5 @@
1
1
  import { isFrontend } from '../../typeGuards';
2
- export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories, authOption }) => {
2
+ export const generateRoutesBlock = ({ databaseEngine, frontendDirectories, authOption }) => {
3
3
  const hasDatabase = databaseEngine !== undefined && databaseEngine !== 'none';
4
4
  const routes = [];
5
5
  const wrap = (handlerCall, isAsync = false) => authOption === 'abs'
@@ -16,61 +16,56 @@ export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories
16
16
  return ${handlerCall};
17
17
  }`
18
18
  : `${isAsync ? 'async ' : ''}() => ${handlerCall}`;
19
- const createHandlerCall = (frontend, directory) => {
19
+ const createHandlerCall = (frontend) => {
20
20
  if (frontend === 'angular')
21
- return `handleAngularPageRequest(
22
- () => import('../frontend${directory ? `/${directory}` : ''}/pages/angular-example'),
23
- asset(manifest, 'AngularExample'),
24
- asset(manifest, 'AngularExampleIndex'),
25
- generateHeadElement({
21
+ return `handleAngularPageRequest<typeof AngularExamplePage>({
22
+ headTag: generateHeadElement({
26
23
  cssPath: asset(manifest, 'AngularExampleCSS'),
27
24
  title: 'AbsoluteJS + Angular'
28
25
  }),
29
- { initialCount: 0 }
30
- )`;
26
+ indexPath: asset(manifest, 'AngularExampleIndex'),
27
+ pagePath: asset(manifest, 'AngularExample'),
28
+ props: { initialCount: 0 }
29
+ })`;
31
30
  if (frontend === 'html')
32
31
  return `handleHTMLPageRequest(asset(manifest, 'HTMLExample'))`;
33
32
  if (frontend === 'htmx')
34
33
  return `handleHTMXPageRequest(asset(manifest, 'HTMXExample'))`;
35
34
  if (frontend === 'react') {
36
35
  const reactProps = authOption === 'abs'
37
- ? `{ initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS'), user, providerConfiguration }`
38
- : `{ initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS') }`;
39
- return `handleReactPageRequest(
40
- ReactExample,
41
- asset(manifest, 'ReactExampleIndex'),
42
- ${reactProps}
43
- )`;
36
+ ? `{ cssPath: asset(manifest, 'ReactExampleCSS'), initialCount: 0, providerConfiguration, user }`
37
+ : `{ cssPath: asset(manifest, 'ReactExampleCSS'), initialCount: 0 }`;
38
+ return `handleReactPageRequest({
39
+ Page: ReactExample,
40
+ index: asset(manifest, 'ReactExampleIndex'),
41
+ props: ${reactProps}
42
+ })`;
44
43
  }
45
44
  if (frontend === 'svelte')
46
- return `handleSveltePageRequest(
47
- SvelteExample,
48
- asset(manifest, 'SvelteExample'),
49
- asset(manifest, 'SvelteExampleIndex'),
50
- { initialCount: 0, cssPath: asset(manifest, 'SvelteExampleCSS') }
51
- )`;
52
- if (frontend === 'vue') {
53
- const vueComponent = flags.requiresSvelte
54
- ? 'vueImports.VueExample'
55
- : 'VueExample';
56
- return `handleVuePageRequest(
57
- ${vueComponent},
58
- asset(manifest, 'VueExample'),
59
- asset(manifest, 'VueExampleIndex'),
60
- generateHeadElement({
61
- cssPath: asset(manifest, 'VueExampleCSS'),
62
- title: 'AbsoluteJS + Vue',
63
- description: 'A Vue.js example with AbsoluteJS'
45
+ return `handleSveltePageRequest<typeof SvelteExample>({
46
+ indexPath: asset(manifest, 'SvelteExampleIndex'),
47
+ pagePath: asset(manifest, 'SvelteExample'),
48
+ props: { cssPath: asset(manifest, 'SvelteExampleCSS'), initialCount: 0 }
49
+ })`;
50
+ if (frontend === 'vue')
51
+ return `handleVuePageRequest<typeof VueExample>({
52
+ headTag: generateHeadElement({
53
+ cssPath: [
54
+ asset(manifest, 'VueExampleCSS'),
55
+ asset(manifest, 'VueExampleCompiledCSS')
56
+ ],
57
+ title: 'AbsoluteJS + Vue'
64
58
  }),
65
- { initialCount: 0 }
66
- )`;
67
- }
59
+ indexPath: asset(manifest, 'VueExampleIndex'),
60
+ pagePath: asset(manifest, 'VueExample'),
61
+ props: { initialCount: 0 }
62
+ })`;
68
63
  return '';
69
64
  };
70
- Object.entries(frontendDirectories).forEach(([frontend, directory], entryIndex) => {
65
+ Object.entries(frontendDirectories).forEach(([frontend], entryIndex) => {
71
66
  if (!isFrontend(frontend))
72
67
  return;
73
- const handlerCall = createHandlerCall(frontend, directory ?? '');
68
+ const handlerCall = createHandlerCall(frontend);
74
69
  if (!handlerCall)
75
70
  return;
76
71
  const isAsync = frontend === 'angular';
@@ -12,7 +12,6 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
12
12
  const deps = collectDependencies({ authOption, flags, plugins });
13
13
  const importsBlock = generateImportsBlock({
14
14
  authOption,
15
- backendDirectory,
16
15
  databaseEngine,
17
16
  databaseHost,
18
17
  deps,
@@ -61,7 +60,6 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
61
60
  const routesBlock = generateRoutesBlock({
62
61
  authOption,
63
62
  databaseEngine,
64
- flags,
65
63
  frontendDirectories
66
64
  });
67
65
  const content = `${importsBlock}
@@ -1,5 +1,5 @@
1
1
  import { copyFileSync, cpSync, mkdirSync } from 'fs';
2
- import { join } from 'path';
2
+ import { dirname, join } from 'path';
3
3
  import { scaffoldAngular } from '../angular/scaffoldAngular';
4
4
  import { scaffoldHTML } from '../html/scaffoldHTML';
5
5
  import { scaffoldHTMX } from '../htmx/scaffoldHTMX';
@@ -7,10 +7,15 @@ import { scaffoldReact } from '../react/scaffoldReact';
7
7
  import { scaffoldSvelte } from '../svelte/scaffoldSvelte';
8
8
  import { scaffoldVue } from '../vue/scaffoldVue';
9
9
  export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProviders, authOption, templatesDirectory, projectAssetsDirectory, typesDirectory, useHTMLScripts, useTailwind, frontendDirectories, frontends }) => {
10
- const stylesTargetDirectory = join(frontendDirectory, 'styles');
11
- cpSync(join(templatesDirectory, 'styles'), stylesTargetDirectory, {
10
+ const srcDirectory = dirname(frontendDirectory);
11
+ const globalStylesDirectory = join(srcDirectory, 'styles');
12
+ const stylesIndexesDirectory = join(globalStylesDirectory, 'indexes');
13
+ cpSync(join(templatesDirectory, 'styles'), globalStylesDirectory, {
12
14
  recursive: true
13
15
  });
16
+ mkdirSync(stylesIndexesDirectory, { recursive: true });
17
+ const stylesTargetDirectory = join(frontendDirectory, 'styles');
18
+ mkdirSync(stylesTargetDirectory, { recursive: true });
14
19
  if (useTailwind) {
15
20
  copyFileSync(join(templatesDirectory, 'tailwind', 'tailwind.css'), join(stylesTargetDirectory, 'tailwind.css'));
16
21
  }
@@ -39,6 +44,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
39
44
  frontends,
40
45
  isSingleFrontend,
41
46
  projectAssetsDirectory,
47
+ stylesDirectory: stylesTargetDirectory,
48
+ stylesIndexesDirectory,
42
49
  targetDirectory,
43
50
  templatesDirectory
44
51
  });
@@ -52,6 +59,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
52
59
  frontends,
53
60
  isSingleFrontend,
54
61
  projectAssetsDirectory,
62
+ stylesDirectory: stylesTargetDirectory,
63
+ stylesIndexesDirectory,
55
64
  targetDirectory,
56
65
  templatesDirectory
57
66
  });
@@ -64,6 +73,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
64
73
  editBasePath,
65
74
  frontends,
66
75
  projectAssetsDirectory,
76
+ stylesDirectory: stylesTargetDirectory,
77
+ stylesIndexesDirectory,
67
78
  targetDirectory,
68
79
  templatesDirectory
69
80
  });
@@ -78,6 +89,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
78
89
  frontends,
79
90
  isSingleFrontend,
80
91
  projectAssetsDirectory,
92
+ stylesDirectory: stylesTargetDirectory,
93
+ stylesIndexesDirectory,
81
94
  targetDirectory,
82
95
  templatesDirectory
83
96
  });
@@ -91,6 +104,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
91
104
  frontends,
92
105
  isSingleFrontend,
93
106
  projectAssetsDirectory,
107
+ stylesDirectory: stylesTargetDirectory,
108
+ stylesIndexesDirectory,
94
109
  targetDirectory,
95
110
  templatesDirectory,
96
111
  useHTMLScripts
@@ -105,6 +120,8 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
105
120
  frontends,
106
121
  isSingleFrontend,
107
122
  projectAssetsDirectory,
123
+ stylesDirectory: stylesTargetDirectory,
124
+ stylesIndexesDirectory,
108
125
  targetDirectory,
109
126
  templatesDirectory
110
127
  });
@@ -1,2 +1,2 @@
1
1
  import { ScaffoldFrontendProps } from '../../types';
2
- export declare const scaffoldReact: ({ isSingleFrontend, authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders }: ScaffoldFrontendProps) => void;
2
+ export declare const scaffoldReact: ({ authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
@@ -2,7 +2,7 @@ import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { generateMarkupCSS } from '../project/generateMarkupCSS';
4
4
  import { generateAppComponent, generateDropdownComponent, generateReactExamplePage, generateSignInComponent } from './generateReactComponents';
5
- export const scaffoldReact = ({ isSingleFrontend, authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders }) => {
5
+ export const scaffoldReact = ({ authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }) => {
6
6
  mkdirSync(join(projectAssetsDirectory, 'svg'), { recursive: true });
7
7
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'react.svg'), join(projectAssetsDirectory, 'svg', 'react.svg'));
8
8
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'google-logo.svg'), join(projectAssetsDirectory, 'svg', 'google-logo.svg'));
@@ -20,9 +20,7 @@ export const scaffoldReact = ({ isSingleFrontend, authOption, editBasePath, targ
20
20
  const pageComponent = generateReactExamplePage(authOption);
21
21
  mkdirSync(join(targetDirectory, 'pages'), { recursive: true });
22
22
  writeFileSync(join(targetDirectory, 'pages', 'ReactExample.tsx'), pageComponent, 'utf-8');
23
- const cssOutputDir = join(targetDirectory, 'styles');
24
- mkdirSync(cssOutputDir, { recursive: true });
25
- const cssOutputFile = join(cssOutputDir, 'react-example.css');
26
- const reactCSS = generateMarkupCSS('react', '#61dafbaa', isSingleFrontend);
23
+ const cssOutputFile = join(stylesIndexesDirectory, 'react-example.css');
24
+ const reactCSS = generateMarkupCSS('react', '#61dafbaa');
27
25
  writeFileSync(cssOutputFile, reactCSS, 'utf-8');
28
26
  };
@@ -1,2 +1,2 @@
1
1
  import { ScaffoldFrontendProps } from '../../types';
2
- export declare const scaffoldSvelte: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }: ScaffoldFrontendProps) => void;
2
+ export declare const scaffoldSvelte: ({ editBasePath, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
@@ -1,7 +1,7 @@
1
1
  import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { generateSveltePage } from './generateSveltePage';
4
- export const scaffoldSvelte = ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }) => {
4
+ export const scaffoldSvelte = ({ editBasePath, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory, stylesIndexesDirectory }) => {
5
5
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'svelte-logo.svg'), join(projectAssetsDirectory, 'svg', 'svelte-logo.svg'));
6
6
  cpSync(join(templatesDirectory, 'svelte'), targetDirectory, {
7
7
  recursive: true
@@ -11,9 +11,7 @@ export const scaffoldSvelte = ({ editBasePath, isSingleFrontend, targetDirectory
11
11
  mkdirSync(pagesDirectory, { recursive: true });
12
12
  const svelteFilePath = join(pagesDirectory, 'SvelteExample.svelte');
13
13
  writeFileSync(svelteFilePath, sveltePage, 'utf-8');
14
- const cssOutputDirectory = join(targetDirectory, 'styles');
15
- mkdirSync(cssOutputDirectory, { recursive: true });
16
- const cssOutputFile = join(cssOutputDirectory, 'svelte-example.css');
17
- const svelteCSS = `@import url('${isSingleFrontend ? '../' : '../../'}styles/reset.css');`;
14
+ const cssOutputFile = join(stylesIndexesDirectory, 'svelte-example.css');
15
+ const svelteCSS = `@import url('../reset.css');`;
18
16
  writeFileSync(cssOutputFile, svelteCSS, 'utf-8');
19
17
  };
@@ -75,32 +75,6 @@ ${frontends.length > 1
75
75
  </template>
76
76
 
77
77
  <style scoped>
78
- :global(*) {
79
- box-sizing: border-box;
80
- line-height: 1.5;
81
- margin: 0;
82
- padding: 0;
83
- }
84
-
85
- :global(html) {
86
- font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
87
- height: 100%;
88
- }
89
-
90
- :global(body) {
91
- background-color: #2c2c2c;
92
- color: #f5f5f5;
93
- color-scheme: light dark;
94
- display: flex;
95
- flex-direction: column;
96
- font-synthesis: none;
97
- font-weight: 400;
98
- height: 100%;
99
- -moz-osx-font-smoothing: grayscale;
100
- text-rendering: optimizeLegibility;
101
- -webkit-font-smoothing: antialiased;
102
- }
103
-
104
78
  :global(#root) {
105
79
  display: flex;
106
80
  flex-direction: column;
@@ -108,225 +82,6 @@ ${frontends.length > 1
108
82
  height: 100%;
109
83
  width: 100%;
110
84
  }
111
-
112
- :global(main) {
113
- align-items: center;
114
- display: flex;
115
- flex: 1;
116
- flex-direction: column;
117
- justify-content: center;
118
- text-align: center;
119
- }
120
-
121
- :global(h1),
122
- :global(h2),
123
- :global(h3),
124
- :global(h4),
125
- :global(h5),
126
- :global(h6) {
127
- line-height: 1.1;
128
- }
129
-
130
- :global(p) {
131
- font-size: 1.2rem;
132
- max-width: 1280px;
133
- }
134
-
135
- a {
136
- color: #5fbeeb;
137
- font-size: 1.5rem;
138
- font-weight: 500;
139
- position: relative;
140
- text-decoration: none;
141
- }
142
-
143
- header {
144
- align-items: center;
145
- background-color: #1a1a1a;
146
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
147
- display: flex;
148
- justify-content: space-between;
149
- padding: 2rem;
150
- text-align: center;
151
- }
152
-
153
- header a {
154
- position: relative;
155
- color: #5fbeeb;
156
- text-decoration: none;
157
- }
158
-
159
- header a::after {
160
- content: '';
161
- position: absolute;
162
- left: 0;
163
- bottom: 0;
164
- width: 100%;
165
- height: 2px;
166
- background: linear-gradient(90deg, #5fbeeb 0%, #35d5a2 50%, #ff4b91 100%);
167
- transform: scaleX(0);
168
- transform-origin: left;
169
- transition: transform 0.25s ease-in-out;
170
- }
171
-
172
- header a:hover::after {
173
- transform: scaleX(1);
174
- }
175
-
176
- h1 {
177
- font-size: 2.5rem;
178
- margin-top: 2rem;
179
- }
180
-
181
- .logo {
182
- height: 8rem;
183
- width: 8rem;
184
- will-change: filter;
185
- transition: filter 300ms;
186
- }
187
- .logo:hover {
188
- filter: drop-shadow(0 0 2rem #5fbeeb);
189
- }
190
- .logo.vue:hover {
191
- filter: drop-shadow(0 0 2rem #42b883);
192
- }
193
-
194
- button:hover {
195
- border-color: #42b883;
196
- }
197
-
198
- nav {
199
- display: flex;
200
- gap: 4rem;
201
- justify-content: center;
202
- }
203
-
204
- header details {
205
- position: relative;
206
- }
207
-
208
- header details summary {
209
- list-style: none;
210
- appearance: none;
211
- -webkit-appearance: none;
212
- cursor: pointer;
213
- user-select: none;
214
- color: #5fbeeb;
215
- font-size: 1.5rem;
216
- font-weight: 500;
217
- padding: 0.5rem 1rem;
218
- }
219
-
220
- header summary::after {
221
- content: '▼';
222
- display: inline-block;
223
- margin-left: 0.5rem;
224
- font-size: 0.75rem;
225
- transition: transform 0.3s ease;
226
- }
227
-
228
- header details[open] summary::after {
229
- transform: rotate(180deg);
230
- }
231
-
232
- header details nav {
233
- content-visibility: visible;
234
- position: absolute;
235
- top: 100%;
236
- right: -0.5rem;
237
- display: flex;
238
- flex-direction: column;
239
- gap: 0.75rem;
240
- background: rgba(128, 128, 128, 0.15);
241
- backdrop-filter: blur(4px);
242
- border: 1px solid #5fbeeb;
243
- border-radius: 1rem;
244
- padding: 1rem 1.5rem;
245
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
246
- opacity: 0;
247
- transform: translateY(-8px);
248
- pointer-events: none;
249
- transition:
250
- opacity 0.3s ease,
251
- transform 0.3s ease;
252
- z-index: 1000;
253
- }
254
-
255
- header details[open] nav {
256
- opacity: 1;
257
- transform: translateY(0);
258
- pointer-events: auto;
259
- }
260
-
261
- header details nav a {
262
- font-size: 1.1rem;
263
- padding: 0.25rem 0;
264
- white-space: nowrap;
265
- }
266
-
267
- @media (max-width: 480px) {
268
- :global(main) {
269
- padding: 1rem;
270
- }
271
-
272
- :global(p) {
273
- font-size: 1rem;
274
- }
275
-
276
- header {
277
- padding: 1rem;
278
- }
279
-
280
- a {
281
- font-size: 1.2rem;
282
- }
283
-
284
- h1 {
285
- font-size: 1.75rem;
286
- }
287
-
288
- .logo {
289
- height: 5rem;
290
- width: 5rem;
291
- }
292
-
293
- nav {
294
- gap: 2rem;
295
- }
296
-
297
- header details summary {
298
- font-size: 1.2rem;
299
- }
300
- }
301
-
302
- code {
303
- background-color: rgba(255, 255, 255, 0.08);
304
- border: 1px solid rgba(255, 255, 255, 0.1);
305
- border-radius: 0.375rem;
306
- font-family: 'SF Mono', SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
307
- font-size: 0.875em;
308
- padding: 0.2rem 0.5rem;
309
- }
310
-
311
- @media (prefers-color-scheme: light) {
312
- :global(body) {
313
- background-color: #f5f5f5;
314
- color: #1a1a1a;
315
- }
316
-
317
- header {
318
- background-color: #ffffff;
319
- }
320
-
321
- button {
322
- background-color: #ffffff;
323
- }
324
-
325
- code {
326
- background-color: rgba(0, 0, 0, 0.06);
327
- border-color: rgba(0, 0, 0, 0.1);
328
- }
329
- }
330
85
  </style>
331
86
  `;
332
87
  };
@@ -1,4 +1,4 @@
1
1
  import { ScaffoldFrontendProps } from '../../types';
2
2
  type ScaffoldVueProps = Omit<ScaffoldFrontendProps, 'isSingleFrontend'>;
3
- export declare const scaffoldVue: ({ editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory }: ScaffoldVueProps) => void;
3
+ export declare const scaffoldVue: ({ editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, stylesIndexesDirectory }: ScaffoldVueProps) => void;
4
4
  export {};
@@ -1,7 +1,8 @@
1
1
  import { cpSync, copyFileSync, mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
+ import { generateMarkupCSS } from '../project/generateMarkupCSS';
3
4
  import { generateVuePage } from './generateVuePage';
4
- export const scaffoldVue = ({ editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory }) => {
5
+ export const scaffoldVue = ({ editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, stylesIndexesDirectory }) => {
5
6
  copyFileSync(join(templatesDirectory, 'assets', 'svg', 'vue-logo.svg'), join(projectAssetsDirectory, 'svg', 'vue-logo.svg'));
6
7
  cpSync(join(templatesDirectory, 'vue'), targetDirectory, {
7
8
  recursive: true
@@ -11,4 +12,7 @@ export const scaffoldVue = ({ editBasePath, targetDirectory, templatesDirectory,
11
12
  mkdirSync(pagesDirectory, { recursive: true });
12
13
  const vueFilePath = join(pagesDirectory, 'VueExample.vue');
13
14
  writeFileSync(vueFilePath, vuePage, 'utf-8');
15
+ const cssOutputFile = join(stylesIndexesDirectory, 'vue-example.css');
16
+ const vueCSS = generateMarkupCSS('vue', '#42b883');
17
+ writeFileSync(cssOutputFile, vueCSS, 'utf-8');
14
18
  };
package/dist/types.d.ts CHANGED
@@ -8,6 +8,8 @@ export type ScaffoldFrontendProps = {
8
8
  targetDirectory: string;
9
9
  templatesDirectory: string;
10
10
  projectAssetsDirectory: string;
11
+ stylesDirectory: string;
12
+ stylesIndexesDirectory: string;
11
13
  isSingleFrontend: boolean;
12
14
  frontends: Frontend[];
13
15
  };
@@ -4,15 +4,15 @@
4
4
  * Run `bun run check-versions` to compare against latest npm versions.
5
5
  */
6
6
  export declare const versions: {
7
- readonly '@absolutejs/absolute': "0.17.12";
7
+ readonly '@absolutejs/absolute': "0.19.0-beta.872";
8
8
  readonly '@absolutejs/auth': "0.22.4";
9
- readonly '@angular/common': "21.0.0";
10
- readonly '@angular/compiler': "21.0.0";
11
- readonly '@angular/compiler-cli': "21.0.0";
12
- readonly '@angular/core': "21.0.0";
13
- readonly '@angular/platform-browser': "21.0.0";
14
- readonly '@angular/platform-server': "21.0.0";
15
- readonly '@angular/ssr': "21.0.0";
9
+ readonly '@angular/common': "21.2.0";
10
+ readonly '@angular/compiler': "21.2.0";
11
+ readonly '@angular/compiler-cli': "21.2.0";
12
+ readonly '@angular/core': "21.2.0";
13
+ readonly '@angular/platform-browser': "21.2.0";
14
+ readonly '@angular/platform-server': "21.2.0";
15
+ readonly '@angular/ssr': "21.2.0";
16
16
  readonly '@elysiajs/cors': "1.4.1";
17
17
  readonly '@elysiajs/eden': "1.4.8";
18
18
  readonly '@elysiajs/static': "1.4.7";
@@ -53,6 +53,7 @@ export declare const versions: {
53
53
  readonly 'prettier-plugin-svelte': "3.5.0";
54
54
  readonly react: "19.2.4";
55
55
  readonly 'react-dom': "19.2.4";
56
+ readonly 'react-refresh': "0.18.0";
56
57
  readonly svelte: "5.53.0";
57
58
  readonly tailwindcss: "4.2.0";
58
59
  readonly typescript: "5.9.3";
package/dist/versions.js CHANGED
@@ -5,16 +5,16 @@
5
5
  */
6
6
  export const versions = {
7
7
  /* ── Core ─────────────────────────────────────────────── */
8
- '@absolutejs/absolute': '0.17.12',
8
+ '@absolutejs/absolute': '0.19.0-beta.872',
9
9
  '@absolutejs/auth': '0.22.4',
10
10
  /* ── Angular ─────────────────────────────────────────── */
11
- '@angular/common': '21.0.0',
12
- '@angular/compiler': '21.0.0',
13
- '@angular/compiler-cli': '21.0.0',
14
- '@angular/core': '21.0.0',
15
- '@angular/platform-browser': '21.0.0',
16
- '@angular/platform-server': '21.0.0',
17
- '@angular/ssr': '21.0.0',
11
+ '@angular/common': '21.2.0',
12
+ '@angular/compiler': '21.2.0',
13
+ '@angular/compiler-cli': '21.2.0',
14
+ '@angular/core': '21.2.0',
15
+ '@angular/platform-browser': '21.2.0',
16
+ '@angular/platform-server': '21.2.0',
17
+ '@angular/ssr': '21.2.0',
18
18
  '@elysiajs/cors': '1.4.1',
19
19
  /* ── Plugins ──────────────────────────────────────────── */
20
20
  '@elysiajs/eden': '1.4.8',
@@ -64,6 +64,7 @@ export const versions = {
64
64
  'prettier-plugin-svelte': '3.5.0',
65
65
  react: '19.2.4',
66
66
  'react-dom': '19.2.4',
67
+ 'react-refresh': '0.18.0',
67
68
  svelte: '5.53.0',
68
69
  tailwindcss: '4.2.0',
69
70
  /* ── Build / TypeScript ───────────────────────────────── */
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "description": "A CLI tool to create a new AbsoluteJS project",
12
12
  "devDependencies": {
13
- "@absolutejs/absolute": "0.17.12",
13
+ "@absolutejs/absolute": "0.19.0-beta.872",
14
14
  "@eslint/compat": "2.0.2",
15
15
  "@stylistic/eslint-plugin": "5.9.0",
16
16
  "@types/bun": "1.3.8",
@@ -51,5 +51,5 @@
51
51
  "typecheck": "bun run tsc --noEmit"
52
52
  },
53
53
  "type": "module",
54
- "version": "0.11.0"
54
+ "version": "0.12.0"
55
55
  }