@tobi2409/fullsty 0.5.5 → 0.5.6

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 (26) hide show
  1. package/README.md +7 -7
  2. package/package.json +1 -1
  3. package/scripts/create-project.js +21 -21
  4. package/scripts/extension-wrappers/@tobi2409/authentication-core-db/current-user.ts +37 -17
  5. package/scripts/extension-wrappers/@tobi2409/authentication-core-db/login.ts +45 -22
  6. package/scripts/extension-wrappers/@tobi2409/authentication-core-db/register.ts +65 -44
  7. package/scripts/extension-wrappers/@tobi2409/authentication-core-db/shared.ts +11 -11
  8. package/scripts/extension-wrappers/@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts +1 -1
  9. package/scripts/extension-wrappers/db-connection/db-connection-wrapper.ts +17 -14
  10. package/scripts/extension-wrappers/db-connection/extension.json +1 -1
  11. package/scripts/extension-wrappers/kysely/extension.json +1 -1
  12. package/scripts/extension-wrappers/kysely/kysely-wrapper.ts +22 -20
  13. package/scripts/extension-wrappers/pg/extension.json +1 -1
  14. package/scripts/extension-wrappers/pg/pg-wrapper.ts +37 -33
  15. package/scripts/extension-wrappers/sql-template-tag/extension.json +1 -1
  16. package/scripts/extension-wrappers/sql-template-tag/sql-template-tag-wrapper.ts +1 -1
  17. package/scripts/fullsty-server-pkg.js +25 -25
  18. package/scripts/project-frame/package.json +1 -1
  19. package/scripts/project-frame/proc2rest.config.json +10 -1
  20. package/scripts/project-frame/server-package.json +5 -4
  21. package/scripts/project-frame/src/client/index.html +33 -29
  22. package/scripts/project-frame/src/client/index.js +8 -5
  23. package/scripts/project-frame/src/server/server.ts +1 -1
  24. package/scripts/shared/file-copy.js +11 -11
  25. package/scripts/shared/project-json-utils.js +8 -8
  26. package/scripts/shared/server-package-utils.js +41 -39
package/README.md CHANGED
@@ -73,11 +73,11 @@ Alternatively, you can also use `npx fullsty-server-pkg`.
73
73
  What it does:
74
74
 
75
75
  - `add <package>`
76
- - adds the package to the project's server package file, which is initially created from [project-frame/server-package.json](project-frame/server-package.json)
77
- - copies a matching wrapper from [scripts/extension-wrappers](scripts/extension-wrappers) into [projects/demo1/src/server](projects/demo1/src/server)
76
+ - adds the package to the project's server package file, which is initially created from [project-frame/server-package.json](project-frame/server-package.json)
77
+ - copies a matching wrapper from [scripts/extension-wrappers](scripts/extension-wrappers) into [projects/demo1/src/server](projects/demo1/src/server)
78
78
  - `remove <package>`
79
- - removes the package from the project's server package file
80
- - removes the matching wrapper from [projects/demo1/src/server](projects/demo1/src/server)
79
+ - removes the package from the project's server package file
80
+ - removes the matching wrapper from [projects/demo1/src/server](projects/demo1/src/server)
81
81
 
82
82
  The script does not manage the project-level [package.json](project-frame/package.json).
83
83
 
@@ -98,10 +98,10 @@ npm run start
98
98
  ## package.json responsibilities
99
99
 
100
100
  - Project-level package file: [project-frame/package.json](project-frame/package.json)
101
- - Used for generation tasks (`generate-server`, `generate-client`, `generate`).
101
+ - Used for generation tasks (`generate-server`, `generate-client`, `generate`).
102
102
  - Generated server package file: [project-frame/server-package.json](project-frame/server-package.json)
103
- - Becomes `generated/server/package.json`.
104
- - Used to run the generated server (`npm run start`).
103
+ - Becomes `generated/server/package.json`.
104
+ - Used to run the generated server (`npm run start`).
105
105
 
106
106
  ## 6) Install client dependencies
107
107
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tobi2409/fullsty",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Fullsty is a modular fullstack framework starter built from three core parts: template-engine, layout and proc2rest. It provides a project frame for building fullstack applications with a clear separation of client and server code.",
5
5
  "license": "ISC",
6
6
  "author": "Tobias Hollstein",
@@ -1,46 +1,46 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import fs from "fs";
4
- import path from "path";
5
- import { copyDirectory } from "./shared/file-copy.js";
6
- import { readJson, writeJson } from "./shared/project-json-utils.js";
3
+ import fs from 'fs'
4
+ import path from 'path'
5
+ import { copyDirectory } from './shared/file-copy.js'
6
+ import { readJson, writeJson } from './shared/project-json-utils.js'
7
7
 
8
8
  // Update package.json name in the copied project frame.
9
9
  function updatePackageName(targetProjectDir, projectName) {
10
- const packageJson = readJson(targetProjectDir, "package.json");
11
- packageJson.name = projectName;
12
- writeJson(targetProjectDir, "package.json", packageJson);
10
+ const packageJson = readJson(targetProjectDir, 'package.json')
11
+ packageJson.name = projectName
12
+ writeJson(targetProjectDir, 'package.json', packageJson)
13
13
  }
14
14
 
15
15
  function main() {
16
- const projectName = process.argv[2];
16
+ const projectName = process.argv[2]
17
17
 
18
18
  if (!projectName) {
19
- console.error("Usage: node create-project.js <project-name>");
20
- process.exit(1);
19
+ console.error('Usage: node create-project.js <project-name>')
20
+ process.exit(1)
21
21
  }
22
22
 
23
- const scriptDir = path.dirname(new URL(import.meta.url).pathname);
24
- const sourceFrameDir = path.join(scriptDir, "project-frame");
25
- const targetProjectDir = path.resolve(process.cwd(), projectName);
23
+ const scriptDir = path.dirname(new URL(import.meta.url).pathname)
24
+ const sourceFrameDir = path.join(scriptDir, 'project-frame')
25
+ const targetProjectDir = path.resolve(process.cwd(), projectName)
26
26
 
27
27
  if (!fs.existsSync(sourceFrameDir)) {
28
- throw new Error(`project-frame not found: ${sourceFrameDir}`);
28
+ throw new Error(`project-frame not found: ${sourceFrameDir}`)
29
29
  }
30
30
 
31
31
  if (fs.existsSync(targetProjectDir)) {
32
- throw new Error(`Target directory already exists: ${targetProjectDir}`);
32
+ throw new Error(`Target directory already exists: ${targetProjectDir}`)
33
33
  }
34
34
 
35
- copyDirectory(sourceFrameDir, targetProjectDir);
36
- updatePackageName(targetProjectDir, projectName);
35
+ copyDirectory(sourceFrameDir, targetProjectDir)
36
+ updatePackageName(targetProjectDir, projectName)
37
37
 
38
- console.log(`\n✅ Project created: ${targetProjectDir}`);
38
+ console.log(`\n✅ Project created: ${targetProjectDir}`)
39
39
  }
