create-absolutejs 0.10.2 → 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.
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/data.d.ts +10 -10
- package/dist/data.js +104 -95
- package/dist/generators/angular/generateAngularPage.d.ts +7 -0
- package/dist/generators/angular/generateAngularPage.js +175 -0
- package/dist/generators/angular/scaffoldAngular.d.ts +2 -0
- package/dist/generators/angular/scaffoldAngular.js +34 -0
- package/dist/generators/configurations/generateEslintConfig.d.ts +2 -0
- package/dist/generators/configurations/generateEslintConfig.js +253 -0
- package/dist/generators/configurations/generatePackageJson.js +26 -3
- package/dist/generators/configurations/scaffoldConfigurationFiles.js +28 -3
- 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 +2 -2
- package/dist/generators/html/scaffoldHTML.d.ts +1 -1
- package/dist/generators/html/scaffoldHTML.js +2 -2
- package/dist/generators/htmx/generateHTMXPage.d.ts +1 -1
- package/dist/generators/htmx/generateHTMXPage.js +2 -2
- package/dist/generators/htmx/scaffoldHTMX.d.ts +1 -1
- package/dist/generators/htmx/scaffoldHTMX.js +2 -2
- 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 +11 -7
- package/dist/generators/project/generateDBBlock.js +6 -0
- package/dist/generators/project/generateImportsBlock.js +39 -27
- package/dist/generators/project/generateMarkupCSS.js +4 -0
- package/dist/generators/project/generateRoutesBlock.d.ts +1 -2
- package/dist/generators/project/generateRoutesBlock.js +28 -17
- package/dist/generators/project/generateServer.js +5 -10
- package/dist/generators/project/scaffoldFrontends.js +20 -1
- 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 +2 -2
- 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 +2 -2
- package/dist/generators/vue/generateVuePage.d.ts +1 -1
- package/dist/generators/vue/generateVuePage.js +20 -2
- package/dist/generators/vue/scaffoldVue.d.ts +1 -1
- package/dist/generators/vue/scaffoldVue.js +2 -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/{eslint.config.mjs → eslint.config.example.mjs} +10 -10
- 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 +1 -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 +45 -33
- package/dist/versions.js +55 -42
- package/package.json +10 -9
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatNavLink } from '../../utils/formatNavLink';
|
|
2
|
-
export const generateHTMXPage = (isSingle, frontends) => {
|
|
2
|
+
export const generateHTMXPage = (isSingle, frontends, editBasePath) => {
|
|
3
3
|
const navLinks = frontends.map(formatNavLink).join('\n\t\t\t');
|
|
4
4
|
return `<!doctype html>
|
|
5
5
|
<html>
|
|
@@ -73,7 +73,7 @@ export const generateHTMXPage = (isSingle, frontends) => {
|
|
|
73
73
|
>
|
|
74
74
|
</button>
|
|
75
75
|
<p>
|
|
76
|
-
Edit <code
|
|
76
|
+
Edit <code>${editBasePath}/pages/HTMXExample.html</code> and save
|
|
77
77
|
to test HMR.
|
|
78
78
|
</p>
|
|
79
79
|
${frontends.length > 1
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ScaffoldFrontendProps } from '../../types';
|
|
2
|
-
export declare const scaffoldHTMX: ({ targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }: ScaffoldFrontendProps) => void;
|
|
2
|
+
export declare const scaffoldHTMX: ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }: 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 = ({ targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }) => {
|
|
6
|
+
export const scaffoldHTMX = ({ editBasePath, targetDirectory, templatesDirectory, projectAssetsDirectory, frontends, isSingleFrontend }) => {
|
|
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');
|
|
@@ -15,7 +15,7 @@ export const scaffoldHTMX = ({ targetDirectory, templatesDirectory, projectAsset
|
|
|
15
15
|
copyFileSync(src, dest);
|
|
16
16
|
break;
|
|
17
17
|
}
|
|
18
|
-
const htmxPage = generateHTMXPage(isSingleFrontend, frontends);
|
|
18
|
+
const htmxPage = generateHTMXPage(isSingleFrontend, frontends, editBasePath);
|
|
19
19
|
const pagesDirectory = join(targetDirectory, 'pages');
|
|
20
20
|
mkdirSync(pagesDirectory, { recursive: true });
|
|
21
21
|
const htmxFilePath = join(pagesDirectory, 'HTMXExample.html');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FrontendDirectories } from '../../types';
|
|
2
2
|
export type FrameworkFlags = ReturnType<typeof computeFlags>;
|
|
3
3
|
export declare const computeFlags: (dirs: FrontendDirectories) => {
|
|
4
|
+
requiresAngular: boolean;
|
|
4
5
|
requiresHtml: boolean;
|
|
5
6
|
requiresHtmx: boolean;
|
|
6
7
|
requiresReact: boolean;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { CreateConfiguration, FrontendDirectories } from '../../types';
|
|
2
2
|
type GenerateBuildBlockProps = {
|
|
3
3
|
assetsDirectory: string;
|
|
4
|
+
backendDirectory: string;
|
|
4
5
|
buildDirectory: string;
|
|
5
6
|
frontendDirectories: FrontendDirectories;
|
|
6
7
|
publicDirectory: string;
|
|
7
8
|
tailwind: CreateConfiguration['tailwind'];
|
|
8
9
|
};
|
|
9
|
-
export declare const generateBuildBlock: ({ assetsDirectory, buildDirectory, frontendDirectories, publicDirectory, tailwind }: GenerateBuildBlockProps) => string;
|
|
10
|
+
export declare const generateBuildBlock: ({ assetsDirectory, backendDirectory, buildDirectory, frontendDirectories, publicDirectory, tailwind }: GenerateBuildBlockProps) => string;
|
|
10
11
|
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
export const generateBuildBlock = ({ assetsDirectory, backendDirectory, buildDirectory, frontendDirectories, publicDirectory, tailwind }) => {
|
|
2
4
|
const configEntries = [
|
|
3
5
|
`assetsDirectory: '${assetsDirectory}'`,
|
|
4
6
|
`buildDirectory: '${buildDirectory}'`,
|
|
@@ -7,11 +9,13 @@ export const generateBuildBlock = ({ assetsDirectory, buildDirectory, frontendDi
|
|
|
7
9
|
tailwind ? `tailwind: ${JSON.stringify(tailwind)}` : ''
|
|
8
10
|
]
|
|
9
11
|
.filter(Boolean)
|
|
10
|
-
.join(',\n
|
|
11
|
-
|
|
12
|
-
${configEntries}
|
|
13
|
-
};
|
|
12
|
+
.join(',\n\t');
|
|
13
|
+
const configContent = `import { defineConfig } from '@absolutejs/absolute'
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
export default defineConfig({
|
|
16
|
+
\t${configEntries}
|
|
17
|
+
})
|
|
18
|
+
`;
|
|
19
|
+
writeFileSync(join(backendDirectory, '..', '..', 'absolute.config.ts'), configContent);
|
|
20
|
+
return `const { absolutejs, manifest } = await prepare()`;
|
|
17
21
|
};
|
|
@@ -64,6 +64,12 @@ export const generateDBBlock = ({ databaseEngine, orm, databaseHost }) => {
|
|
|
64
64
|
return `
|
|
65
65
|
const pool = createPool(getEnv("DATABASE_URL"))
|
|
66
66
|
const db = drizzle(pool, { schema, mode: 'default' })
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
if (databaseEngine === 'mssql' && hostKey === 'none') {
|
|
70
|
+
return `
|
|
71
|
+
const pool = await connect(getEnv("DATABASE_URL"))
|
|
72
|
+
const db = drizzle({ client: pool }, { schema })
|
|
67
73
|
`;
|
|
68
74
|
}
|
|
69
75
|
if (databaseEngine === 'postgresql' && databaseHost === 'neon') {
|
|
@@ -4,6 +4,8 @@ import { isDrizzleDialect } from '../../typeGuards';
|
|
|
4
4
|
export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }) => {
|
|
5
5
|
const rawImports = [];
|
|
6
6
|
const pushHandler = (cond, name, pkg = '@absolutejs/absolute') => cond && rawImports.push(`import { ${name} } from '${pkg}'`);
|
|
7
|
+
pushHandler(flags.requiresAngular, 'handleAngularPageRequest', '@absolutejs/absolute/angular');
|
|
8
|
+
pushHandler(flags.requiresAngular, 'generateHeadElement');
|
|
7
9
|
pushHandler(flags.requiresHtml, 'handleHTMLPageRequest');
|
|
8
10
|
pushHandler(flags.requiresReact, 'handleReactPageRequest');
|
|
9
11
|
pushHandler(flags.requiresSvelte, 'handleSveltePageRequest', '@absolutejs/absolute/svelte');
|
|
@@ -11,6 +13,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
11
13
|
pushHandler(flags.requiresVue, 'generateHeadElement');
|
|
12
14
|
pushHandler(flags.requiresHtmx, 'handleHTMXPageRequest');
|
|
13
15
|
const nonFrameworkOnly = (flags.requiresHtml || flags.requiresHtmx) &&
|
|
16
|
+
!flags.requiresAngular &&
|
|
14
17
|
!flags.requiresReact &&
|
|
15
18
|
!flags.requiresSvelte &&
|
|
16
19
|
!flags.requiresVue;
|
|
@@ -26,7 +29,6 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
26
29
|
.sort()
|
|
27
30
|
.join(', ')} } from '${dependency.value}'`);
|
|
28
31
|
}
|
|
29
|
-
rawImports.push(`import { env } from 'bun'`);
|
|
30
32
|
const buildExamplePath = (dir, file) => `../frontend${dir ? `/${dir}` : ''}/pages/${file}`;
|
|
31
33
|
const reactDir = frontendDirectories.react;
|
|
32
34
|
const svelteDir = frontendDirectories.svelte;
|
|
@@ -63,6 +65,19 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
63
65
|
: [`import { schema } from '../../db/schema'`])
|
|
64
66
|
]
|
|
65
67
|
};
|
|
68
|
+
const getPostgresqlOrmDatabaseImports = () => {
|
|
69
|
+
if (!isRemoteHost)
|
|
70
|
+
return [
|
|
71
|
+
`import { SQL } from 'bun'`,
|
|
72
|
+
`import { drizzle } from 'drizzle-orm/bun-sql'`
|
|
73
|
+
];
|
|
74
|
+
if (databaseHost === 'planetscale')
|
|
75
|
+
return [
|
|
76
|
+
`import { drizzle } from 'drizzle-orm/node-postgres'`,
|
|
77
|
+
`import { Pool } from 'pg'`
|
|
78
|
+
];
|
|
79
|
+
return [];
|
|
80
|
+
};
|
|
66
81
|
const ormDatabaseImports = {
|
|
67
82
|
drizzle: {
|
|
68
83
|
gel: [
|
|
@@ -73,23 +88,17 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
73
88
|
`import { drizzle } from 'drizzle-orm/mysql2'`,
|
|
74
89
|
`import { createPool } from 'mysql2/promise'`
|
|
75
90
|
],
|
|
91
|
+
mssql: [
|
|
92
|
+
`import { connect } from 'mssql'`,
|
|
93
|
+
`import { drizzle } from 'drizzle-orm/node-mssql'`
|
|
94
|
+
],
|
|
76
95
|
mysql: !isRemoteHost
|
|
77
96
|
? [
|
|
78
97
|
`import { drizzle } from 'drizzle-orm/mysql2'`,
|
|
79
98
|
`import { createPool } from 'mysql2/promise'`
|
|
80
99
|
]
|
|
81
100
|
: [],
|
|
82
|
-
postgresql:
|
|
83
|
-
? [
|
|
84
|
-
`import { SQL } from 'bun'`,
|
|
85
|
-
`import { drizzle } from 'drizzle-orm/bun-sql'`
|
|
86
|
-
]
|
|
87
|
-
: isRemoteHost && databaseHost === 'planetscale'
|
|
88
|
-
? [
|
|
89
|
-
`import { drizzle } from 'drizzle-orm/node-postgres'`,
|
|
90
|
-
`import { Pool } from 'pg'`
|
|
91
|
-
]
|
|
92
|
-
: [],
|
|
101
|
+
postgresql: getPostgresqlOrmDatabaseImports(),
|
|
93
102
|
singlestore: [
|
|
94
103
|
`import { drizzle } from 'drizzle-orm/singlestore'`,
|
|
95
104
|
`import { createPool } from 'mysql2/promise'`
|
|
@@ -102,6 +111,22 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
102
111
|
: []
|
|
103
112
|
}
|
|
104
113
|
};
|
|
114
|
+
const getPostgresqlNoOrmImports = () => {
|
|
115
|
+
if (isRemoteHost && databaseHost === 'neon')
|
|
116
|
+
return [
|
|
117
|
+
...connectorImports[databaseHost],
|
|
118
|
+
`import { getEnv } from '@absolutejs/absolute'`
|
|
119
|
+
];
|
|
120
|
+
if (isRemoteHost && databaseHost === 'planetscale')
|
|
121
|
+
return [
|
|
122
|
+
`import { Pool } from 'pg'`,
|
|
123
|
+
`import { getEnv } from '@absolutejs/absolute'`
|
|
124
|
+
];
|
|
125
|
+
return [
|
|
126
|
+
`import { SQL } from 'bun'`,
|
|
127
|
+
`import { getEnv } from '@absolutejs/absolute'`
|
|
128
|
+
];
|
|
129
|
+
};
|
|
105
130
|
const noOrmImports = {
|
|
106
131
|
cockroachdb: [
|
|
107
132
|
`import { SQL } from 'bun'`,
|
|
@@ -132,20 +157,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
132
157
|
`import { SQL } from 'bun'`,
|
|
133
158
|
`import { getEnv } from '@absolutejs/absolute'`
|
|
134
159
|
],
|
|
135
|
-
postgresql:
|
|
136
|
-
? [
|
|
137
|
-
...connectorImports[databaseHost],
|
|
138
|
-
`import { getEnv } from '@absolutejs/absolute'`
|
|
139
|
-
]
|
|
140
|
-
: isRemoteHost && databaseHost === 'planetscale'
|
|
141
|
-
? [
|
|
142
|
-
`import { Pool } from 'pg'`,
|
|
143
|
-
`import { getEnv } from '@absolutejs/absolute'`
|
|
144
|
-
]
|
|
145
|
-
: [
|
|
146
|
-
`import { SQL } from 'bun'`,
|
|
147
|
-
`import { getEnv } from '@absolutejs/absolute'`
|
|
148
|
-
],
|
|
160
|
+
postgresql: getPostgresqlNoOrmImports(),
|
|
149
161
|
singlestore: [
|
|
150
162
|
`import { createPool } from 'mysql2/promise'`,
|
|
151
163
|
`import { getEnv } from '@absolutejs/absolute'`
|
|
@@ -160,7 +172,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
|
|
|
160
172
|
if (orm === 'drizzle') {
|
|
161
173
|
rawImports.push(...ormImports[orm]);
|
|
162
174
|
}
|
|
163
|
-
if (orm
|
|
175
|
+
if (orm === 'drizzle' &&
|
|
164
176
|
isRemoteHost &&
|
|
165
177
|
!(databaseEngine === 'postgresql' && databaseHost === 'planetscale')) {
|
|
166
178
|
rawImports.push(...connectorImports[databaseHost], ...dialectImports[databaseHost]);
|
|
@@ -5,7 +5,6 @@ type GenerateRoutesBlockProps = {
|
|
|
5
5
|
flags: FrameworkFlags;
|
|
6
6
|
frontendDirectories: FrontendDirectories;
|
|
7
7
|
authOption: AuthOption;
|
|
8
|
-
buildDirectory: string;
|
|
9
8
|
};
|
|
10
|
-
export declare const generateRoutesBlock: ({ databaseEngine, flags, frontendDirectories, authOption
|
|
9
|
+
export declare const generateRoutesBlock: ({ databaseEngine, flags, frontendDirectories, authOption }: GenerateRoutesBlockProps) => string;
|
|
11
10
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isFrontend } from '../../typeGuards';
|
|
2
|
-
export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories, authOption
|
|
2
|
+
export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories, authOption }) => {
|
|
3
3
|
const hasDatabase = databaseEngine !== undefined && databaseEngine !== 'none';
|
|
4
4
|
const routes = [];
|
|
5
|
-
const wrap = (handlerCall) => authOption === 'abs'
|
|
5
|
+
const wrap = (handlerCall, isAsync = false) => authOption === 'abs'
|
|
6
6
|
? `async ({ cookie: { auth_provider, user_session_id }, store: { session }, status }) => {
|
|
7
7
|
const { user, error } = await getStatus(session, user_session_id);
|
|
8
8
|
|
|
@@ -15,29 +15,39 @@ export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories
|
|
|
15
15
|
|
|
16
16
|
return ${handlerCall};
|
|
17
17
|
}`
|
|
18
|
-
:
|
|
18
|
+
: `${isAsync ? 'async ' : ''}() => ${handlerCall}`;
|
|
19
19
|
const createHandlerCall = (frontend, directory) => {
|
|
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({
|
|
26
|
+
cssPath: asset(manifest, 'AngularExampleCSS'),
|
|
27
|
+
title: 'AbsoluteJS + Angular'
|
|
28
|
+
}),
|
|
29
|
+
{ initialCount: 0 }
|
|
30
|
+
)`;
|
|
21
31
|
if (frontend === 'html')
|
|
22
|
-
return `handleHTMLPageRequest(
|
|
32
|
+
return `handleHTMLPageRequest(asset(manifest, 'HTMLExample'))`;
|
|
23
33
|
if (frontend === 'htmx')
|
|
24
|
-
return `handleHTMXPageRequest(
|
|
34
|
+
return `handleHTMXPageRequest(asset(manifest, 'HTMXExample'))`;
|
|
25
35
|
if (frontend === 'react') {
|
|
26
36
|
const reactProps = authOption === 'abs'
|
|
27
|
-
? `{ initialCount: 0, cssPath: asset(
|
|
28
|
-
: `{ initialCount: 0, cssPath: asset(
|
|
37
|
+
? `{ initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS'), user, providerConfiguration }`
|
|
38
|
+
: `{ initialCount: 0, cssPath: asset(manifest, 'ReactExampleCSS') }`;
|
|
29
39
|
return `handleReactPageRequest(
|
|
30
40
|
ReactExample,
|
|
31
|
-
asset(
|
|
41
|
+
asset(manifest, 'ReactExampleIndex'),
|
|
32
42
|
${reactProps}
|
|
33
43
|
)`;
|
|
34
44
|
}
|
|
35
45
|
if (frontend === 'svelte')
|
|
36
46
|
return `handleSveltePageRequest(
|
|
37
47
|
SvelteExample,
|
|
38
|
-
asset(
|
|
39
|
-
asset(
|
|
40
|
-
{ initialCount: 0, cssPath: asset(
|
|
48
|
+
asset(manifest, 'SvelteExample'),
|
|
49
|
+
asset(manifest, 'SvelteExampleIndex'),
|
|
50
|
+
{ initialCount: 0, cssPath: asset(manifest, 'SvelteExampleCSS') }
|
|
41
51
|
)`;
|
|
42
52
|
if (frontend === 'vue') {
|
|
43
53
|
const vueComponent = flags.requiresSvelte
|
|
@@ -45,10 +55,10 @@ export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories
|
|
|
45
55
|
: 'VueExample';
|
|
46
56
|
return `handleVuePageRequest(
|
|
47
57
|
${vueComponent},
|
|
48
|
-
asset(
|
|
49
|
-
asset(
|
|
58
|
+
asset(manifest, 'VueExample'),
|
|
59
|
+
asset(manifest, 'VueExampleIndex'),
|
|
50
60
|
generateHeadElement({
|
|
51
|
-
cssPath: asset(
|
|
61
|
+
cssPath: asset(manifest, 'VueExampleCSS'),
|
|
52
62
|
title: 'AbsoluteJS + Vue',
|
|
53
63
|
description: 'A Vue.js example with AbsoluteJS'
|
|
54
64
|
}),
|
|
@@ -60,10 +70,11 @@ export const generateRoutesBlock = ({ databaseEngine, flags, frontendDirectories
|
|
|
60
70
|
Object.entries(frontendDirectories).forEach(([frontend, directory], entryIndex) => {
|
|
61
71
|
if (!isFrontend(frontend))
|
|
62
72
|
return;
|
|
63
|
-
const handlerCall = createHandlerCall(frontend, directory);
|
|
73
|
+
const handlerCall = createHandlerCall(frontend, directory ?? '');
|
|
64
74
|
if (!handlerCall)
|
|
65
75
|
return;
|
|
66
|
-
const
|
|
76
|
+
const isAsync = frontend === 'angular';
|
|
77
|
+
const handler = wrap(handlerCall, isAsync);
|
|
67
78
|
if (entryIndex === 0) {
|
|
68
79
|
routes.push(`.get('/', ${handler})`);
|
|
69
80
|
}
|
|
@@ -22,6 +22,7 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
|
|
|
22
22
|
});
|
|
23
23
|
const manifestBlock = generateBuildBlock({
|
|
24
24
|
assetsDirectory,
|
|
25
|
+
backendDirectory,
|
|
25
26
|
buildDirectory,
|
|
26
27
|
frontendDirectories,
|
|
27
28
|
publicDirectory,
|
|
@@ -59,31 +60,25 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
|
|
|
59
60
|
})`;
|
|
60
61
|
const routesBlock = generateRoutesBlock({
|
|
61
62
|
authOption,
|
|
62
|
-
buildDirectory,
|
|
63
63
|
databaseEngine,
|
|
64
64
|
flags,
|
|
65
65
|
frontendDirectories
|
|
66
66
|
});
|
|
67
|
-
const hmrBlock = `
|
|
68
|
-
if (
|
|
69
|
-
typeof result.hmrState !== 'string' &&
|
|
70
|
-
typeof result.manifest === 'object'
|
|
71
|
-
) {
|
|
72
|
-
server.use(hmr(result.hmrState, result.manifest));
|
|
73
|
-
}`;
|
|
74
67
|
const content = `${importsBlock}
|
|
75
68
|
|
|
76
69
|
${manifestBlock}
|
|
77
70
|
${dbBlock ? `${dbBlock}\n` : ''}
|
|
78
71
|
const server = new Elysia()
|
|
72
|
+
.use(absolutejs)
|
|
79
73
|
${useBlock}${authOption === 'abs' ? `\n${guardBlock}` : ''}
|
|
80
74
|
${routesBlock}
|
|
81
75
|
.use(networking)
|
|
82
76
|
.on('error', err => {
|
|
83
77
|
const { request } = err
|
|
84
78
|
console.error(\`Server error on \${request.method} \${request.url}: \${err.message}\`)
|
|
85
|
-
})
|
|
86
|
-
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
export type Server = typeof server
|
|
87
82
|
`;
|
|
88
83
|
writeFileSync(serverFilePath, content);
|
|
89
84
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { copyFileSync, cpSync, mkdirSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
+
import { scaffoldAngular } from '../angular/scaffoldAngular';
|
|
3
4
|
import { scaffoldHTML } from '../html/scaffoldHTML';
|
|
4
5
|
import { scaffoldHTMX } from '../htmx/scaffoldHTMX';
|
|
5
6
|
import { scaffoldReact } from '../react/scaffoldReact';
|
|
@@ -25,12 +26,16 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
25
26
|
const targetDirectory = join(frontendDirectory, directory);
|
|
26
27
|
if (!isSingleFrontend)
|
|
27
28
|
mkdirSync(targetDirectory);
|
|
29
|
+
const editBasePath = directory
|
|
30
|
+
? `src/frontend/${directory}`
|
|
31
|
+
: 'src/frontend';
|
|
28
32
|
switch (frontendName) {
|
|
29
33
|
case 'react':
|
|
30
34
|
scaffoldReact({
|
|
31
35
|
absProviders,
|
|
32
36
|
assetsDirectory,
|
|
33
37
|
authOption,
|
|
38
|
+
editBasePath,
|
|
34
39
|
frontends,
|
|
35
40
|
isSingleFrontend,
|
|
36
41
|
projectAssetsDirectory,
|
|
@@ -43,6 +48,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
43
48
|
absProviders,
|
|
44
49
|
assetsDirectory,
|
|
45
50
|
authOption,
|
|
51
|
+
editBasePath,
|
|
46
52
|
frontends,
|
|
47
53
|
isSingleFrontend,
|
|
48
54
|
projectAssetsDirectory,
|
|
@@ -55,6 +61,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
55
61
|
absProviders,
|
|
56
62
|
assetsDirectory,
|
|
57
63
|
authOption,
|
|
64
|
+
editBasePath,
|
|
58
65
|
frontends,
|
|
59
66
|
projectAssetsDirectory,
|
|
60
67
|
targetDirectory,
|
|
@@ -63,13 +70,24 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
63
70
|
copyFileSync(join(templatesDirectory, 'types', 'vue-shim.d.ts'), join(typesDirectory, 'vue-shim.d.ts'));
|
|
64
71
|
break;
|
|
65
72
|
case 'angular':
|
|
66
|
-
|
|
73
|
+
scaffoldAngular({
|
|
74
|
+
absProviders,
|
|
75
|
+
assetsDirectory,
|
|
76
|
+
authOption,
|
|
77
|
+
editBasePath,
|
|
78
|
+
frontends,
|
|
79
|
+
isSingleFrontend,
|
|
80
|
+
projectAssetsDirectory,
|
|
81
|
+
targetDirectory,
|
|
82
|
+
templatesDirectory
|
|
83
|
+
});
|
|
67
84
|
break;
|
|
68
85
|
case 'html':
|
|
69
86
|
scaffoldHTML({
|
|
70
87
|
absProviders,
|
|
71
88
|
assetsDirectory,
|
|
72
89
|
authOption,
|
|
90
|
+
editBasePath,
|
|
73
91
|
frontends,
|
|
74
92
|
isSingleFrontend,
|
|
75
93
|
projectAssetsDirectory,
|
|
@@ -83,6 +101,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
83
101
|
absProviders,
|
|
84
102
|
assetsDirectory,
|
|
85
103
|
authOption,
|
|
104
|
+
editBasePath,
|
|
86
105
|
frontends,
|
|
87
106
|
isSingleFrontend,
|
|
88
107
|
projectAssetsDirectory,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ProviderOption } from '@absolutejs/auth';
|
|
2
2
|
import { AuthOption, Frontend } from '../../types';
|
|
3
|
-
export declare const generateAppComponent: (frontends: Frontend[]) => string;
|
|
3
|
+
export declare const generateAppComponent: (frontends: Frontend[], editBasePath: string) => string;
|
|
4
4
|
export declare const generateDropdownComponent: (frontends: Frontend[]) => string;
|
|
5
|
-
export declare const generateSignInComponent: (absProviders: ProviderOption[] | undefined) => string;
|
|
6
5
|
export declare const generateReactExamplePage: (authOption: AuthOption) => string;
|
|
6
|
+
export declare const generateSignInComponent: (absProviders: ProviderOption[] | undefined) => string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatNavLink } from '../../utils/formatNavLink';
|
|
2
|
-
export const generateAppComponent = (frontends) => {
|
|
2
|
+
export const generateAppComponent = (frontends, editBasePath) => {
|
|
3
3
|
const exploreBlock = frontends.length > 1
|
|
4
4
|
? `\n\t\t\t<p style={{ marginTop: '2rem' }}>\n\t\t\t\tExplore the other pages to see multiple frameworks running\n\t\t\t\ttogether.\n\t\t\t</p>`
|
|
5
5
|
: '';
|
|
@@ -33,7 +33,7 @@ export const App = ({ initialCount }: AppProps) => {
|
|
|
33
33
|
count is {count}
|
|
34
34
|
</button>
|
|
35
35
|
<p>
|
|
36
|
-
Edit <code
|
|
36
|
+
Edit <code>${editBasePath}/pages/ReactExample.tsx</code> and save
|
|
37
37
|
to test HMR.
|
|
38
38
|
</p>${exploreBlock}
|
|
39
39
|
<p
|
|
@@ -73,37 +73,6 @@ export const generateDropdownComponent = (frontends) => {
|
|
|
73
73
|
);
|
|
74
74
|
`;
|
|
75
75
|
};
|
|
76
|
-
export const generateSignInComponent = (absProviders) => `import { OAuthLink } from './OAuthLink';
|
|
77
|
-
|
|
78
|
-
export const SignIn = () => (
|
|
79
|
-
<details
|
|
80
|
-
onPointerEnter={(event) => {
|
|
81
|
-
if (event.pointerType === 'mouse') {
|
|
82
|
-
event.currentTarget.open = true;
|
|
83
|
-
}
|
|
84
|
-
}}
|
|
85
|
-
onPointerLeave={(event) => {
|
|
86
|
-
if (event.pointerType === 'mouse') {
|
|
87
|
-
event.currentTarget.open = false;
|
|
88
|
-
}
|
|
89
|
-
}}
|
|
90
|
-
>
|
|
91
|
-
<summary>Sign In</summary>
|
|
92
|
-
<nav>
|
|
93
|
-
${absProviders && absProviders.length > 0
|
|
94
|
-
? absProviders
|
|
95
|
-
.map((provider) => {
|
|
96
|
-
const logoUrl = `/assets/svg/google-logo.svg`;
|
|
97
|
-
const name = provider.charAt(0).toUpperCase() +
|
|
98
|
-
provider.slice(1).toLowerCase();
|
|
99
|
-
return `<OAuthLink provider="${provider}" logoUrl="${logoUrl}" name="${name}" mode="in" />`;
|
|
100
|
-
})
|
|
101
|
-
.join('\n\t\t\t')
|
|
102
|
-
: `<p>No OAuth providers configured</p>`}
|
|
103
|
-
</nav>
|
|
104
|
-
</details>
|
|
105
|
-
);
|
|
106
|
-
`;
|
|
107
76
|
export const generateReactExamplePage = (authOption) => {
|
|
108
77
|
const useBlockReturn = authOption === 'abs';
|
|
109
78
|
const propsType = `
|
|
@@ -178,3 +147,34 @@ ${authOption === 'abs' ? extractProps : ''}
|
|
|
178
147
|
${closing}
|
|
179
148
|
`;
|
|
180
149
|
};
|
|
150
|
+
export const generateSignInComponent = (absProviders) => `import { OAuthLink } from './OAuthLink';
|
|
151
|
+
|
|
152
|
+
export const SignIn = () => (
|
|
153
|
+
<details
|
|
154
|
+
onPointerEnter={(event) => {
|
|
155
|
+
if (event.pointerType === 'mouse') {
|
|
156
|
+
event.currentTarget.open = true;
|
|
157
|
+
}
|
|
158
|
+
}}
|
|
159
|
+
onPointerLeave={(event) => {
|
|
160
|
+
if (event.pointerType === 'mouse') {
|
|
161
|
+
event.currentTarget.open = false;
|
|
162
|
+
}
|
|
163
|
+
}}
|
|
164
|
+
>
|
|
165
|
+
<summary>Sign In</summary>
|
|
166
|
+
<nav>
|
|
167
|
+
${absProviders && absProviders.length > 0
|
|
168
|
+
? absProviders
|
|
169
|
+
.map((provider) => {
|
|
170
|
+
const logoUrl = `/assets/svg/google-logo.svg`;
|
|
171
|
+
const name = provider.charAt(0).toUpperCase() +
|
|
172
|
+
provider.slice(1).toLowerCase();
|
|
173
|
+
return `<OAuthLink provider="${provider}" logoUrl="${logoUrl}" name="${name}" mode="in" />`;
|
|
174
|
+
})
|
|
175
|
+
.join('\n\t\t\t')
|
|
176
|
+
: `<p>No OAuth providers configured</p>`}
|
|
177
|
+
</nav>
|
|
178
|
+
</details>
|
|
179
|
+
);
|
|
180
|
+
`;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ScaffoldFrontendProps } from '../../types';
|
|
2
|
-
export declare const scaffoldReact: ({ isSingleFrontend, authOption, targetDirectory, templatesDirectory, frontends,
|
|
2
|
+
export declare const scaffoldReact: ({ isSingleFrontend, authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders }: ScaffoldFrontendProps) => void;
|
|
@@ -2,14 +2,14 @@ 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, targetDirectory, templatesDirectory, frontends,
|
|
5
|
+
export const scaffoldReact = ({ isSingleFrontend, authOption, editBasePath, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders }) => {
|
|
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'));
|
|
9
9
|
cpSync(join(templatesDirectory, 'react'), targetDirectory, {
|
|
10
10
|
recursive: true
|
|
11
11
|
});
|
|
12
|
-
const appComponent = generateAppComponent(frontends);
|
|
12
|
+
const appComponent = generateAppComponent(frontends, editBasePath);
|
|
13
13
|
writeFileSync(join(targetDirectory, 'components', 'App.tsx'), appComponent, 'utf-8');
|
|
14
14
|
const dropdownComponent = generateDropdownComponent(frontends);
|
|
15
15
|
writeFileSync(join(targetDirectory, 'components', 'Dropdown.tsx'), dropdownComponent, 'utf-8');
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { Frontend } from '../../types';
|
|
2
|
-
export declare const generateSveltePage: (frontends: Frontend[]) => string;
|
|
2
|
+
export declare const generateSveltePage: (frontends: Frontend[], editBasePath: string) => string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatNavLink } from '../../utils/formatNavLink';
|
|
2
|
-
export const generateSveltePage = (frontends) => {
|
|
2
|
+
export const generateSveltePage = (frontends, editBasePath) => {
|
|
3
3
|
const navLinks = frontends.map(formatNavLink).join('\n\t\t\t');
|
|
4
4
|
return `<script lang="ts">
|
|
5
5
|
type SvelteExampleProps = {
|
|
@@ -77,7 +77,7 @@ export const generateSveltePage = (frontends) => {
|
|
|
77
77
|
<h1>AbsoluteJS + Svelte</h1>
|
|
78
78
|
<Counter {initialCount} />
|
|
79
79
|
<p>
|
|
80
|
-
Edit <code
|
|
80
|
+
Edit <code>${editBasePath}/pages/SvelteExample.svelte</code> and save
|
|
81
81
|
to test HMR.
|
|
82
82
|
</p>
|
|
83
83
|
${frontends.length > 1
|
|
@@ -149,6 +149,10 @@ ${frontends.length > 1
|
|
|
149
149
|
filter: drop-shadow(0 0 2rem #ff3e00);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
button:hover {
|
|
153
|
+
border-color: #ff3e00;
|
|
154
|
+
}
|
|
155
|
+
|
|
152
156
|
nav {
|
|
153
157
|
display: flex;
|
|
154
158
|
gap: 4rem;
|
|
@@ -241,10 +245,24 @@ ${frontends.length > 1
|
|
|
241
245
|
}
|
|
242
246
|
}
|
|
243
247
|
|
|
248
|
+
code {
|
|
249
|
+
background-color: rgba(255, 255, 255, 0.08);
|
|
250
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
251
|
+
border-radius: 0.375rem;
|
|
252
|
+
font-family: 'SF Mono', SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
|
|
253
|
+
font-size: 0.875em;
|
|
254
|
+
padding: 0.2rem 0.5rem;
|
|
255
|
+
}
|
|
256
|
+
|
|
244
257
|
@media (prefers-color-scheme: light) {
|
|
245
258
|
header {
|
|
246
259
|
background-color: #ffffff;
|
|
247
260
|
}
|
|
261
|
+
|
|
262
|
+
code {
|
|
263
|
+
background-color: rgba(0, 0, 0, 0.06);
|
|
264
|
+
border-color: rgba(0, 0, 0, 0.1);
|
|
265
|
+
}
|
|
248
266
|
}
|
|
249
267
|
</style>
|
|
250
268
|
`;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ScaffoldFrontendProps } from '../../types';
|
|
2
|
-
export declare const scaffoldSvelte: ({ isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }: ScaffoldFrontendProps) => void;
|
|
2
|
+
export declare const scaffoldSvelte: ({ editBasePath, isSingleFrontend, targetDirectory, frontends, templatesDirectory, projectAssetsDirectory }: ScaffoldFrontendProps) => void;
|