create-absolutejs 0.4.2 → 0.5.1

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.
@@ -5,11 +5,12 @@ import { dim, yellow } from 'picocolors';
5
5
  import { isDrizzleDialect } from '../../typeGuards';
6
6
  import { checkSqliteInstalled } from '../../utils/checkSqliteInstalled';
7
7
  import { createDrizzleConfig } from '../configurations/generateDrizzleConfig';
8
+ import { generateDatabaseTypes } from './generateDatabaseTypes';
8
9
  import { generateDrizzleSchema } from './generateDrizzleSchema';
9
10
  import { generateDBHandlers } from './generateHandlers';
10
11
  import { generateSqliteSchema } from './generateSqliteSchema';
11
12
  import { scaffoldDocker } from './scaffoldDocker';
12
- export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm }) => {
13
+ export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm, typesDirectory }) => {
13
14
  const projectDatabaseDirectory = join(projectName, databaseDirectory);
14
15
  const handlerDirectory = join(backendDirectory, 'handlers');
15
16
  mkdirSync(projectDatabaseDirectory, { recursive: true });
@@ -49,11 +50,16 @@ export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHo
49
50
  }
50
51
  const drizzleSchema = generateDrizzleSchema({
51
52
  authProvider,
52
- databaseEngine,
53
- databaseHost
53
+ databaseEngine
54
54
  });
55
55
  writeFileSync(join(projectDatabaseDirectory, 'schema.ts'), drizzleSchema);
56
56
  createDrizzleConfig({ databaseDirectory, databaseEngine, projectName });
57
+ const drizzleTypes = generateDatabaseTypes({
58
+ authProvider,
59
+ databaseEngine,
60
+ databaseHost
61
+ });
62
+ writeFileSync(join(typesDirectory, 'databaseTypes.ts'), drizzleTypes);
57
63
  return;
58
64
  }