40
40
 
41
41
  try {
42
- main();
42
+ main()
43
43
  } catch (error) {
44
- console.error(`\n❌ ${error.message}`);
45
- process.exit(1);
44
+ console.error(`\n❌ ${error.message}`)
45
+ process.exit(1)
46
46
  }
@@ -1,47 +1,67 @@
1
- import { DbConnection } from "../../db-connection/db-connection-wrapper.ts";
1
+ import { DbConnection } from '../../db-connection/db-connection-wrapper.ts'
2
2
  // @ts-ignore kysely is supplied by the server package in generated projects.
3
- import { KyselyWrapper } from "../../kysely/kysely-wrapper.ts";
4
- import { authenticationCoreLib } from "../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts";
5
- import { DEFAULT_TABLE_NAME, DEFAULT_USER_COLUMN, UserColumn } from "./shared.ts";
3
+ import { KyselyWrapper } from '../../kysely/kysely-wrapper.ts'
4
+ import { authenticationCoreLib } from '../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts'
5
+ import {
6
+ DEFAULT_TABLE_NAME,
7
+ DEFAULT_USER_COLUMN,
8
+ UserColumn
9
+ } from './shared.ts'
6
10
 
7
11
  export namespace AuthenticationCoreKyselyCurrentUser {
8
12
  export async function getCurrentUser(
9
13
  token: string,
10
- jwtKey: Parameters<typeof authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser>[1],
14
+ jwtKey: Parameters<
15
+ typeof authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser
16
+ >[1],
11
17
  dbConnection: DbConnection,
12
18
  tableName: string = DEFAULT_TABLE_NAME,
13
19
  columns: UserColumn = DEFAULT_USER_COLUMN,
14
- verifyOptions: Parameters<typeof authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser>[3] = {}
20
+ verifyOptions: Parameters<
21
+ typeof authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser
22
+ >[3] = {}
15
23
  ): Promise<string> {
16
24
  try {
17
- const db = KyselyWrapper.buildQueryCompiler(dbConnection.getDriverName());
25
+ const db = KyselyWrapper.buildQueryCompiler(
26
+ dbConnection.getDriverName()
27
+ )
18
28
 
19
29
  const isActiveCallback = async (uuid: string): Promise<boolean> => {
20
30
  const compiledQuery = db
21
31
  .selectFrom(tableName)
22
32
  .select([
23
- KyselyWrapper.sql.ref(columns.isActive).as("isActive")
33
+ KyselyWrapper.sql.ref(columns.isActive).as('isActive')
24
34
  ])
25
- .where(KyselyWrapper.sql.ref(columns.uuid), "=", uuid)
35
+ .where(KyselyWrapper.sql.ref(columns.uuid), '=', uuid)
26
36
  .limit(1)
27
- .compile();
37
+ .compile()
28
38
 
29
39
  // 'any' is used instead of 'unknown' because calling .query() on an unknown type requires
30
40
  // either a type assertion or a separate interface. DbConnection is driver-agnostic, so
31
41
  // the concrete pool type (e.g. pg.Pool) is not available here without adding a dependency.
32
- const connection = await dbConnection.getConnection() as any;
33
- const result = await connection.query(compiledQuery.sql, compiledQuery.parameters);
42
+ const connection = (await dbConnection.getConnection()) as any
43
+ const result = await connection.query(
44
+ compiledQuery.sql,
45
+ compiledQuery.parameters
46
+ )
34
47
 
35
48
  if (!result.rows?.[0]) {
36
- return false;
49
+ return false
37
50
  }
38
51
 
39
- return Boolean((result.rows[0] as Record<string, unknown>).isActive);
40
- };
52
+ return Boolean(
53
+ (result.rows[0] as Record<string, unknown>).isActive
54
+ )
55
+ }
41
56
 
42
- return authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser(token, jwtKey, isActiveCallback, verifyOptions);
57
+ return authenticationCoreLib.AuthenticationCoreCurrentUser.getCurrentUser(
58
+ token,
59
+ jwtKey,
60
+ isActiveCallback,
61
+ verifyOptions
62
+ )
43
63
  } catch (error) {
44
- throw error;
64
+ throw error
45
65
  }
46
66
  }
47
67
  }
@@ -1,13 +1,19 @@
1
- import { DbConnection } from "../../db-connection/db-connection-wrapper.ts";
1
+ import { DbConnection } from '../../db-connection/db-connection-wrapper.ts'
2
2
  // @ts-ignore kysely is supplied by the server package in generated projects.
3
- import { KyselyWrapper } from "../../kysely/kysely-wrapper.ts";
4
- import { authenticationCoreLib } from "../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts";
5
- import { DEFAULT_TABLE_NAME, DEFAULT_USER_COLUMN, UserColumn } from "./shared.ts";
3
+ import { KyselyWrapper } from '../../kysely/kysely-wrapper.ts'
4
+ import { authenticationCoreLib } from '../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts'
5
+ import {
6
+ DEFAULT_TABLE_NAME,
7
+ DEFAULT_USER_COLUMN,
8
+ UserColumn
9
+ } from './shared.ts'
6
10
 
