create-absolutejs 0.15.3 → 0.15.4
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/data.js +1 -1
- package/dist/generators/configurations/generatePackageJson.js +5 -0
- package/dist/generators/db/generateDatabaseTypes.js +1 -1
- package/dist/generators/db/handlerTemplates.d.ts +0 -24
- package/dist/generators/db/handlerTemplates.js +26 -31
- package/dist/generators/db/scaffoldDatabase.js +6 -6
- package/dist/generators/project/generateAbsoluteAuthConfig.d.ts +1 -0
- package/dist/generators/project/generateAbsoluteAuthConfig.js +31 -15
- package/dist/generators/project/generateRoutesBlock.js +3 -2
- package/dist/generators/project/generateServer.js +9 -6
- package/dist/generators/project/scaffoldBackend.d.ts +2 -1
- package/dist/generators/project/scaffoldBackend.js +10 -2
- package/dist/generators/project/scaffoldFrontends.js +6 -0
- package/dist/generators/react/generateReactComponents.d.ts +1 -1
- package/dist/generators/react/generateReactComponents.js +7 -3
- package/dist/generators/react/scaffoldReact.d.ts +1 -1
- package/dist/generators/react/scaffoldReact.js +9 -4
- package/dist/scaffold.js +2 -1
- package/dist/types.d.ts +3 -0
- package/dist/versions.d.ts +3 -1
- package/dist/versions.js +4 -1
- package/package.json +2 -2
package/dist/data.js
CHANGED
|
@@ -134,6 +134,9 @@ export const createPackageJson = async ({ agentic, projectName, authOption, plug
|
|
|
134
134
|
const dependencies = {};
|
|
135
135
|
const devDependencies = {};
|
|
136
136
|
devDependencies['typescript'] = resolveVersion('typescript', versions['typescript']);
|
|
137
|
+
/* Every scaffolded project runs on Bun, and the local database drivers type
|
|
138
|
+
against its built-in modules (`bun:sqlite`, `SQL` from `bun`). */
|
|
139
|
+
devDependencies['@types/bun'] = resolveVersion('@types/bun', versions['@types/bun']);
|
|
137
140
|
for (const p of defaultPlugins) {
|
|
138
141
|
dependencies[p.value] = resolveVersion(p.value, p.latestVersion);
|
|
139
142
|
}
|
|
@@ -289,6 +292,8 @@ export const createPackageJson = async ({ agentic, projectName, authOption, plug
|
|
|
289
292
|
if (orm === 'drizzle') {
|
|
290
293
|
scripts['db:studio'] = 'drizzle-kit studio';
|
|
291
294
|
scripts['db:push'] = 'drizzle-kit push';
|
|
295
|
+
/* `drizzle.config.ts` imports it and the scripts above shell out to it. */
|
|
296
|
+
devDependencies['drizzle-kit'] = resolveVersion('drizzle-kit', versions['drizzle-kit']);
|
|
292
297
|
}
|
|
293
298
|
const packageJson = {
|
|
294
299
|
dependencies,
|
|
@@ -163,7 +163,7 @@ export const generateDatabaseTypes = ({ databaseEngine, databaseHost, authOption
|
|
|
163
163
|
}
|
|
164
164
|
const schemaImport = authOption === 'abs'
|
|
165
165
|
? `import { users, schema } from '../../db/schema';`
|
|
166
|
-
: `import { countHistory } from '../../db/schema';`;
|
|
166
|
+
: `import { countHistory, schema } from '../../db/schema';`;
|
|
167
167
|
const extraTypes = authOption === 'abs'
|
|
168
168
|
? `export type User = typeof users.$inferSelect;
|
|
169
169
|
export type NewUser = typeof users.$inferInsert;`
|
|
@@ -6,122 +6,98 @@ type QueryOperations = {
|
|
|
6
6
|
};
|
|
7
7
|
declare const driverConfigurations: {
|
|
8
8
|
readonly 'cockroachdb:sql:local': {
|
|
9
|
-
readonly dbType: "SQL";
|
|
10
9
|
readonly importLines: "";
|
|
11
10
|
readonly queries: QueryOperations;
|
|
12
11
|
};
|
|
13
12
|
readonly 'gel:drizzle:local': {
|
|
14
|
-
readonly dbType: "GelJsDatabase<SchemaType>";
|
|
15
13
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'\n";
|
|
16
14
|
readonly queries: QueryOperations;
|
|
17
15
|
};
|
|
18
16
|
readonly 'gel:sql:local': {
|
|
19
|
-
readonly dbType: "Client";
|
|
20
17
|
readonly importLines: "";
|
|
21
18
|
readonly queries: QueryOperations;
|
|
22
19
|
};
|
|
23
20
|
readonly 'mariadb:drizzle:local': {
|
|
24
|
-
readonly dbType: "MySql2Database<SchemaType>";
|
|
25
21
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
26
22
|
readonly queries: QueryOperations;
|
|
27
23
|
};
|
|
28
24
|
readonly 'mariadb:sql:local': {
|
|
29
|
-
readonly dbType: "SQL";
|
|
30
25
|
readonly importLines: "";
|
|
31
26
|
readonly queries: QueryOperations;
|
|
32
27
|
};
|
|
33
28
|
readonly 'mongodb:sql:local': {
|
|
34
|
-
readonly dbType: "Db";
|
|
35
29
|
readonly importLines: "";
|
|
36
30
|
readonly queries: QueryOperations;
|
|
37
31
|
};
|
|
38
32
|
readonly 'mssql:drizzle:local': {
|
|
39
|
-
readonly dbType: "NodeMssqlDatabase<SchemaType>";
|
|
40
33
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
41
34
|
readonly queries: QueryOperations;
|
|
42
35
|
};
|
|
43
36
|
readonly 'mssql:sql:local': {
|
|
44
|
-
readonly dbType: "ConnectionPool";
|
|
45
37
|
readonly importLines: "";
|
|
46
38
|
readonly queries: QueryOperations;
|
|
47
39
|
};
|
|
48
40
|
readonly 'mysql:drizzle:local': {
|
|
49
|
-
readonly dbType: "MySql2Database<SchemaType>";
|
|
50
41
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
51
42
|
readonly queries: QueryOperations;
|
|
52
43
|
};
|
|
53
44
|
readonly 'mysql:drizzle:planetscale': {
|
|
54
|
-
readonly dbType: "PlanetScaleDatabase<SchemaType>";
|
|
55
45
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
56
46
|
readonly queries: QueryOperations;
|
|
57
47
|
};
|
|
58
48
|
readonly 'mysql:sql:local': {
|
|
59
|
-
readonly dbType: "SQL";
|
|
60
49
|
readonly importLines: "";
|
|
61
50
|
readonly queries: QueryOperations;
|
|
62
51
|
};
|
|
63
52
|
readonly 'mysql:sql:planetscale': {
|
|
64
|
-
readonly dbType: "Client";
|
|
65
53
|
readonly importLines: "";
|
|
66
54
|
readonly queries: QueryOperations;
|
|
67
55
|
};
|
|
68
56
|
readonly 'postgresql:drizzle:local': {
|
|
69
|
-
readonly dbType: "BunSQLDatabase<SchemaType>";
|
|
70
57
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
71
58
|
readonly queries: QueryOperations;
|
|
72
59
|
};
|
|
73
60
|
readonly 'postgresql:drizzle:neon': {
|
|
74
|
-
readonly dbType: "NeonDatabase<SchemaType>";
|
|
75
61
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
76
62
|
readonly queries: QueryOperations;
|
|
77
63
|
};
|
|
78
64
|
readonly 'postgresql:drizzle:planetscale': {
|
|
79
|
-
readonly dbType: "NodePgDatabase<SchemaType>";
|
|
80
65
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
81
66
|
readonly queries: QueryOperations;
|
|
82
67
|
};
|
|
83
68
|
readonly 'postgresql:sql:local': {
|
|
84
|
-
readonly dbType: "SQL";
|
|
85
69
|
readonly importLines: "";
|
|
86
70
|
readonly queries: QueryOperations;
|
|
87
71
|
};
|
|
88
72
|
readonly 'postgresql:sql:neon': {
|
|
89
|
-
readonly dbType: "Pool";
|
|
90
73
|
readonly importLines: "";
|
|
91
74
|
readonly queries: QueryOperations;
|
|
92
75
|
};
|
|
93
76
|
readonly 'postgresql:sql:planetscale': {
|
|
94
|
-
readonly dbType: "Pool";
|
|
95
77
|
readonly importLines: "";
|
|
96
78
|
readonly queries: QueryOperations;
|
|
97
79
|
};
|
|
98
80
|
readonly 'singlestore:drizzle:local': {
|
|
99
|
-
readonly dbType: "SingleStoreDriverDatabase<SchemaType>";
|
|
100
81
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
101
82
|
readonly queries: QueryOperations;
|
|
102
83
|
};
|
|
103
84
|
readonly 'singlestore:sql:local': {
|
|
104
|
-
readonly dbType: "Pool";
|
|
105
85
|
readonly importLines: "import { RowDataPacket } from 'mysql2/promise'\n";
|
|
106
86
|
readonly queries: QueryOperations;
|
|
107
87
|
};
|
|
108
88
|
readonly 'sqlite:drizzle:local': {
|
|
109
|
-
readonly dbType: "BunSQLiteDatabase<SchemaType>";
|
|
110
89
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
111
90
|
readonly queries: QueryOperations;
|
|
112
91
|
};
|
|
113
92
|
readonly 'sqlite:drizzle:turso': {
|
|
114
|
-
readonly dbType: "LibSQLDatabase<SchemaType>";
|
|
115
93
|
readonly importLines: "import { eq } from 'drizzle-orm'\nimport { schema } from '../../../db/schema'";
|
|
116
94
|
readonly queries: QueryOperations;
|
|
117
95
|
};
|
|
118
96
|
readonly 'sqlite:sql:local': {
|
|
119
|
-
readonly dbType: "Database";
|
|
120
97
|
readonly importLines: "";
|
|
121
98
|
readonly queries: QueryOperations;
|
|
122
99
|
};
|
|
123
100
|
readonly 'sqlite:sql:turso': {
|
|
124
|
-
readonly dbType: "Client";
|
|
125
101
|
readonly importLines: "";
|
|
126
102
|
readonly queries: QueryOperations;
|
|
127
103
|
};
|
|
@@ -1,22 +1,38 @@
|
|
|
1
|
-
const buildSqlAuthTemplate = ({ importLines, queries }) => `
|
|
2
|
-
import { DatabaseType, NewUser } from '../../types/databaseTypes';
|
|
1
|
+
const buildSqlAuthTemplate = ({ importLines, queries, rowsAreTyped }) => `
|
|
2
|
+
import { DatabaseType, NewUser${rowsAreTyped ? '' : ', User'} } from '../../types/databaseTypes';
|
|
3
3
|
${importLines}
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
${rowsAreTyped
|
|
6
|
+
? `export const getUser = async (db: DatabaseType, authSub: string) => {
|
|
7
|
+
${queries.selectUser}
|
|
8
|
+
};`
|
|
9
|
+
: `const selectUserRow = async (db: DatabaseType, authSub: string) => {
|
|
6
10
|
${queries.selectUser}
|
|
7
11
|
};
|
|
8
12
|
|
|
13
|
+
/* The driver returns the row untyped, so it is asserted to the shape the query
|
|
14
|
+
above selects. */
|
|
15
|
+
export const getUser = async (
|
|
16
|
+
db: DatabaseType,
|
|
17
|
+
authSub: string
|
|
18
|
+
): Promise<User | null> =>
|
|
19
|
+
((await selectUserRow(db, authSub)) as User | null) ?? null;`}
|
|
20
|
+
|
|
9
21
|
export const createUser = async (db: DatabaseType, newUserData: NewUser) => {
|
|
10
22
|
const { auth_sub: authSub, metadata: userIdentity } = newUserData;
|
|
11
23
|
${queries.insertUser}
|
|
12
24
|
}`;
|
|
13
|
-
|
|
25
|
+
/* Takes `db` as the `DatabaseType` alias rather than naming the driver type
|
|
26
|
+
inline, matching the auth template — the driver type is only ever spelled out
|
|
27
|
+
in types/databaseTypes, so it does not need importing at every call site. */
|
|
28
|
+
const buildSqlCountTemplate = ({ importLines, queries }) => `
|
|
29
|
+
import { DatabaseType } from '../../types/databaseTypes';
|
|
14
30
|
${importLines}
|
|
15
|
-
export const getCountHistory = async (db:
|
|
31
|
+
export const getCountHistory = async (db: DatabaseType, uid: number) => {
|
|
16
32
|
${queries.selectHistory}
|
|
17
33
|
}
|
|
18
34
|
|
|
19
|
-
export const createCountHistory = async (db:
|
|
35
|
+
export const createCountHistory = async (db: DatabaseType, count: number) => {
|
|
20
36
|
${queries.insertHistory}
|
|
21
37
|
}
|
|
22
38
|
`;
|
|
@@ -322,135 +338,111 @@ const mysqlPlanetScaleQueryOperations = {
|
|
|
322
338
|
};
|
|
323
339
|
const driverConfigurations = {
|
|
324
340
|
'cockroachdb:sql:local': {
|
|
325
|
-
dbType: 'SQL',
|
|
326
341
|
importLines: ``,
|
|
327
342
|
queries: postgresSqlQueryOperations
|
|
328
343
|
},
|
|
329
344
|
'gel:drizzle:local': {
|
|
330
|
-
dbType: 'GelJsDatabase<SchemaType>',
|
|
331
345
|
importLines: `import { eq } from 'drizzle-orm'
|
|
332
346
|
import { schema } from '../../../db/schema'
|
|
333
347
|
`,
|
|
334
348
|
queries: drizzleQueryOperations
|
|
335
349
|
},
|
|
336
350
|
'gel:sql:local': {
|
|
337
|
-
dbType: 'Client',
|
|
338
351
|
importLines: ``,
|
|
339
352
|
queries: gelClientQueryOperations
|
|
340
353
|
},
|
|
341
354
|
'mariadb:drizzle:local': {
|
|
342
|
-
dbType: 'MySql2Database<SchemaType>',
|
|
343
355
|
importLines: `import { eq } from 'drizzle-orm'
|
|
344
356
|
import { schema } from '../../../db/schema'`,
|
|
345
357
|
queries: mysqlDrizzleQueryOperations
|
|
346
358
|
},
|
|
347
359
|
'mariadb:sql:local': {
|
|
348
|
-
dbType: 'SQL',
|
|
349
360
|
importLines: ``,
|
|
350
361
|
queries: mysqlSqlQueryOperations
|
|
351
362
|
},
|
|
352
363
|
'mongodb:sql:local': {
|
|
353
|
-
dbType: 'Db',
|
|
354
364
|
importLines: ``,
|
|
355
365
|
queries: mongodbQueryOperations
|
|
356
366
|
},
|
|
357
367
|
'mssql:drizzle:local': {
|
|
358
|
-
dbType: 'NodeMssqlDatabase<SchemaType>',
|
|
359
368
|
importLines: `import { eq } from 'drizzle-orm'
|
|
360
369
|
import { schema } from '../../../db/schema'`,
|
|
361
370
|
queries: drizzleQueryOperations
|
|
362
371
|
},
|
|
363
372
|
'mssql:sql:local': {
|
|
364
|
-
dbType: 'ConnectionPool',
|
|
365
373
|
importLines: ``,
|
|
366
374
|
queries: mssqlSqlQueryOperations
|
|
367
375
|
},
|
|
368
376
|
'mysql:drizzle:local': {
|
|
369
|
-
dbType: 'MySql2Database<SchemaType>',
|
|
370
377
|
importLines: `import { eq } from 'drizzle-orm'
|
|
371
378
|
import { schema } from '../../../db/schema'`,
|
|
372
379
|
queries: mysqlDrizzleQueryOperations
|
|
373
380
|
},
|
|
374
381
|
'mysql:drizzle:planetscale': {
|
|
375
|
-
dbType: 'PlanetScaleDatabase<SchemaType>',
|
|
376
382
|
importLines: `import { eq } from 'drizzle-orm'
|
|
377
383
|
import { schema } from '../../../db/schema'`,
|
|
378
384
|
queries: mysqlDrizzleQueryOperations
|
|
379
385
|
},
|
|
380
386
|
'mysql:sql:local': {
|
|
381
|
-
dbType: 'SQL',
|
|
382
387
|
importLines: ``,
|
|
383
388
|
queries: mysqlSqlQueryOperations
|
|
384
389
|
},
|
|
385
390
|
'mysql:sql:planetscale': {
|
|
386
|
-
dbType: 'Client',
|
|
387
391
|
importLines: ``,
|
|
388
392
|
queries: mysqlPlanetScaleQueryOperations
|
|
389
393
|
},
|
|
390
394
|
'postgresql:drizzle:local': {
|
|
391
|
-
dbType: 'BunSQLDatabase<SchemaType>',
|
|
392
395
|
importLines: `import { eq } from 'drizzle-orm'
|
|
393
396
|
import { schema } from '../../../db/schema'`,
|
|
394
397
|
queries: drizzleQueryOperations
|
|
395
398
|
},
|
|
396
399
|
'postgresql:drizzle:neon': {
|
|
397
|
-
dbType: 'NeonDatabase<SchemaType>',
|
|
398
400
|
importLines: `import { eq } from 'drizzle-orm'
|
|
399
401
|
import { schema } from '../../../db/schema'`,
|
|
400
402
|
queries: drizzleQueryOperations
|
|
401
403
|
},
|
|
402
404
|
'postgresql:drizzle:planetscale': {
|
|
403
|
-
dbType: 'NodePgDatabase<SchemaType>',
|
|
404
405
|
importLines: `import { eq } from 'drizzle-orm'
|
|
405
406
|
import { schema } from '../../../db/schema'`,
|
|
406
407
|
queries: drizzleQueryOperations
|
|
407
408
|
},
|
|
408
409
|
'postgresql:sql:local': {
|
|
409
|
-
dbType: 'SQL',
|
|
410
410
|
importLines: ``,
|
|
411
411
|
queries: postgresSqlQueryOperations
|
|
412
412
|
},
|
|
413
413
|
'postgresql:sql:neon': {
|
|
414
|
-
dbType: 'Pool',
|
|
415
414
|
importLines: ``,
|
|
416
415
|
queries: postgresQueryOperations
|
|
417
416
|
},
|
|
418
417
|
'postgresql:sql:planetscale': {
|
|
419
|
-
dbType: 'Pool',
|
|
420
418
|
importLines: ``,
|
|
421
419
|
queries: postgresQueryOperations
|
|
422
420
|
},
|
|
423
421
|
'singlestore:drizzle:local': {
|
|
424
|
-
dbType: 'SingleStoreDriverDatabase<SchemaType>',
|
|
425
422
|
importLines: `import { eq } from 'drizzle-orm'
|
|
426
423
|
import { schema } from '../../../db/schema'`,
|
|
427
424
|
queries: mysqlDrizzleQueryOperations
|
|
428
425
|
},
|
|
429
426
|
'singlestore:sql:local': {
|
|
430
|
-
dbType: 'Pool',
|
|
431
427
|
importLines: `import { RowDataPacket } from 'mysql2/promise'
|
|
432
428
|
`,
|
|
433
429
|
queries: singlestoreSqlQueryOperations
|
|
434
430
|
},
|
|
435
431
|
'sqlite:drizzle:local': {
|
|
436
|
-
dbType: 'BunSQLiteDatabase<SchemaType>',
|
|
437
432
|
importLines: `import { eq } from 'drizzle-orm'
|
|
438
433
|
import { schema } from '../../../db/schema'`,
|
|
439
434
|
queries: drizzleQueryOperations
|
|
440
435
|
},
|
|
441
436
|
'sqlite:drizzle:turso': {
|
|
442
|
-
dbType: 'LibSQLDatabase<SchemaType>',
|
|
443
437
|
importLines: `import { eq } from 'drizzle-orm'
|
|
444
438
|
import { schema } from '../../../db/schema'`,
|
|
445
439
|
queries: drizzleQueryOperations
|
|
446
440
|
},
|
|
447
441
|
'sqlite:sql:local': {
|
|
448
|
-
dbType: 'Database',
|
|
449
442
|
importLines: ``,
|
|
450
443
|
queries: bunSqliteQueryOperations
|
|
451
444
|
},
|
|
452
445
|
'sqlite:sql:turso': {
|
|
453
|
-
dbType: 'Client',
|
|
454
446
|
importLines: ``,
|
|
455
447
|
queries: libsqlQueryOperations
|
|
456
448
|
}
|
|
@@ -459,7 +451,10 @@ export const getAuthTemplate = (key) => {
|
|
|
459
451
|
const configuration = driverConfigurations[key];
|
|
460
452
|
if (!configuration)
|
|
461
453
|
throw new Error(`Unsupported driver configuration: ${key}`);
|
|
462
|
-
return buildSqlAuthTemplate(
|
|
454
|
+
return buildSqlAuthTemplate({
|
|
455
|
+
...configuration,
|
|
456
|
+
rowsAreTyped: key.includes(':drizzle:')
|
|
457
|
+
});
|
|
463
458
|
};
|
|
464
459
|
export const getCountTemplate = (key) => {
|
|
465
460
|
const configuration = driverConfigurations[key];
|
|
@@ -26,12 +26,12 @@ export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHo
|
|
|
26
26
|
usesAuth
|
|
27
27
|
});
|
|
28
28
|
writeFileSync(join(handlerDirectory, handlerFileName), dbHandlers, 'utf-8');
|
|
29
|
-
// Raw-SQL (no-ORM)
|
|
30
|
-
// types/databaseTypes (so do the auth config and the example
|
|
31
|
-
// the drizzle-backed type module below is only written on the
|
|
32
|
-
// path. Generate a self-contained, driver-typed version here so the
|
|
33
|
-
// non-drizzle
|
|
34
|
-
if (
|
|
29
|
+
// Raw-SQL (no-ORM) handlers import `DatabaseType` (and `NewUser` on the auth
|
|
30
|
+
// path) from types/databaseTypes (so do the auth config and the example
|
|
31
|
+
// page), but the drizzle-backed type module below is only written on the
|
|
32
|
+
// drizzle path. Generate a self-contained, driver-typed version here so the
|
|
33
|
+
// non-drizzle scaffold actually type-checks and builds.
|
|
34
|
+
if (orm !== 'drizzle') {
|
|
35
35
|
mkdirSync(typesDirectory, { recursive: true });
|
|
36
36
|
const sqlTypes = generateDatabaseTypes({
|
|
37
37
|
authOption,
|
|
@@ -12,6 +12,15 @@ const defaultProviderConfigurations = {
|
|
|
12
12
|
searchParams: [['access_type', 'offline']]
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
+
/* Mirrors the `User` shape the raw-SQL path writes into types/databaseTypes, so
|
|
16
|
+
an auth scaffold without a database resolves the same type from the same
|
|
17
|
+
module the example page already imports. */
|
|
18
|
+
export const generateSessionUserType = () => `export type User = {
|
|
19
|
+
auth_sub: string;
|
|
20
|
+
created_at: Date;
|
|
21
|
+
metadata: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
`;
|
|
15
24
|
export const generateAbsoluteAuthConfig = (absProviders, hasDatabase) => {
|
|
16
25
|
const providerConfigs = (absProviders ?? [])
|
|
17
26
|
.map((provider) => {
|
|
@@ -45,38 +54,46 @@ ${credentialsLines}
|
|
|
45
54
|
if (!hasDatabase) {
|
|
46
55
|
return `import { getEnv } from '@absolutejs/absolute';
|
|
47
56
|
import {
|
|
48
|
-
|
|
49
|
-
|
|
57
|
+
createInMemoryAuthSessionStore,
|
|
58
|
+
defineAuthConfig
|
|
50
59
|
} from '@absolutejs/auth';
|
|
60
|
+
import { User } from '../../types/databaseTypes';
|
|
51
61
|
|
|
52
|
-
export const absoluteAuthConfig = ()
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
export const absoluteAuthConfig = () =>
|
|
63
|
+
defineAuthConfig<User>({
|
|
64
|
+
authSessionStore: createInMemoryAuthSessionStore(),
|
|
65
|
+
/* Without a database there is nowhere to persist users, so no user is
|
|
66
|
+
ever registered and this resolver has nothing to look a subject up in.
|
|
67
|
+
Scaffold with a database to persist users and resolve them here. */
|
|
68
|
+
getUser: () => null,
|
|
69
|
+
providersConfiguration: {
|
|
55
70
|
${providerConfigs}
|
|
56
|
-
|
|
57
|
-
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
58
73
|
`;
|
|
59
74
|
}
|
|
60
75
|
return `import { getEnv } from '@absolutejs/absolute';
|
|
61
76
|
import {
|
|
62
|
-
AbsoluteAuthProps,
|
|
63
77
|
createInMemoryAuthSessionStore,
|
|
78
|
+
defineAuthConfig,
|
|
64
79
|
extractPropFromIdentity,
|
|
65
|
-
instantiateUserSession
|
|
66
|
-
providers
|
|
80
|
+
instantiateUserSession
|
|
67
81
|
} from '@absolutejs/auth';
|
|
68
82
|
import { DatabaseType, User } from '../../types/databaseTypes';
|
|
69
83
|
import { createUser, getUser } from '../handlers/userHandlers';
|
|
70
84
|
|
|
71
|
-
export const absoluteAuthConfig = (
|
|
72
|
-
|
|
73
|
-
): AbsoluteAuthProps<User> => ({
|
|
85
|
+
export const absoluteAuthConfig = (db: DatabaseType) =>
|
|
86
|
+
defineAuthConfig<User>({
|
|
74
87
|
authSessionStore: createInMemoryAuthSessionStore(),
|
|
88
|
+
getUser: async (sub) => (await getUser(db, sub)) ?? null,
|
|
75
89
|
providersConfiguration: {
|
|
76
90
|
${providerConfigs}
|
|
77
91
|
},
|
|
92
|
+
/* \`providerConfiguration\` is handed to the callback rather than looked up by
|
|
93
|
+
name, so identity extraction also works for custom providers. */
|
|
78
94
|
onCallbackSuccess: async ({
|
|
79
95
|
authProvider,
|
|
96
|
+
providerConfiguration,
|
|
80
97
|
providerInstance,
|
|
81
98
|
tokenResponse,
|
|
82
99
|
unregisteredSession,
|
|
@@ -86,6 +103,7 @@ ${providerConfigs}
|
|
|
86
103
|
}) =>
|
|
87
104
|
instantiateUserSession({
|
|
88
105
|
authProvider,
|
|
106
|
+
providerConfiguration,
|
|
89
107
|
providerInstance,
|
|
90
108
|
session,
|
|
91
109
|
tokenResponse,
|
|
@@ -93,7 +111,6 @@ ${providerConfigs}
|
|
|
93
111
|
user_session_id,
|
|
94
112
|
getUser: async (userIdentity) => {
|
|
95
113
|
const provider = authProvider.toUpperCase();
|
|
96
|
-
const providerConfiguration = providers[authProvider];
|
|
97
114
|
|
|
98
115
|
const subject = extractPropFromIdentity(
|
|
99
116
|
userIdentity,
|
|
@@ -116,7 +133,6 @@ ${providerConfigs}
|
|
|
116
133
|
},
|
|
117
134
|
onNewUser: async (userIdentity) => {
|
|
118
135
|
const provider = authProvider.toUpperCase();
|
|
119
|
-
const providerConfiguration = providers[authProvider];
|
|
120
136
|
|
|
121
137
|
const subject = extractPropFromIdentity(
|
|
122
138
|
userIdentity,
|
|
@@ -10,8 +10,9 @@ export const generateRoutesBlock = ({ databaseEngine, frontendDirectories, authO
|
|
|
10
10
|
return status(error.code, error.message);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
const providerConfiguration =
|
|
14
|
-
|
|
13
|
+
const providerConfiguration = auth_client.value
|
|
14
|
+
? providers[auth_client.value as ProviderOption]
|
|
15
|
+
: undefined;
|
|
15
16
|
|
|
16
17
|
return ${handlerCall};
|
|
17
18
|
}`
|
|
@@ -36,11 +36,8 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
|
|
|
36
36
|
.filter((pluginImport) => pluginImport.isPlugin &&
|
|
37
37
|
pluginImport.packageName !== 'networking')
|
|
38
38
|
.map((pluginImport) => {
|
|
39
|
-
if (pluginImport.packageName === '
|
|
40
|
-
|
|
41
|
-
return hasDatabase
|
|
42
|
-
? `.use(absoluteAuth(absoluteAuthConfig(db)))`
|
|
43
|
-
: `.use(absoluteAuth(absoluteAuthConfig()))`;
|
|
39
|
+
if (pluginImport.packageName === 'auth') {
|
|
40
|
+
return `.use(authPlugin)`;
|
|
44
41
|
}
|
|
45
42
|
if (pluginImport.config === undefined) {
|
|
46
43
|
return `.use(${pluginImport.packageName})`;
|
|
@@ -63,10 +60,16 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
|
|
|
63
60
|
databaseEngine,
|
|
64
61
|
frontendDirectories
|
|
65
62
|
});
|
|
63
|
+
const hasDatabase = databaseEngine !== undefined && databaseEngine !== 'none';
|
|
64
|
+
/* `auth()` is async, so it is hoisted out of the `.use()` chain rather than
|
|
65
|
+
inlined — Elysia accepts the promise as a plugin. */
|
|
66
|
+
const authBlock = authOption === 'abs'
|
|
67
|
+
? `const authPlugin = auth(absoluteAuthConfig(${hasDatabase ? 'db' : ''}))\n`
|
|
68
|
+
: '';
|
|
66
69
|
const content = `${importsBlock}
|
|
67
70
|
|
|
68
71
|
${manifestBlock}
|
|
69
|
-
${dbBlock ? `${dbBlock}\n` : ''}
|
|
72
|
+
${dbBlock ? `${dbBlock}\n` : ''}${authBlock}
|
|
70
73
|
const server = new Elysia()
|
|
71
74
|
.use(absolutejs)
|
|
72
75
|
${useBlock}${authOption === 'abs' ? `\n${guardBlock}` : ''}
|
|
@@ -2,6 +2,7 @@ import { CreateConfiguration } from '../../types';
|
|
|
2
2
|
type ScaffoldBackendProps = Pick<CreateConfiguration, 'assetsDirectory' | 'absProviders' | 'authOption' | 'buildDirectory' | 'databaseEngine' | 'databaseHost' | 'frontendDirectories' | 'orm' | 'plugins' | 'tailwind'> & {
|
|
3
3
|
backendDirectory: string;
|
|
4
4
|
publicDirectory: string;
|
|
5
|
+
typesDirectory: string;
|
|
5
6
|
};
|
|
6
|
-
export declare const scaffoldBackend: ({ assetsDirectory, authOption, absProviders, backendDirectory, buildDirectory, databaseEngine, databaseHost, frontendDirectories, orm, plugins, publicDirectory, tailwind }: ScaffoldBackendProps) => void;
|
|
7
|
+
export declare const scaffoldBackend: ({ assetsDirectory, authOption, absProviders, backendDirectory, buildDirectory, databaseEngine, databaseHost, frontendDirectories, orm, plugins, publicDirectory, tailwind, typesDirectory }: ScaffoldBackendProps) => void;
|
|
7
8
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
|
-
import { generateAbsoluteAuthConfig } from './generateAbsoluteAuthConfig';
|
|
3
|
+
import { generateAbsoluteAuthConfig, generateSessionUserType } from './generateAbsoluteAuthConfig';
|
|
4
4
|
import { generateServerFile } from './generateServer';
|
|
5
|
-
export const scaffoldBackend = ({ assetsDirectory, authOption, absProviders, backendDirectory, buildDirectory, databaseEngine, databaseHost, frontendDirectories, orm, plugins, publicDirectory, tailwind }) => {
|
|
5
|
+
export const scaffoldBackend = ({ assetsDirectory, authOption, absProviders, backendDirectory, buildDirectory, databaseEngine, databaseHost, frontendDirectories, orm, plugins, publicDirectory, tailwind, typesDirectory }) => {
|
|
6
6
|
generateServerFile({
|
|
7
7
|
assetsDirectory,
|
|
8
8
|
authOption,
|
|
@@ -21,5 +21,13 @@ export const scaffoldBackend = ({ assetsDirectory, authOption, absProviders, bac
|
|
|
21
21
|
const hasDatabase = databaseEngine !== undefined && databaseEngine !== 'none';
|
|
22
22
|
const absoluteAuthConfig = generateAbsoluteAuthConfig(absProviders, hasDatabase);
|
|
23
23
|
writeFileSync(join(backendDirectory, 'utils', 'absoluteAuthConfig.ts'), absoluteAuthConfig, 'utf-8');
|
|
24
|
+
/* The auth config and the example page both import `User` from
|
|
25
|
+
types/databaseTypes, which scaffoldDatabase only writes when there is
|
|
26
|
+
a database. Without one, emit the session user shape on its own so the
|
|
27
|
+
auth scaffold still type-checks. */
|
|
28
|
+
if (!hasDatabase) {
|
|
29
|
+
mkdirSync(typesDirectory, { recursive: true });
|
|
30
|
+
writeFileSync(join(typesDirectory, 'databaseTypes.ts'), generateSessionUserType(), 'utf-8');
|
|
31
|
+
}
|
|
24
32
|
}
|
|
25
33
|
};
|
|
@@ -40,6 +40,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
40
40
|
absProviders,
|
|
41
41
|
assetsDirectory,
|
|
42
42
|
authOption,
|
|
43
|
+
directory,
|
|
43
44
|
editBasePath,
|
|
44
45
|
frontends,
|
|
45
46
|
includeExamples,
|
|
@@ -56,6 +57,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
56
57
|
absProviders,
|
|
57
58
|
assetsDirectory,
|
|
58
59
|
authOption,
|
|
60
|
+
directory,
|
|
59
61
|
editBasePath,
|
|
60
62
|
frontends,
|
|
61
63
|
includeExamples,
|
|
@@ -72,6 +74,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
72
74
|
absProviders,
|
|
73
75
|
assetsDirectory,
|
|
74
76
|
authOption,
|
|
77
|
+
directory,
|
|
75
78
|
editBasePath,
|
|
76
79
|
frontends,
|
|
77
80
|
includeExamples,
|
|
@@ -88,6 +91,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
88
91
|
absProviders,
|
|
89
92
|
assetsDirectory,
|
|
90
93
|
authOption,
|
|
94
|
+
directory,
|
|
91
95
|
editBasePath,
|
|
92
96
|
frontends,
|
|
93
97
|
includeExamples,
|
|
@@ -104,6 +108,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
104
108
|
absProviders,
|
|
105
109
|
assetsDirectory,
|
|
106
110
|
authOption,
|
|
111
|
+
directory,
|
|
107
112
|
editBasePath,
|
|
108
113
|
frontends,
|
|
109
114
|
includeExamples,
|
|
@@ -121,6 +126,7 @@ export const scaffoldFrontends = ({ frontendDirectory, assetsDirectory, absProvi
|
|
|
121
126
|
absProviders,
|
|
122
127
|
assetsDirectory,
|
|
123
128
|
authOption,
|
|
129
|
+
directory,
|
|
124
130
|
editBasePath,
|
|
125
131
|
frontends,
|
|
126
132
|
includeExamples,
|
|
@@ -2,5 +2,5 @@ import { ProviderOption } from '@absolutejs/auth';
|
|
|
2
2
|
import { AuthOption, Frontend } from '../../types';
|
|
3
3
|
export declare const generateAppComponent: (frontends: Frontend[], editBasePath: string) => string;
|
|
4
4
|
export declare const generateDropdownComponent: (frontends: Frontend[]) => string;
|
|
5
|
-
export declare const generateReactExamplePage: (authOption: AuthOption, includeExamples: boolean) => string;
|
|
5
|
+
export declare const generateReactExamplePage: (authOption: AuthOption, includeExamples: boolean, reactDirectory: string) => string;
|
|
6
6
|
export declare const generateSignInComponent: (absProviders: ProviderOption[] | undefined) => string;
|
|
@@ -73,10 +73,14 @@ export const generateDropdownComponent = (frontends) => {
|
|
|
73
73
|
);
|
|
74
74
|
`;
|
|
75
75
|
};
|
|
76
|
-
|
|
76
|
+
/* Pages live at `src/frontend/<reactDirectory>/pages`, but `reactDirectory` is
|
|
77
|
+
empty when React is the only frontend, which moves the page one level up. */
|
|
78
|
+
const buildDatabaseTypesPath = (reactDirectory) => `${reactDirectory ? '../../../' : '../../'}types/databaseTypes`;
|
|
79
|
+
export const generateReactExamplePage = (authOption, includeExamples, reactDirectory) => {
|
|
80
|
+
const databaseTypesPath = buildDatabaseTypesPath(reactDirectory);
|
|
77
81
|
if (!includeExamples) {
|
|
78
82
|
const authImports = authOption === 'abs'
|
|
79
|
-
? `import type { User } from '
|
|
83
|
+
? `import type { User } from '${databaseTypesPath}';\nimport type { ProviderConfiguration } from '@absolutejs/auth';\n`
|
|
80
84
|
: '';
|
|
81
85
|
const authProps = authOption === 'abs'
|
|
82
86
|
? '\n\tuser: User | null;\n\tproviderConfiguration: ProviderConfiguration | undefined;'
|
|
@@ -146,7 +150,7 @@ export const ReactExample = ({ cssPath }: ReactExampleProps) => (
|
|
|
146
150
|
: `<Dropdown />`;
|
|
147
151
|
const closing = authOption === 'abs' ? `};` : `);`;
|
|
148
152
|
return `
|
|
149
|
-
${authOption === 'abs' ? `import type { User } from '
|
|
153
|
+
${authOption === 'abs' ? `import type { User } from '${databaseTypesPath}';\nimport { extractPropFromIdentity } from '@absolutejs/auth';\nimport type { ProviderConfiguration } from '@absolutejs/auth';` : ''}
|
|
150
154
|
import { App } from '../components/App';
|
|
151
155
|
import { Dropdown } from '../components/Dropdown';
|
|
152
156
|
import { Head } from '../components/Head';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ScaffoldFrontendProps } from '../../types';
|
|
2
|
-
export declare const scaffoldReact: ({ authOption, editBasePath, includeExamples, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
|
|
2
|
+
export declare const scaffoldReact: ({ authOption, directory, editBasePath, includeExamples, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }: ScaffoldFrontendProps) => void;
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import { copyFileSync, cpSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
2
|
+
import { basename, join } from 'path';
|
|
3
3
|
import { generateMarkupCSS } from '../project/generateMarkupCSS';
|
|
4
4
|
import { generateAppComponent, generateDropdownComponent, generateReactExamplePage, generateSignInComponent } from './generateReactComponents';
|
|
5
|
-
export const scaffoldReact = ({ authOption, editBasePath, includeExamples, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }) => {
|
|
5
|
+
export const scaffoldReact = ({ authOption, directory, editBasePath, includeExamples, targetDirectory, templatesDirectory, frontends, projectAssetsDirectory, absProviders, stylesIndexesDirectory }) => {
|
|
6
6
|
if (!includeExamples) {
|
|
7
7
|
mkdirSync(join(targetDirectory, 'components'), { recursive: true });
|
|
8
8
|
copyFileSync(join(templatesDirectory, 'react', 'components', 'Head.tsx'), join(targetDirectory, 'components', 'Head.tsx'));
|
|
9
9
|
mkdirSync(join(targetDirectory, 'pages'), { recursive: true });
|
|
10
|
-
writeFileSync(join(targetDirectory, 'pages', 'ReactExample.tsx'), generateReactExamplePage(authOption, false), 'utf-8');
|
|
10
|
+
writeFileSync(join(targetDirectory, 'pages', 'ReactExample.tsx'), generateReactExamplePage(authOption, false, directory), 'utf-8');
|
|
11
11
|
writeFileSync(join(stylesIndexesDirectory, 'react-example.css'), `@import url('../reset.css');`, 'utf-8');
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
14
|
mkdirSync(join(projectAssetsDirectory, 'svg'), { recursive: true });
|
|
15
15
|
copyFileSync(join(templatesDirectory, 'assets', 'svg', 'react.svg'), join(projectAssetsDirectory, 'svg', 'react.svg'));
|
|
16
16
|
copyFileSync(join(templatesDirectory, 'assets', 'svg', 'google-logo.svg'), join(projectAssetsDirectory, 'svg', 'google-logo.svg'));
|
|
17
|
+
/* `OAuthLink` is only rendered by the generated `SignIn` component, and it
|
|
18
|
+
types its provider against `citra`, which only ships as a transitive
|
|
19
|
+
dependency of `@absolutejs/auth`. Without Absolute Auth the import cannot
|
|
20
|
+
resolve, so the component is left out entirely. */
|
|
17
21
|
cpSync(join(templatesDirectory, 'react'), targetDirectory, {
|
|
22
|
+
filter: (source) => authOption === 'abs' || basename(source) !== 'OAuthLink.tsx',
|
|
18
23
|
recursive: true
|
|
19
24
|
});
|
|
20
25
|
const appComponent = generateAppComponent(frontends, editBasePath);
|
|
@@ -25,7 +30,7 @@ export const scaffoldReact = ({ authOption, editBasePath, includeExamples, targe
|
|
|
25
30
|
const signInComponent = generateSignInComponent(absProviders);
|
|
26
31
|
writeFileSync(join(targetDirectory, 'components', 'SignIn.tsx'), signInComponent, 'utf-8');
|
|
27
32
|
}
|
|
28
|
-
const pageComponent = generateReactExamplePage(authOption, true);
|
|
33
|
+
const pageComponent = generateReactExamplePage(authOption, true, directory);
|
|
29
34
|
mkdirSync(join(targetDirectory, 'pages'), { recursive: true });
|
|
30
35
|
writeFileSync(join(targetDirectory, 'pages', 'ReactExample.tsx'), pageComponent, 'utf-8');
|
|
31
36
|
const cssOutputFile = join(stylesIndexesDirectory, 'react-example.css');
|
package/dist/scaffold.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export type ScaffoldFrontendProps = {
|
|
|
4
4
|
absProviders: ProviderOption[] | undefined;
|
|
5
5
|
assetsDirectory: string;
|
|
6
6
|
authOption: AuthOption;
|
|
7
|
+
/** Frontend's directory under `src/frontend`; empty when it is the only
|
|
8
|
+
* frontend and no directory was configured for it. */
|
|
9
|
+
directory: string;
|
|
7
10
|
editBasePath: string;
|
|
8
11
|
includeExamples: boolean;
|
|
9
12
|
targetDirectory: string;
|
package/dist/versions.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
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.19.0-beta.
|
|
7
|
+
readonly '@absolutejs/absolute': "0.19.0-beta.1106";
|
|
8
8
|
readonly '@absolutejs/a2a': "0.1.0";
|
|
9
9
|
readonly '@absolutejs/agency': "0.4.0";
|
|
10
10
|
readonly '@absolutejs/agent-conformance': "0.3.0";
|
|
@@ -42,11 +42,13 @@ export declare const versions: {
|
|
|
42
42
|
readonly '@planetscale/database': "1.19.0";
|
|
43
43
|
readonly '@stylistic/eslint-plugin': "5.9.0";
|
|
44
44
|
readonly '@tailwindcss/cli': "4.2.0";
|
|
45
|
+
readonly '@types/bun': "1.3.14";
|
|
45
46
|
readonly '@types/mssql': "9.1.9";
|
|
46
47
|
readonly '@types/pg': "8.16.0";
|
|
47
48
|
readonly '@types/react': "19.2.14";
|
|
48
49
|
readonly '@typescript-eslint/parser': "8.56.0";
|
|
49
50
|
readonly autoprefixer: "10.4.24";
|
|
51
|
+
readonly 'drizzle-kit': "0.31.10";
|
|
50
52
|
readonly 'drizzle-orm': "0.45.1";
|
|
51
53
|
readonly elysia: "1.4.28";
|
|
52
54
|
readonly 'elysia-rate-limit': "4.5.0";
|
package/dist/versions.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export const versions = {
|
|
7
7
|
/* ── Core ─────────────────────────────────────────────── */
|
|
8
|
-
'@absolutejs/absolute': '0.19.0-beta.
|
|
8
|
+
'@absolutejs/absolute': '0.19.0-beta.1106',
|
|
9
9
|
'@absolutejs/a2a': '0.1.0',
|
|
10
10
|
'@absolutejs/agency': '0.4.0',
|
|
11
11
|
'@absolutejs/agent-conformance': '0.3.0',
|
|
@@ -48,6 +48,8 @@ export const versions = {
|
|
|
48
48
|
'@stylistic/eslint-plugin': '5.9.0',
|
|
49
49
|
/* ── Tailwind CSS ─────────────────────────────────────── */
|
|
50
50
|
'@tailwindcss/cli': '4.2.0',
|
|
51
|
+
/* ── Bun ──────────────────────────────────────────────── */
|
|
52
|
+
'@types/bun': '1.3.14',
|
|
51
53
|
/* ── Database Drivers ─────────────────────────────────── */
|
|
52
54
|
'@types/mssql': '9.1.9',
|
|
53
55
|
'@types/pg': '8.16.0',
|
|
@@ -56,6 +58,7 @@ export const versions = {
|
|
|
56
58
|
'@typescript-eslint/parser': '8.56.0',
|
|
57
59
|
autoprefixer: '10.4.24',
|
|
58
60
|
/* ── ORM ──────────────────────────────────────────────── */
|
|
61
|
+
'drizzle-kit': '0.31.10',
|
|
59
62
|
'drizzle-orm': '0.45.1',
|
|
60
63
|
elysia: '1.4.28',
|
|
61
64
|
'elysia-rate-limit': '4.5.0',
|
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.19.0-beta.
|
|
13
|
+
"@absolutejs/absolute": "0.19.0-beta.1106",
|
|
14
14
|
"@eslint/compat": "2.0.2",
|
|
15
15
|
"@stylistic/eslint-plugin": "5.9.0",
|
|
16
16
|
"@types/bun": "1.3.8",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"typecheck": "bun run tsc --noEmit"
|
|
55
55
|
},
|
|
56
56
|
"type": "module",
|
|
57
|
-
"version": "0.15.
|
|
57
|
+
"version": "0.15.4"
|
|
58
58
|
}
|