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.
Files changed (75) hide show
  1. package/dist/constants.d.ts +2 -2
  2. package/dist/constants.js +2 -2
  3. package/dist/data.d.ts +10 -10
  4. package/dist/data.js +88 -95
  5. package/dist/generators/angular/generateAngularPage.d.ts +11 -0
  6. package/dist/generators/angular/generateAngularPage.js +174 -0
  7. package/dist/generators/angular/scaffoldAngular.d.ts +2 -0
  8. package/dist/generators/angular/scaffoldAngular.js +38 -0
  9. package/dist/generators/configurations/generatePackageJson.js +28 -3
  10. package/dist/generators/configurations/scaffoldConfigurationFiles.js +26 -2
  11. package/dist/generators/db/dockerInitTemplates.d.ts +9 -9
  12. package/dist/generators/db/dockerInitTemplates.js +9 -9
  13. package/dist/generators/db/generateDatabaseTypes.js +5 -0
  14. package/dist/generators/db/generateDockerContainer.js +4 -2
  15. package/dist/generators/db/generateDrizzleSchema.js +16 -6
  16. package/dist/generators/db/handlerTemplates.d.ts +5 -0
  17. package/dist/generators/db/handlerTemplates.js +6 -0
  18. package/dist/generators/db/scaffoldDocker.js +42 -30
  19. package/dist/generators/html/generateHTMLPage.d.ts +1 -1
  20. package/dist/generators/html/generateHTMLPage.js +3 -3
  21. package/dist/generators/html/scaffoldHTML.d.ts +1 -1
  22. package/dist/generators/html/scaffoldHTML.js +4 -6
  23. package/dist/generators/htmx/generateHTMXPage.d.ts +1 -1
  24. package/dist/generators/htmx/generateHTMXPage.js +3 -3
  25. package/dist/generators/htmx/scaffoldHTMX.d.ts +1 -1
  26. package/dist/generators/htmx/scaffoldHTMX.js +4 -6
  27. package/dist/generators/project/computeFlags.d.ts +1 -0
  28. package/dist/generators/project/computeFlags.js +1 -0
  29. package/dist/generators/project/generateBuildBlock.d.ts +2 -1
  30. package/dist/generators/project/generateBuildBlock.js +12 -7
  31. package/dist/generators/project/generateDBBlock.js +6 -0
  32. package/dist/generators/project/generateImportsBlock.d.ts +1 -2
  33. package/dist/generators/project/generateImportsBlock.js +48 -50
  34. package/dist/generators/project/generateMarkupCSS.d.ts +1 -1
  35. package/dist/generators/project/generateMarkupCSS.js +5 -1
  36. package/dist/generators/project/generateRoutesBlock.d.ts +1 -4
  37. package/dist/generators/project/generateRoutesBlock.js +44 -38
  38. package/dist/generators/project/generateServer.js +5 -12
  39. package/dist/generators/project/scaffoldFrontends.js +40 -4
  40. package/dist/generators/react/generateReactComponents.d.ts +2 -2
  41. package/dist/generators/react/generateReactComponents.js +33 -33
  42. package/dist/generators/react/scaffoldReact.d.ts +1 -1
  43. package/dist/generators/react/scaffoldReact.js +4 -6
  44. package/dist/generators/svelte/generateSveltePage.d.ts +1 -1
  45. package/dist/generators/svelte/generateSveltePage.js +20 -2
  46. package/dist/generators/svelte/scaffoldSvelte.d.ts +1 -1
  47. package/dist/generators/svelte/scaffoldSvelte.js +4 -6
  48. package/dist/generators/vue/generateVuePage.d.ts +1 -1
  49. package/dist/generators/vue/generateVuePage.js +2 -229
  50. package/dist/generators/vue/scaffoldVue.d.ts +1 -1
  51. package/dist/generators/vue/scaffoldVue.js +6 -2
  52. package/dist/questions/databaseEngine.d.ts +1 -1
  53. package/dist/questions/frontendDirectoryConfigurations.d.ts +1 -1
  54. package/dist/questions/frontends.d.ts +1 -1
  55. package/dist/questions/frontends.js +3 -3
  56. package/dist/scaffold.js +14 -2
  57. package/dist/templates/assets/svg/angular.svg +18 -0
  58. package/dist/templates/configurations/tsconfig.example.json +12 -12
  59. package/dist/templates/react/components/App.tsx +2 -2
  60. package/dist/templates/react/components/Head.tsx +7 -7
  61. package/dist/templates/react/components/OAuthLink.tsx +2 -2
  62. package/dist/templates/styles/colors.ts +6 -8
  63. package/dist/templates/styles/reset.css +15 -0
  64. package/dist/templates/svelte/components/Counter.svelte +4 -0
  65. package/dist/templates/vue/components/CountButton.vue +1 -1
  66. package/dist/typeGuards.d.ts +6 -6
  67. package/dist/typeGuards.js +6 -6
  68. package/dist/types.d.ts +3 -0
  69. package/dist/utils/checkDockerInstalled.d.ts +4 -4
  70. package/dist/utils/checkDockerInstalled.js +78 -71
  71. package/dist/utils/parseCommandLineOptions.js +13 -16
  72. package/dist/versions.d.ts +38 -29
  73. package/dist/versions.js +49 -39
  74. package/package.json +10 -9
  75. /package/dist/templates/configurations/{eslint.config.mjs → eslint.config.example.mjs} +0 -0