7
11
  export namespace AuthenticationCoreKyselyLogin {
8
- function mapFetchedUser(row: Record<string, unknown> | undefined): authenticationCoreLib.FetchedUser | undefined {
12
+ function mapFetchedUser(
13
+ row: Record<string, unknown> | undefined
14
+ ): authenticationCoreLib.FetchedUser | undefined {
9
15
  if (!row) {
10
- return undefined;
16
+ return undefined
11
17
  }
12
18
 
13
19
  return {
@@ -15,43 +21,60 @@ export namespace AuthenticationCoreKyselyLogin {
15
21
  mail: String(row.mail),
16
22
  password: String(row.password),
17
23
  isActive: Boolean(row.isActive)
18
- };
24
+ }
19
25
  }
20
26
 
21
27
  export async function login(
22
28
  typedMail: string,
23
29
  typedPassword: string,
24
- jwtKey: Parameters<typeof authenticationCoreLib.AuthenticationCoreLogin.login>[3],
30
+ jwtKey: Parameters<
31
+ typeof authenticationCoreLib.AuthenticationCoreLogin.login
32
+ >[3],
25
33
  dbConnection: DbConnection,
26
34
  tableName: string = DEFAULT_TABLE_NAME,
27
35
  columns: UserColumn = DEFAULT_USER_COLUMN,
28
- jwtOptions: Parameters<typeof authenticationCoreLib.AuthenticationCoreLogin.login>[4] = {}
36
+ jwtOptions: Parameters<
37
+ typeof authenticationCoreLib.AuthenticationCoreLogin.login
38
+ >[4] = {}
29
39
  ): Promise<string> {
30
40
  try {
31
- const db = KyselyWrapper.buildQueryCompiler(dbConnection.getDriverName());
41
+ const db = KyselyWrapper.buildQueryCompiler(
42
+ dbConnection.getDriverName()
43
+ )
32
44
 
33
45
  const compiledQuery = db
34
46
  .selectFrom(tableName)
35
47
  .select([
36
- KyselyWrapper.sql.ref(columns.uuid).as("uuid"),
37
- KyselyWrapper.sql.ref(columns.mail).as("mail"),
38
- KyselyWrapper.sql.ref(columns.password).as("password"),
39
- KyselyWrapper.sql.ref(columns.isActive).as("isActive")
48
+ KyselyWrapper.sql.ref(columns.uuid).as('uuid'),
49
+ KyselyWrapper.sql.ref(columns.mail).as('mail'),
50
+ KyselyWrapper.sql.ref(columns.password).as('password'),
51
+ KyselyWrapper.sql.ref(columns.isActive).as('isActive')
40
52
  ])
41
- .where(KyselyWrapper.sql.ref(columns.mail), "=", typedMail)
53
+ .where(KyselyWrapper.sql.ref(columns.mail), '=', typedMail)
42
54
  .limit(1)
43
- .compile();
55
+ .compile()
44
56
 
45
57
  // 'any' is used instead of 'unknown' because calling .query() on an unknown type requires
46
58
  // either a type assertion or a separate interface. DbConnection is driver-agnostic, so
47
59
  // the concrete pool type (e.g. pg.Pool) is not available here without adding a dependency.
48
- const connection = await dbConnection.getConnection() as any;
49
- const result = await connection.query(compiledQuery.sql, compiledQuery.parameters);
60
+ const connection = (await dbConnection.getConnection()) as any
61
+ const result = await connection.query(
62
+ compiledQuery.sql,
63
+ compiledQuery.parameters
64
+ )
50
65
 
51
- const fetchedUser = mapFetchedUser(result.rows?.[0] as Record<string, unknown> | undefined);
52
- return authenticationCoreLib.AuthenticationCoreLogin.login(typedMail, typedPassword, fetchedUser, jwtKey, jwtOptions);
66
+ const fetchedUser = mapFetchedUser(
67
+ result.rows?.[0] as Record<string, unknown> | undefined
68
+ )
69
+ return authenticationCoreLib.AuthenticationCoreLogin.login(
70
+ typedMail,
71
+ typedPassword,
72
+ fetchedUser,
73
+ jwtKey,
74
+ jwtOptions
75
+ )
53
76
  } catch (error) {
54
- throw error;
77
+ throw error
55
78
  }
56
79
  }
57
- }
80
+ }
@@ -1,13 +1,19 @@
1
- import { DbConnection } from "../../db-connection/db-connection-wrapper.ts";
1
+ import { DbConnection } from '../../db-connection/db-connection-wrapper.ts'
2
2
  // @ts-ignore kysely is supplied by the server package in generated projects.
3
- import { KyselyWrapper } from "../../kysely/kysely-wrapper.ts";
4
- import { authenticationCoreLib } from "../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts";
5
- import { DEFAULT_TABLE_NAME, DEFAULT_USER_COLUMN, UserColumn } from "./shared.ts";
3
+ import { KyselyWrapper } from '../../kysely/kysely-wrapper.ts'
4
+ import { authenticationCoreLib } from '../../@tobi2409/authentication-core-lib/authentication-core-lib-wrapper.ts'
5
+ import {
6
+ DEFAULT_TABLE_NAME,
7
+ DEFAULT_USER_COLUMN,
8
+ UserColumn
9
+ } from './shared.ts'
6
10
 