59
65
  if (orm === 'prisma') {
@@ -1,32 +1,35 @@
1
1
  import { availableDrizzleDialects } from '../../data';
2
2
  const connectionMap = {
3
3
  cockroachdb: {
4
- none: { expr: 'new Pool({ connectionString: getEnv("DATABASE_URL") })' }
4
+ none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
5
5
  },
6
6
  gel: {
7
- none: { expr: 'gelClient({ url: getEnv("DATABASE_URL") })' }
7
+ none: { expr: 'createClient(getEnv("DATABASE_URL"))' }
8
8
  },
9
9
  mariadb: {
10
- none: { expr: 'createPool(getEnv("DATABASE_URL"))' }
10
+ none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
11
11
  },
12
12
  mongodb: {
13
- none: { expr: 'new MongoClient(getEnv("DATABASE_URL") })' }
13
+ none: { expr: 'new MongoClient(getEnv("DATABASE_URL"))' }
14
14
  },
15
15
  mssql: {
16
16
  none: { expr: 'await connect(getEnv("DATABASE_URL"))' }
17
17
  },
18
18
  mysql: {
19
- none: { expr: 'createPool(getEnv("DATABASE_URL"))' },
20
- planetscale: { expr: 'connect({ url: getEnv("DATABASE_URL") })' }
19
+ none: { expr: 'new SQL(getEnv("DATABASE_URL"))' },
20
+ planetscale: { expr: 'new Client({ url: getEnv("DATABASE_URL") })' }
21
21
  },
22
22
  postgresql: {
23
23
  neon: {
24
24
  expr: 'new Pool({ connectionString: getEnv("DATABASE_URL") })'
25
25
  },
26
- none: { expr: 'new Pool({ connectionString: getEnv("DATABASE_URL") })' }
26
+ none: { expr: 'new SQL(getEnv("DATABASE_URL"))' },
27
+ planetscale: {
28
+ expr: 'new Pool({ connectionString: getEnv("DATABASE_URL") })'
29
+ }
27
30
  },
28
31
  singlestore: {
29
- none: { expr: 'createClient({ url: getEnv("DATABASE_URL") })' }
32
+ none: { expr: 'createPool(getEnv("DATABASE_URL"))' }
30
33
  },
31
34
  sqlite: {
32
35
  none: { expr: 'new Database("db/database.sqlite")' },
@@ -35,7 +38,7 @@ const connectionMap = {
35
38
  };
36
39
  const remoteDrizzleInit = {
37
40
  neon: 'new Pool({ connectionString: getEnv("DATABASE_URL") })',
38
- planetscale: 'connect({ url: getEnv("DATABASE_URL") })',
41
+ planetscale: 'new Client({ url: getEnv("DATABASE_URL") })',
39
42
  turso: 'createClient({ url: getEnv("DATABASE_URL") })'
40
43
  };
41
44
  const drizzleDialectSet = new Set([...availableDrizzleDialects]);
@@ -49,28 +52,18 @@ export const generateDBBlock = ({ databaseEngine, orm, databaseHost }) => {
49
52
  return '';
50
53
  if (orm !== 'drizzle') {
51
54
  const hostCfg = engineGroup[hostKey];
52
- if (!hostCfg)
53
- return '';
54
- return `
55
- const pool = ${hostCfg.expr}
56
- `;
55
+ return hostCfg ? `const db = ${hostCfg.expr}` : '';
57
56
  }
58
57
  if (!drizzleDialectSet.has(databaseEngine))
59
58
  return '';
60
59
  const expr = engineGroup[hostKey]?.expr ?? remoteDrizzleInit[hostKey];
61
60
  if (!expr)
62
61
  return '';
63
- if (databaseEngine === 'mysql') {
64
- const mode = databaseHost === 'planetscale' ? 'planetscale' : 'default';
62
+ if ((databaseEngine === 'mysql' || databaseEngine === 'mariadb') &&
63
+ databaseHost !== 'planetscale') {
65
64
  return `
66
- const pool = ${expr}
67
- const db = drizzle(pool, { schema, mode: '${mode}' })
68
- `;
69
- }
70
- if (databaseEngine === 'sqlite') {
71
- return `
72
- const pool = ${expr}
73
- const db = drizzle(pool, { schema })
65
+ const pool = createPool(getEnv("DATABASE_URL"))
66
+ const db = drizzle(pool, { schema, mode: 'default' })
74
67
  `;
75
68
  }
76
69
  return `
@@ -1,5 +1,6 @@
1
1
  import { mkdirSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
+ import { isDrizzleDialect } from '../../typeGuards';
3
4
  export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authProvider, databaseEngine, databaseHost, frontendDirectories }) => {
4
5
  const rawImports = [];
5
6
  const pushHandler = (cond, name) => cond &&
@@ -38,7 +39,7 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authP
38
39
  rawImports.push(`import VueExample from '${buildExamplePath(vueDir, 'VueExample.vue')}'`);
39
40
  const connectorImports = {
40
41
  neon: [`import { Pool } from '@neondatabase/serverless'`],
41
- planetscale: [`import { connect } from '@planetscale/database'`],
42
+ planetscale: [`import { Client } from '@planetscale/database'`],
42
43
  turso: [`import { createClient } from '@libsql/client'`]
43
44
  };
44
45
  const dialectImports = {
@@ -51,44 +52,124 @@ export const generateImportsBlock = ({ backendDirectory, deps, flags, orm, authP
51
52
  const isRemoteHost = databaseHost !== undefined && databaseHost !== 'none';
52
53
  const hasDatabase = databaseEngine !== undefined && databaseEngine !== 'none';
53
54
  const noOrm = orm === undefined || orm === 'none';
54
- if (orm === 'drizzle' && isRemoteHost) {
55
- const key = databaseHost;
56
- rawImports.push(...connectorImports[key], ...dialectImports[key]);
57
- }
58
- if (orm === 'drizzle' && !isRemoteHost && databaseEngine === 'postgresql')
59
- rawImports.push(`import { Pool } from 'pg'`, `import { drizzle } from 'drizzle-orm/node-postgres'`);
60
- if (orm === 'drizzle' && databaseEngine === 'sqlite' && !isRemoteHost)
61
- rawImports.push(`import { Database } from 'bun:sqlite'`, `import { drizzle } from 'drizzle-orm/bun-sqlite'`);
62
- if (noOrm && databaseEngine === 'sqlite')
63
- rawImports.push(...(databaseHost === 'turso'
55
+ const ormImports = {
56
+ drizzle: [
57
+ `import { Elysia } from 'elysia'`,
58
+ ...(databaseEngine === 'sqlite' && !isRemoteHost
59
+ ? []
60
+ : [`import { getEnv } from '@absolutejs/absolute'`]),
61
+ ...(authProvider === 'absoluteAuth'
62
+ ? [
63
+ `import { schema } from '../../db/schema'`,
64
+ `import { User } from '../types/databaseTypes'`
65
+ ]
66
+ : [`import { schema } from '../../db/schema'`])
67
+ ]
68
+ };
69
+ const ormDatabaseImports = {
70
+ drizzle: {
71
+ gel: [
72
+ `import { createClient } from 'gel'`,
73
+ `import { drizzle } from 'drizzle-orm/gel'`
74
+ ],
75
+ mariadb: [
76
+ `import { drizzle } from 'drizzle-orm/mysql2'`,
77
+ `import { createPool } from 'mysql2/promise'`
78
+ ],
79
+ mysql: !isRemoteHost
80
+ ? [
81
+ `import { drizzle } from 'drizzle-orm/mysql2'`,
82
+ `import { createPool } from 'mysql2/promise'`
83
+ ]
84
+ : [],
85
+ postgresql: !isRemoteHost
86
+ ? [
87
+ `import { SQL } from 'bun'`,
88
+ `import { drizzle } from 'drizzle-orm/bun-sql'`
89
+ ]
90
+ : isRemoteHost && databaseHost === 'planetscale'
91
+ ? [
92
+ `import { drizzle } from 'drizzle-orm/node-postgres'`,
93
+ `import { Pool } from 'pg'`
94
+ ]
95
+ : [],
96
+ singlestore: [
97
+ `import { drizzle } from 'drizzle-orm/singlestore'`,
98
+ `import { createPool } from 'mysql2/promise'`
99
+ ],
100
+ sqlite: !isRemoteHost
101
+ ? [
102
+ `import { Database } from 'bun:sqlite'`,
103
+ `import { drizzle } from 'drizzle-orm/bun-sqlite'`
104
+ ]
105
+ : []
106
+ }
107
+ };
108
+ const noOrmImports = {
109
+ cockroachdb: [
110
+ `import { SQL } from 'bun'`,
111
+ `import { getEnv } from '@absolutejs/absolute'`
112
+ ],
113
+ gel: [
114
+ `import { createClient } from 'gel'`,
115
+ `import { getEnv } from '@absolutejs/absolute'`
116
+ ],
117
+ mariadb: [
118
+ `import { SQL } from 'bun'`,
119
+ `import { getEnv } from '@absolutejs/absolute'`
120
+ ],
121
+ mongodb: [],
122
+ mssql: [
123
+ `import { connect } from 'mssql'`,
124
+ `import { getEnv } from '@absolutejs/absolute'`
125
+ ],
126
+ mysql: isRemoteHost
64
127
  ? [
65
- `import { createClient } from '@libsql/client'`,
128
+ ...connectorImports[databaseHost],
66
129
  `import { getEnv } from '@absolutejs/absolute'`
67
130
  ]
68
- : [`import { Database } from 'bun:sqlite'`]));
69
- if (databaseEngine === 'mysql' && isRemoteHost) {
70
- const key = databaseHost;
71
- rawImports.push(...connectorImports[key]);
72
- }
73
- if (databaseEngine === 'mysql' && !isRemoteHost) {
74
- rawImports.push(`import { createPool } from 'mysql2/promise'`);
131
+ : [
132
+ `import { SQL } from 'bun'`,
133
+ `import { getEnv } from '@absolutejs/absolute'`
134
+ ],
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
+ ],
149
+ singlestore: [
150
+ `import { createPool } from 'mysql2/promise'`,
151
+ `import { getEnv } from '@absolutejs/absolute'`
152
+ ],
153
+ sqlite: isRemoteHost
154
+ ? [
155
+ ...connectorImports[databaseHost],
156
+ `import { getEnv } from '@absolutejs/absolute'`
157
+ ]
158
+ : [`import { Database } from 'bun:sqlite'`]
159
+ };
160
+ if (orm === 'drizzle') {
161
+ rawImports.push(...ormImports[orm]);
75
162
  }
76
- if (databaseEngine === 'mysql' && orm === 'drizzle') {
77
- rawImports.push(`import { drizzle } from 'drizzle-orm/mysql2'`);
163
+ if (orm == 'drizzle' &&
164
+ isRemoteHost &&
165
+ !(databaseEngine === 'postgresql' && databaseHost === 'planetscale')) {
166
+ rawImports.push(...connectorImports[databaseHost], ...dialectImports[databaseHost]);
78
167
  }
79
- if (databaseEngine === 'mysql') {
80
- rawImports.push(`import { getEnv } from '@absolutejs/absolute'`);
168
+ if (orm === 'drizzle' && isDrizzleDialect(databaseEngine)) {
169
+ rawImports.push(...ormDatabaseImports[orm][databaseEngine]);
81
170
  }
82
- if (noOrm && databaseEngine === 'postgresql')
83
- rawImports.push(...(isRemoteHost
84
- ? connectorImports[databaseHost]
85
- : [`import { Pool } from 'pg'`]), `import { getEnv } from '@absolutejs/absolute'`);
86
- if (orm === 'drizzle') {
87
- rawImports.push(`import { Elysia } from 'elysia'`, ...(databaseEngine === 'sqlite' && !isRemoteHost
88
- ? []
89
- : [`import { getEnv } from '@absolutejs/absolute'`]), authProvider === 'absoluteAuth'
90
- ? `import { schema, User } from '../../db/schema'`
91
- : `import { schema } from '../../db/schema'`);
171
+ if (noOrm && hasDatabase && noOrmImports[databaseEngine]) {
172
+ rawImports.push(...noOrmImports[databaseEngine]);
92
173
  }
93
174
  if (authProvider === 'absoluteAuth')
94
175
  rawImports.push(`import { absoluteAuth, instantiateUserSession } from '@absolutejs/auth'`, ...(hasDatabase
@@ -12,7 +12,11 @@ export const generateUseBlock = ({ deps, databaseEngine, orm }) => deps
12
12
  const instantiate = 'instantiateUserSession';
13
13
  const pluginGeneric = hasOrm ? '<User>' : '';
14
14
  const callback = hasDatabase
15
- ? `async ({ authProvider, providerInstance, tokenResponse, userSessionId, session }) => ${instantiate}({ authProvider, providerInstance, session, tokenResponse, userSessionId, createUser: (userIdentity) => createUser({ authProvider, db, userIdentity }), getUser: (userIdentity) => getUser({ authProvider, db, userIdentity }) })`
15
+ ? `async ({ authProvider, providerInstance, tokenResponse, unregisteredSession, cookie: { user_session_id }, session }) => ${instantiate}(
16
+ { authProvider, providerInstance, session, tokenResponse, unregisteredSession, user_session_id,
17
+ getUser: async (userIdentity) => getUser({ authProvider, db, userIdentity }),
18
+ onNewUser: async (userIdentity) => createUser({ authProvider, db, userIdentity })
19
+ })`
16
20
  : `({ authProvider, tokenResponse, userSessionId }) => { console.log(\`Successfully authorized OAuth2 with \${authProvider} (session: \${userSessionId})\`, tokenResponse); }`;
17
21
  const mergedConfig = `{ ${baseConfigString}${baseConfigString ? ',' : ''} onCallbackSuccess: ${callback} }`;
18
22
  return `.use(absoluteAuth${pluginGeneric}(${mergedConfig}))`;
package/dist/messages.js CHANGED
@@ -34,7 +34,7 @@ Options:
34
34
  ${cyan('--plugin')} ${dim(cyan('<plugin>'))} Elysia plugin(s) to include (repeatable); 'none' skips plugin setup
35
35
  ${cyan('--react')} Include a React frontend
36
36
  ${cyan('--react-dir')} ${dim(cyan('<directory>'))} Specify the directory for and use the React frontend
37
- ${cyan('--skip')} Skip non-required prompts; uses 'none' for all optional configs
37
+ ${cyan('--skip')} Skip non-required prompts; use 'none' for all optional configs and "absolutejs-project" when no project name is provided.
38
38
  ${cyan('--svelte')} Include a Svelte frontend
39
39
  ${cyan('--svelte-dir')} ${dim(cyan('<directory>'))} Specify the directory for and use the Svelte frontend
40
40
  ${cyan('--tailwind')} Include Tailwind CSS setup
@@ -1 +1 @@
1
- export declare const getDatabaseEngine: () => Promise<"gel" | "mysql" | "postgresql" | "sqlite" | "singlestore" | "mongodb" | "mariadb" | "cockroachdb" | "mssql" | undefined>;
1
+ export declare const getDatabaseEngine: () => Promise<"gel" | "mysql" | "postgresql" | "sqlite" | "singlestore" | "mariadb" | "mongodb" | "cockroachdb" | "mssql" | undefined>;
@@ -15,6 +15,18 @@ export const getDatabaseHost = async (databaseEngine) => {
15
15
  abort();
16
16
  return databaseHost === 'none' ? undefined : databaseHost;
17
17
  }
18
+ if (databaseEngine === 'mysql') {
19
+ const databaseHost = await select({
20
+ message: 'Select database host:',
21
+ options: [
22
+ { label: 'None', value: 'none' },
23
+ { label: cyan('PlanetScale'), value: 'planetscale' }
24
+ ]
25
+ });
26
+ if (isCancel(databaseHost))
27
+ abort();
28
+ return databaseHost === 'none' ? undefined : databaseHost;
29
+ }
18
30
  if (databaseEngine === 'sqlite') {
19
31
  const databaseHost = await select({
20
32
  message: 'Select database host:',
package/dist/scaffold.js CHANGED
@@ -13,7 +13,7 @@ import { scaffoldFrontends } from './generators/project/scaffoldFrontends';
13
13
  export const scaffold = async ({ response: { projectName, codeQualityTool, initializeGitNow, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, orm, frontends, plugins, authProvider, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, envVariables, packageManager }) => {
14
14
  const __dirname = dirname(fileURLToPath(import.meta.url));
15
15
  const templatesDirectory = join(__dirname, '/templates');
16
- const { frontendDirectory, backendDirectory, projectAssetsDirectory } = initalizeRoot(projectName, templatesDirectory);
16
+ const { frontendDirectory, backendDirectory, projectAssetsDirectory, typesDirectory } = initalizeRoot(projectName, templatesDirectory);
17
17
  copyFileSync(join(templatesDirectory, 'README.md'), join(projectName, 'README.md'));
18
18
  scaffoldConfigurationFiles({
19
19
  codeQualityTool,
@@ -60,7 +60,8 @@ export const scaffold = async ({ response: { projectName, codeQualityTool, initi
60
60
  databaseEngine,
61
61
  databaseHost,
62
62
  orm,
63
- projectName
63
+ projectName,
64
+ typesDirectory
64
65
  })));
65
66
  scaffoldFrontends({
66
67
  frontendDirectories,
@@ -0,0 +1 @@
1
+ @import 'tailwindcss';
@@ -46,7 +46,7 @@ export const parseCommandLineOptions = () => {
46
46
  }
47
47
  });
48
48
  const errors = [];
49
- const projectName = positionals[0] ?? (values.skip ? undefined : 'absolutejs-project');
49
+ const projectName = positionals[0] ?? (values.skip ? 'absolutejs-project' : undefined);
50
50
  let authProvider;
51
51
  if (values.auth !== undefined && !isAuthProvider(values.auth)) {
52
52
  errors.push(`Invalid auth provider: "${values.auth}". Expected: [ ${availableAuthProviders.join(', ')} ]`);
package/package.json CHANGED
@@ -47,5 +47,5 @@
47
47
  "typecheck": "bun run tsc --noEmit"
48
48
  },
49
49
  "type": "module",
50
- "version": "0.4.2"
50
+ "version": "0.5.1"
51
51
  }