create-epinoetics-app 1.0.2 → 1.0.5

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 (3) hide show
  1. package/README +2 -0
  2. package/package.json +1 -1
  3. package/src/cloner.js +110 -9
package/README CHANGED
@@ -0,0 +1,2 @@
1
+ ```shell
2
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-epinoetics-app",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "Scaffold a new project from your boilerplate repos",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cloner.js CHANGED
@@ -64,18 +64,27 @@ export async function cloneAndMergeNest({ projectName, database, selectedFeature
64
64
  );
65
65
  }
66
66
 
67
- // 3. Prune schema.tsremove export lines for deleted features
68
- await pruneSchema({ dest, toRemove });
67
+ // 3. Prune schema — Drizzle or Prisma depending on db choice
68
+ if (database.id === 'drizzle') {
69
+ pruneDrizzleSchema({ dest, toRemove });
70
+ } else if (database.id === 'prisma') {
71
+ prunePrismaSchema({ dest, toRemove });
72
+ }
73
+
74
+ // 4. Prune app.module.ts — remove imports and module references
75
+ pruneAppModule({ dest, toRemove });
69
76
 
70
- // 4. Strip .git
77
+ // 5. Remove migrations directory
78
+ pruneMigrations({ dest, database });
79
+
80
+ // 6. Strip .git
71
81
  fs.rmSync(join(dest, '.git'), { recursive: true, force: true });
72
82
  }
73
83
 
74
- // ── Remove export * lines from schema.ts for deleted features ─────
75
- async function pruneSchema({ dest, toRemove }) {
84
+ // ── Drizzle: remove export * lines from schema.ts ─────────────────
85
+ function pruneDrizzleSchema({ dest, toRemove }) {
76
86
  if (toRemove.length === 0) return;
77
87
 
78
- // Check common schema.ts locations
79
88
  const candidates = [
80
89
  join(dest, 'src', 'database', 'schema.ts'),
81
90
  join(dest, 'src', 'db', 'schema.ts'),
@@ -92,9 +101,7 @@ async function pruneSchema({ dest, toRemove }) {
92
101
  const before = content;
93
102
 
94
103
  for (const feature of toRemove) {
95
- // Matches lines like:
96
- // export * from '../features/posts/post.schema';
97
- // export * from "../features/seo/seo.schema";
104
+ // Removes: export * from '../features/posts/post.schema';
98
105
  const pattern = new RegExp(
99
106
  `^export \\* from ['"].*features\\/${feature.id}\\/.*['"];?\\n?`,
100
107
  'gm'
@@ -106,4 +113,98 @@ async function pruneSchema({ dest, toRemove }) {
106
113
  fs.writeFileSync(schemaPath, content, 'utf8');
107
114
  p.log.step(`Pruned schema.ts ${chalk.dim(`(removed ${toRemove.length} export line(s))`)}`);
108
115
  }
116
+ }
117
+
118
+ // ── Prisma: remove model blocks from schema.prisma ────────────────
119
+ //
120
+ // Convention in schema.prisma:
121
+ //
122
+ // // @feature:posts
123
+ // model Post { ... }
124
+ // model PostTag { ... }
125
+ // // @end:posts
126
+ //
127
+ function prunePrismaSchema({ dest, toRemove }) {
128
+ if (toRemove.length === 0) return;
129
+
130
+ const candidates = [
131
+ join(dest, 'prisma', 'schema.prisma'),
132
+ join(dest, 'schema.prisma'),
133
+ ];
134
+
135
+ const schemaPath = candidates.find(f => fs.existsSync(f));
136
+ if (!schemaPath) {
137
+ p.log.warn('Could not find schema.prisma — remove unused models manually.');
138
+ return;
139
+ }
140
+
141
+ let content = fs.readFileSync(schemaPath, 'utf8');
142
+ const before = content;
143
+
144
+ for (const feature of toRemove) {
145
+ // Removes everything between // @feature:posts and // @end:posts (inclusive)
146
+ const pattern = new RegExp(
147
+ `\\/\\/ @feature:${feature.id}\\n[\\s\\S]*?\\/\\/ @end:${feature.id}\\n?`,
148
+ 'g'
149
+ );
150
+ content = content.replace(pattern, '');
151
+ }
152
+
153
+ if (content !== before) {
154
+ fs.writeFileSync(schemaPath, content, 'utf8');
155
+ p.log.step(`Pruned schema.prisma ${chalk.dim(`(removed ${toRemove.length} model block(s))`)}`);
156
+ }
157
+ }
158
+
159
+ // ── Remove import + Module reference from app.module.ts ───────────
160
+ function pruneAppModule({ dest, toRemove }) {
161
+ if (toRemove.length === 0) return;
162
+
163
+ const appModulePath = join(dest, 'src', 'app.module.ts');
164
+ if (!fs.existsSync(appModulePath)) {
165
+ p.log.warn('Could not find app.module.ts — remove unused imports manually.');
166
+ return;
167
+ }
168
+
169
+ let content = fs.readFileSync(appModulePath, 'utf8');
170
+ const before = content;
171
+
172
+ for (const feature of toRemove) {
173
+ // e.g. posts → PostsModule, seo → SeoModule
174
+ const moduleName = feature.id.charAt(0).toUpperCase() + feature.id.slice(1) + 'Module';
175
+
176
+ // Remove the import line:
177
+ // import { PostsModule } from './features/posts/posts.module';
178
+ const importPattern = new RegExp(
179
+ `^import \\{[^}]*${moduleName}[^}]*\\} from ['"].*features\\/${feature.id}\\/.*['"];?\\n?`,
180
+ 'gm'
181
+ );
182
+ content = content.replace(importPattern, '');
183
+
184
+ // Remove the module from the imports array
185
+ const refPattern = new RegExp(
186
+ `\\n?\\s*${moduleName},?|,?\\s*${moduleName}`,
187
+ 'g'
188
+ );
189
+ content = content.replace(refPattern, '');
190
+ }
191
+
192
+ if (content !== before) {
193
+ fs.writeFileSync(appModulePath, content, 'utf8');
194
+ p.log.step(`Pruned app.module.ts ${chalk.dim(`(removed ${toRemove.length} module(s))`)}`);
195
+ }
196
+ }
197
+
198
+ // ── Remove migrations directory ───────────────────────────────────
199
+ function pruneMigrations({ dest, database }) {
200
+ const candidates = database.id === 'drizzle'
201
+ ? [join(dest, 'migrations'), join(dest, 'drizzle')]
202
+ : [join(dest, 'prisma', 'migrations')];
203
+
204
+ for (const dir of candidates) {
205
+ if (fs.existsSync(dir)) {
206
+ fs.rmSync(dir, { recursive: true, force: true });
207
+ p.log.step(`Removed migrations ${chalk.dim(dir.replace(dest, ''))}`);
208
+ }
209
+ }
109
210
  }