@@ -34,6 +34,11 @@ export const generateDatabaseTypes = ({ databaseEngine, databaseHost, authOption
34
34
  dbTypeLine =
35
35
  'export type DatabaseType = Mysql2Database<SchemaType>;';
36
36
  break;
37
+ case 'mssql':
38
+ dbImport = `import { NodeMssqlDatabase } from 'drizzle-orm/node-mssql';`;
39
+ dbTypeLine =
40
+ 'export type DatabaseType = NodeMssqlDatabase<SchemaType>;';
41
+ break;
37
42
  case 'postgresql':
38
43
  dbImport = `import { BunSQLDatabase } from 'drizzle-orm/bun-sql';`;
39
44
  dbTypeLine =
@@ -104,6 +104,7 @@ const templates = {
104
104
  test: 'singlestore -u root -ppassword -e "SELECT 1" >/dev/null 2>&1'
105
105
  },
106
106
  image: 'ghcr.io/singlestore-labs/singlestoredb-dev', // NOTE: No tag specified due to data persistence
107
+ platform: 'linux/amd64', // Required for ARM64 (Apple Silicon); no-op on amd64
107
108
  port: '3306:3306',
108
109
  volumePath: '/data'
109
110
  }
@@ -114,14 +115,15 @@ export const generateDockerContainer = (databaseEngine) => {
114
115
  databaseEngine === 'sqlite') {
115
116
  throw new Error('Internal type error: Expected a valid local database engine');
116
117
  }
117
- const { command, env, healthcheck, image, port, volumePath } = templates[databaseEngine];
118
+ const { command, env, healthcheck, image, platform, port, volumePath } = templates[databaseEngine];
118
119
  const commandLine = command ? `\n command: ${command}` : '';
120
+ const platformLine = platform ? `\n platform: ${platform}` : '';
119
121
  const envLines = Object.entries(env)
120
122
  .map(([key, value]) => ` ${key}: ${value}`)
121
123
  .join('\n');
122
124
  return `services:
123
125
  db:
124
- image: ${image}
126
+ image: ${image}${platformLine}
125
127
  restart: always
126
128
  environment:
127
129
  ${envLines}
@@ -15,6 +15,14 @@ const DIALECTS = {
15
15
  table: 'mysqlTable',
16
16
  time: 'timestamp()'
17
17
  },
18
+ mssql: {
19
+ builders: ['datetime2', 'int', 'mssqlTable', 'nvarchar', 'json'],
20
+ json: "nvarchar({ length: 'max', mode: 'json' })",
21
+ pkg: 'mssql-core',
22
+ string: 'nvarchar({ length: 255 })',
23
+ table: 'mssqlTable',
24
+ time: 'datetime2()'
25
+ },
18
26
  mysql: {
19
27
  builders: ['json', 'mysqlTable', 'timestamp', 'varchar', 'int'],
20
28
  json: 'json()',
@@ -51,9 +59,10 @@ const DIALECTS = {
51
59
  const builder = (expr) => expr.split('(')[0];
52
60
  export const generateDrizzleSchema = ({ databaseEngine, authOption }) => {
53
61
  const cfg = DIALECTS[databaseEngine];
54
- const intBuilder = databaseEngine === 'mysql' ||
55
- databaseEngine === 'singlestore' ||
56
- databaseEngine === 'mariadb'
62
+ const intBuilder = databaseEngine === 'mariadb' ||
63
+ databaseEngine === 'mssql' ||
64
+ databaseEngine === 'mysql' ||
65
+ databaseEngine === 'singlestore'
57
66
  ? 'int'
58
67
  : 'integer';
59
68
  const timeBuilder = builder(cfg.time);
@@ -68,9 +77,10 @@ export const generateDrizzleSchema = ({ databaseEngine, authOption }) => {
68
77
  ? `import { sql } from 'drizzle-orm';\n`
69
78
  : '';
70
79
  let uidColumn;
71
- if (databaseEngine === 'mysql' ||
72
- databaseEngine === 'singlestore' ||
73
- databaseEngine === 'mariadb') {
80
+ if (databaseEngine === 'mariadb' ||
81
+ databaseEngine === 'mssql' ||
82
+ databaseEngine === 'mysql' ||
83
+ databaseEngine === 'singlestore') {
74
84
  uidColumn = `${intBuilder}('uid').primaryKey().autoincrement()`;
75
85
  }
76
86
  else if (databaseEngine === 'sqlite') {
@@ -35,6 +35,11 @@ declare const driverConfigurations: {
35
35
  readonly importLines: "";
36
36
  readonly queries: QueryOperations;
37
37
  };
38
+ readonly 'mssql:drizzle:local': {
39
+ readonly dbType: "NodeMssqlDatabase<SchemaType>";
40
+ readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
41
+ readonly queries: QueryOperations;
42
+ };
38
43
  readonly 'mssql:sql:local': {
39
44
  readonly dbType: "ConnectionPool";
40
45
  readonly importLines: "";
@@ -353,6 +353,12 @@ import { schema } from '../../../db/schema'`,
353
353
  importLines: ``,
354
354
  queries: mongodbQueryOperations
355
355
  },
