create-prisma-php-app 4.0.0-alpha.45 → 4.0.0-alpha.47

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 (2) hide show
  1. package/dist/index.js +93 -331
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -411,7 +411,7 @@ async function createOrUpdateEnvFile(baseDir, content) {
411
411
  fs.writeFileSync(envPath, content, { flag: "w" });
412
412
  }
413
413
  function checkExcludeFiles(destPath) {
414
- if (!updateAnswer) return false;
414
+ if (!updateAnswer?.isUpdate) return false;
415
415
  return (
416
416
  updateAnswer?.excludeFilePath?.includes(destPath.replace(/\\/g, "/")) ??
417
417
  false
@@ -1061,9 +1061,39 @@ async function downloadStarterKit(starterKit, tempDir) {
1061
1061
  }
1062
1062
  async function mergeStarterKitFiles(starterKitPath, projectPath, answer) {
1063
1063
  console.log(chalk.blue("Merging starter kit files..."));
1064
- // Use the new copy function that respects exclusions
1065
- copyRecursiveSyncWithExclusions(starterKitPath, projectPath, answer, true);
1066
- // Look for starter kit specific configuration
1064
+ // First, check if starter kit has a prisma-php.json to preserve excludeFiles
1065
+ const starterKitConfigPath = path.join(starterKitPath, "prisma-php.json");
1066
+ let starterKitExcludeFiles = [];
1067
+ if (fs.existsSync(starterKitConfigPath)) {
1068
+ try {
1069
+ const starterKitConfig = JSON.parse(
1070
+ fs.readFileSync(starterKitConfigPath, "utf8")
1071
+ );
1072
+ starterKitExcludeFiles = starterKitConfig.excludeFiles || [];
1073
+ console.log(
1074
+ chalk.blue(
1075
+ `Found ${starterKitExcludeFiles.length} excluded files in starter kit`
1076
+ )
1077
+ );
1078
+ } catch (error) {
1079
+ console.warn(chalk.yellow("Failed to parse starter kit prisma-php.json"));
1080
+ }
1081
+ }
1082
+ // Temporarily store excludeFiles for the copy process
1083
+ const tempUpdateAnswer = updateAnswer;
1084
+ updateAnswer = {
1085
+ ...answer,
1086
+ isUpdate: false, // Treat as new project for copying
1087
+ excludeFiles: starterKitExcludeFiles,
1088
+ excludeFilePath: starterKitExcludeFiles.map((file) =>
1089
+ path.join(projectPath, file).replace(/\\/g, "/")
1090
+ ),
1091
+ };
1092
+ // Copy all files from starter kit
1093
+ copyRecursiveSync(starterKitPath, projectPath, answer);
1094
+ // Restore original updateAnswer
1095
+ updateAnswer = tempUpdateAnswer;
1096
+ // Handle starter kit specific configuration
1067
1097
  const starterKitConfig = path.join(starterKitPath, "starter-kit.json");
1068
1098
  if (fs.existsSync(starterKitConfig)) {
1069
1099
  const config = JSON.parse(fs.readFileSync(starterKitConfig, "utf8"));
@@ -1090,6 +1120,18 @@ async function mergeStarterKitFiles(starterKitPath, projectPath, answer) {
1090
1120
  );
1091
1121
  }
1092
1122
  }
1123
+ // Store the excludeFiles for later use in main()
1124
+ if (starterKitExcludeFiles.length > 0) {
1125
+ // Create a temporary marker file to pass excludeFiles to main()
1126
+ const tempConfigPath = path.join(
1127
+ projectPath,
1128
+ ".temp-starter-kit-config.json"
1129
+ );
1130
+ fs.writeFileSync(
1131
+ tempConfigPath,
1132
+ JSON.stringify({ excludeFiles: starterKitExcludeFiles })
1133
+ );
1134
+ }
1093
1135
  }
1094
1136
  async function setupStarterKit(baseDir, answer) {
1095
1137
  if (!answer.starterKit) return;
@@ -1183,168 +1225,6 @@ function showStarterKits() {
1183
1225
  );
1184
1226
  console.log();
1185
1227
  }
1186
- // Starter kit specific copy function that respects exclusions
1187
- function copyRecursiveSyncWithExclusions(
1188
- src,
1189
- dest,
1190
- answer,
1191
- respectExclusions = true
1192
- ) {
1193
- const exists = fs.existsSync(src);
1194
- const stats = exists && fs.statSync(src);
1195
- const isDirectory = exists && stats && stats.isDirectory();
1196
- if (isDirectory) {
1197
- const destLower = dest.toLowerCase();
1198
- // Apply feature-based exclusions
1199
- if (!answer.websocket && destLower.includes("websocket")) return;
1200
- if (!answer.mcp && destLower.includes("mcp")) return;
1201
- if (!answer.swaggerDocs && destLower.includes("swagger-docs")) return;
1202
- if (
1203
- answer.backendOnly &&
1204
- (destLower.includes("js") ||
1205
- destLower.includes("css") ||
1206
- destLower.includes("assets"))
1207
- )
1208
- return;
1209
- // Apply user-defined exclusions
1210
- const destModified = dest.replace(/\\/g, "/");
1211
- if (
1212
- respectExclusions &&
1213
- updateAnswer?.excludeFilePath?.includes(destModified)
1214
- ) {
1215
- console.log(chalk.yellow(`Skipping excluded directory: ${destModified}`));
1216
- return;
1217
- }
1218
- if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
1219
- fs.readdirSync(src).forEach((childItemName) => {
1220
- copyRecursiveSyncWithExclusions(
1221
- path.join(src, childItemName),
1222
- path.join(dest, childItemName),
1223
- answer,
1224
- respectExclusions
1225
- );
1226
- });
1227
- } else {
1228
- const fileName = path.basename(dest);
1229
- // Always exclude critical config files from starter kit overwrites
1230
- if (fileName === "prisma-php.json") {
1231
- console.log(
1232
- chalk.yellow(`Protecting config file: ${dest.replace(/\\/g, "/")}`)
1233
- );
1234
- return;
1235
- }
1236
- // Apply user-defined exclusions for files
1237
- if (respectExclusions && checkExcludeFiles(dest)) {
1238
- console.log(
1239
- chalk.yellow(`Skipping excluded file: ${dest.replace(/\\/g, "/")}`)
1240
- );
1241
- return;
1242
- }
1243
- // Apply feature-based exclusions
1244
- if (
1245
- !answer.tailwindcss &&
1246
- (dest.includes("tailwind.css") || dest.includes("styles.css"))
1247
- )
1248
- return;
1249
- if (!answer.websocket && dest.includes("restart-websocket.ts")) return;
1250
- if (!answer.mcp && dest.includes("restart-mcp.ts")) return;
1251
- if (!answer.docker && dockerFiles.some((file) => dest.includes(file)))
1252
- return;
1253
- if (
1254
- answer.backendOnly &&
1255
- nonBackendFiles.some((file) => dest.includes(file))
1256
- )
1257
- return;
1258
- if (!answer.backendOnly && dest.includes("route.php")) return;
1259
- if (
1260
- answer.backendOnly &&
1261
- !answer.swaggerDocs &&
1262
- dest.includes("layout.php")
1263
- )
1264
- return;
1265
- if (!answer.swaggerDocs && dest.includes("swagger-config.ts")) return;
1266
- if (answer.tailwindcss && dest.includes("index.css")) return;
1267
- fs.copyFileSync(src, dest, 0);
1268
- }
1269
- }
1270
- function mergeConfigurationFiles(
1271
- projectPath,
1272
- answer,
1273
- latestVersion,
1274
- existingConfig
1275
- ) {
1276
- const projectPathModified = projectPath.replace(/\\/g, "\\");
1277
- const bsConfig = bsConfigUrls(projectPathModified);
1278
- // If we have existing config, merge with it
1279
- if (existingConfig) {
1280
- console.log(chalk.blue("Merging with existing configuration..."));
1281
- console.log(
1282
- chalk.gray(
1283
- `Preserving excludeFiles: ${JSON.stringify(
1284
- existingConfig.excludeFiles || []
1285
- )}`
1286
- )
1287
- );
1288
- const mergedConfig = {
1289
- ...existingConfig, // Start with existing config to preserve all existing fields
1290
- // Only update specific fields that should be updated for starter kits
1291
- projectName: answer.projectName,
1292
- projectRootPath: projectPathModified,
1293
- bsTarget: bsConfig.bsTarget,
1294
- bsPathRewrite: bsConfig.bsPathRewrite,
1295
- version: latestVersion,
1296
- // Update feature flags based on starter kit
1297
- backendOnly: answer.backendOnly,
1298
- swaggerDocs: answer.swaggerDocs,
1299
- tailwindcss: answer.tailwindcss,
1300
- websocket: answer.websocket,
1301
- mcp: answer.mcp,
1302
- prisma: answer.prisma,
1303
- docker: answer.docker,
1304
- // CRITICAL: Always preserve existing excludeFiles
1305
- excludeFiles: existingConfig.excludeFiles || [],
1306
- };
1307
- fs.writeFileSync(
1308
- path.join(projectPath, "prisma-php.json"),
1309
- JSON.stringify(mergedConfig, null, 2),
1310
- { flag: "w" }
1311
- );
1312
- console.log(chalk.green("✓ Configuration merged successfully!"));
1313
- console.log(
1314
- chalk.green(
1315
- `✓ Preserved ${
1316
- (existingConfig.excludeFiles || []).length
1317
- } excluded files`
1318
- )
1319
- );
1320
- } else {
1321
- console.log(chalk.blue("Creating new configuration..."));
1322
- // New project - create fresh config
1323
- const prismaPhpConfig = {
1324
- projectName: answer.projectName,
1325
- projectRootPath: projectPathModified,
1326
- phpEnvironment: "XAMPP",
1327
- phpRootPathExe: "C:\\xampp\\php\\php.exe",
1328
- bsTarget: bsConfig.bsTarget,
1329
- bsPathRewrite: bsConfig.bsPathRewrite,
1330
- backendOnly: answer.backendOnly,
1331
- swaggerDocs: answer.swaggerDocs,
1332
- tailwindcss: answer.tailwindcss,
1333
- websocket: answer.websocket,
1334
- mcp: answer.mcp,
1335
- prisma: answer.prisma,
1336
- docker: answer.docker,
1337
- version: latestVersion,
1338
- excludeFiles: [],
1339
- };
1340
- fs.writeFileSync(
1341
- path.join(projectPath, "prisma-php.json"),
1342
- JSON.stringify(prismaPhpConfig, null, 2),
1343
- { flag: "w" }
1344
- );
1345
- console.log(chalk.green("✓ New configuration created"));
1346
- }
1347
- }
1348
1228
  async function main() {
1349
1229
  try {
1350
1230
  const args = process.argv.slice(2);
@@ -1366,31 +1246,16 @@ async function main() {
1366
1246
  if (projectName) {
1367
1247
  const currentDir = process.cwd();
1368
1248
  const configPath = path.join(currentDir, "prisma-php.json");
1369
- const projectNamePath = path.join(currentDir, projectName);
1370
- const projectNameConfigPath = path.join(
1371
- projectNamePath,
1372
- "prisma-php.json"
1373
- );
1374
- // Check if there's an existing config in current directory or project directory
1375
- let existingConfigPath = null;
1376
1249
  if (fs.existsSync(configPath)) {
1377
- existingConfigPath = configPath;
1378
- } else if (fs.existsSync(projectNameConfigPath)) {
1379
- existingConfigPath = projectNameConfigPath;
1380
- }
1381
- // If we found an existing config and we're using a starter kit, load exclusions
1382
- if (existingConfigPath && (starterKitFromArgs || starterKitSource)) {
1383
- const localSettings = readJsonFile(existingConfigPath);
1250
+ // It's an update - read existing settings
1251
+ const localSettings = readJsonFile(configPath);
1384
1252
  let excludeFiles = [];
1385
1253
  localSettings.excludeFiles?.map((file) => {
1386
- const filePath = path.join(
1387
- existingConfigPath === configPath ? currentDir : projectNamePath,
1388
- file
1389
- );
1254
+ const filePath = path.join(currentDir, file);
1390
1255
  if (fs.existsSync(filePath))
1391
1256
  excludeFiles.push(filePath.replace(/\\/g, "/"));
1392
1257
  });
1393
- // Set updateAnswer to respect exclusions during starter kit setup
1258
+ // Set updateAnswer with OLD settings initially (for checkExcludeFiles function)
1394
1259
  updateAnswer = {
1395
1260
  projectName,
1396
1261
  backendOnly: localSettings.backendOnly,
@@ -1400,11 +1265,10 @@ async function main() {
1400
1265
  mcp: localSettings.mcp,
1401
1266
  prisma: localSettings.prisma,
1402
1267
  docker: localSettings.docker,
1403
- isUpdate: false, // Not a true update, but we need exclusions to work
1268
+ isUpdate: true,
1404
1269
  excludeFiles: localSettings.excludeFiles ?? [],
1405
1270
  excludeFilePath: excludeFiles ?? [],
1406
- filePath:
1407
- existingConfigPath === configPath ? currentDir : projectNamePath,
1271
+ filePath: currentDir,
1408
1272
  };
1409
1273
  // For updates, use existing settings but allow CLI overrides
1410
1274
  const predefinedAnswers = {
@@ -1524,10 +1388,6 @@ async function main() {
1524
1388
  projectPath = path.join(currentDir, answer.projectName);
1525
1389
  process.chdir(answer.projectName);
1526
1390
  }
1527
- // Add starter kit setup before npm/composer installation
1528
- if (answer.starterKit) {
1529
- await setupStarterKit(projectPath, answer);
1530
- }
1531
1391
  let npmDependencies = [
1532
1392
  npmPkg("typescript"),
1533
1393
  npmPkg("@types/node"),
@@ -1576,6 +1436,10 @@ async function main() {
1576
1436
  if (answer.prisma) {
1577
1437
  execSync("npm install -g prisma-client-php", { stdio: "inherit" });
1578
1438
  }
1439
+ // Add starter kit setup before npm/composer installation
1440
+ if (answer.starterKit) {
1441
+ await setupStarterKit(projectPath, answer);
1442
+ }
1579
1443
  await installNpmDependencies(projectPath, npmDependencies, true);
1580
1444
  await installComposerDependencies(projectPath, composerDependencies);
1581
1445
  if (!projectName) {
@@ -1809,149 +1673,47 @@ async function main() {
1809
1673
  await uninstallComposerDependencies(projectPath, composerToUninstall);
1810
1674
  }
1811
1675
  }
1812
- // Check for existing config to merge with
1813
- let existingConfig = null;
1814
- const finalProjectConfigPath = path.join(projectPath, "prisma-php.json");
1815
- // Function to find prisma-php.json files with excludeFiles
1816
- const findConfigWithExclusions = (searchDir, preferredProjectName) => {
1817
- const entries = fs.readdirSync(searchDir, { withFileTypes: true });
1818
- // First, try to find the preferred project directory
1819
- if (preferredProjectName) {
1820
- const preferredEntry = entries.find(
1821
- (entry) =>
1822
- entry.isDirectory() &&
1823
- entry.name.toLowerCase() === preferredProjectName.toLowerCase()
1824
- );
1825
- if (preferredEntry) {
1826
- const preferredConfigPath = path.join(
1827
- searchDir,
1828
- preferredEntry.name,
1829
- "prisma-php.json"
1830
- );
1831
- if (fs.existsSync(preferredConfigPath)) {
1832
- try {
1833
- const config = JSON.parse(
1834
- fs.readFileSync(preferredConfigPath, "utf8")
1835
- );
1836
- if (config.excludeFiles && config.excludeFiles.length > 0) {
1837
- console.log(
1838
- chalk.blue(
1839
- `Found preferred configuration with exclusions in: ${preferredEntry.name}/`
1840
- )
1841
- );
1842
- console.log(
1843
- chalk.gray(
1844
- `Preferred excludeFiles: ${JSON.stringify(
1845
- config.excludeFiles
1846
- )}`
1847
- )
1848
- );
1849
- return config;
1850
- }
1851
- } catch (error) {
1852
- console.warn(
1853
- chalk.yellow(
1854
- `Could not read preferred config in ${preferredEntry.name}/`
1855
- )
1856
- );
1857
- }
1858
- }
1859
- }
1860
- }
1861
- // If no preferred project found, search all directories
1862
- for (const entry of entries) {
1863
- if (
1864
- entry.isDirectory() &&
1865
- (!preferredProjectName ||
1866
- entry.name.toLowerCase() !== preferredProjectName.toLowerCase())
1867
- ) {
1868
- const subConfigPath = path.join(
1869
- searchDir,
1870
- entry.name,
1871
- "prisma-php.json"
1872
- );
1873
- if (fs.existsSync(subConfigPath)) {
1874
- try {
1875
- const config = JSON.parse(fs.readFileSync(subConfigPath, "utf8"));
1876
- if (config.excludeFiles && config.excludeFiles.length > 0) {
1877
- console.log(
1878
- chalk.blue(
1879
- `Found fallback configuration with exclusions in: ${entry.name}/`
1880
- )
1881
- );
1882
- console.log(
1883
- chalk.gray(
1884
- `Fallback excludeFiles: ${JSON.stringify(
1885
- config.excludeFiles
1886
- )}`
1887
- )
1888
- );
1889
- return config;
1890
- }
1891
- } catch (error) {
1892
- console.warn(
1893
- chalk.yellow(`Could not read config in ${entry.name}/`)
1894
- );
1895
- }
1896
- }
1897
- }
1898
- }
1899
- return null;
1900
- };
1901
- // If no config in current directory, search subdirectories for configs with excludeFiles
1902
- if (!existingConfig) {
1903
- console.log(
1904
- chalk.blue("Searching for existing configurations with exclusions...")
1905
- );
1906
- // Extract project name from starter kit source URL to prioritize the right project
1907
- let preferredProjectName;
1908
- if (answer.starterKitSource) {
1909
- const urlParts = answer.starterKitSource.split("/");
1910
- const repoName = urlParts[urlParts.length - 1].replace(".git", "");
1911
- preferredProjectName = repoName;
1912
- console.log(
1913
- chalk.gray(
1914
- `Looking for local project matching: ${preferredProjectName}`
1915
- )
1916
- );
1917
- }
1918
- existingConfig = findConfigWithExclusions(
1919
- currentDir,
1920
- preferredProjectName
1921
- );
1922
- }
1923
- // If still no config, check the target project directory
1924
- if (!existingConfig && fs.existsSync(finalProjectConfigPath)) {
1676
+ const projectPathModified = projectPath.replace(/\\/g, "\\");
1677
+ const bsConfig = bsConfigUrls(projectPathModified);
1678
+ let starterKitExcludeFiles = [];
1679
+ const tempConfigPath = path.join(
1680
+ projectPath,
1681
+ ".temp-starter-kit-config.json"
1682
+ );
1683
+ if (fs.existsSync(tempConfigPath)) {
1925
1684
  try {
1926
- const rawConfig = fs.readFileSync(finalProjectConfigPath, "utf8");
1927
- existingConfig = JSON.parse(rawConfig);
1928
- console.log(
1929
- chalk.blue("Found existing configuration in project directory")
1930
- );
1931
- console.log(
1932
- chalk.gray(
1933
- `Project excludeFiles: ${JSON.stringify(
1934
- existingConfig.excludeFiles || []
1935
- )}`
1936
- )
1937
- );
1685
+ const tempConfig = JSON.parse(fs.readFileSync(tempConfigPath, "utf8"));
1686
+ starterKitExcludeFiles = tempConfig.excludeFiles || [];
1687
+ fs.unlinkSync(tempConfigPath); // Clean up temp file
1938
1688
  } catch (error) {
1939
- console.warn(chalk.yellow("Could not read project config"));
1940
- existingConfig = null;
1689
+ console.warn("Failed to read temp starter kit config");
1941
1690
  }
1942
1691
  }
1943
- // If still no existing config found
1944
- if (!existingConfig) {
1945
- console.log(
1946
- chalk.blue("No existing configuration found, creating new one...")
1947
- );
1948
- }
1949
- // Merge or create configuration
1950
- mergeConfigurationFiles(
1951
- projectPath,
1952
- answer,
1953
- latestVersionOfCreatePrismaPhpApp,
1954
- existingConfig
1692
+ // Then update the prismaPhpConfig creation:
1693
+ const prismaPhpConfig = {
1694
+ projectName: answer.projectName,
1695
+ projectRootPath: projectPathModified,
1696
+ phpEnvironment: "XAMPP",
1697
+ phpRootPathExe: "C:\\xampp\\php\\php.exe",
1698
+ bsTarget: bsConfig.bsTarget,
1699
+ bsPathRewrite: bsConfig.bsPathRewrite,
1700
+ backendOnly: answer.backendOnly,
1701
+ swaggerDocs: answer.swaggerDocs,
1702
+ tailwindcss: answer.tailwindcss,
1703
+ websocket: answer.websocket,
1704
+ mcp: answer.mcp,
1705
+ prisma: answer.prisma,
1706
+ docker: answer.docker,
1707
+ version: latestVersionOfCreatePrismaPhpApp,
1708
+ excludeFiles:
1709
+ starterKitExcludeFiles.length > 0
1710
+ ? starterKitExcludeFiles
1711
+ : updateAnswer?.excludeFiles ?? [],
1712
+ };
1713
+ fs.writeFileSync(
1714
+ path.join(projectPath, "prisma-php.json"),
1715
+ JSON.stringify(prismaPhpConfig, null, 2),
1716
+ { flag: "w" }
1955
1717
  );
1956
1718
  if (updateAnswer?.isUpdate) {
1957
1719
  execSync(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-prisma-php-app",
3
- "version": "4.0.0-alpha.45",
3
+ "version": "4.0.0-alpha.47",
4
4
  "description": "Prisma-PHP: A Revolutionary Library Bridging PHP with Prisma ORM",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",