create-prisma-php-app 5.0.0-alpha.7 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -2
- package/dist/.github/copilot-instructions.md +191 -0
- package/dist/AGENTS.md +588 -193
- package/dist/bootstrap.php +426 -213
- package/dist/index.js +2 -2
- package/dist/phpunit.xml +25 -0
- package/dist/postcss.config.js +4 -2
- package/dist/prisma-php.js +2 -2
- package/dist/public/.htaccess +1 -1
- package/dist/public/js/main.js +13 -1
- package/dist/public/js/pp-reactive-v2.min.js +1 -0
- package/dist/settings/auto-swagger-docs.ts +10 -10
- package/dist/settings/bs-config.ts +47 -27
- package/dist/settings/build.ts +2 -32
- package/dist/settings/component-map.ts +476 -0
- package/dist/settings/files-list.ts +2 -2
- package/dist/settings/project-name.ts +3 -6
- package/dist/settings/restart-mcp.ts +2 -2
- package/dist/settings/restart-websocket.ts +2 -2
- package/dist/settings/run-postcss.ts +205 -0
- package/dist/settings/run-tests.ts +35 -0
- package/dist/settings/swagger-config.ts +3 -3
- package/dist/settings/utils.ts +3 -3
- package/dist/src/Lib/Auth/Auth.php +63 -35
- package/dist/src/Lib/MCP/mcp-server.php +2 -3
- package/dist/src/Lib/Middleware/AuthMiddleware.php +2 -2
- package/dist/src/Lib/Middleware/CorsMiddleware.php +72 -0
- package/dist/src/Lib/Websocket/ConnectionManager.php +460 -7
- package/dist/src/Lib/Websocket/Socket.php +170 -0
- package/dist/src/Lib/Websocket/SocketPool.php +50 -0
- package/dist/src/Lib/Websocket/SocketRegistry.php +88 -0
- package/dist/src/Lib/Websocket/sockets.php +50 -0
- package/dist/src/Lib/Websocket/websocket-server.php +10 -3
- package/dist/src/app/globals.css +3 -1
- package/dist/src/app/layout.php +1 -1
- package/dist/tests/AuthTest.php +59 -0
- package/dist/tests/ConnectionManagerTest.php +277 -0
- package/dist/tests/CsrfTest.php +119 -0
- package/dist/tests/DeferComponentRootsTest.php +147 -0
- package/dist/tests/FeaturesTest.php +41 -0
- package/dist/tests/README.md +119 -0
- package/dist/tests/RpcWireContractTest.php +101 -0
- package/dist/tests/SocketPoolTest.php +69 -0
- package/dist/tests/SocketRegistryTest.php +77 -0
- package/dist/tests/SocketTest.php +124 -0
- package/dist/tests/SocketsRegistrationTest.php +40 -0
- package/dist/tests/Support/FakeConnection.php +62 -0
- package/dist/tests/Support/Features.php +38 -0
- package/dist/tests/Support/RequiresFeature.php +26 -0
- package/dist/tests/bootstrap.php +44 -0
- package/dist/ts/main.ts +21 -3
- package/dist/ts/tailwind-merge.ts +13 -0
- package/package.json +4 -4
- package/dist/README.md +0 -213
- package/dist/public/js/pp-reactive-v2.js +0 -1
- package/dist/settings/bs-config.json +0 -6
- package/dist/settings/class-imports.ts +0 -165
- package/dist/settings/class-log.ts +0 -244
- package/dist/settings/component-import-checker.ts +0 -90
- package/dist/settings/files-list.json +0 -1
- package/dist/settings/prisma-schema-config.json +0 -16
|
@@ -457,7 +457,7 @@ function generateEndpoints(modelName: string, fields: any[]): void {
|
|
|
457
457
|
const baseDir = `src/app/${kebabCasedModelName}`;
|
|
458
458
|
const idField = fields.find((field) => field.isId);
|
|
459
459
|
const fieldsToCreateAndUpdate = fields.filter(
|
|
460
|
-
(field) => shouldSkipField(field) === false
|
|
460
|
+
(field) => shouldSkipField(field) === false,
|
|
461
461
|
);
|
|
462
462
|
const idFieldName = idField.name;
|
|
463
463
|
const baseDirPath = resolve(__dirname, `../${baseDir}`);
|
|
@@ -476,7 +476,7 @@ function generateEndpoints(modelName: string, fields: any[]): void {
|
|
|
476
476
|
writeFileSync(
|
|
477
477
|
resolve(__dirname, `../${listRoutePath}`),
|
|
478
478
|
listRouteContent,
|
|
479
|
-
"utf-8"
|
|
479
|
+
"utf-8",
|
|
480
480
|
);
|
|
481
481
|
|
|
482
482
|
const idDir = `${baseDir}/[id]`;
|
|
@@ -508,7 +508,7 @@ echo json_encode($${camelCaseModelName});`;
|
|
|
508
508
|
writeFileSync(
|
|
509
509
|
resolve(__dirname, `../${idRoutePath}`),
|
|
510
510
|
idRouteContent,
|
|
511
|
-
"utf-8"
|
|
511
|
+
"utf-8",
|
|
512
512
|
);
|
|
513
513
|
|
|
514
514
|
const createDir = `${baseDir}/create`;
|
|
@@ -564,7 +564,7 @@ echo json_encode($new${modelName});`;
|
|
|
564
564
|
writeFileSync(
|
|
565
565
|
resolve(__dirname, `../${createRoutePath}`),
|
|
566
566
|
createRouteContent,
|
|
567
|
-
"utf-8"
|
|
567
|
+
"utf-8",
|
|
568
568
|
);
|
|
569
569
|
|
|
570
570
|
const updateDir = `${baseDir}/update/[id]`;
|
|
@@ -624,7 +624,7 @@ echo json_encode($updated${modelName});`;
|
|
|
624
624
|
writeFileSync(
|
|
625
625
|
resolve(__dirname, `../${updateRoutePath}`),
|
|
626
626
|
updateRouteContent,
|
|
627
|
-
"utf-8"
|
|
627
|
+
"utf-8",
|
|
628
628
|
);
|
|
629
629
|
|
|
630
630
|
const deleteDir = `${baseDir}/delete/[id]`;
|
|
@@ -655,7 +655,7 @@ echo json_encode($deleted${modelName});`;
|
|
|
655
655
|
writeFileSync(
|
|
656
656
|
resolve(__dirname, `../${deleteRoutePath}`),
|
|
657
657
|
deleteRouteContent,
|
|
658
|
-
"utf-8"
|
|
658
|
+
"utf-8",
|
|
659
659
|
);
|
|
660
660
|
}
|
|
661
661
|
|
|
@@ -675,7 +675,7 @@ async function promptUserForGenerationOptions() {
|
|
|
675
675
|
writeFileSync(
|
|
676
676
|
resolve(__dirname, "./prisma-schema-config.json"),
|
|
677
677
|
JSON.stringify(prismaSchemaConfigJson, null, 2),
|
|
678
|
-
"utf-8"
|
|
678
|
+
"utf-8",
|
|
679
679
|
);
|
|
680
680
|
|
|
681
681
|
await swaggerConfig();
|
|
@@ -704,7 +704,7 @@ async function promptUserForGenerationOptions() {
|
|
|
704
704
|
writeFileSync(
|
|
705
705
|
resolve(__dirname, "./prisma-schema-config.json"),
|
|
706
706
|
JSON.stringify(prismaSchemaConfigJson, null, 2),
|
|
707
|
-
"utf-8"
|
|
707
|
+
"utf-8",
|
|
708
708
|
);
|
|
709
709
|
}
|
|
710
710
|
|
|
@@ -752,8 +752,8 @@ function generateAndSaveSwaggerDocsForModel(model: any): void {
|
|
|
752
752
|
writeFileSync(outputFilePath, swaggerAnnotation, "utf-8");
|
|
753
753
|
console.log(
|
|
754
754
|
`Swagger annotations for model "${model.name}" generated at: ${chalk.blue(
|
|
755
|
-
whereToSave
|
|
756
|
-
)}
|
|
755
|
+
whereToSave,
|
|
756
|
+
)}`,
|
|
757
757
|
);
|
|
758
758
|
|
|
759
759
|
if (prismaSchemaConfigJson.generateEndpoints) {
|
|
@@ -2,27 +2,21 @@ import {
|
|
|
2
2
|
createProxyMiddleware,
|
|
3
3
|
responseInterceptor,
|
|
4
4
|
} from "http-proxy-middleware";
|
|
5
|
-
import { writeFileSync, existsSync, mkdirSync } from "fs";
|
|
5
|
+
import { writeFileSync, existsSync, mkdirSync, readFileSync } from "fs";
|
|
6
6
|
import { networkInterfaces } from "os";
|
|
7
7
|
import browserSync, { BrowserSyncInstance } from "browser-sync";
|
|
8
8
|
import prismaPhpConfigJson from "../prisma-php.json";
|
|
9
9
|
import { generateFileListJson } from "./files-list.js";
|
|
10
10
|
import { join, dirname, relative } from "path";
|
|
11
11
|
import { getFileMeta, PUBLIC_DIR, SRC_DIR } from "./utils.js";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
analyzeImportsInFile,
|
|
15
|
-
getAllPhpFiles,
|
|
16
|
-
updateComponentImports,
|
|
17
|
-
} from "./class-imports";
|
|
18
|
-
import { checkComponentImports } from "./component-import-checker";
|
|
12
|
+
import { updateComponentMap } from "./component-map";
|
|
19
13
|
import { DebouncedWorker, createSrcWatcher, DEFAULT_AWF } from "./utils.js";
|
|
20
14
|
import chalk from "chalk";
|
|
21
15
|
|
|
22
16
|
const { __dirname } = getFileMeta();
|
|
23
17
|
const bs: BrowserSyncInstance = browserSync.create();
|
|
24
18
|
|
|
25
|
-
const PUBLIC_IGNORE_DIRS = [""];
|
|
19
|
+
const PUBLIC_IGNORE_DIRS = ["uploads"];
|
|
26
20
|
|
|
27
21
|
function getExternalIP(): string | null {
|
|
28
22
|
const nets = networkInterfaces();
|
|
@@ -39,24 +33,7 @@ function getExternalIP(): string | null {
|
|
|
39
33
|
const pipeline = new DebouncedWorker(
|
|
40
34
|
async () => {
|
|
41
35
|
await generateFileListJson();
|
|
42
|
-
await
|
|
43
|
-
await updateComponentImports();
|
|
44
|
-
|
|
45
|
-
const phpFiles = await getAllPhpFiles(SRC_DIR);
|
|
46
|
-
for (const file of phpFiles) {
|
|
47
|
-
const rawFileImports = await analyzeImportsInFile(file);
|
|
48
|
-
const fileImports: Record<
|
|
49
|
-
string,
|
|
50
|
-
{ className: string; filePath: string; importer?: string }[]
|
|
51
|
-
> = {};
|
|
52
|
-
for (const key in rawFileImports) {
|
|
53
|
-
const v = rawFileImports[key];
|
|
54
|
-
fileImports[key] = Array.isArray(v)
|
|
55
|
-
? v
|
|
56
|
-
: [{ className: key, filePath: v }];
|
|
57
|
-
}
|
|
58
|
-
await checkComponentImports(file, fileImports);
|
|
59
|
-
}
|
|
36
|
+
await updateComponentMap();
|
|
60
37
|
|
|
61
38
|
if (bs.active) {
|
|
62
39
|
bs.reload();
|
|
@@ -127,11 +104,43 @@ createSrcWatcher(viteFlagFile, {
|
|
|
127
104
|
interval: 500,
|
|
128
105
|
});
|
|
129
106
|
|
|
107
|
+
// ── PulsePoint named-socket proxy ────────────────────────────────────────────
|
|
108
|
+
// `pp.socket("name", ...)` connects to `/__pulsepoint/ws` on the page origin;
|
|
109
|
+
// in development that origin is this BrowserSync server, so the upgrade is
|
|
110
|
+
// proxied to the Ratchet websocket server (WS_HOST/WS_PORT from .env).
|
|
111
|
+
function getWebsocketTarget(): string {
|
|
112
|
+
let host = "127.0.0.1";
|
|
113
|
+
let port = "9001";
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const envPath = join(__dirname, "..", ".env");
|
|
117
|
+
if (existsSync(envPath)) {
|
|
118
|
+
const env = readFileSync(envPath, "utf8");
|
|
119
|
+
const portMatch = env.match(/^\s*WS_PORT\s*=\s*["']?(\d+)["']?\s*$/m);
|
|
120
|
+
if (portMatch) port = portMatch[1];
|
|
121
|
+
const hostMatch = env.match(/^\s*WS_HOST\s*=\s*["']?([^"'\s#]+)["']?\s*$/m);
|
|
122
|
+
if (hostMatch && hostMatch[1] !== "0.0.0.0") host = hostMatch[1];
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// Fall back to the defaults; the websocket feature may be unused.
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return `ws://${host}:${port}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const pulsePointSocketProxy = createProxyMiddleware({
|
|
132
|
+
pathFilter: "/__pulsepoint/ws",
|
|
133
|
+
target: getWebsocketTarget(),
|
|
134
|
+
ws: true,
|
|
135
|
+
changeOrigin: true,
|
|
136
|
+
});
|
|
137
|
+
|
|
130
138
|
bs.init(
|
|
131
139
|
{
|
|
132
140
|
proxy: "http://localhost:3000",
|
|
133
141
|
online: true,
|
|
134
142
|
middleware: [
|
|
143
|
+
pulsePointSocketProxy,
|
|
135
144
|
(_req, res, next) => {
|
|
136
145
|
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
137
146
|
res.setHeader("Pragma", "no-cache");
|
|
@@ -231,6 +240,17 @@ bs.init(
|
|
|
231
240
|
return;
|
|
232
241
|
}
|
|
233
242
|
|
|
243
|
+
// WebSocket upgrades bypass connect middleware, so the named-socket
|
|
244
|
+
// proxy has to hook the raw HTTP server's upgrade event itself.
|
|
245
|
+
const httpServer = (bsInstance as any).server;
|
|
246
|
+
if (httpServer && pulsePointSocketProxy.upgrade) {
|
|
247
|
+
httpServer.on("upgrade", (req: any, socket: any, head: any) => {
|
|
248
|
+
if (req.url?.startsWith("/__pulsepoint/ws")) {
|
|
249
|
+
pulsePointSocketProxy.upgrade!(req, socket, head);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
234
254
|
const bsPort = bsInstance.getOption("port");
|
|
235
255
|
const urls = bsInstance.getOption("urls");
|
|
236
256
|
const localUrl = urls.get("local") || `http://localhost:${bsPort}`;
|
package/dist/settings/build.ts
CHANGED
|
@@ -1,19 +1,11 @@
|
|
|
1
|
-
import { join } from "path";
|
|
2
1
|
import { generateFileListJson } from "./files-list.js";
|
|
3
|
-
import { updateAllClassLogs } from "./class-log.js";
|
|
4
2
|
import {
|
|
5
3
|
deleteFilesIfExist,
|
|
6
4
|
filesToDelete,
|
|
7
5
|
deleteDirectoriesIfExist,
|
|
8
6
|
dirsToDelete,
|
|
9
7
|
} from "./project-name.js";
|
|
10
|
-
import {
|
|
11
|
-
analyzeImportsInFile,
|
|
12
|
-
getAllPhpFiles,
|
|
13
|
-
SRC_DIR,
|
|
14
|
-
updateComponentImports,
|
|
15
|
-
} from "./class-imports";
|
|
16
|
-
import { checkComponentImports } from "./component-import-checker";
|
|
8
|
+
import { updateComponentMap } from "./component-map.js";
|
|
17
9
|
|
|
18
10
|
(async () => {
|
|
19
11
|
console.log("📦 Generating files for production...");
|
|
@@ -21,29 +13,7 @@ import { checkComponentImports } from "./component-import-checker";
|
|
|
21
13
|
await deleteFilesIfExist(filesToDelete);
|
|
22
14
|
await deleteDirectoriesIfExist(dirsToDelete);
|
|
23
15
|
await generateFileListJson();
|
|
24
|
-
await
|
|
25
|
-
await updateComponentImports();
|
|
26
|
-
|
|
27
|
-
const phpFiles = await getAllPhpFiles(join(SRC_DIR, "app"));
|
|
28
|
-
for (const file of phpFiles) {
|
|
29
|
-
const rawFileImports = await analyzeImportsInFile(file);
|
|
30
|
-
|
|
31
|
-
const fileImports: Record<
|
|
32
|
-
string,
|
|
33
|
-
{ className: string; filePath: string; importer?: string }[]
|
|
34
|
-
> = {};
|
|
35
|
-
|
|
36
|
-
for (const key in rawFileImports) {
|
|
37
|
-
const val = rawFileImports[key];
|
|
38
|
-
if (typeof val === "string") {
|
|
39
|
-
fileImports[key] = [{ className: key, filePath: val }];
|
|
40
|
-
} else {
|
|
41
|
-
fileImports[key] = val;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
await checkComponentImports(file, fileImports);
|
|
46
|
-
}
|
|
16
|
+
await updateComponentMap();
|
|
47
17
|
|
|
48
18
|
console.log("✅ Generating files for production completed.");
|
|
49
19
|
})();
|