356
+ 'mssql:drizzle:local': {
357
+ dbType: 'NodeMssqlDatabase<SchemaType>',
358
+ importLines: `import { eq } from 'drizzle-orm'
359
+ import { schema } from '../../../db/schema'`,
360
+ queries: drizzleQueryOperations
361
+ },
356
362
  'mssql:sql:local': {
357
363
  dbType: 'ConnectionPool',
358
364
  importLines: ``,
@@ -6,6 +6,33 @@ import { green, red } from 'picocolors';
6
6
  import { checkDockerInstalled, ensureDockerDaemonRunning, resolveDockerExe, shutdownDockerDaemon } from '../../utils/checkDockerInstalled';
7
7
  import { countHistoryTables, initTemplates, userTables } from './dockerInitTemplates';
8
8
  import { generateDockerContainer } from './generateDockerContainer';
9
+ const initDockerSchema = async ({ authOption, databaseEngine, docker, projectName, spin }) => {
10
+ const dbKey = databaseEngine;
11
+ const { wait, cli } = initTemplates[dbKey];
12
+ const usesAuth = authOption !== undefined && authOption !== 'none';
13
+ const dbCommand = usesAuth ? userTables[dbKey] : countHistoryTables[dbKey];
14
+ await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml up -d db`
15
+ .cwd(projectName)
16
+ .quiet();
17
+ spin.message(`Initializing ${databaseEngine} schema`);
18
+ await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml exec -T db \
19
+ bash -lc '${wait} && ${cli} "${dbCommand}"'`
20
+ .cwd(projectName)
21
+ .quiet();
22
+ spin.message(`Stopping ${databaseEngine} container`);
23
+ await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml down`
24
+ .cwd(projectName)
25
+ .quiet();
26
+ };
27
+ const verifyDockerContainer = async ({ databaseEngine, docker, projectName, spin }) => {
28
+ await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml up -d --wait db`
29
+ .cwd(projectName)
30
+ .quiet();
31
+ spin.message(`Stopping ${databaseEngine} container`);
32
+ await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml down`
33
+ .cwd(projectName)
34
+ .quiet();
35
+ };
9
36
  export const scaffoldDocker = async ({ databaseEngine, projectDatabaseDirectory, projectName, authOption }) => {
10
37
  if (databaseEngine === undefined ||
11
38
  databaseEngine === 'none' ||
@@ -19,37 +46,22 @@ export const scaffoldDocker = async ({ databaseEngine, projectDatabaseDirectory,
19
46
  const docker = resolveDockerExe();
20
47
  const spin = spinner();
21
48
  spin.start(`Starting ${databaseEngine} container`);
49
+ const dockerAction = databaseEngine in userTables
50
+ ? () => initDockerSchema({
51
+ authOption,
52
+ databaseEngine,
53
+ docker,
54
+ projectName,
55
+ spin
56
+ })
57
+ : () => verifyDockerContainer({
58
+ databaseEngine,
59
+ docker,
60
+ projectName,
61
+ spin
62
+ });
22
63
  try {
23
- const hasSchemaInit = databaseEngine in userTables;
24
- if (hasSchemaInit) {
25
- const dbKey = databaseEngine;
26
- const { wait, cli } = initTemplates[dbKey];
27
- const usesAuth = authOption !== undefined && authOption !== 'none';
28
- const dbCommand = usesAuth
29
- ? userTables[dbKey]
30
- : countHistoryTables[dbKey];
31
- await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml up -d db`
32
- .cwd(projectName)
33
- .quiet();
34
- spin.message(`Initializing ${databaseEngine} schema`);
35
- await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml exec -T db \
36
- bash -lc '${wait} && ${cli} "${dbCommand}"'`
37
- .cwd(projectName)
38
- .quiet();
39
- spin.message(`Stopping ${databaseEngine} container`);
40
- await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml down`
41
- .cwd(projectName)
42
- .quiet();
43
- }
44
- else {
45
- await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml up -d --wait db`
46
- .cwd(projectName)
47
- .quiet();
48
- spin.message(`Stopping ${databaseEngine} container`);
49
- await $ `${docker} compose -p ${databaseEngine} -f db/docker-compose.db.yml down`
50
- .cwd(projectName)
51
- .quiet();
52
- }
64
+ await dockerAction();
53
65
  spin.stop(green('Docker container verified'));
54
66
  }
55
67
  catch (err) {
@@ -1,2 +1,2 @@
1
1
  import { CreateConfiguration, Frontend } from '../../types';
2
- export declare const generateHTMLPage: (frontends: Frontend[], useHTMLScripts: CreateConfiguration["useHTMLScripts"]) => 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) => {
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) => {
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>
@@ -54,7 +54,7 @@ export const generateHTMLPage = (frontends, useHTMLScripts) => {
54
54
  count is <span id="counter">${initialCount}</span>
55
55
  </button>
56
56
  <p>
57
- Edit <code>example/html/pages/HtmlExample.html</code> and save
57
+ Edit <code>${editBasePath}/pages/HTMLExample.html</code> and save
58
58
  to test HMR.
59
59
  </p>
60
60
  ${frontends.length > 1
@@ -2,5 +2,5 @@ import { ScaffoldFrontendProps } from '../../types';
2
2
  type ScaffoldHTMLProps = ScaffoldFrontendProps & {
3
3
  useHTMLScripts: boolean;
4
4
  };
5
- export declare const scaffoldHTML: ({ 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 = ({ 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);
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 = ({ isSingleFrontend, targetDirectory, frontends, use
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
  };
@@ -1,2 +1,2 @@
1
1
  import { Frontend } from '../../types';
2
- export declare const generateHTMXPage: (isSingle: boolean, frontends: Frontend[]) => string;
2
+ export declare const generateHTMXPage: (isSingle: boolean, frontends: Frontend[], editBasePath: string) => string;
@@ -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>
@@ -11,7 +11,7 @@ export const generateHTMXPage = (isSingle, frontends) => {
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>
@@ -73,7 +73,7 @@ export const generateHTMXPage = (isSingle, frontends) => {
73
73
  >
74
74
  </button>
75
75
  <p>
76
- Edit <code>example/htmx/pages/HtmxHome.html</code> and save
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, 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 = ({ 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');
@@ -15,14 +15,12 @@ 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');
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
  };
@@ -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,4 +1,5 @@
1
1
  export const computeFlags = (dirs) => ({
2
+ requiresAngular: dirs.angular !== undefined,
2
3
  requiresHtml: dirs.html !== undefined,
3
4
  requiresHtmx: dirs.htmx !== undefined,
4
5
  requiresReact: dirs.react !== undefined,
@@ -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,17 +1,22 @@
1
- export const generateBuildBlock = ({ assetsDirectory, buildDirectory, frontendDirectories, publicDirectory, tailwind }) => {
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}'`,
5
7
  ...Object.entries(frontendDirectories).map(([f, dir]) => `${f}Directory: 'src/frontend${dir ? `/${dir}` : ''}'`),
6
8
  `publicDirectory: '${publicDirectory}'`,
9
+ `stylesConfig: 'src/styles/indexes'`,
7
10
  tailwind ? `tailwind: ${JSON.stringify(tailwind)}` : ''
8
11
  ]
9
12
  .filter(Boolean)
10
- .join(',\n ');
11
- return `const buildConfig: BuildConfig = {
12
- ${configEntries}
13
- };
13
+ .join(',\n\t');
14
+ const configContent = `import { defineConfig } from '@absolutejs/absolute'
14
15
 
15
- const isDev = env.NODE_ENV === 'development';
16
- const result = isDev ? await devBuild(buildConfig) : await build(buildConfig);`;
16
+ export default defineConfig({
17
+ \t${configEntries}
18
+ })
19
+ `;
20
+ writeFileSync(join(backendDirectory, '..', '..', 'absolute.config.ts'), configContent);
21
+ return `const { absolutejs, manifest } = await prepare()`;
17
22
  };