7
11
  export namespace AuthenticationCoreKyselyRegister {
8
- function mapFetchedUser(row: Record<string, unknown> | undefined): authenticationCoreLib.FetchedUser | undefined {
12
+ function mapFetchedUser(
13
+ row: Record<string, unknown> | undefined
14
+ ): authenticationCoreLib.FetchedUser | undefined {
9
15
  if (!row) {
10
- return undefined;
16
+ return undefined
11
17
  }
12
18
 
13
19
  return {
@@ -15,7 +21,7 @@ export namespace AuthenticationCoreKyselyRegister {
15
21
  mail: String(row.mail),
16
22
  password: String(row.password),
17
23
  isActive: Boolean(row.isActive)
18
- };
24
+ }
19
25
  }
20
26
 
21
27
  export async function register(
@@ -25,29 +31,38 @@ export namespace AuthenticationCoreKyselyRegister {
25
31
  dbConnection: DbConnection,
26
32
  tableName: string = DEFAULT_TABLE_NAME,
27
33
  columns: UserColumn = DEFAULT_USER_COLUMN,
28
- mailTransportConfig?: Parameters<typeof authenticationCoreLib.AuthenticationCoreRegister.register>[5],
29
- hashOptions?: Parameters<typeof authenticationCoreLib.AuthenticationCoreRegister.register>[6],
34
+ mailTransportConfig?: Parameters<
35
+ typeof authenticationCoreLib.AuthenticationCoreRegister.register
36
+ >[5],
37
+ hashOptions?: Parameters<
38
+ typeof authenticationCoreLib.AuthenticationCoreRegister.register
39
+ >[6]
30
40
  ): Promise<authenticationCoreLib.FetchedUser> {
31
- const db = KyselyWrapper.buildQueryCompiler(dbConnection.getDriverName());
41
+ const db = KyselyWrapper.buildQueryCompiler(
42
+ dbConnection.getDriverName()
43
+ )
32
44
 
33
45
  // 'any' is used instead of 'unknown' because calling pool/client APIs on an unknown type requires
34
46
  // either a type assertion or a separate interface. DbConnection is driver-agnostic, so
35
47
  // the concrete pool/client type (e.g. pg.Pool/PoolClient) is not available here without adding a dependency.
36
- const pool = await dbConnection.getConnection() as any;
37
- const transactionConnection = await pool.connect();
48
+ const pool = (await dbConnection.getConnection()) as any
49
+ const transactionConnection = await pool.connect()
38
50
 
39
51
  const mailExistsRoutine = async (mail: string): Promise<boolean> => {
40
52
  const compiledQuery = db
41
53
  .selectFrom(tableName)
42
- .select((eb: any) => [eb.val(1).as("exists")])
43
- .where(KyselyWrapper.sql.ref(columns.mail), "=", mail)
54
+ .select((eb: any) => [eb.val(1).as('exists')])
55
+ .where(KyselyWrapper.sql.ref(columns.mail), '=', mail)
44
56
  .limit(1)
45
- .compile();
57
+ .compile()
46
58
 
47
- const result = await transactionConnection.query(compiledQuery.sql, compiledQuery.parameters);
59
+ const result = await transactionConnection.query(
60
+ compiledQuery.sql,
61
+ compiledQuery.parameters
62
+ )
48
63
 
49
- return (result.rows?.length ?? 0) > 0;
50
- };
64
+ return (result.rows?.length ?? 0) > 0
65
+ }
51
66
 
52
67
  const dataProcessing = async (
53
68
  identification: string,
@@ -59,50 +74,56 @@ export namespace AuthenticationCoreKyselyRegister {
59
74
  [columns.password]: hashedPassword,
60
75
  [columns.isActive]: false,
61
76
  ...inputData
62
- };
77
+ }
63
78
 
64
79
  const compiledQuery = db
65
80
  .insertInto(tableName)
66
81
  .values(userData as any)
67
82
  .returning([
68
- KyselyWrapper.sql.ref(columns.uuid).as("uuid"),
69
- KyselyWrapper.sql.ref(columns.mail).as("mail"),
70
- KyselyWrapper.sql.ref(columns.password).as("password"),
71
- KyselyWrapper.sql.ref(columns.isActive).as("isActive")
83
+ KyselyWrapper.sql.ref(columns.uuid).as('uuid'),
84
+ KyselyWrapper.sql.ref(columns.mail).as('mail'),
85
+ KyselyWrapper.sql.ref(columns.password).as('password'),
86
+ KyselyWrapper.sql.ref(columns.isActive).as('isActive')
72
87
  ])
73
- .compile();
88
+ .compile()
74
89
 
75
- const result = await transactionConnection.query(compiledQuery.sql, compiledQuery.parameters);
76
- return mapFetchedUser(result.rows?.[0] as Record<string, unknown> | undefined);
77
- };
90
+ const result = await transactionConnection.query(
91
+ compiledQuery.sql,
92
+ compiledQuery.parameters
93
+ )
94
+ return mapFetchedUser(
95
+ result.rows?.[0] as Record<string, unknown> | undefined
96
+ )
97
+ }
78
98
 
79
99
  try {
80
- await transactionConnection.query("BEGIN");
100
+ await transactionConnection.query('BEGIN')
81
101
 
82
- const registeredUser = await authenticationCoreLib.AuthenticationCoreRegister.register(
83
- registrationInputData,
84
- mailExistsRoutine,
85
- customInputData,
86
- dataProcessing,
87
- verificationMail,
88
- mailTransportConfig,
89
- hashOptions
90
- );
102
+ const registeredUser =
103
+ await authenticationCoreLib.AuthenticationCoreRegister.register(
104
+ registrationInputData,
105
+ mailExistsRoutine,
106
+ customInputData,
107
+ dataProcessing,
108
+ verificationMail,
109
+ mailTransportConfig,
110
+ hashOptions
111
+ )
91
112
 
92
- await transactionConnection.query("COMMIT");
93
- return registeredUser;
113
+ await transactionConnection.query('COMMIT')
114
+ return registeredUser
94
115
  } catch (error) {
95
116
  try {
96
- await transactionConnection.query("ROLLBACK");
117
+ await transactionConnection.query('ROLLBACK')
97
118
  } catch {
98
119
  // Ignore rollback errors, original error is more relevant.
99
120
  }
100
121
 
101
- throw error;
122
+ throw error
102
123
  } finally {
103
- if (typeof transactionConnection.release === "function") {
104
- transactionConnection.release();
124
+ if (typeof transactionConnection.release === 'function') {
125
+ transactionConnection.release()
105
126
  }
106
127
  }
107
128
  }
108
- }
129
+ }
@@ -1,15 +1,15 @@
1
1
  export type UserColumn = {
2
- uuid: string;
3
- mail: string;
4
- password: string;
5
- isActive: string;
6
- };
2
+ uuid: string
3
+ mail: string
4
+ password: string
5
+ isActive: string
6
+ }
7
7
 
8
- export const DEFAULT_TABLE_NAME = "users";
8
+ export const DEFAULT_TABLE_NAME = 'users'
9
9
 
10
10
  export const DEFAULT_USER_COLUMN: UserColumn = {
11
- uuid: "uuid",
12
- mail: "mail",
13
- password: "password",
14
- isActive: "isActive"
15
- };
11
+ uuid: 'uuid',
12
+ mail: 'mail',
13
+ password: 'password',
14
+ isActive: 'isActive'
15
+ }
@@ -1,2 +1,2 @@
1
1
  // @ts-ignore package is supplied by the server package in generated projects.
2
- export * as authenticationCoreLib from "@tobi2409/authentication-core-lib";
2
+ export * as authenticationCoreLib from '@tobi2409/authentication-core-lib'
@@ -1,11 +1,11 @@
1
- type DriverName = "pg" | "mysql" | "sqlite";
1
+ type DriverName = 'pg' | 'mysql' | 'sqlite'
2
2
 
3
3
  interface ConnectionData {
4
- connectionName?: string;
5
- };
4
+ connectionName?: string
5
+ }
6
6
 
