strapi2front 0.3.2 → 0.4.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/dist/bin/strapi2front.js +133 -48
- package/dist/bin/strapi2front.js.map +1 -1
- package/dist/index.js +133 -48
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/bin/strapi2front.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import pc4 from 'picocolors';
|
|
4
4
|
import * as p from '@clack/prompts';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
5
|
+
import fs5 from 'fs/promises';
|
|
6
|
+
import path6 from 'path';
|
|
7
7
|
import { spawn, execSync } from 'child_process';
|
|
8
|
-
import
|
|
8
|
+
import fs6 from 'fs';
|
|
9
9
|
import { loadConfig, detectStrapiVersion, fetchSchema, parseSchema } from '@strapi2front/core';
|
|
10
10
|
import { generateByFeature, generateTypes, generateClient, generateLocales, generateServices, generateActions } from '@strapi2front/generators';
|
|
11
11
|
|
|
@@ -24,17 +24,17 @@ var FRAMEWORK_DETECTORS = {
|
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
async function detectFramework(cwd = process.cwd()) {
|
|
27
|
-
const pkgPath =
|
|
27
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
28
28
|
try {
|
|
29
|
-
const pkgContent = await
|
|
29
|
+
const pkgContent = await fs5.readFile(pkgPath, "utf-8");
|
|
30
30
|
const pkg = JSON.parse(pkgContent);
|
|
31
31
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
32
32
|
for (const [pkgName, detector] of Object.entries(FRAMEWORK_DETECTORS)) {
|
|
33
33
|
if (deps[pkgName]) {
|
|
34
34
|
for (const configFile of detector.configFiles) {
|
|
35
|
-
const configPath =
|
|
35
|
+
const configPath = path6.join(cwd, configFile);
|
|
36
36
|
try {
|
|
37
|
-
await
|
|
37
|
+
await fs5.access(configPath);
|
|
38
38
|
return {
|
|
39
39
|
name: detector.name,
|
|
40
40
|
version: deps[pkgName],
|
|
@@ -70,12 +70,12 @@ function getFrameworkDisplayName(framework) {
|
|
|
70
70
|
var TS_CONFIG_FILES = ["tsconfig.json", "tsconfig.app.json"];
|
|
71
71
|
async function detectTypeScript(cwd = process.cwd()) {
|
|
72
72
|
for (const configFile of TS_CONFIG_FILES) {
|
|
73
|
-
const configPath =
|
|
73
|
+
const configPath = path6.join(cwd, configFile);
|
|
74
74
|
try {
|
|
75
|
-
await
|
|
76
|
-
const pkgPath =
|
|
75
|
+
await fs5.access(configPath);
|
|
76
|
+
const pkgPath = path6.join(cwd, "package.json");
|
|
77
77
|
try {
|
|
78
|
-
const pkgContent = await
|
|
78
|
+
const pkgContent = await fs5.readFile(pkgPath, "utf-8");
|
|
79
79
|
const pkg = JSON.parse(pkgContent);
|
|
80
80
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
81
81
|
return {
|
|
@@ -107,9 +107,9 @@ var LOCK_FILES = {
|
|
|
107
107
|
};
|
|
108
108
|
async function detectPackageManager(cwd = process.cwd()) {
|
|
109
109
|
for (const [lockFile, pm] of Object.entries(LOCK_FILES)) {
|
|
110
|
-
const lockPath =
|
|
110
|
+
const lockPath = path6.join(cwd, lockFile);
|
|
111
111
|
try {
|
|
112
|
-
await
|
|
112
|
+
await fs5.access(lockPath);
|
|
113
113
|
return {
|
|
114
114
|
name: pm,
|
|
115
115
|
lockFile
|
|
@@ -140,6 +140,34 @@ function getInstallDevCommand(pm, pkg) {
|
|
|
140
140
|
};
|
|
141
141
|
return commands2[pm];
|
|
142
142
|
}
|
|
143
|
+
async function detectModuleType(cwd = process.cwd()) {
|
|
144
|
+
try {
|
|
145
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
146
|
+
const content = await fs5.readFile(packageJsonPath, "utf-8");
|
|
147
|
+
const packageJson = JSON.parse(content);
|
|
148
|
+
if (packageJson.type === "module") {
|
|
149
|
+
return { type: "esm", reason: 'package.json has "type": "module"' };
|
|
150
|
+
}
|
|
151
|
+
if (packageJson.type === "commonjs") {
|
|
152
|
+
return { type: "commonjs", reason: 'package.json has "type": "commonjs"' };
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
const esmIndicators = [
|
|
157
|
+
"next.config.mjs",
|
|
158
|
+
"nuxt.config.mjs",
|
|
159
|
+
"vite.config.mjs",
|
|
160
|
+
"astro.config.mjs"
|
|
161
|
+
];
|
|
162
|
+
for (const file of esmIndicators) {
|
|
163
|
+
try {
|
|
164
|
+
await fs5.access(path6.join(cwd, file));
|
|
165
|
+
return { type: "esm", reason: `Found ${file} (ESM config file)` };
|
|
166
|
+
} catch {
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return { type: "commonjs", reason: "Default (no ESM indicators found)" };
|
|
170
|
+
}
|
|
143
171
|
function getMajorVersion(version) {
|
|
144
172
|
if (!version) return null;
|
|
145
173
|
const match = version.replace(/^[\^~]/, "").match(/^(\d+)/);
|
|
@@ -350,6 +378,11 @@ async function initCommand(_options) {
|
|
|
350
378
|
}
|
|
351
379
|
s.start("Creating configuration files...");
|
|
352
380
|
try {
|
|
381
|
+
let moduleType = "commonjs";
|
|
382
|
+
if (answers.outputFormat === "jsdoc") {
|
|
383
|
+
const detected = await detectModuleType(cwd);
|
|
384
|
+
moduleType = detected.type;
|
|
385
|
+
}
|
|
353
386
|
const configExtension = answers.outputFormat === "jsdoc" ? "js" : "ts";
|
|
354
387
|
const configContent = generateConfigFile({
|
|
355
388
|
strapiUrl: answers.strapiUrl,
|
|
@@ -358,17 +391,18 @@ async function initCommand(_options) {
|
|
|
358
391
|
outputFormat: answers.outputFormat,
|
|
359
392
|
outputDir: answers.outputDir,
|
|
360
393
|
generateActions: answers.generateActions,
|
|
361
|
-
generateServices: answers.generateServices
|
|
394
|
+
generateServices: answers.generateServices,
|
|
395
|
+
moduleType
|
|
362
396
|
});
|
|
363
|
-
const configPath =
|
|
364
|
-
await
|
|
365
|
-
const envPath =
|
|
397
|
+
const configPath = path6.join(cwd, `strapi.config.${configExtension}`);
|
|
398
|
+
await fs5.writeFile(configPath, configContent, "utf-8");
|
|
399
|
+
const envPath = path6.join(cwd, ".env");
|
|
366
400
|
await appendToEnvFile(envPath, {
|
|
367
401
|
STRAPI_URL: answers.strapiUrl,
|
|
368
402
|
STRAPI_TOKEN: answers.strapiToken
|
|
369
403
|
});
|
|
370
|
-
const outputPath =
|
|
371
|
-
await
|
|
404
|
+
const outputPath = path6.join(cwd, answers.outputDir);
|
|
405
|
+
await fs5.mkdir(outputPath, { recursive: true });
|
|
372
406
|
s.stop("Configuration files created");
|
|
373
407
|
const installDeps = await p.confirm({
|
|
374
408
|
message: "Install required dependencies (strapi2front, strapi-sdk-js)?",
|
|
@@ -428,6 +462,7 @@ async function initCommand(_options) {
|
|
|
428
462
|
}
|
|
429
463
|
function generateConfigFile(answers) {
|
|
430
464
|
const isTypeScript = answers.outputFormat === "typescript";
|
|
465
|
+
const useESM = answers.moduleType === "esm";
|
|
431
466
|
if (isTypeScript) {
|
|
432
467
|
return `import { defineConfig } from "strapi2front";
|
|
433
468
|
|
|
@@ -461,6 +496,44 @@ export default defineConfig({
|
|
|
461
496
|
// Strapi version
|
|
462
497
|
strapiVersion: "${answers.strapiVersion}",
|
|
463
498
|
});
|
|
499
|
+
`;
|
|
500
|
+
}
|
|
501
|
+
if (useESM) {
|
|
502
|
+
return `// @ts-check
|
|
503
|
+
import { defineConfig } from "strapi2front";
|
|
504
|
+
|
|
505
|
+
export default defineConfig({
|
|
506
|
+
// Strapi connection
|
|
507
|
+
url: process.env.STRAPI_URL || "${answers.strapiUrl}",
|
|
508
|
+
token: process.env.STRAPI_TOKEN,
|
|
509
|
+
|
|
510
|
+
// API prefix (default: "/api")
|
|
511
|
+
apiPrefix: "${answers.apiPrefix}",
|
|
512
|
+
|
|
513
|
+
// Output format: "typescript" (.ts) or "jsdoc" (.js with JSDoc)
|
|
514
|
+
outputFormat: "jsdoc",
|
|
515
|
+
|
|
516
|
+
// Module type: auto-detected as ESM
|
|
517
|
+
moduleType: "esm",
|
|
518
|
+
|
|
519
|
+
// Output configuration
|
|
520
|
+
output: {
|
|
521
|
+
path: "${answers.outputDir}",
|
|
522
|
+
types: "types",
|
|
523
|
+
services: "services",
|
|
524
|
+
structure: 'by-feature' // or 'by-layer'
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
// Features to generate
|
|
528
|
+
features: {
|
|
529
|
+
types: true,
|
|
530
|
+
services: ${answers.generateServices},
|
|
531
|
+
actions: false, // Actions require TypeScript
|
|
532
|
+
},
|
|
533
|
+
|
|
534
|
+
// Strapi version
|
|
535
|
+
strapiVersion: "${answers.strapiVersion}",
|
|
536
|
+
});
|
|
464
537
|
`;
|
|
465
538
|
}
|
|
466
539
|
return `// @ts-check
|
|
@@ -500,7 +573,7 @@ module.exports = defineConfig({
|
|
|
500
573
|
async function appendToEnvFile(envPath, variables) {
|
|
501
574
|
let content = "";
|
|
502
575
|
try {
|
|
503
|
-
content = await
|
|
576
|
+
content = await fs5.readFile(envPath, "utf-8");
|
|
504
577
|
} catch {
|
|
505
578
|
}
|
|
506
579
|
const lines = content.split("\n");
|
|
@@ -516,7 +589,7 @@ async function appendToEnvFile(envPath, variables) {
|
|
|
516
589
|
if (newLines.length > 0) {
|
|
517
590
|
const separator = content.endsWith("\n") || content === "" ? "" : "\n";
|
|
518
591
|
const newContent = content + separator + newLines.join("\n") + "\n";
|
|
519
|
-
await
|
|
592
|
+
await fs5.writeFile(envPath, newContent, "utf-8");
|
|
520
593
|
}
|
|
521
594
|
}
|
|
522
595
|
var BLOCKS_RENDERER_PACKAGE = "@strapi/blocks-react-renderer";
|
|
@@ -542,9 +615,9 @@ function schemaHasBlocks(schema) {
|
|
|
542
615
|
}
|
|
543
616
|
function isPackageInstalled(packageName, cwd) {
|
|
544
617
|
try {
|
|
545
|
-
const packageJsonPath =
|
|
546
|
-
if (!
|
|
547
|
-
const packageJson = JSON.parse(
|
|
618
|
+
const packageJsonPath = path6.join(cwd, "package.json");
|
|
619
|
+
if (!fs6.existsSync(packageJsonPath)) return false;
|
|
620
|
+
const packageJson = JSON.parse(fs6.readFileSync(packageJsonPath, "utf-8"));
|
|
548
621
|
const deps = {
|
|
549
622
|
...packageJson.dependencies,
|
|
550
623
|
...packageJson.devDependencies
|
|
@@ -555,9 +628,9 @@ function isPackageInstalled(packageName, cwd) {
|
|
|
555
628
|
}
|
|
556
629
|
}
|
|
557
630
|
function detectPackageManager2(cwd) {
|
|
558
|
-
if (
|
|
559
|
-
if (
|
|
560
|
-
if (
|
|
631
|
+
if (fs6.existsSync(path6.join(cwd, "bun.lockb"))) return "bun";
|
|
632
|
+
if (fs6.existsSync(path6.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
633
|
+
if (fs6.existsSync(path6.join(cwd, "yarn.lock"))) return "yarn";
|
|
561
634
|
return "npm";
|
|
562
635
|
}
|
|
563
636
|
function installPackage(packageName, cwd) {
|
|
@@ -575,22 +648,22 @@ function getOrphanedFolders(outputPath, currentStructure) {
|
|
|
575
648
|
if (currentStructure === "by-feature") {
|
|
576
649
|
const byLayerFolders = ["types", "services", "actions"];
|
|
577
650
|
for (const folder of byLayerFolders) {
|
|
578
|
-
const folderPath =
|
|
579
|
-
if (
|
|
651
|
+
const folderPath = path6.join(outputPath, folder);
|
|
652
|
+
if (fs6.existsSync(folderPath)) {
|
|
580
653
|
orphanedFolders.push(folder);
|
|
581
654
|
}
|
|
582
655
|
}
|
|
583
|
-
if (
|
|
656
|
+
if (fs6.existsSync(path6.join(outputPath, "client.ts"))) {
|
|
584
657
|
orphanedFolders.push("client.ts");
|
|
585
658
|
}
|
|
586
|
-
if (
|
|
659
|
+
if (fs6.existsSync(path6.join(outputPath, "locales.ts"))) {
|
|
587
660
|
orphanedFolders.push("locales.ts");
|
|
588
661
|
}
|
|
589
662
|
} else {
|
|
590
663
|
const byFeatureFolders = ["collections", "singles", "shared", "components"];
|
|
591
664
|
for (const folder of byFeatureFolders) {
|
|
592
|
-
const folderPath =
|
|
593
|
-
if (
|
|
665
|
+
const folderPath = path6.join(outputPath, folder);
|
|
666
|
+
if (fs6.existsSync(folderPath)) {
|
|
594
667
|
orphanedFolders.push(folder);
|
|
595
668
|
}
|
|
596
669
|
}
|
|
@@ -599,13 +672,13 @@ function getOrphanedFolders(outputPath, currentStructure) {
|
|
|
599
672
|
}
|
|
600
673
|
function cleanOrphanedFiles(outputPath, orphanedItems) {
|
|
601
674
|
for (const item of orphanedItems) {
|
|
602
|
-
const itemPath =
|
|
603
|
-
if (
|
|
604
|
-
const stat =
|
|
675
|
+
const itemPath = path6.join(outputPath, item);
|
|
676
|
+
if (fs6.existsSync(itemPath)) {
|
|
677
|
+
const stat = fs6.statSync(itemPath);
|
|
605
678
|
if (stat.isDirectory()) {
|
|
606
|
-
|
|
679
|
+
fs6.rmSync(itemPath, { recursive: true, force: true });
|
|
607
680
|
} else {
|
|
608
|
-
|
|
681
|
+
fs6.unlinkSync(itemPath);
|
|
609
682
|
}
|
|
610
683
|
}
|
|
611
684
|
}
|
|
@@ -672,12 +745,12 @@ async function syncCommand(options) {
|
|
|
672
745
|
p.log.info(pc4.dim(`Skipping ${BLOCKS_RENDERER_PACKAGE}. BlocksContent will be typed as unknown[]`));
|
|
673
746
|
}
|
|
674
747
|
}
|
|
675
|
-
const outputPath =
|
|
748
|
+
const outputPath = path6.join(cwd, config.output.path);
|
|
676
749
|
const generatedFiles = [];
|
|
677
750
|
const generateAll = !options.typesOnly && !options.servicesOnly && !options.actionsOnly;
|
|
678
751
|
const isByFeature = config.output.structure === "by-feature";
|
|
679
752
|
const currentStructure = isByFeature ? "by-feature" : "by-layer";
|
|
680
|
-
if (
|
|
753
|
+
if (fs6.existsSync(outputPath)) {
|
|
681
754
|
const orphanedFolders = getOrphanedFolders(outputPath, currentStructure);
|
|
682
755
|
if (orphanedFolders.length > 0) {
|
|
683
756
|
const otherStructure = isByFeature ? "by-layer" : "by-feature";
|
|
@@ -707,6 +780,17 @@ async function syncCommand(options) {
|
|
|
707
780
|
}
|
|
708
781
|
}
|
|
709
782
|
const outputFormat = config.outputFormat || "typescript";
|
|
783
|
+
let moduleType = "commonjs";
|
|
784
|
+
if (outputFormat === "jsdoc") {
|
|
785
|
+
if (config.moduleType) {
|
|
786
|
+
moduleType = config.moduleType;
|
|
787
|
+
p.log.info(`Module type: ${pc4.cyan(moduleType)} (from config)`);
|
|
788
|
+
} else {
|
|
789
|
+
const detected = await detectModuleType(cwd);
|
|
790
|
+
moduleType = detected.type;
|
|
791
|
+
p.log.info(`Module type: ${pc4.cyan(moduleType)} (${detected.reason})`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
710
794
|
if (isByFeature) {
|
|
711
795
|
s.start(`Generating files (by-feature, ${outputFormat})...`);
|
|
712
796
|
const files = await generateByFeature(schema, rawSchema.locales, {
|
|
@@ -719,7 +803,8 @@ async function syncCommand(options) {
|
|
|
719
803
|
blocksRendererInstalled,
|
|
720
804
|
strapiVersion: config.strapiVersion,
|
|
721
805
|
apiPrefix: config.apiPrefix,
|
|
722
|
-
outputFormat
|
|
806
|
+
outputFormat,
|
|
807
|
+
moduleType
|
|
723
808
|
});
|
|
724
809
|
generatedFiles.push(...files);
|
|
725
810
|
s.stop(`Generated ${files.length} files`);
|
|
@@ -727,7 +812,7 @@ async function syncCommand(options) {
|
|
|
727
812
|
if (generateAll || options.typesOnly) {
|
|
728
813
|
if (config.features.types) {
|
|
729
814
|
s.start(`Generating types (${outputFormat})...`);
|
|
730
|
-
const typesPath =
|
|
815
|
+
const typesPath = path6.join(outputPath, config.output.types);
|
|
731
816
|
const files = await generateTypes(schema, {
|
|
732
817
|
outputDir: typesPath,
|
|
733
818
|
blocksRendererInstalled,
|
|
@@ -757,8 +842,8 @@ async function syncCommand(options) {
|
|
|
757
842
|
if (generateAll || options.servicesOnly) {
|
|
758
843
|
if (config.features.services) {
|
|
759
844
|
s.start(`Generating services (${outputFormat})...`);
|
|
760
|
-
const servicesPath =
|
|
761
|
-
const typesImportPath =
|
|
845
|
+
const servicesPath = path6.join(outputPath, config.output.services);
|
|
846
|
+
const typesImportPath = path6.relative(servicesPath, path6.join(outputPath, config.output.types)).replace(/\\/g, "/") || ".";
|
|
762
847
|
const files = await generateServices(schema, {
|
|
763
848
|
outputDir: servicesPath,
|
|
764
849
|
typesImportPath: typesImportPath.startsWith(".") ? typesImportPath : "./" + typesImportPath,
|
|
@@ -772,9 +857,9 @@ async function syncCommand(options) {
|
|
|
772
857
|
if ((generateAll || options.actionsOnly) && outputFormat === "typescript") {
|
|
773
858
|
if (config.features.actions) {
|
|
774
859
|
s.start("Generating Astro actions...");
|
|
775
|
-
const actionsPath =
|
|
776
|
-
const servicesPath =
|
|
777
|
-
const servicesImportPath =
|
|
860
|
+
const actionsPath = path6.join(outputPath, config.output.actions);
|
|
861
|
+
const servicesPath = path6.join(outputPath, config.output.services);
|
|
862
|
+
const servicesImportPath = path6.relative(actionsPath, servicesPath).replace(/\\/g, "/") || ".";
|
|
778
863
|
const files = await generateActions(schema, {
|
|
779
864
|
outputDir: actionsPath,
|
|
780
865
|
servicesImportPath: servicesImportPath.startsWith(".") ? servicesImportPath : "./" + servicesImportPath,
|
|
@@ -790,7 +875,7 @@ async function syncCommand(options) {
|
|
|
790
875
|
`Generated ${generatedFiles.length} files in ${pc4.cyan(config.output.path)}`,
|
|
791
876
|
"",
|
|
792
877
|
"Files generated:",
|
|
793
|
-
...generatedFiles.slice(0, 10).map((f) => ` ${pc4.dim(
|
|
878
|
+
...generatedFiles.slice(0, 10).map((f) => ` ${pc4.dim(path6.relative(cwd, f))}`),
|
|
794
879
|
generatedFiles.length > 10 ? ` ${pc4.dim(`... and ${generatedFiles.length - 10} more`)}` : ""
|
|
795
880
|
].filter(Boolean).join("\n"),
|
|
796
881
|
"Sync complete!"
|