@tobi2409/fullsty 0.5.0 → 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.
- package/README.md +3 -3
- package/package.json +1 -1
- package/scripts/extension-wrappers/db-connection/db-connection-wrapper.ts +32 -0
- package/scripts/extension-wrappers/db-connection/extension.json +3 -0
- package/scripts/extension-wrappers/drizzle-orm/drizzle-orm-wrapper.ts +1 -0
- package/scripts/extension-wrappers/drizzle-orm/extension.json +3 -0
- package/scripts/extension-wrappers/pg/extension.json +3 -0
- package/scripts/extension-wrappers/pg/pg-wrapper.ts +6 -2
- package/scripts/extension-wrappers/sql-template-tag/extension.json +3 -0
- package/scripts/shared/file-copy.js +8 -2
- package/scripts/shared/server-package-utils.js +23 -29
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Run it from the project root, for example:
|
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
58
|
../../scripts/fullsty-server-pkg.js add pg
|
|
59
|
-
../../scripts/fullsty-server-pkg.js add
|
|
59
|
+
../../scripts/fullsty-server-pkg.js add drizzle-orm
|
|
60
60
|
../../scripts/fullsty-server-pkg.js remove pg
|
|
61
61
|
```
|
|
62
62
|
|
|
@@ -66,7 +66,7 @@ What it does:
|
|
|
66
66
|
|
|
67
67
|
- `add <package>`
|
|
68
68
|
- 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)
|
|
69
|
-
- copies a matching wrapper from [extension-wrappers](extension-wrappers) into [projects/demo1/src/server](projects/demo1/src/server)
|
|
69
|
+
- copies a matching wrapper from [scripts/extension-wrappers](scripts/extension-wrappers) into [projects/demo1/src/server](projects/demo1/src/server)
|
|
70
70
|
- `remove <package>`
|
|
71
71
|
- removes the package from the project's server package file
|
|
72
72
|
- removes the matching wrapper from [projects/demo1/src/server](projects/demo1/src/server)
|
|
@@ -75,7 +75,7 @@ The script does not manage the project-level [package.json](project-frame/packag
|
|
|
75
75
|
|
|
76
76
|
After `fullsty-server-pkg.js add <package>` you should run `npm run generate` again so the updated project server package file is copied into `generated/server/package.json`. After that, run `npm install` again inside [projects/demo1/generated/server](projects/demo1/generated/server) so the generated server gets the updated dependencies.
|
|
77
77
|
|
|
78
|
-
`fullsty-server-pkg.js add
|
|
78
|
+
`fullsty-server-pkg.js add drizzle-orm` copies [scripts/extension-wrappers/drizzle-orm/drizzle-orm-wrapper.ts](scripts/extension-wrappers/drizzle-orm/drizzle-orm-wrapper.ts) into [projects/demo1/src/server](projects/demo1/src/server). This keeps `drizzle-orm` visible as the recommended SQL style without coupling it to a specific DBMS wrapper. For PostgreSQL pooling and env handling you can add `pg` separately.
|
|
79
79
|
|
|
80
80
|
## 5) Start the generated server
|
|
81
81
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tobi2409/fullsty",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
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",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// @ts-ignore pg-wrapper is supplied by the pg extension in generated projects.
|
|
2
|
+
import { getPgPool, closeAllPgPools } from "../pg/pg-wrapper";
|
|
3
|
+
|
|
4
|
+
type DriverName = "pg" | "mysql" | "sqlite";
|
|
5
|
+
|
|
6
|
+
type ConnectionData = {
|
|
7
|
+
connectionName?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export class DbConnection {
|
|
11
|
+
constructor(
|
|
12
|
+
private readonly driverName: DriverName,
|
|
13
|
+
private readonly connectionData: ConnectionData = {},
|
|
14
|
+
) {}
|
|
15
|
+
|
|
16
|
+
connect() {
|
|
17
|
+
if (this.driverName === "pg") {
|
|
18
|
+
return getPgPool(this.connectionData.connectionName ?? "default");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
throw new Error(`Driver is not integrated yet: ${this.driverName}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async close() {
|
|
25
|
+
if (this.driverName === "pg") {
|
|
26
|
+
await closeAllPgPools();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
throw new Error(`Driver is not integrated yet: ${this.driverName}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sql } from "drizzle-orm";
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import dotenv from "dotenv";
|
|
2
2
|
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
3
4
|
import { Pool } from "pg";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
4
6
|
|
|
5
7
|
const pools = new Map<string, Pool>();
|
|
6
8
|
let pgEnv: Record<string, string> = {};
|
|
7
9
|
let pgEnvLoaded = false;
|
|
10
|
+
const wrapperDir = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const envFilePath = path.join(wrapperDir, ".env.pg");
|
|
8
12
|
|
|
9
13
|
function envKey(connectionName: string, key: string): string {
|
|
10
14
|
const prefix = connectionName.toUpperCase().replace(/[^A-Z0-9_]/g, "_");
|
|
@@ -19,8 +23,8 @@ function loadPgEnv(): void {
|
|
|
19
23
|
// Load .env.pg into a local cache instead of writing into process.env.
|
|
20
24
|
// This keeps the pg wrapper isolated from other wrappers such as auth,
|
|
21
25
|
// which may load their own .env files later.
|
|
22
|
-
const envFileContent = fs.existsSync(
|
|
23
|
-
? fs.readFileSync(
|
|
26
|
+
const envFileContent = fs.existsSync(envFilePath)
|
|
27
|
+
? fs.readFileSync(envFilePath, "utf8")
|
|
24
28
|
: "";
|
|
25
29
|
|
|
26
30
|
pgEnv = dotenv.parse(envFileContent);
|
|
@@ -2,16 +2,22 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
4
|
// Recursively copy a directory and all nested files/folders.
|
|
5
|
-
export function copyDirectory(sourceDir, targetDir) {
|
|
5
|
+
export function copyDirectory(sourceDir, targetDir, options = {}) {
|
|
6
|
+
const excludedNames = new Set(options.excludedNames ?? []);
|
|
7
|
+
|
|
6
8
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
7
9
|
const entries = fs.readdirSync(sourceDir, { withFileTypes: true });
|
|
8
10
|
|
|
9
11
|
for (const entry of entries) {
|
|
12
|
+
if (excludedNames.has(entry.name)) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
const sourcePath = path.join(sourceDir, entry.name);
|
|
11
17
|
const targetPath = path.join(targetDir, entry.name);
|
|
12
18
|
|
|
13
19
|
if (entry.isDirectory()) {
|
|
14
|
-
copyDirectory(sourcePath, targetPath);
|
|
20
|
+
copyDirectory(sourcePath, targetPath, options);
|
|
15
21
|
} else {
|
|
16
22
|
fs.copyFileSync(sourcePath, targetPath);
|
|
17
23
|
}
|
|
@@ -1,31 +1,17 @@
|
|
|
1
|
-
import fs
|
|
1
|
+
import fs from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { copyDirectory } from "./file-copy.js";
|
|
4
4
|
import { readJson, writeJson } from "./project-json-utils.js";
|
|
5
5
|
|
|
6
|
+
const EXTENSION_CONFIG_FILE = "extension.json";
|
|
7
|
+
|
|
6
8
|
function wrapperDirFromPackage(scriptDir, packageName) {
|
|
7
9
|
return path.join(scriptDir, "extension-wrappers", packageName);
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
function
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
for (const entry of entries) {
|
|
14
|
-
const sourcePath = path.join(sourceWrapperDir, entry.name);
|
|
15
|
-
const targetPath = path.join(targetServerDir, entry.name);
|
|
16
|
-
|
|
17
|
-
if (entry.isDirectory()) {
|
|
18
|
-
if (fs.existsSync(targetPath)) {
|
|
19
|
-
removeWrapperFiles(sourcePath, targetPath);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (fs.existsSync(targetPath)) {
|
|
26
|
-
fs.rmSync(targetPath, { force: true });
|
|
27
|
-
}
|
|
28
|
-
}
|
|
12
|
+
function shouldAddToServerPackage(wrapperDir) {
|
|
13
|
+
const extensionConfig = readJson(wrapperDir, EXTENSION_CONFIG_FILE);
|
|
14
|
+
return extensionConfig.addToServerPackage;
|
|
29
15
|
}
|
|
30
16
|
|
|
31
17
|
export function handleAdd(projectDir, scriptDir, serverDir, packageNames) {
|
|
@@ -37,12 +23,17 @@ export function handleAdd(projectDir, scriptDir, serverDir, packageNames) {
|
|
|
37
23
|
|
|
38
24
|
for (const packageName of packageNames) {
|
|
39
25
|
const wrapperDir = wrapperDirFromPackage(scriptDir, packageName);
|
|
26
|
+
const targetWrapperDir = path.join(serverDir, packageName);
|
|
40
27
|
|
|
41
|
-
|
|
28
|
+
if (shouldAddToServerPackage(wrapperDir)) {
|
|
29
|
+
json.dependencies[packageName] = "latest";
|
|
30
|
+
}
|
|
42
31
|
|
|
43
32
|
if (fs.existsSync(wrapperDir)) {
|
|
44
|
-
copyDirectory(wrapperDir,
|
|
45
|
-
|
|
33
|
+
copyDirectory(wrapperDir, targetWrapperDir, {
|
|
34
|
+
excludedNames: [EXTENSION_CONFIG_FILE],
|
|
35
|
+
});
|
|
36
|
+
console.log(`\n✅ Copied wrapper for ${packageName} to src/server/${packageName}`);
|
|
46
37
|
}
|
|
47
38
|
}
|
|
48
39
|
|
|
@@ -62,15 +53,18 @@ export function handleRemove(projectDir, scriptDir, serverDir, packageNames) {
|
|
|
62
53
|
|
|
63
54
|
for (const packageName of packageNames) {
|
|
64
55
|
const wrapperDir = wrapperDirFromPackage(scriptDir, packageName);
|
|
56
|
+
const targetWrapperDir = path.join(serverDir, packageName);
|
|
65
57
|
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
if (shouldAddToServerPackage(wrapperDir)) {
|
|
59
|
+
delete json.dependencies[packageName];
|
|
60
|
+
delete json.devDependencies[packageName];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (fs.existsSync(wrapperDir) && fs.existsSync(targetWrapperDir)) {
|
|
64
|
+
fs.rmSync(targetWrapperDir, { recursive: true, force: true });
|
|
68
65
|
|
|
69
|
-
if (fs.existsSync(wrapperDir)) {
|
|
70
|
-
removeWrapperFiles(wrapperDir, serverDir);
|
|
71
|
-
|
|
72
66
|
console.log(
|
|
73
|
-
`\n✅ Removed wrapper for ${packageName} from src/server`,
|
|
67
|
+
`\n✅ Removed wrapper for ${packageName} from src/server/${packageName}`,
|
|
74
68
|
);
|
|
75
69
|
}
|
|
76
70
|
}
|