7
7
  export class DbConnection {
8
- private connectionWrapper?: unknown;
8
+ private connectionWrapper?: unknown
9
9
 
10
10
  constructor(
11
11
  private readonly driverName: DriverName,
@@ -13,32 +13,35 @@ export class DbConnection {
13
13
  ) {}
14
14
 
15
15
  getDriverName(): DriverName {
16
- return this.driverName;
16
+ return this.driverName
17
17
  }
18
18
 
19
19
  async getConnection(): Promise<unknown> {
20
- if (this.driverName === "pg") {
20
+ if (this.driverName === 'pg') {
21
21
  if (!this.connectionWrapper) {
22
22
  // @ts-ignore pg-wrapper is supplied by the pg extension in generated projects.
23
- const { PgConnectionWrapper } = await import("../pg/pg-wrapper.ts");
24
- this.connectionWrapper = new PgConnectionWrapper(this.connectionData.connectionName ?? "default");
23
+ const { PgConnectionWrapper } =
24
+ await import('../pg/pg-wrapper.ts')
25
+ this.connectionWrapper = new PgConnectionWrapper(
26
+ this.connectionData.connectionName ?? 'default'
27
+ )
25
28
  }
26
29
 
27
- return (this.connectionWrapper as any).getPgPool();
30
+ return (this.connectionWrapper as any).getPgPool()
28
31
  }
29
32
 
30
- throw new Error(`Driver is not integrated yet: ${this.driverName}`);
33
+ throw new Error(`Driver is not integrated yet: ${this.driverName}`)
31
34
  }
32
35
 
33
36
  async close(): Promise<void> {
34
- if (this.driverName === "pg") {
37
+ if (this.driverName === 'pg') {
35
38
  if (this.connectionWrapper) {
36
- await (this.connectionWrapper as any).closePool();
39
+ await (this.connectionWrapper as any).closePool()
37
40
  }
38
41
 
39
- return;
42
+ return
40
43
  }
41
44
 
42
- throw new Error(`Driver is not integrated yet: ${this.driverName}`);
45
+ throw new Error(`Driver is not integrated yet: ${this.driverName}`)
43
46
  }
44
47
  }
@@ -1,3 +1,3 @@
1
1
  {
2
2
  "addToServerPackage": false
3
- }
3
+ }
@@ -1,3 +1,3 @@
1
1
  {
2
2
  "addToServerPackage": true
3
- }
3
+ }
@@ -1,29 +1,31 @@
1
1
  // @ts-ignore kysely is supplied by the server package in generated projects.
2
- import * as k from "kysely";
2
+ import * as k from 'kysely'
3
3
 
4
- type DriverName = "pg" | "mysql" | "sqlite";
4
+ type DriverName = 'pg' | 'mysql' | 'sqlite'
5
5
 
6
6
  export namespace KyselyWrapper {
7
- export const sql = k.sql;
7
+ export const sql = k.sql
8
8
 
9
- export function getKysely(): typeof k {
10
- return k;
11
- }
9
+ export function getKysely(): typeof k {
10
+ return k
11
+ }
12
12
 
13
- export function buildQueryCompiler(driverName: DriverName): k.Kysely<any> {
14
- const kysely = getKysely() as any;
13
+ export function buildQueryCompiler(driverName: DriverName): k.Kysely<any> {
14
+ const kysely = getKysely() as any
15
15
 
16
- if (driverName === "pg") {
17
- return new kysely.Kysely({
18
- dialect: {
19
- createAdapter: () => new kysely.PostgresAdapter(),
20
- createDriver: () => new kysely.DummyDriver(),
21
- createIntrospector: (db: any) => new kysely.PostgresIntrospector(db),
22
- createQueryCompiler: () => new kysely.PostgresQueryCompiler(),
23
- }
24
- });
25
- }
16
+ if (driverName === 'pg') {
17
+ return new kysely.Kysely({
18
+ dialect: {
19
+ createAdapter: () => new kysely.PostgresAdapter(),
20
+ createDriver: () => new kysely.DummyDriver(),
21
+ createIntrospector: (db: any) =>
22
+ new kysely.PostgresIntrospector(db),
23
+ createQueryCompiler: () =>
24
+ new kysely.PostgresQueryCompiler()
25
+ }
26
+ })
27
+ }
26
28
 
27
- throw new Error(`Driver is not integrated yet: ${driverName}`);
28
- }
29
+ throw new Error(`Driver is not integrated yet: ${driverName}`)
30
+ }
29
31
  }
@@ -1,3 +1,3 @@
1
1
  {
2
2
  "addToServerPackage": true
3
- }
3
+ }
@@ -1,73 +1,77 @@
1
1
  // @ts-ignore pg dependencies are supplied by the server package in generated projects.
2
- import dotenv from "dotenv";
2
+ import dotenv from 'dotenv'
3
3
  // @ts-ignore node types are supplied by the server package in generated projects.
4
- import fs from "fs";
4
+ import fs from 'fs'
5
5
  // @ts-ignore node types are supplied by the server package in generated projects.
6
- import path from "path";
6
+ import path from 'path'
7
7
  // @ts-ignore pg dependencies are supplied by the server package in generated projects.
8
- import { Pool } from "pg";
8
+ import { Pool } from 'pg'
9
9
  // @ts-ignore node types are supplied by the server package in generated projects.
10
- import { fileURLToPath } from "url";
10
+ import { fileURLToPath } from 'url'
11
11
 
