@kithinji/pod 1.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 (98) hide show
  1. package/build.js +22 -0
  2. package/dist/main.js +4464 -0
  3. package/dist/main.js.map +7 -0
  4. package/dist/types/add/component/component.d.ts +5 -0
  5. package/dist/types/add/component/component.d.ts.map +1 -0
  6. package/dist/types/add/component/index.d.ts +2 -0
  7. package/dist/types/add/component/index.d.ts.map +1 -0
  8. package/dist/types/add/index.d.ts +4 -0
  9. package/dist/types/add/index.d.ts.map +1 -0
  10. package/dist/types/add/module/index.d.ts +2 -0
  11. package/dist/types/add/module/index.d.ts.map +1 -0
  12. package/dist/types/add/module/module.d.ts +3 -0
  13. package/dist/types/add/module/module.d.ts.map +1 -0
  14. package/dist/types/add/new/index.d.ts +2 -0
  15. package/dist/types/add/new/index.d.ts.map +1 -0
  16. package/dist/types/config/config.d.ts +18 -0
  17. package/dist/types/config/config.d.ts.map +1 -0
  18. package/dist/types/config/index.d.ts +2 -0
  19. package/dist/types/config/index.d.ts.map +1 -0
  20. package/dist/types/dev/index.d.ts +2 -0
  21. package/dist/types/dev/index.d.ts.map +1 -0
  22. package/dist/types/dev/project.d.ts +9 -0
  23. package/dist/types/dev/project.d.ts.map +1 -0
  24. package/dist/types/dev/server.d.ts +2 -0
  25. package/dist/types/dev/server.d.ts.map +1 -0
  26. package/dist/types/docker/docker.d.ts +2 -0
  27. package/dist/types/docker/docker.d.ts.map +1 -0
  28. package/dist/types/docker/index.d.ts +2 -0
  29. package/dist/types/docker/index.d.ts.map +1 -0
  30. package/dist/types/macros/expand_macros.d.ts +48 -0
  31. package/dist/types/macros/expand_macros.d.ts.map +1 -0
  32. package/dist/types/macros/index.d.ts +3 -0
  33. package/dist/types/macros/index.d.ts.map +1 -0
  34. package/dist/types/macros/macro_executer.d.ts +12 -0
  35. package/dist/types/macros/macro_executer.d.ts.map +1 -0
  36. package/dist/types/main.d.ts +13 -0
  37. package/dist/types/main.d.ts.map +1 -0
  38. package/dist/types/plugins/analyzers/graph.d.ts +25 -0
  39. package/dist/types/plugins/analyzers/graph.d.ts.map +1 -0
  40. package/dist/types/plugins/css/index.d.ts +7 -0
  41. package/dist/types/plugins/css/index.d.ts.map +1 -0
  42. package/dist/types/plugins/generators/generate_controller.d.ts +2 -0
  43. package/dist/types/plugins/generators/generate_controller.d.ts.map +1 -0
  44. package/dist/types/plugins/generators/generate_rsc.d.ts +2 -0
  45. package/dist/types/plugins/generators/generate_rsc.d.ts.map +1 -0
  46. package/dist/types/plugins/generators/generate_server_component.d.ts +2 -0
  47. package/dist/types/plugins/generators/generate_server_component.d.ts.map +1 -0
  48. package/dist/types/plugins/generators/tsx_server_stub.d.ts +2 -0
  49. package/dist/types/plugins/generators/tsx_server_stub.d.ts.map +1 -0
  50. package/dist/types/plugins/index.d.ts +4 -0
  51. package/dist/types/plugins/index.d.ts.map +1 -0
  52. package/dist/types/plugins/my.d.ts +10 -0
  53. package/dist/types/plugins/my.d.ts.map +1 -0
  54. package/dist/types/plugins/transformers/j2d.d.ts +11 -0
  55. package/dist/types/plugins/transformers/j2d.d.ts.map +1 -0
  56. package/dist/types/store/index.d.ts +2 -0
  57. package/dist/types/store/index.d.ts.map +1 -0
  58. package/dist/types/store/store.d.ts +14 -0
  59. package/dist/types/store/store.d.ts.map +1 -0
  60. package/dist/types/utils/cases.d.ts +4 -0
  61. package/dist/types/utils/cases.d.ts.map +1 -0
  62. package/dist/types/utils/create.d.ts +12 -0
  63. package/dist/types/utils/create.d.ts.map +1 -0
  64. package/dist/types/utils/index.d.ts +3 -0
  65. package/dist/types/utils/index.d.ts.map +1 -0
  66. package/package.json +44 -0
  67. package/src/add/component/component.ts +496 -0
  68. package/src/add/component/index.ts +1 -0
  69. package/src/add/index.ts +3 -0
  70. package/src/add/module/index.ts +1 -0
  71. package/src/add/module/module.ts +521 -0
  72. package/src/add/new/index.ts +135 -0
  73. package/src/config/config.ts +141 -0
  74. package/src/config/index.ts +1 -0
  75. package/src/dev/index.ts +1 -0
  76. package/src/dev/project.ts +45 -0
  77. package/src/dev/server.ts +190 -0
  78. package/src/docker/docker.ts +452 -0
  79. package/src/docker/index.ts +1 -0
  80. package/src/macros/expand_macros.ts +791 -0
  81. package/src/macros/index.ts +2 -0
  82. package/src/macros/macro_executer.ts +189 -0
  83. package/src/main.ts +95 -0
  84. package/src/plugins/analyzers/graph.ts +291 -0
  85. package/src/plugins/css/index.ts +25 -0
  86. package/src/plugins/generators/generate_controller.ts +308 -0
  87. package/src/plugins/generators/generate_rsc.ts +274 -0
  88. package/src/plugins/generators/generate_server_component.ts +279 -0
  89. package/src/plugins/generators/tsx_server_stub.ts +295 -0
  90. package/src/plugins/index.ts +3 -0
  91. package/src/plugins/my.ts +274 -0
  92. package/src/plugins/transformers/j2d.ts +1014 -0
  93. package/src/store/index.ts +1 -0
  94. package/src/store/store.ts +44 -0
  95. package/src/utils/cases.ts +15 -0
  96. package/src/utils/create.ts +26 -0
  97. package/src/utils/index.ts +2 -0
  98. package/tsconfig.json +27 -0
