@ubean/auto-imports 0.1.2 → 0.1.4

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.
@@ -0,0 +1,87 @@
1
+ import { Import, InlinePreset } from "unimport";
2
+ import { ScanResult } from "@ubean/routing";
3
+ //#region src/index.d.ts
4
+ interface AutoImportOptions {
5
+ cwd: string;
6
+ srcDir: string;
7
+ buildDir: string;
8
+ composablesDirs?: string[];
9
+ componentsDirs?: string[];
10
+ dirs?: {
11
+ composables?: string;
12
+ components?: string;
13
+ };
14
+ imports?: {
15
+ autoImport?: boolean;
16
+ global?: boolean;
17
+ };
18
+ components?: {
19
+ autoImport?: boolean;
20
+ directoryAsNamespace?: boolean;
21
+ };
22
+ }
23
+ declare const VUE_PRESET: InlinePreset;
24
+ declare const VUE_MACROS_PRESET: InlinePreset;
25
+ /**
26
+ * Client-safe symbols that are available in `ubean/runtime/vue`.
27
+ * These are safe to auto-import in Vue components (browser-side) because
28
+ * `ubean/runtime/vue` does not transitively import `vite` or other build tools.
29
+ */
30
+ declare const UBEAN_CLIENT_PRESET: InlinePreset;
31
+ /**
32
+ * Server-only symbols that come from the main `ubean` package.
33
+ * These import the full ubean entry (which includes build tools like `vite`),
34
+ * so they must only be used in server-side files (API routes, middleware, etc.).
35
+ */
36
+ declare const UBEAN_SERVER_PRESET: InlinePreset;
37
+ /** @deprecated Use UBEAN_CLIENT_PRESET + UBEAN_SERVER_PRESET instead */
38
+ declare const UBEAN_PRESET: InlinePreset;
39
+ declare const HONO_OPENAPI_PRESET: InlinePreset;
40
+ declare const BUILTIN_PRESETS: InlinePreset[];
41
+ interface ComponentInfo {
42
+ name: string;
43
+ filePath: string;
44
+ importPath: string;
45
+ pascalName: string;
46
+ }
47
+ interface AutoImportResult {
48
+ composablesImports: Import[];
49
+ components: ComponentInfo[];
50
+ autoImportsDtsPath: string;
51
+ componentsDtsPath: string;
52
+ }
53
+ declare function generateAutoImports(_scanResult: ScanResult, options: AutoImportOptions): Promise<AutoImportResult>;
54
+ declare function getBuiltinComposables(): Import[];
55
+ declare function getUbeanAutoImportConfig(options?: {
56
+ cwd?: string;
57
+ srcDir?: string;
58
+ buildDir?: string;
59
+ composablesDirs?: string[];
60
+ }): {
61
+ imports: InlinePreset[];
62
+ dirs: string[];
63
+ dts: string;
64
+ vueTemplate: boolean;
65
+ eslintrc: {
66
+ enabled: boolean;
67
+ };
68
+ };
69
+ declare function getUbeanComponentsConfig(options?: {
70
+ cwd?: string;
71
+ srcDir?: string;
72
+ buildDir?: string;
73
+ componentsDirs?: string[];
74
+ directoryAsNamespace?: boolean;
75
+ }): {
76
+ dirs: string[];
77
+ extensions: string[];
78
+ directoryAsNamespace: boolean;
79
+ dts: string;
80
+ deep: boolean;
81
+ };
82
+ declare function generateImportsTransform(imports: Import[]): {
83
+ code: string;
84
+ map?: null;
85
+ };
86
+ //#endregion
87
+ export { AutoImportOptions, AutoImportResult, BUILTIN_PRESETS, ComponentInfo, HONO_OPENAPI_PRESET, type Import, type InlinePreset, UBEAN_CLIENT_PRESET, UBEAN_PRESET, UBEAN_SERVER_PRESET, VUE_MACROS_PRESET, VUE_PRESET, generateAutoImports, generateImportsTransform, getBuiltinComposables, getUbeanAutoImportConfig, getUbeanComponentsConfig };
package/dist/index.js ADDED
@@ -0,0 +1,353 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join, normalize, relative } from "pathe";
3
+ import { glob } from "tinyglobby";
4
+ import { createUnimport, toTypeDeclarationFile } from "unimport";
5
+ //#region src/index.ts
6
+ const VUE_PRESET = {
7
+ from: "vue",
8
+ imports: [
9
+ "ref",
10
+ "computed",
11
+ "reactive",
12
+ "readonly",
13
+ "watch",
14
+ "watchEffect",
15
+ "watchPostEffect",
16
+ "watchSyncEffect",
17
+ "onMounted",
18
+ "onUnmounted",
19
+ "onBeforeMount",
20
+ "onBeforeUnmount",
21
+ "onUpdated",
22
+ "onBeforeUpdate",
23
+ "onActivated",
24
+ "onDeactivated",
25
+ "onErrorCaptured",
26
+ "onServerPrefetch",
27
+ "onRenderTracked",
28
+ "onRenderTriggered",
29
+ "provide",
30
+ "inject",
31
+ "shallowRef",
32
+ "shallowReactive",
33
+ "shallowReadonly",
34
+ "isRef",
35
+ "isReactive",
36
+ "isReadonly",
37
+ "isProxy",
38
+ "unref",
39
+ "toRef",
40
+ "toRefs",
41
+ "toRaw",
42
+ "markRaw",
43
+ "triggerRef",
44
+ "customRef",
45
+ "effectScope",
46
+ "getCurrentScope",
47
+ "onScopeDispose",
48
+ "defineComponent",
49
+ "defineAsyncComponent",
50
+ "defineProps",
51
+ "defineEmits",
52
+ "defineExpose",
53
+ "defineOptions",
54
+ "defineSlots",
55
+ "defineModel",
56
+ "useSlots",
57
+ "useAttrs",
58
+ "useTemplateRef",
59
+ "nextTick",
60
+ "toValue",
61
+ "useId",
62
+ "useCssModule",
63
+ "useCssVars",
64
+ "useTransitionState"
65
+ ]
66
+ };
67
+ const VUE_MACROS_PRESET = {
68
+ from: "vue/macros",
69
+ imports: [
70
+ "$",
71
+ "$$",
72
+ "$ref",
73
+ "$computed",
74
+ "$shallowRef",
75
+ "$customRef",
76
+ "$toRef"
77
+ ]
78
+ };
79
+ /**
80
+ * Client-safe symbols that are available in `ubean/runtime/vue`.
81
+ * These are safe to auto-import in Vue components (browser-side) because
82
+ * `ubean/runtime/vue` does not transitively import `vite` or other build tools.
83
+ */
84
+ const UBEAN_CLIENT_PRESET = {
85
+ from: "ubean/runtime/vue",
86
+ imports: [
87
+ "definePage",
88
+ "defineMiddleware",
89
+ "defineApp",
90
+ "applyAppConfig",
91
+ "createDefaultAppConfig",
92
+ "t",
93
+ "useI18n",
94
+ "useSeoMeta",
95
+ "usePage",
96
+ "useRouter",
97
+ "useHead",
98
+ "useViewTransition",
99
+ "useCacheViews",
100
+ "enablePageCache",
101
+ "disablePageCache",
102
+ "excludePageCache",
103
+ "includePageCache",
104
+ "isPageExcluded",
105
+ "resetRouteCache",
106
+ "invalidatePageCache",
107
+ "isPageCached",
108
+ "usePageTransition",
109
+ "setPageTransition",
110
+ "clearPageTransition",
111
+ "useReloadSignal",
112
+ "reloadPage",
113
+ "isReloading"
114
+ ]
115
+ };
116
+ /**
117
+ * Server-only symbols that come from the main `ubean` package.
118
+ * These import the full ubean entry (which includes build tools like `vite`),
119
+ * so they must only be used in server-side files (API routes, middleware, etc.).
120
+ */
121
+ const UBEAN_SERVER_PRESET = {
122
+ from: "ubean",
123
+ imports: [
124
+ "defineHandlerMeta",
125
+ "useData",
126
+ "createInternalAdapter",
127
+ "defineScheduled",
128
+ "defineQueue",
129
+ "sendMessage",
130
+ "sendMessages",
131
+ "getQueueStats",
132
+ "useDatabase",
133
+ "defineDatabase",
134
+ "useKV",
135
+ "createKV",
136
+ "useStorage"
137
+ ]
138
+ };
139
+ /** @deprecated Use UBEAN_CLIENT_PRESET + UBEAN_SERVER_PRESET instead */
140
+ const UBEAN_PRESET = UBEAN_SERVER_PRESET;
141
+ const HONO_OPENAPI_PRESET = {
142
+ from: "hono-openapi",
143
+ imports: ["validator", "describeRoute"]
144
+ };
145
+ const BUILTIN_PRESETS = [
146
+ UBEAN_CLIENT_PRESET,
147
+ UBEAN_SERVER_PRESET,
148
+ HONO_OPENAPI_PRESET
149
+ ];
150
+ function toPosixPath(p) {
151
+ return p.replace(/\\/g, "/");
152
+ }
153
+ function toCamelCase(str) {
154
+ return str.replace(/[-_](\w)/g, (_, c) => c.toUpperCase());
155
+ }
156
+ function toPascalCase(str) {
157
+ const camel = toCamelCase(str);
158
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
159
+ }
160
+ function fileBasename(p, ext) {
161
+ const parts = toPosixPath(p).split("/");
162
+ let base = parts[parts.length - 1] || "";
163
+ if (ext && base.endsWith(ext)) base = base.slice(0, -ext.length);
164
+ else if (!ext) {
165
+ const dotIdx = base.lastIndexOf(".");
166
+ if (dotIdx > 0) base = base.slice(0, dotIdx);
167
+ }
168
+ return base;
169
+ }
170
+ function fileDirname(p) {
171
+ const parts = toPosixPath(p).split("/");
172
+ parts.pop();
173
+ return parts.join("/") || ".";
174
+ }
175
+ function transformImportPath(filePath, srcDir) {
176
+ const posixPath = toPosixPath(normalize(filePath));
177
+ return `~/${toPosixPath(relative(toPosixPath(normalize(srcDir)), posixPath)).replace(/\.(ts|js|mts|mjs|cts|cjs|tsx|jsx)$/, "")}`;
178
+ }
179
+ async function scanComponentsDir(dir, srcDir, directoryAsNamespace, ignore = [
180
+ "**/*.test.*",
181
+ "**/*.spec.*",
182
+ "**/_*"
183
+ ]) {
184
+ const components = [];
185
+ const files = await glob("**/*.vue", {
186
+ cwd: dir,
187
+ dot: true,
188
+ ignore,
189
+ absolute: true
190
+ }).catch(() => []);
191
+ for (const fullPath of files.sort()) {
192
+ const relativeToSrc = toPosixPath(relative(srcDir, fullPath));
193
+ const relativeToDir = toPosixPath(relative(dir, fullPath));
194
+ const base = fileBasename(fullPath);
195
+ if (base.startsWith("_")) continue;
196
+ let name;
197
+ if (directoryAsNamespace) {
198
+ const dirPart = fileDirname(relativeToDir) === "." ? "" : fileDirname(relativeToDir);
199
+ const parts = dirPart ? dirPart.split("/").filter(Boolean) : [];
200
+ parts.push(base);
201
+ name = parts.map(toPascalCase).join("");
202
+ } else name = toPascalCase(base);
203
+ components.push({
204
+ name,
205
+ filePath: fullPath,
206
+ importPath: `~/${relativeToSrc}`,
207
+ pascalName: name
208
+ });
209
+ }
210
+ return components;
211
+ }
212
+ async function generateAutoImports(_scanResult, options) {
213
+ const { cwd, srcDir, buildDir, composablesDirs = [], componentsDirs = [], dirs = {}, imports: importsConfig, components: componentsConfig } = options;
214
+ const outDir = join(cwd, buildDir);
215
+ await mkdir(outDir, { recursive: true });
216
+ const autoImportEnabled = importsConfig?.autoImport !== false;
217
+ const componentAutoImportEnabled = componentsConfig?.autoImport !== false;
218
+ const directoryAsNamespace = componentsConfig?.directoryAsNamespace ?? false;
219
+ const composablesDir = dirs.composables || "composables";
220
+ const componentsDir = dirs.components || "components";
221
+ let composablesImports = [];
222
+ let components = [];
223
+ const autoImportsDtsPath = join(outDir, "auto-imports.d.ts");
224
+ const componentsDtsPath = join(outDir, "components.d.ts");
225
+ if (autoImportEnabled) {
226
+ const allComposablesDirs = [join(srcDir, composablesDir), ...composablesDirs];
227
+ const existingDirs = [];
228
+ for (const dir of allComposablesDirs) try {
229
+ const { statSync } = await import("node:fs");
230
+ if (statSync(dir).isDirectory()) existingDirs.push(dir);
231
+ } catch {}
232
+ const unimport = createUnimport({
233
+ presets: BUILTIN_PRESETS,
234
+ dirs: existingDirs,
235
+ dirsScanOptions: {
236
+ cwd: srcDir,
237
+ filePatterns: ["*.{ts,js,mts,mjs,cts,cjs}"],
238
+ types: false
239
+ }
240
+ });
241
+ await unimport.init();
242
+ composablesImports = (await unimport.getImports()).map((imp) => {
243
+ if (imp.from === "vue" || imp.from === "vue/macros" || imp.from === "ubean" || imp.from.startsWith("ubean/")) return imp;
244
+ return {
245
+ ...imp,
246
+ from: transformImportPath(imp.from, srcDir)
247
+ };
248
+ });
249
+ await writeFile(autoImportsDtsPath, toTypeDeclarationFile(composablesImports, { resolvePath: (imp) => {
250
+ if (imp.from === "vue" || imp.from === "vue/macros" || imp.from === "ubean" || imp.from.startsWith("ubean/")) return imp.from;
251
+ return transformImportPath(imp.from, srcDir);
252
+ } }), "utf-8");
253
+ } else await writeFile(autoImportsDtsPath, "// Auto-generated by ubean - auto-imports disabled\n/* eslint-disable */\n// @ts-nocheck\nexport {}\n", "utf-8");
254
+ if (componentAutoImportEnabled) {
255
+ const allComponentsDirs = [join(srcDir, componentsDir), ...componentsDirs];
256
+ for (const dir of allComponentsDirs) {
257
+ const scanned = await scanComponentsDir(dir, srcDir, directoryAsNamespace);
258
+ components.push(...scanned);
259
+ }
260
+ }
261
+ await writeFile(componentsDtsPath, generateComponentsDts(components), "utf-8");
262
+ return {
263
+ composablesImports,
264
+ components,
265
+ autoImportsDtsPath,
266
+ componentsDtsPath
267
+ };
268
+ }
269
+ function generateComponentsDts(components) {
270
+ const lines = [
271
+ "// Auto-generated by ubean - do not edit manually",
272
+ "/* eslint-disable */",
273
+ "// @ts-nocheck",
274
+ "",
275
+ "declare module 'vue' {"
276
+ ];
277
+ const importLines = [];
278
+ const componentEntries = [];
279
+ for (const name of ["Link", "Head"]) {
280
+ importLines.push(` const ${name}: typeof import('ubean/runtime/vue')['${name}'];`);
281
+ componentEntries.push(` ${name}: typeof ${name};`);
282
+ }
283
+ for (const comp of components) {
284
+ importLines.push(` import ${comp.pascalName} from ${JSON.stringify(comp.importPath)};`);
285
+ componentEntries.push(` ${comp.pascalName}: typeof ${comp.pascalName};`);
286
+ }
287
+ if (importLines.length > 0) {
288
+ lines.push(...importLines);
289
+ lines.push("");
290
+ lines.push(" export interface GlobalComponents {");
291
+ lines.push(...componentEntries);
292
+ lines.push(" }");
293
+ } else lines.push(" export interface GlobalComponents {}");
294
+ lines.push("}");
295
+ lines.push("");
296
+ lines.push("export {}");
297
+ return `${lines.join("\n")}\n`;
298
+ }
299
+ function getBuiltinComposables() {
300
+ const imports = [];
301
+ for (const preset of BUILTIN_PRESETS) for (const name of preset.imports) if (typeof name === "string") imports.push({
302
+ name,
303
+ from: preset.from
304
+ });
305
+ else if (Array.isArray(name)) imports.push({
306
+ name: name[0],
307
+ as: name[1],
308
+ from: preset.from
309
+ });
310
+ return imports;
311
+ }
312
+ function getUbeanAutoImportConfig(options = {}) {
313
+ const cwd = options.cwd || process.cwd();
314
+ const srcDir = options.srcDir || join(cwd, "src");
315
+ const buildDir = options.buildDir || ".ubean";
316
+ const composablesDirs = [join(srcDir, "composables"), ...options.composablesDirs || []];
317
+ return {
318
+ imports: [
319
+ UBEAN_CLIENT_PRESET,
320
+ UBEAN_SERVER_PRESET,
321
+ HONO_OPENAPI_PRESET
322
+ ],
323
+ dirs: composablesDirs,
324
+ dts: join(cwd, buildDir, "auto-imports.d.ts"),
325
+ vueTemplate: true,
326
+ eslintrc: { enabled: false }
327
+ };
328
+ }
329
+ function getUbeanComponentsConfig(options = {}) {
330
+ const cwd = options.cwd || process.cwd();
331
+ const srcDir = options.srcDir || join(cwd, "src");
332
+ const buildDir = options.buildDir || ".ubean";
333
+ return {
334
+ dirs: [join(srcDir, "components"), ...options.componentsDirs || []],
335
+ extensions: ["vue"],
336
+ directoryAsNamespace: options.directoryAsNamespace ?? false,
337
+ dts: join(cwd, buildDir, "components.d.ts"),
338
+ deep: true
339
+ };
340
+ }
341
+ function generateImportsTransform(imports) {
342
+ const importGroups = /* @__PURE__ */ new Map();
343
+ for (const imp of imports) {
344
+ if (!importGroups.has(imp.from)) importGroups.set(imp.from, /* @__PURE__ */ new Set());
345
+ const namePart = imp.as ? `${imp.name} as ${imp.as}` : imp.name;
346
+ importGroups.get(imp.from).add(namePart);
347
+ }
348
+ const importStatements = [];
349
+ for (const [from, names] of importGroups) importStatements.push(`import { ${Array.from(names).join(", ")} } from '${from}';`);
350
+ return { code: importStatements.join("\n") };
351
+ }
352
+ //#endregion
353
+ export { BUILTIN_PRESETS, HONO_OPENAPI_PRESET, UBEAN_CLIENT_PRESET, UBEAN_PRESET, UBEAN_SERVER_PRESET, VUE_MACROS_PRESET, VUE_PRESET, generateAutoImports, generateImportsTransform, getBuiltinComposables, getUbeanAutoImportConfig, getUbeanComponentsConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ubean/auto-imports",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Auto-import presets for ubean (VUE_PRESET, UBEAN_CLIENT_PRESET, UBEAN_SERVER_PRESET)",
5
5
  "files": [
6
6
  "dist"
@@ -26,7 +26,7 @@
26
26
  "vite-plus": "0.2.6"
27
27
  },
28
28
  "peerDependencies": {
29
- "@ubean/routing": "0.1.2"
29
+ "@ubean/routing": "0.1.4"
30
30
  },
31
31
  "peerDependenciesMeta": {
32
32
  "@ubean/routing": {