12
12
  export class PgConnectionWrapper {
13
- private pool: Pool | null = null;
14
- private pgEnv: Record<string, string> = {};
15
- private pgEnvLoaded: boolean = false;
16
- private readonly wrapperDir: string = path.dirname(fileURLToPath(import.meta.url));
17
- private readonly envFilePath: string = path.join(this.wrapperDir, ".env.pg");
13
+ private pool: Pool | null = null
14
+ private pgEnv: Record<string, string> = {}
15
+ private pgEnvLoaded: boolean = false
16
+ private readonly wrapperDir: string = path.dirname(
17
+ fileURLToPath(import.meta.url)
18
+ )
19
+ private readonly envFilePath: string = path.join(this.wrapperDir, '.env.pg')
18
20
 
19
- constructor(private readonly connectionName: string = "default") {}
21
+ constructor(private readonly connectionName: string = 'default') {}
20
22
 
21
23
  private envKey(key: string): string {
22
- const prefix = this.connectionName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
23
- return `${prefix}_${key}`;
24
+ const prefix = this.connectionName
25
+ .toUpperCase()
26
+ .replace(/[^A-Z0-9_]/g, '_')
27
+ return `${prefix}_${key}`
24
28
  }
25
29
 
26
30
  private loadPgEnv(): void {
27
31
  // only load the .env.pg file once
28
32
  if (this.pgEnvLoaded) {
29
- return;
33
+ return
30
34
  }
31
35
 
32
36
  // Load .env.pg into a local cache instead of writing into process.env.
33
37
  // This keeps the pg wrapper isolated from other wrappers such as auth,
34
38
  // which may load their own .env files later.
35
39
  const envFileContent = fs.existsSync(this.envFilePath)
36
- ? fs.readFileSync(this.envFilePath, "utf8")
37
- : "";
40
+ ? fs.readFileSync(this.envFilePath, 'utf8')
41
+ : ''
38
42
 
39
- this.pgEnv = dotenv.parse(envFileContent);
40
- this.pgEnvLoaded = true;
43
+ this.pgEnv = dotenv.parse(envFileContent)
44
+ this.pgEnvLoaded = true
41
45
  }
42
46
 
43
47
  private getEnv(key: string, fallback?: string): string {
44
- this.loadPgEnv();
45
- return this.pgEnv[this.envKey(key)] ?? fallback ?? "";
48
+ this.loadPgEnv()
49
+ return this.pgEnv[this.envKey(key)] ?? fallback ?? ''
46
50
  }
47
51
 
48
52
  getPgPool(): Pool {
49
53
  if (this.pool) {
50
- return this.pool;
54
+ return this.pool
51
55
  }
52
56
 
53
57
  this.pool = new Pool({
54
- host: this.getEnv("PGHOST", "127.0.0.1"),
55
- port: Number(this.getEnv("PGPORT", "5432")),
56
- user: this.getEnv("PGUSER", "postgres"),
57
- password: this.getEnv("PGPASSWORD", "postgres"),
58
- database: this.getEnv("PGDATABASE", "fullsty_demo"),
59
- max: Number(this.getEnv("POOL_MAX", "10"))
60
- });
58
+ host: this.getEnv('PGHOST', '127.0.0.1'),
59
+ port: Number(this.getEnv('PGPORT', '5432')),
60
+ user: this.getEnv('PGUSER', 'postgres'),
61
+ password: this.getEnv('PGPASSWORD', 'postgres'),
62
+ database: this.getEnv('PGDATABASE', 'fullsty_demo'),
63
+ max: Number(this.getEnv('POOL_MAX', '10'))
64
+ })
61
65
 
62
- return this.pool;
66
+ return this.pool
63
67
  }
64
68
 
65
69
  async closePool(): Promise<void> {
66
70
  if (!this.pool) {
67
- return;
71
+ return
68
72
  }
69
73
 
70
- await this.pool.end();
71
- this.pool = null;
74
+ await this.pool.end()
75
+ this.pool = null
72
76
  }
73
- }
77
+ }
@@ -1,3 +1,3 @@
1
1
  {
2
2
  "addToServerPackage": true
3
- }
3
+ }
@@ -1 +1 @@
1
- export { default as sql } from "sql-template-tag";
1
+ export { default as sql } from 'sql-template-tag'
@@ -1,46 +1,46 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import path from "path";
4
- import { handleAdd, handleRemove } from "./shared/server-package-utils.js";
3
+ import path from 'path'
4
+ import { handleAdd, handleRemove } from './shared/server-package-utils.js'
5
5
 
6
6
  function main() {
7
- const args = process.argv.slice(2);
8
- const command = args[0];
7
+ const args = process.argv.slice(2)
8
+ const command = args[0]
9
9
 
10
10
  if (!command) {
11
11
  console.log(
12
- "Usage: node fullsty-server-pkg.js <add|remove> <package-name> [more-package-names...]",
13
- );
14
-
15
- process.exit(1);
12
+ 'Usage: node fullsty-server-pkg.js <add|remove> <package-name> [more-package-names...]'
13
+ )
14
+
15
+ process.exit(1)
16
16
  }
17
17
 
18
- const scriptDir = path.dirname(new URL(import.meta.url).pathname);
19
- const projectDir = process.cwd();
20
- const serverDir = path.join(projectDir, "src", "server");
21
- const packageNames = args.slice(1).filter((arg) => !arg.startsWith("-"));
18
+ const scriptDir = path.dirname(new URL(import.meta.url).pathname)
19
+ const projectDir = process.cwd()
20
+ const serverDir = path.join(projectDir, 'src', 'server')
21
+ const packageNames = args.slice(1).filter((arg) => !arg.startsWith('-'))
22
22
 
23
- if (packageNames.length === 0 || !["add", "remove"].includes(command)) {
23
+ if (packageNames.length === 0 || !['add', 'remove'].includes(command)) {
24
24
  console.log(
25
- "Usage: node fullsty-server-pkg.js <add|remove> <package-name> [more-package-names...]",
26
- );
25
+ 'Usage: node fullsty-server-pkg.js <add|remove> <package-name> [more-package-names...]'
26
+ )
27
27
 
28
- process.exit(1);
28
+ process.exit(1)
29
29
  }
30
30
 
31
- if (command === "add") {
32
- handleAdd(projectDir, scriptDir, serverDir, packageNames);
33
- return;
31
+ if (command === 'add') {
32
+ handleAdd(projectDir, scriptDir, serverDir, packageNames)
33
+ return
34
34
  }
35
35
 
36
- handleRemove(projectDir, scriptDir, serverDir, packageNames);
36
+ handleRemove(projectDir, scriptDir, serverDir, packageNames)
37
37
  }
38
38
 
39
39
  try {
40
- main();
40
+ main()
41
41
  } catch (error) {
42
42
  console.error(
43
- `\n❌ ${error instanceof Error ? error.message : String(error)}`,
44
- );
45
- process.exit(1);
46
- }
43
+ `\n❌ ${error instanceof Error ? error.message : String(error)}`
44
+ )
45
+ process.exit(1)
46
+ }
@@ -12,6 +12,6 @@
12
12
  "test": "echo \"Error: no test specified\" && exit 1"
13
13
  },
14
14
  "devDependencies": {
15
- "@tobi2409/proc2rest": "^0.4.1"
15
+ "@tobi2409/proc2rest": "^0.5.0"
16
16
  }
17
17
  }
@@ -6,16 +6,25 @@
6
6
  "namespace": "Server"
7
7
  }