@@ -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') {
@@ -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,42 +1,37 @@
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}'`);
5
+ pushHandler(flags.requiresAngular, 'handleAngularPageRequest', '@absolutejs/absolute/angular');
6
+ pushHandler(flags.requiresAngular, 'generateHeadElement');
7
7
  pushHandler(flags.requiresHtml, 'handleHTMLPageRequest');
8
- pushHandler(flags.requiresReact, 'handleReactPageRequest');
8
+ pushHandler(flags.requiresReact, 'handleReactPageRequest', '@absolutejs/absolute/react');
9
9
  pushHandler(flags.requiresSvelte, 'handleSveltePageRequest', '@absolutejs/absolute/svelte');
10
10
  pushHandler(flags.requiresVue, 'handleVuePageRequest', '@absolutejs/absolute/vue');
11
11
  pushHandler(flags.requiresVue, 'generateHeadElement');
12
12
  pushHandler(flags.requiresHtmx, 'handleHTMXPageRequest');
13
- const nonFrameworkOnly = (flags.requiresHtml || flags.requiresHtmx) &&
14
- !flags.requiresReact &&
15
- !flags.requiresSvelte &&
16
- !flags.requiresVue;
17
13
  for (const dependency of deps) {
18
14
  const importsList = dependency.imports ?? [];
19
- const relevantImports = nonFrameworkOnly
20
- ? importsList.filter((imp) => imp.packageName !== 'asset')
21
- : importsList;
22
- if (relevantImports.length === 0)
15
+ if (importsList.length === 0)
23
16
  continue;
24
- rawImports.push(`import { ${relevantImports
17
+ rawImports.push(`import { ${importsList
25
18
  .map((imp) => imp.packageName)
26
19
  .sort()
27
20
  .join(', ')} } from '${dependency.value}'`);
28
21
  }
29
- rawImports.push(`import { env } from 'bun'`);
30
22
  const buildExamplePath = (dir, file) => `../frontend${dir ? `/${dir}` : ''}/pages/${file}`;
31
23
  const reactDir = frontendDirectories.react;
32
24
  const svelteDir = frontendDirectories.svelte;
33
25
  const vueDir = frontendDirectories.vue;
26
+ const angularDir = frontendDirectories.angular;
34
27
  if (flags.requiresReact && reactDir !== undefined)
35
28
  rawImports.push(`import { ReactExample } from '${buildExamplePath(reactDir, 'ReactExample')}'`);
36
29
  if (flags.requiresSvelte && svelteDir !== undefined)
37
- rawImports.push(`import SvelteExample from '${buildExamplePath(svelteDir, 'SvelteExample.svelte')}'`);
38
- if (flags.requiresVue && !flags.requiresSvelte && vueDir !== undefined)
39
- 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')}'`);
40
35
  const connectorImports = {
41
36
  neon: [`import { neon } from '@neondatabase/serverless'`],
42
37
  planetscale: [`import { Client } from '@planetscale/database'`],
@@ -63,6 +58,19 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
63
58
  : [`import { schema } from '../../db/schema'`])
64
59
  ]
