create-caspian-app 0.0.19 → 0.0.20
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 +2 -2
- package/dist/settings/vite-plugins/generate-global-types.ts +107 -50
- package/dist/vite.config.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -352,11 +352,11 @@ npx create-caspian-app
|
|
|
352
352
|
|
|
353
353
|
### Useful flags
|
|
354
354
|
|
|
355
|
+
- `--backend-only` skip frontend assets
|
|
355
356
|
- `--tailwindcss` Tailwind CSS v4 + PostCSS + `globals.css`
|
|
356
357
|
- `--typescript` TypeScript support with Vite + `tsconfig.json`
|
|
357
|
-
- `--websocket` WebSocket server scaffolding
|
|
358
358
|
- `--mcp` Model Context Protocol server scaffolding (AI Agents)
|
|
359
|
-
- `--
|
|
359
|
+
- `--prisma` Prisma ORM integration + sample schema
|
|
360
360
|
|
|
361
361
|
### Code generation
|
|
362
362
|
|
|
@@ -29,10 +29,12 @@ export function generateGlobalTypes(): Plugin {
|
|
|
29
29
|
},
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
+
|
|
32
33
|
interface GlobalDeclaration {
|
|
33
34
|
name: string;
|
|
34
35
|
importPath: string;
|
|
35
36
|
exportName: string;
|
|
37
|
+
isNamespace: boolean;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
function parseGlobalSingletons(
|
|
@@ -47,7 +49,10 @@ function parseGlobalSingletons(
|
|
|
47
49
|
);
|
|
48
50
|
|
|
49
51
|
const globals: GlobalDeclaration[] = [];
|
|
50
|
-
const importMap = new Map<
|
|
52
|
+
const importMap = new Map<
|
|
53
|
+
string,
|
|
54
|
+
{ path: string; originalName: string; isNamespace: boolean }
|
|
55
|
+
>();
|
|
51
56
|
|
|
52
57
|
sf.statements.forEach((stmt) => {
|
|
53
58
|
if (ts.isImportDeclaration(stmt) && stmt.importClause) {
|
|
@@ -64,9 +69,24 @@ function parseGlobalSingletons(
|
|
|
64
69
|
importMap.set(localName, {
|
|
65
70
|
path: moduleSpecifier,
|
|
66
71
|
originalName: importedName,
|
|
72
|
+
isNamespace: false,
|
|
67
73
|
});
|
|
68
74
|
});
|
|
75
|
+
} else if (ts.isNamespaceImport(stmt.importClause.namedBindings)) {
|
|
76
|
+
const localName = stmt.importClause.namedBindings.name.text;
|
|
77
|
+
importMap.set(localName, {
|
|
78
|
+
path: moduleSpecifier,
|
|
79
|
+
originalName: localName,
|
|
80
|
+
isNamespace: true,
|
|
81
|
+
});
|
|
69
82
|
}
|
|
83
|
+
} else if (stmt.importClause.name) {
|
|
84
|
+
const localName = stmt.importClause.name.text;
|
|
85
|
+
importMap.set(localName, {
|
|
86
|
+
path: moduleSpecifier,
|
|
87
|
+
originalName: "default",
|
|
88
|
+
isNamespace: false,
|
|
89
|
+
});
|
|
70
90
|
}
|
|
71
91
|
}
|
|
72
92
|
});
|
|
@@ -91,12 +111,12 @@ function parseGlobalSingletons(
|
|
|
91
111
|
name,
|
|
92
112
|
importPath: importInfo.path,
|
|
93
113
|
exportName: importInfo.originalName,
|
|
114
|
+
isNamespace: importInfo.isNamespace,
|
|
94
115
|
});
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
|
-
|
|
100
120
|
ts.forEachChild(node, visit);
|
|
101
121
|
}
|
|
102
122
|
|
|
@@ -114,82 +134,121 @@ function generateDtsWithTypeChecker(
|
|
|
114
134
|
ts.sys.fileExists,
|
|
115
135
|
"tsconfig.json"
|
|
116
136
|
);
|
|
117
|
-
|
|
118
137
|
const { config } = configPath
|
|
119
138
|
? ts.readConfigFile(configPath, ts.sys.readFile)
|
|
120
139
|
: { config: {} };
|
|
121
|
-
|
|
122
|
-
const { options } = ts.parseJsonConfigFileContent(
|
|
140
|
+
const parsedConfig = ts.parseJsonConfigFileContent(
|
|
123
141
|
config,
|
|
124
142
|
ts.sys,
|
|
125
143
|
process.cwd()
|
|
126
144
|
);
|
|
127
145
|
|
|
128
|
-
const program = ts.createProgram(
|
|
146
|
+
const program = ts.createProgram(
|
|
147
|
+
parsedConfig.fileNames,
|
|
148
|
+
parsedConfig.options
|
|
149
|
+
);
|
|
129
150
|
const checker = program.getTypeChecker();
|
|
130
151
|
const sourceFile = program.getSourceFile(mainPath);
|
|
131
152
|
|
|
132
153
|
if (!sourceFile) {
|
|
133
|
-
console.warn("⚠️ Could not load main.ts for type checking");
|
|
134
154
|
generateFallbackDts(globals, dtsPath);
|
|
135
155
|
return;
|
|
136
156
|
}
|
|
137
157
|
|
|
138
158
|
const signatures = new Map<string, string>();
|
|
139
|
-
|
|
140
159
|
const importMap = new Map<string, ts.ImportDeclaration>();
|
|
160
|
+
|
|
141
161
|
sourceFile.statements.forEach((stmt) => {
|
|
142
|
-
if (ts.isImportDeclaration(stmt)
|
|
143
|
-
if (
|
|
144
|
-
stmt.importClause.namedBindings
|
|
145
|
-
|
|
146
|
-
|
|
162
|
+
if (ts.isImportDeclaration(stmt)) {
|
|
163
|
+
if (stmt.importClause?.namedBindings) {
|
|
164
|
+
if (ts.isNamedImports(stmt.importClause.namedBindings)) {
|
|
165
|
+
stmt.importClause.namedBindings.elements.forEach((element) => {
|
|
166
|
+
importMap.set(element.name.text, stmt);
|
|
167
|
+
});
|
|
168
|
+
} else if (ts.isNamespaceImport(stmt.importClause.namedBindings)) {
|
|
169
|
+
importMap.set(stmt.importClause.namedBindings.name.text, stmt);
|
|
170
|
+
}
|
|
171
|
+
} else if (stmt.importClause?.name) {
|
|
172
|
+
importMap.set(stmt.importClause.name.text, stmt);
|
|
147
173
|
}
|
|
148
174
|
}
|
|
149
175
|
});
|
|
150
176
|
|
|
151
|
-
globals.forEach(({ name, exportName }) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
signatures.set(name, "(...args: any[]) => any");
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
177
|
+
globals.forEach(({ name, exportName, importPath, isNamespace }) => {
|
|
178
|
+
// RESOLVE SIGNATURE
|
|
179
|
+
const isExternalLibrary =
|
|
180
|
+
!importPath.startsWith(".") && !importPath.startsWith("/");
|
|
158
181
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
182
|
+
if (isExternalLibrary) {
|
|
183
|
+
if (isNamespace) {
|
|
184
|
+
signatures.set(name, `typeof import("${importPath}")`);
|
|
185
|
+
} else {
|
|
186
|
+
signatures.set(name, `typeof import("${importPath}").${exportName}`);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
163
190
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
191
|
+
try {
|
|
192
|
+
const importDecl =
|
|
193
|
+
importMap.get(exportName === "default" ? name : exportName) ||
|
|
194
|
+
importMap.get(isNamespace ? name : exportName);
|
|
195
|
+
let symbol: ts.Symbol | undefined;
|
|
196
|
+
|
|
197
|
+
if (importDecl && importDecl.importClause) {
|
|
198
|
+
if (importDecl.importClause.namedBindings) {
|
|
199
|
+
if (ts.isNamedImports(importDecl.importClause.namedBindings)) {
|
|
200
|
+
const importSpec =
|
|
201
|
+
importDecl.importClause.namedBindings.elements.find(
|
|
202
|
+
(el) =>
|
|
203
|
+
(el.propertyName?.text || el.name.text) === exportName ||
|
|
204
|
+
el.name.text === exportName
|
|
205
|
+
);
|
|
206
|
+
if (importSpec)
|
|
207
|
+
symbol = checker.getSymbolAtLocation(importSpec.name);
|
|
208
|
+
} else if (
|
|
209
|
+
ts.isNamespaceImport(importDecl.importClause.namedBindings)
|
|
210
|
+
) {
|
|
211
|
+
symbol = checker.getSymbolAtLocation(
|
|
212
|
+
importDecl.importClause.namedBindings.name
|
|
175
213
|
);
|
|
176
|
-
signatures.set(name, signature);
|
|
177
|
-
return;
|
|
178
214
|
}
|
|
215
|
+
} else if (importDecl.importClause.name) {
|
|
216
|
+
symbol = checker.getSymbolAtLocation(importDecl.importClause.name);
|
|
179
217
|
}
|
|
180
218
|
}
|
|
181
219
|
|
|
182
|
-
|
|
220
|
+
if (symbol) {
|
|
221
|
+
const aliasedSymbol = checker.getAliasedSymbol(symbol);
|
|
222
|
+
const targetSymbol = aliasedSymbol || symbol;
|
|
223
|
+
const type = checker.getTypeOfSymbolAtLocation(
|
|
224
|
+
targetSymbol,
|
|
225
|
+
targetSymbol.valueDeclaration!
|
|
226
|
+
);
|
|
227
|
+
const signature = checker.typeToString(
|
|
228
|
+
type,
|
|
229
|
+
undefined,
|
|
230
|
+
ts.TypeFormatFlags.NoTruncation |
|
|
231
|
+
ts.TypeFormatFlags.UseFullyQualifiedType
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
if (signature !== "any") {
|
|
235
|
+
signatures.set(name, signature);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
183
239
|
} catch (error) {
|
|
184
|
-
console.warn(
|
|
185
|
-
signatures.set(name, "(...args: any[]) => any");
|
|
240
|
+
console.warn(`Failed to resolve type for ${name}`);
|
|
186
241
|
}
|
|
242
|
+
|
|
243
|
+
// Fallback
|
|
244
|
+
signatures.set(name, "any");
|
|
187
245
|
});
|
|
188
246
|
|
|
189
247
|
const declarations = globals
|
|
190
|
-
.map(({ name }) => {
|
|
191
|
-
const sig = signatures.get(name) || "
|
|
192
|
-
|
|
248
|
+
.map(({ name, importPath }) => {
|
|
249
|
+
const sig = signatures.get(name) || "any";
|
|
250
|
+
// ⚡ FIX: Inject the source path as a comment for the Extension to read
|
|
251
|
+
return ` // @source: ${importPath}\n const ${name}: ${sig};`;
|
|
193
252
|
})
|
|
194
253
|
.join("\n");
|
|
195
254
|
|
|
@@ -213,17 +272,17 @@ export {};
|
|
|
213
272
|
`;
|
|
214
273
|
|
|
215
274
|
const dir = path.dirname(dtsPath);
|
|
216
|
-
if (!existsSync(dir)) {
|
|
217
|
-
mkdirSync(dir, { recursive: true });
|
|
218
|
-
}
|
|
219
|
-
|
|
275
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
220
276
|
writeFileSync(dtsPath, content, "utf-8");
|
|
221
277
|
console.log(`✅ Generated ${path.relative(process.cwd(), dtsPath)}`);
|
|
222
278
|
}
|
|
223
279
|
|
|
224
280
|
function generateFallbackDts(globals: GlobalDeclaration[], dtsPath: string) {
|
|
225
281
|
const declarations = globals
|
|
226
|
-
.map(
|
|
282
|
+
.map(
|
|
283
|
+
({ name, importPath }) =>
|
|
284
|
+
` // @source: ${importPath}\n const ${name}: any;`
|
|
285
|
+
)
|
|
227
286
|
.join("\n");
|
|
228
287
|
|
|
229
288
|
const windowDeclarations = globals
|
|
@@ -238,9 +297,7 @@ ${declarations}
|
|
|
238
297
|
${windowDeclarations}
|
|
239
298
|
}
|
|
240
299
|
}
|
|
241
|
-
|
|
242
300
|
export {};
|
|
243
301
|
`;
|
|
244
|
-
|
|
245
302
|
writeFileSync(dtsPath, content, "utf-8");
|
|
246
303
|
}
|
package/dist/vite.config.ts
CHANGED
|
@@ -36,6 +36,7 @@ export default defineConfig(({ command, mode }) => ({
|
|
|
36
36
|
emptyOutDir: false,
|
|
37
37
|
minify: "esbuild",
|
|
38
38
|
sourcemap: false,
|
|
39
|
+
chunkSizeWarningLimit: 1000,
|
|
39
40
|
watch:
|
|
40
41
|
command === "build" && mode === "development"
|
|
41
42
|
? { exclude: VITE_WATCH_EXCLUDE }
|
|
@@ -47,6 +48,15 @@ export default defineConfig(({ command, mode }) => ({
|
|
|
47
48
|
entryFileNames: "[name].js",
|
|
48
49
|
chunkFileNames: "chunks/[name]-[hash].js",
|
|
49
50
|
assetFileNames: "assets/[name]-[hash][extname]",
|
|
51
|
+
manualChunks(id) {
|
|
52
|
+
if (id.includes("node_modules")) {
|
|
53
|
+
return id
|
|
54
|
+
.toString()
|
|
55
|
+
.split("node_modules/")[1]
|
|
56
|
+
.split("/")[0]
|
|
57
|
+
.toString();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
50
60
|
},
|
|
51
61
|
},
|
|
52
62
|
},
|