8
8
  ],
9
+ "rawServerFiles": [],
9
10
  "apiUrl": "http://localhost:3000",
10
11
  "cors": {
11
- "origin": "*"
12
+ "allowOrigin": "*"
12
13
  },
14
+ "rateLimit": {
15
+ "windowDurationMs": 900000,
16
+ "maxRequests": 100,
17
+ "useStandardHeaders": true,
18
+ "useLegacyHeaders": false
19
+ },
20
+ "errorStatusCodes": {},
13
21
  "method-rules": {
14
22
  "GET": "^(get|list|find)",
15
23
  "POST": "^(create|add|insert)",
16
24
  "PATCH": "^(update|set|patch)",
17
25
  "DELETE": "^(delete|remove)"
18
26
  },
27
+ "method-rules-custom-functions": {},
19
28
  "binaryTypes": [
20
29
  "ArrayBuffer",
21
30
  "Uint8Array",
@@ -6,11 +6,12 @@
6
6
  "start": "tsx routes.generated.ts"
7
7
  },
8
8
  "dependencies": {
9
- "@msgpack/msgpack": "^3.0.0",
10
- "cors": "^2.8.5",
11
- "dotenv": "^16.4.7",
9
+ "@msgpack/msgpack": "^3.1.3",
10
+ "cors": "^2.8.6",
11
+ "dotenv": "^17.4.2",
12
12
  "express": "^5.2.1",
13
- "express-rate-limit": "^7.5.1"
13
+ "express-rate-limit": "^8.3.1",
14
+ "helmet": "^8.3.0"
14
15
  },
15
16
  "devDependencies": {
16
17
  "@types/cors": "^2.8.17",
@@ -1,36 +1,40 @@
1
- <!DOCTYPE html>
1
+ <!doctype html>
2
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Document</title>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Document</title>
7
7
 
8
- <script type="importmap">
9
- {
10
- "imports": {
11
- "template-engine/": "./node_modules/@tobi2409/template-engine/src/"
12
- }
13
- }
14
- </script>
8
+ <script type="importmap">
9
+ {
10
+ "imports": {
11
+ "template-engine/": "./node_modules/@tobi2409/template-engine/src/"
12
+ }
13
+ }
14
+ </script>
15
15
 
16
- <link rel="stylesheet" href="node_modules/@tobi2409/layout/src/layout.css">
17
- <link rel="stylesheet" href="index.css">
18
- </head>
19
- <body>
20
-
21
- <div id="app">
22
- </div>
16
+ <link
17
+ rel="stylesheet"
18
+ href="node_modules/@tobi2409/layout/src/layout.css"
19
+ />
20
+ <link rel="stylesheet" href="index.css" />
21
+ </head>
22
+ <body>
23
+ <div id="app"></div>
23
24
 
24
- <template id="app-template">
25
- <h1>👋 Hello, <get>name</get></h1>
25
+ <template id="app-template">
26
+ <h1>👋 Hello, <get>name</get></h1>
26
27
 
27
- <p><get>serverMessage</get></p>
28
- </template>
28
+ <p><get>serverMessage</get></p>
29
+ </template>
29
30
 
30
- <template-use id="app-template-use" template-id="app-template" mount-id="app">
31
- </template-use>
31
+ <template-use
32
+ id="app-template-use"
33
+ template-id="app-template"
34
+ mount-id="app"
35
+ >
36
+ </template-use>
32
37
 
33
- <script type="module" src="index.js"></script>
34
-
35
- </body>
36
- </html>
38
+ <script type="module" src="index.js"></script>
39
+ </body>
40
+ </html>
@@ -2,9 +2,12 @@
2
2
 
3
3
  import TemplateEngine from 'template-engine/template-engine.js'
4
4
 
5
- const data = TemplateEngine.reactive({
6
- name: 'my friend',
7
- serverMessage: 'Server not responded yet'
8
- }, document.getElementById('app-template-use'))
5
+ const data = TemplateEngine.reactive(
6
+ {
7
+ name: 'my friend',
8
+ serverMessage: 'Server not responded yet'
9
+ },
10
+ document.getElementById('app-template-use')
11
+ )
9
12
 
10
- data.serverMessage = await Server.helloFromServer('my friend')
13
+ data.serverMessage = await Server.helloFromServer('my friend')
@@ -1,4 +1,4 @@
1
1
  // @rest
2
2
  export function helloFromServer(name: string): string {
3
3
  return `Hello, ${name}! This is the server speaking.`
4
- }
4
+ }
@@ -1,25 +1,25 @@
1
- import fs from "fs";
2
- import path from "path";
1
+ import fs from 'fs'
2
+ import path from 'path'
3
3
 
4
4
  // Recursively copy a directory and all nested files/folders.
5
5
  export function copyDirectory(sourceDir, targetDir, options = {}) {
6
- const excludedNames = new Set(options.excludedNames ?? []);
6
+ const excludedNames = new Set(options.excludedNames ?? [])
7
7
 
8
- fs.mkdirSync(targetDir, { recursive: true });
9
- const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
8
+ fs.mkdirSync(targetDir, { recursive: true })
9
+ const entries = fs.readdirSync(sourceDir, { withFileTypes: true })
10
10
 
11
11
  for (const entry of entries) {
12
12
  if (excludedNames.has(entry.name)) {
13
- continue;
13
+ continue
14
14
  }
15
15
 
16
- const sourcePath = path.join(sourceDir, entry.name);
17
- const targetPath = path.join(targetDir, entry.name);
16
+ const sourcePath = path.join(sourceDir, entry.name)
17
+ const targetPath = path.join(targetDir, entry.name)
18
18
 
19
19
  if (entry.isDirectory()) {
20
- copyDirectory(sourcePath, targetPath, options);
20
+ copyDirectory(sourcePath, targetPath, options)
21
21
  } else {
22
- fs.copyFileSync(sourcePath, targetPath);
22
+ fs.copyFileSync(sourcePath, targetPath)
23
23
  }
24
24
  }
25
- }
25
+ }
@@ -1,17 +1,17 @@
1
- import fs from "fs";
2
- import path from "path";
1
+ import fs from 'fs'
2
+ import path from 'path'
3
3
 
