create-prisma-php-app 5.0.0-alpha.8 → 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.
Files changed (60) hide show
  1. package/README.md +23 -2
  2. package/dist/.github/copilot-instructions.md +191 -0
  3. package/dist/AGENTS.md +588 -193
  4. package/dist/bootstrap.php +426 -213
  5. package/dist/index.js +2 -2
  6. package/dist/phpunit.xml +25 -0
  7. package/dist/postcss.config.js +4 -2
  8. package/dist/prisma-php.js +2 -2
  9. package/dist/public/.htaccess +1 -1
  10. package/dist/public/js/main.js +13 -1
  11. package/dist/public/js/pp-reactive-v2.min.js +1 -0
  12. package/dist/settings/auto-swagger-docs.ts +10 -10
  13. package/dist/settings/bs-config.ts +47 -27
  14. package/dist/settings/build.ts +2 -32
  15. package/dist/settings/component-map.ts +476 -0
  16. package/dist/settings/files-list.ts +2 -2
  17. package/dist/settings/project-name.ts +3 -6
  18. package/dist/settings/restart-mcp.ts +2 -2
  19. package/dist/settings/restart-websocket.ts +2 -2
  20. package/dist/settings/run-postcss.ts +205 -0
  21. package/dist/settings/run-tests.ts +35 -0
  22. package/dist/settings/swagger-config.ts +3 -3
  23. package/dist/settings/utils.ts +3 -3
  24. package/dist/src/Lib/Auth/Auth.php +62 -34
  25. package/dist/src/Lib/MCP/mcp-server.php +2 -3
  26. package/dist/src/Lib/Middleware/CorsMiddleware.php +72 -0
  27. package/dist/src/Lib/Websocket/ConnectionManager.php +460 -7
  28. package/dist/src/Lib/Websocket/Socket.php +170 -0
  29. package/dist/src/Lib/Websocket/SocketPool.php +50 -0
  30. package/dist/src/Lib/Websocket/SocketRegistry.php +88 -0
  31. package/dist/src/Lib/Websocket/sockets.php +50 -0
  32. package/dist/src/Lib/Websocket/websocket-server.php +10 -3
  33. package/dist/src/app/globals.css +3 -1
  34. package/dist/src/app/layout.php +1 -1
  35. package/dist/tests/AuthTest.php +59 -0
  36. package/dist/tests/ConnectionManagerTest.php +277 -0
  37. package/dist/tests/CsrfTest.php +119 -0
  38. package/dist/tests/DeferComponentRootsTest.php +147 -0
  39. package/dist/tests/FeaturesTest.php +41 -0
  40. package/dist/tests/README.md +119 -0
  41. package/dist/tests/RpcWireContractTest.php +101 -0
  42. package/dist/tests/SocketPoolTest.php +69 -0
  43. package/dist/tests/SocketRegistryTest.php +77 -0
  44. package/dist/tests/SocketTest.php +124 -0
  45. package/dist/tests/SocketsRegistrationTest.php +40 -0
  46. package/dist/tests/Support/FakeConnection.php +62 -0
  47. package/dist/tests/Support/Features.php +38 -0
  48. package/dist/tests/Support/RequiresFeature.php +26 -0
  49. package/dist/tests/bootstrap.php +44 -0
  50. package/dist/ts/main.ts +21 -3
  51. package/dist/ts/tailwind-merge.ts +13 -0
  52. package/package.json +4 -4
  53. package/dist/README.md +0 -213
  54. package/dist/public/js/pp-reactive-v2.js +0 -1
  55. package/dist/settings/bs-config.json +0 -6
  56. package/dist/settings/class-imports.ts +0 -165
  57. package/dist/settings/class-log.ts +0 -244
  58. package/dist/settings/component-import-checker.ts +0 -90
  59. package/dist/settings/files-list.json +0 -1
  60. 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 { updateAllClassLogs } from "./class-log.js";
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 updateAllClassLogs();
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}`;
@@ -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 updateAllClassLogs();
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
  })();