65
60
  };
61
+ const getPostgresqlOrmDatabaseImports = () => {
62
+ if (!isRemoteHost)
63
+ return [
64
+ `import { SQL } from 'bun'`,
65
+ `import { drizzle } from 'drizzle-orm/bun-sql'`
66
+ ];
67
+ if (databaseHost === 'planetscale')
68
+ return [
69
+ `import { drizzle } from 'drizzle-orm/node-postgres'`,
70
+ `import { Pool } from 'pg'`
71
+ ];
72
+ return [];
73
+ };
66
74
  const ormDatabaseImports = {
67
75
  drizzle: {
68
76
  gel: [
@@ -73,23 +81,17 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
73
81
  `import { drizzle } from 'drizzle-orm/mysql2'`,
74
82
  `import { createPool } from 'mysql2/promise'`
75
83
  ],
84
+ mssql: [
85
+ `import { connect } from 'mssql'`,
86
+ `import { drizzle } from 'drizzle-orm/node-mssql'`
87
+ ],
76
88
  mysql: !isRemoteHost
77
89
  ? [
78
90
  `import { drizzle } from 'drizzle-orm/mysql2'`,
79
91
  `import { createPool } from 'mysql2/promise'`
80
92
  ]
81
93
  : [],
82
- postgresql: !isRemoteHost
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
- : [],
94
+ postgresql: getPostgresqlOrmDatabaseImports(),
93
95
  singlestore: [
94
96
  `import { drizzle } from 'drizzle-orm/singlestore'`,
95
97
  `import { createPool } from 'mysql2/promise'`
@@ -102,6 +104,22 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
102
104
  : []
103
105
  }
104
106
  };
107
+ const getPostgresqlNoOrmImports = () => {
108
+ if (isRemoteHost && databaseHost === 'neon')
109
+ return [
110
+ ...connectorImports[databaseHost],
111
+ `import { getEnv } from '@absolutejs/absolute'`
112
+ ];
113
+ if (isRemoteHost && databaseHost === 'planetscale')
114
+ return [
115
+ `import { Pool } from 'pg'`,
116
+ `import { getEnv } from '@absolutejs/absolute'`
117
+ ];
118
+ return [
119
+ `import { SQL } from 'bun'`,
120
+ `import { getEnv } from '@absolutejs/absolute'`
121
+ ];
122
+ };
105
123
  const noOrmImports = {
106
124
  cockroachdb: [
107
125
  `import { SQL } from 'bun'`,
@@ -132,20 +150,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
132
150
  `import { SQL } from 'bun'`,
133
151
  `import { getEnv } from '@absolutejs/absolute'`
134
152
  ],
135
- postgresql: isRemoteHost && databaseHost === 'neon'
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
- ],
153
+ postgresql: getPostgresqlNoOrmImports(),
149
154
  singlestore: [
150
155
  `import { createPool } from 'mysql2/promise'`,
151
156
  `import { getEnv } from '@absolutejs/absolute'`
@@ -160,7 +165,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
160
165
  if (orm === 'drizzle') {
161
166
  rawImports.push(...ormImports[orm]);
162
167
  }
163
- if (orm == 'drizzle' &&
168
+ if (orm === 'drizzle' &&
164
169
  isRemoteHost &&
165
170
  !(databaseEngine === 'postgresql' && databaseHost === 'planetscale')) {
166
171
  rawImports.push(...connectorImports[databaseHost], ...dialectImports[databaseHost]);
@@ -175,13 +180,6 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authO
175
180
  rawImports.push(`import { absoluteAuthConfig } from './utils/absoluteAuthConfig'`, `import { t } from 'elysia'`, `import { authProviderOption, providers, userSessionIdTypebox, getStatus } from '@absolutejs/auth'`);
176
181
  if (hasDatabase && (authOption === undefined || authOption === 'none'))
177
182
  rawImports.push(`import { getCountHistory, createCountHistory } from './handlers/countHistoryHandlers'`, `import { t } from 'elysia'`);
178
- if (flags.requiresVue && flags.requiresSvelte) {
179
- const utilsDir = join(backendDirectory, 'utils');
180
- mkdirSync(utilsDir, { recursive: true });
181
- const vuePathForUtils = `../../frontend${vueDir ? `/${vueDir}` : ''}/pages/VueExample.vue`;
182
- writeFileSync(join(utilsDir, 'vueImporter.ts'), `import VueExample from "${vuePathForUtils}"\n\nexport const vueImports = { VueExample } as const\n`);
183
- rawImports.push(`import { vueImports } from './utils/vueImporter'`);
184
- }
185
183
  const importMap = new Map();
186
184
  for (const stmt of rawImports) {
187
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;
@@ -53,6 +53,10 @@ h1 {
53
53
  filter: drop-shadow(0 0 2rem ${color});
54
54
  }
55
55
 
56
+ button:hover {
57
+ border-color: ${color};
58
+ }
59
+
56
60
  nav {
57
61
  display: flex;
58
62
  gap: 4rem;
@@ -1,11 +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
- buildDirectory: string;
9
6
  };
10
- export declare const generateRoutesBlock: ({ databaseEngine, flags, frontendDirectories, authOption, buildDirectory }: GenerateRoutesBlockProps) => string;
7
+ export declare const generateRoutesBlock: ({ databaseEngine, frontendDirectories, authOption }: GenerateRoutesBlockProps) => string;
11
8
  export {};