4
4
  export function readJson(projectDir, fileName) {
5
- const filePath = path.join(projectDir, fileName);
5
+ const filePath = path.join(projectDir, fileName)
6
6
 
7
7
  if (!fs.existsSync(filePath)) {
8
- throw new Error(`${fileName} not found: ${filePath}`);
8
+ throw new Error(`${fileName} not found: ${filePath}`)
9
9
  }
10
10
 
11
- return JSON.parse(fs.readFileSync(filePath, "utf8"));
11
+ return JSON.parse(fs.readFileSync(filePath, 'utf8'))
12
12
  }
13
13
 
14
14
  export function writeJson(projectDir, fileName, json) {
15
- const filePath = path.join(projectDir, fileName);
16
- fs.writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\n`, "utf8");
17
- }
15
+ const filePath = path.join(projectDir, fileName)
16
+ fs.writeFileSync(filePath, `${JSON.stringify(json, null, 2)}\n`, 'utf8')
17
+ }
@@ -1,84 +1,86 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import { copyDirectory } from "./file-copy.js";
4
- import { readJson, writeJson } from "./project-json-utils.js";
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { copyDirectory } from './file-copy.js'
4
+ import { readJson, writeJson } from './project-json-utils.js'
5
5
 
6
- const EXTENSION_CONFIG_FILE = "extension.json";
6
+ const EXTENSION_CONFIG_FILE = 'extension.json'
7
7
 
8
8
  function wrapperDirFromPackage(scriptDir, packageName) {
9
- return path.join(scriptDir, "extension-wrappers", packageName);
9
+ return path.join(scriptDir, 'extension-wrappers', packageName)
10
10
  }
11
11
 
12
12
  function shouldAddToServerPackage(wrapperDir) {
13
- const extensionConfig = readJson(wrapperDir, EXTENSION_CONFIG_FILE);
14
- return extensionConfig.addToServerPackage;
13
+ const extensionConfig = readJson(wrapperDir, EXTENSION_CONFIG_FILE)
14
+ return extensionConfig.addToServerPackage
15
15
  }
16
16
 
17
17
  export function handleAdd(projectDir, scriptDir, serverDir, packageNames) {
18
- const json = readJson(projectDir, "server-package.json");
18
+ const json = readJson(projectDir, 'server-package.json')
19
19
 
20
- if (!json.dependencies || typeof json.dependencies !== "object") {
21
- json.dependencies = {};
20
+ if (!json.dependencies || typeof json.dependencies !== 'object') {
21
+ json.dependencies = {}
22
22
  }
23
23
 
24
24
  for (const packageName of packageNames) {
25
- const wrapperDir = wrapperDirFromPackage(scriptDir, packageName);
26
- const targetWrapperDir = path.join(serverDir, packageName);
27
- const wrapperExists = fs.existsSync(wrapperDir);
25
+ const wrapperDir = wrapperDirFromPackage(scriptDir, packageName)
26
+ const targetWrapperDir = path.join(serverDir, packageName)
27
+ const wrapperExists = fs.existsSync(wrapperDir)
28
28
 
29
29
  if (!wrapperExists) {
30
- json.dependencies[packageName] = "latest";
31
- continue;
30
+ json.dependencies[packageName] = 'latest'
31
+ continue
32
32
  }
33
33
 
34
34
  if (shouldAddToServerPackage(wrapperDir)) {
35
- json.dependencies[packageName] = "latest";
35
+ json.dependencies[packageName] = 'latest'
36
36
  }
37
37
 
38
38
  copyDirectory(wrapperDir, targetWrapperDir, {
39
- excludedNames: [EXTENSION_CONFIG_FILE],
40
- });
41
- console.log(`\n✅ Copied wrapper for ${packageName} to src/server/${packageName}`);
39
+ excludedNames: [EXTENSION_CONFIG_FILE]
40
+ })
41
+ console.log(
42
+ `\n✅ Copied wrapper for ${packageName} to src/server/${packageName}`
43
+ )
42
44
  }
43
45
 
44
- writeJson(projectDir, "server-package.json", json);
46
+ writeJson(projectDir, 'server-package.json', json)
45
47
  }
46
48
 
47
49
  export function handleRemove(projectDir, scriptDir, serverDir, packageNames) {
48
- const json = readJson(projectDir, "server-package.json");
50
+ const json = readJson(projectDir, 'server-package.json')
49
51
 
50
- if (!json.dependencies || typeof json.dependencies !== "object") {
51
- json.dependencies = {};
52
+ if (!json.dependencies || typeof json.dependencies !== 'object') {
53
+ json.dependencies = {}
52
54
  }
53
55
 
54
- if (!json.devDependencies || typeof json.devDependencies !== "object") {
55
- json.devDependencies = {};
56
+ if (!json.devDependencies || typeof json.devDependencies !== 'object') {
57
+ json.devDependencies = {}
56
58
  }
57
59
 
58
60
  for (const packageName of packageNames) {
59
- const wrapperDir = wrapperDirFromPackage(scriptDir, packageName);
60
- const targetWrapperDir = path.join(serverDir, packageName);
61
- const wrapperExists = fs.existsSync(wrapperDir);
61
+ const wrapperDir = wrapperDirFromPackage(scriptDir, packageName)
62
+ const targetWrapperDir = path.join(serverDir, packageName)
63
+ const wrapperExists = fs.existsSync(wrapperDir)
62
64
 
63
65
  if (!wrapperExists) {
64
- delete json.dependencies[packageName];
65
- delete json.devDependencies[packageName];
66
- continue;
66
+ delete json.dependencies[packageName]
67
+ delete json.devDependencies[packageName]
68
+ continue
67
69
  }
68
70
 
69
71
  if (shouldAddToServerPackage(wrapperDir)) {
70
- delete json.dependencies[packageName];
71
- delete json.devDependencies[packageName];
72
+ delete json.dependencies[packageName]
73
+ delete json.devDependencies[packageName]
72
74
  }
73
75
 
74
76
  if (fs.existsSync(targetWrapperDir)) {
75
- fs.rmSync(targetWrapperDir, { recursive: true, force: true });
77
+ fs.rmSync(targetWrapperDir, { recursive: true, force: true })
76
78
 
77
79
  console.log(
78
- `\n✅ Removed wrapper for ${packageName} from src/server/${packageName}`,
79
- );
80
+ `\n✅ Removed wrapper for ${packageName} from src/server/${packageName}`
81
+ )
80
82
  }
81
83
  }
82
84
 
83
- writeJson(projectDir, "server-package.json", json);
84
- }
85
+ writeJson(projectDir, 'server-package.json', json)
86
+ }