@@ -0,0 +1,2 @@
1
+ export * from "./expand_macros";
2
+ export * from "./macro_executer";
@@ -0,0 +1,189 @@
1
+ import * as vm from "node:vm";
2
+ import * as esbuild from "esbuild";
3
+ import * as path from "node:path";
4
+ import Module from "node:module";
5
+ import * as fs from "node:fs";
6
+
7
+ type MacroFunction = Function & { name: string };
8
+ type LoadedMacros = Record<string, MacroFunction>;
9
+
10
+ export class MacroExecutor {
11
+ private cache = new Map<string, LoadedMacros>();
12
+
13
+ getMacro(specifier: string, macroName?: string): MacroFunction {
14
+ if (!this.cache.has(specifier)) {
15
+ this.load(specifier);
16
+ }
17
+ const macros = this.cache.get(specifier)!;
18
+ if (macroName) {
19
+ const fn = macros[macroName];
20
+ if (!fn) {
21
+ throw new Error(`Macro "${macroName}" not found in ${specifier}`);
22
+ }
23
+ return fn;
24
+ }
25
+ const names = Object.keys(macros);
26
+ if (names.length === 1) {
27
+ return macros[names[0]];
28
+ }
29
+ if (macros.default) {
30
+ return macros.default;
31
+ }
32
+ throw new Error(`Multiple macros in ${specifier}: ${names.join(", ")}`);
33
+ }
34
+
35
+ private load(specifier: string) {
36
+ const requireFromHere = Module.createRequire(
37
+ process.cwd() + "/package.json"
38
+ );
39
+ const entry = requireFromHere.resolve(specifier);
40
+
41
+ const { outputFiles } = esbuild.buildSync({
42
+ entryPoints: [entry],
43
+ bundle: true,
44
+ write: false,
45
+ platform: "node",
46
+ format: "cjs",
47
+ external: [
48
+ ...Module.builtinModules,
49
+ ...Module.builtinModules.map((m) => `node:${m}`),
50
+ ],
51
+ target: "node18",
52
+ mainFields: ["module", "main"],
53
+ conditions: ["node", "import", "require"],
54
+ packages: "bundle",
55
+ logLevel: "warning",
56
+ });
57
+
58
+ const code = outputFiles[0].text;
59
+ const sandboxRequire = Module.createRequire(entry);
60
+
61
+ const sandbox: any = {
62
+ // Module system
63
+ module: { exports: {} },
64
+ exports: {},
65
+ require: sandboxRequire,
66
+
67
+ console,
68
+ Buffer,
69
+ URL,
70
+ URLSearchParams,
71
+ TextEncoder,
72
+ TextDecoder,
73
+ atob,
74
+ btoa,
75
+
76
+ __filename: entry,
77
+ __dirname: path.dirname(entry),
78
+
79
+ process: {
80
+ env: process.env,
81
+ cwd: process.cwd,
82
+ version: process.version,
83
+ versions: process.versions,
84
+ platform: process.platform,
85
+ arch: process.arch,
86
+ argv: process.argv,
87
+ execPath: process.execPath,
88
+ pid: process.pid,
89
+ },
90
+
91
+ setTimeout,
92
+ setInterval,
93
+ setImmediate,
94
+ clearTimeout,
95
+ clearInterval,
96
+ clearImmediate,
97
+
98
+ Promise,
99
+
100
+ Object,
101
+ Array,
102
+ String,
103
+ Number,
104
+ Boolean,
105
+ Date,
106
+ Math,
107
+ JSON,
108
+ RegExp,
109
+ Error,
110
+ TypeError,
111
+ RangeError,
112
+ SyntaxError,
113
+ Map,
114
+ Set,
115
+ WeakMap,
116
+ WeakSet,
117
+ Symbol,
118
+ BigInt,
119
+ Proxy,
120
+ Reflect,
121
+ };
122
+
123
+ sandbox.global = sandbox;
124
+ sandbox.globalThis = sandbox;
125
+
126
+ const context = vm.createContext(sandbox, {
127
+ name: `macro-${path.basename(entry)}`,
128
+ codeGeneration: {
129
+ strings: true,
130
+ wasm: false,
131
+ },
132
+ });
133
+
134
+ try {
135
+ const script = new vm.Script(code, {
136
+ filename: entry,
137
+ lineOffset: 0,
138
+ columnOffset: 0,
139
+ });
140
+
141
+ script.runInContext(context, {
142
+ breakOnSigint: true,
143
+ });
144
+ } catch (error) {
145
+ throw new Error(
146
+ `Failed to execute macro from ${specifier}: ${
147
+ error instanceof Error ? error.message : String(error)
148
+ }`
149
+ );
150
+ }
151
+
152
+ const macros: LoadedMacros = {};
153
+ const exports = sandbox.module.exports;
154
+
155
+ if (typeof exports === "function") {
156
+ macros.default = exports;
157
+ } else if (typeof exports === "object" && exports !== null) {
158
+ for (const [name, value] of Object.entries(exports)) {
159
+ if (typeof value === "function" && name.endsWith("$")) {
160
+ macros[name] = value as MacroFunction;
161
+ }
162
+ }
163
+
164
+ if (typeof exports.default === "function") {
165
+ macros.default = exports.default;
166
+ }
167
+ }
168
+
169
+ if (!Object.keys(macros).length) {
170
+ throw new Error(`No macros found in ${specifier}`);
171
+ }
172
+
173
+ this.cache.set(specifier, macros);
174
+ }
175
+
176
+ clearCache(specifier?: string) {
177
+ if (specifier) {
178
+ this.cache.delete(specifier);
179
+ } else {
180
+ this.cache.clear();
181
+ }
182
+ }
183
+ }
184
+
185
+ const macroExecutor = new MacroExecutor();
186
+
187
+ export function macroExecuter(): MacroExecutor {
188
+ return macroExecutor;
189
+ }
package/src/main.ts ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { startDevServer } from "./dev";
4
+
5
+ import * as store from "./store";
6
+ export { store };
7
+
8
+ import * as config from "./config";
9
+ export { config };
10
+
11
+ export * from "./config/config";
12
+
13
+ import * as macros from "./macros";
14
+ export { macros };
15
+
16
+ export * from "./macros/expand_macros";
17
+
18
+ import * as plugins from "./plugins";
19
+ export { plugins };
20
+ export * from "./plugins/css";
21
+
22
+ import { addComponent, addNew } from "./add";
23
+ import { addFeature } from "./add/module";
24
+
25
+ import path from "path";
26
+ import { execSync } from "child_process";
27
+ import { dockerize } from "./docker";
28
+
29
+ const program = new Command();
30
+
31
+ program.name("pod").description("Pod cli tool").version("0.0.0");
32
+
33
+ program
34
+ .command("new <name>")
35
+ .description("Start a new Pod Project")
36
+ .action(async (name: string) => {
37
+ await addNew(name);
38
+
39
+ const appDir = path.resolve(process.cwd(), name);
40
+
41
+ console.log("Installing dependencies...");
42
+ execSync("npm install", { stdio: "inherit", cwd: appDir });
43
+
44
+ console.log("Starting development server...");
45
+ execSync("npm run dev", { stdio: "inherit", cwd: appDir });
46
+
47
+ console.log(`All done! Your app "${name}" is running in development mode.`);
48
+ });
49
+
50
+ program
51
+ .command("dev")
52
+ .description("Start Pod development server")
53
+ .action(async (opts) => {
54
+ await startDevServer();
55
+ });
56
+
57
+ program
58
+ .command("add <type> <name>")
59
+ .description("Add a component (c) or a feature (f)")
60
+ .action(async (type, name) => {
61
+ try {
62
+ if (type === "c") {
63
+ await addComponent(name);
64
+ } else if (type === "f") {
65
+ await addFeature(name);
66
+ } else {
67
+ console.error("❌ Unknown type. Use 'c' or 'f'.");
68
+ }
69
+ } catch (err: any) {
70
+ console.error("❌ Error:", err.message);
71
+ }
72
+ });
73
+
74
+ program
75
+ .command("dockerize <env>")
76
+ .description("Dockerize a pod project.")
77
+ .action(async (env) => {
78
+ try {
79
+ await dockerize(env);
80
+ } catch (err: any) {
81
+ console.error("❌ Error:", err.message);
82
+ }
83
+ });
84
+
85
+ program
86
+ .command("deploy <type> <options>")
87
+ .description("Deploy a Pod Project")
88
+ .action(async (type, name) => {
89
+ try {
90
+ } catch (err: any) {
91
+ console.error("❌ Error:", err.message);
92
+ }
93
+ });
94
+
95
+ program.parse(process.argv);
@@ -0,0 +1,291 @@
1
+ import { parseSync } from "@swc/core";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import type { Module, Decorator } from "@swc/core";
5
+
6
+ type SymbolKind =
7
+ | "class"
8
+ | "function"
9
+ | "variable"
10
+ | "interface"
11
+ | "type"
12
+ | "enum"
13
+ | "namespace"
14
+ | "unknown";
15
+
16
+ interface SymbolInfo {
17
+ name: string;
18
+ kind: SymbolKind;
19
+ decorators?: string[];
20
+ isDefault?: boolean;
21
+ }
22
+
23
+ interface ImportInfo {
24
+ sourcePath: string;
25
+ resolvedPath: string | null;
26
+ symbols: SymbolInfo[];
27
+ }
28
+
29
+ export interface FileNode {
30
+ filePath: string;
31
+ isTsx: boolean;
32
+ directive: "public" | "interactive" | null;
33
+ imports: ImportInfo[];
34
+ exports: SymbolInfo[];
35
+ }
36
+
37
+ export interface DependencyGraph {
38
+ [filePath: string]: FileNode;
39
+ }
40
+
41
+ function resolveFilePath(fromFile: string, importPath: string): string | null {
42
+ if (!importPath.startsWith(".")) {
43
+ return null;
44
+ }
45
+
46
+ const dir = path.dirname(fromFile);
47
+ const basePath = path.resolve(dir, importPath);
48
+
49
+ const extensions = ["", ".ts", ".tsx", ".js", ".jsx"];
50
+ for (const ext of extensions) {
51
+ const fullPath = basePath + ext;
52
+ if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
53
+ return fullPath;
54
+ }
55
+ }
56
+
57
+ const indexFiles = ["/index.ts", "/index.tsx", "/index.js", "/index.jsx"];
58
+ for (const indexFile of indexFiles) {
59
+ const fullPath = basePath + indexFile;
60
+ if (fs.existsSync(fullPath)) {
61
+ return fullPath;
62
+ }
63
+ }
64
+
65
+ return null;
66
+ }
67
+
68
+ function extractDecorators(decorators?: Decorator[]): string[] {
69
+ if (!decorators || decorators.length === 0) return [];
70
+
71
+ return decorators
72
+ .map((decorator) => {
73
+ if (decorator.expression.type === "CallExpression") {
74
+ if (decorator.expression.callee.type === "Identifier") {
75
+ return decorator.expression.callee.value;
76
+ }
77
+ } else if (decorator.expression.type === "Identifier") {
78
+ return decorator.expression.value;
79
+ }
80
+ return "unknown";
81
+ })
82
+ .filter((name) => name !== "unknown");
83
+ }
84
+
85
+ function extractDirective(ast: Module): "public" | "interactive" | null {
86
+ for (const item of ast.body) {
87
+ if (
88
+ item.type === "ExpressionStatement" &&
89
+ item.expression.type === "StringLiteral"
90
+ ) {
91
+ const value = item.expression.value;
92
+ if (value === "use public") return "public";
93
+ if (value === "use interactive") return "interactive";
94
+ }
95
+ if (
96
+ item.type !== "ExpressionStatement" ||
97
+ item.expression.type !== "StringLiteral"
98
+ ) {
99
+ break;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+
105
+ function extractExports(ast: Module): SymbolInfo[] {
106
+ const exports: SymbolInfo[] = [];
107
+
108
+ for (const item of ast.body) {
109
+ if (item.type === "ExportDeclaration" && item.declaration) {
110
+ const decl = item.declaration;
111
+
112
+ if (decl.type === "ClassDeclaration" && decl.identifier) {
113
+ const decorators = extractDecorators(decl.decorators);
114
+ exports.push({
115
+ name: decl.identifier.value,
116
+ kind: "class",
117
+ decorators: decorators.length > 0 ? decorators : undefined,
118
+ });
119
+ } else if (decl.type === "FunctionDeclaration" && decl.identifier) {
120
+ exports.push({ name: decl.identifier.value, kind: "function" });
121
+ } else if (decl.type === "VariableDeclaration") {
122
+ for (const declarator of decl.declarations) {
123
+ if (declarator.id.type === "Identifier") {
124
+ exports.push({ name: declarator.id.value, kind: "variable" });
125
+ }
126
+ }
127
+ } else if (decl.type === "TsInterfaceDeclaration") {
128
+ exports.push({ name: decl.id.value, kind: "interface" });
129
+ } else if (decl.type === "TsTypeAliasDeclaration") {
130
+ exports.push({ name: decl.id.value, kind: "type" });
131
+ } else if (decl.type === "TsEnumDeclaration") {
132
+ exports.push({ name: decl.id.value, kind: "enum" });
133
+ }
134
+ }
135
+
136
+ if (item.type === "ExportNamedDeclaration") {
137
+ for (const spec of item.specifiers) {
138
+ if (spec.type === "ExportSpecifier") {
139
+ exports.push({ name: spec.orig.value, kind: "unknown" });
140
+ }
141
+ }
142
+ }
143
+
144
+ if (item.type === "ExportDefaultDeclaration") {
145
+ const decl = item.decl;
146
+ let kind: SymbolKind = "unknown";
147
+ let decorators: string[] | undefined;
148
+
149
+ if (decl.type === "ClassExpression") {
150
+ kind = "class";
151
+ decorators = extractDecorators(decl.decorators);
152
+ } else if (decl.type === "FunctionExpression") {
153
+ kind = "function";
154
+ } else if (decl.type === "TsInterfaceDeclaration") {
155
+ kind = "interface";
156
+ }
157
+
158
+ exports.push({
159
+ name: "default",
160
+ kind,
161
+ isDefault: true,
162
+ decorators:
163
+ decorators && decorators.length > 0 ? decorators : undefined,
164
+ });
165
+ }
166
+
167
+ if (item.type === "ExportDefaultExpression") {
168
+ exports.push({ name: "default", kind: "unknown", isDefault: true });
169
+ }
170
+ }
171
+
172
+ return exports;
173
+ }
174
+
175
+ function extractImports(
176
+ ast: Module
177
+ ): Array<{ path: string; specifiers: any[] }> {
178
+ const imports: Array<{ path: string; specifiers: any[] }> = [];
179
+
180
+ for (const item of ast.body) {
181
+ if (item.type === "ImportDeclaration") {
182
+ imports.push({
183
+ path: item.source.value,
184
+ specifiers: item.specifiers,
185
+ });
186
+ }
187
+ }
188
+
189
+ return imports;
190
+ }
191
+
192
+ export function buildGraph(entryPoints: string[]): DependencyGraph {
193
+ const graph: DependencyGraph = {};
194
+ const visited = new Set<string>();
195
+
196
+ function processFile(filePath: string): void {
197
+ const allowed =
198
+ filePath.endsWith(".ts") ||
199
+ filePath.endsWith(".tsx") ||
200
+ filePath.endsWith(".js") ||
201
+ filePath.endsWith(".jsx");
202
+
203
+ if (!allowed) return;
204
+
205
+ if (visited.has(filePath)) return;
206
+ visited.add(filePath);
207
+
208
+ if (!fs.existsSync(filePath)) {
209
+ console.warn(`File not found: ${filePath}`);
210
+ return;
211
+ }
212
+
213
+ const isTsx = filePath.endsWith(".tsx") || filePath.endsWith(".jsx");
214
+
215
+ const content = fs.readFileSync(filePath, "utf-8");
216
+ const ast = parseSync(content, {
217
+ syntax: "typescript",
218
+ tsx: isTsx,
219
+ decorators: true,
220
+ });
221
+
222
+ const directive = extractDirective(ast);
223
+ const exports = extractExports(ast);
224
+ const rawImports = extractImports(ast);
225
+
226
+ for (const { path: importPath } of rawImports) {
227
+ const resolved = resolveFilePath(filePath, importPath);
228
+ if (resolved) {
229
+ processFile(resolved);
230
+ }
231
+ }
232
+
233
+ const imports: ImportInfo[] = [];
234
+ for (const { path: importPath, specifiers } of rawImports) {
235
+ const resolvedPath = resolveFilePath(filePath, importPath);
236
+ const sourceExports =
237
+ resolvedPath && graph[resolvedPath] ? graph[resolvedPath].exports : [];
238
+ const symbols: SymbolInfo[] = [];
239
+
240
+ for (const spec of specifiers) {
241
+ if (spec.type === "ImportDefaultSpecifier") {
242
+ const defaultExport = sourceExports.find((e) => e.isDefault);
243
+ symbols.push({
244
+ name: spec.local.value,
245
+ kind: defaultExport?.kind || "unknown",
246
+ decorators: defaultExport?.decorators,
247
+ isDefault: true,
248
+ });
249
+ } else if (spec.type === "ImportNamespaceSpecifier") {
250
+ symbols.push({
251
+ name: spec.local.value,
252
+ kind: "namespace",
253
+ });
254
+ } else if (spec.type === "ImportSpecifier") {
255
+ const importedName = spec.imported
256
+ ? spec.imported.value
257
+ : spec.local.value;
258
+ const exportedSymbol = sourceExports.find(
259
+ (e) => e.name === importedName
260
+ );
261
+ symbols.push({
262
+ name: importedName,
263
+ kind: exportedSymbol?.kind || "unknown",
264
+ decorators: exportedSymbol?.decorators,
265
+ });
266
+ }
267
+ }
268
+
269
+ imports.push({
270
+ sourcePath: importPath,
271
+ resolvedPath,
272
+ symbols,
273
+ });
274
+ }
275
+
276
+ graph[filePath] = {
277
+ filePath,
278
+ isTsx,
279
+ directive,
280
+ imports,
281
+ exports,
282
+ };
283
+ }
284
+
285
+ for (const entry of entryPoints) {
286
+ const resolved = path.resolve(entry);
287
+ processFile(resolved);
288
+ }
289
+
290
+ return graph;
291
+ }
@@ -0,0 +1,25 @@
1
+ import { Store } from "@/store";
2
+ import { PluginBuild } from "esbuild";
3
+ import * as fs from "fs";
4
+
5
+ export function stylePlugin(store: Store) {
6
+ return {
7
+ name: "style",
8
+ setup(build: PluginBuild) {
9
+ build.onEnd(() => {
10
+ const styleRules = store.get("style_rules");
11
+
12
+ if (!styleRules || styleRules.length === 0) {
13
+ console.log("No style rules generated");
14
+ return;
15
+ }
16
+
17
+ const allRules = styleRules.flat();
18
+ const uniqueRules = [...new Set(allRules)];
19
+
20
+ const cssOutput = uniqueRules.join("\n");
21
+ fs.writeFileSync("public/index.css", cssOutput);
22
+ });
23
+ },
24
+ };
25
+ }