@devup-api/vite-plugin 0.1.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.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @devup-api/vite-plugin
2
+
3
+ devup API plugin for Vite
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @devup-api/vite-plugin
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import devupApiVitePlugin from '@devup-api/vite-plugin';
15
+ import { defineConfig } from 'vite';
16
+
17
+ export default defineConfig({
18
+ plugins: [
19
+ devupApiVitePlugin({
20
+ // options
21
+ }),
22
+ ],
23
+ });
24
+ ```
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=plugin.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/plugin.test.ts"],"names":[],"mappings":""}
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ var{defineProperty:C,getOwnPropertyNames:H,getOwnPropertyDescriptor:K}=Object,L=Object.prototype.hasOwnProperty;var E=new WeakMap,P=(x)=>{var b=E.get(x),k;if(b)return b;if(b=C({},"__esModule",{value:!0}),x&&typeof x==="object"||typeof x==="function")H(x).map((q)=>!L.call(b,q)&&C(b,q,{get:()=>x[q],enumerable:!(k=K(x,q))||k.enumerable}));return E.set(x,b),b};var Q=(x,b)=>{for(var k in b)C(x,k,{get:b[k],enumerable:!0,configurable:!0,set:(q)=>b[k]=()=>q})};var R={};Q(R,{devupApi:()=>G,default:()=>G});module.exports=P(R);var F=require("node:path"),B=require("@devup-api/generator"),z=require("@devup-api/utils");function G(x){return{name:"devup-api",async configResolved(){let b=await z.createTmpDirAsync(x?.tempDir),k=await z.readOpenapiAsync(x?.openapiFile);await z.writeInterfaceAsync(F.join(b,"api.d.ts"),B.generateInterface(k,x))},async config(){let b=await z.readOpenapiAsync(x?.openapiFile),k=B.createUrlMap(b,x),q={};if(k)q["process.env.DEVUP_API_URL_MAP"]=JSON.stringify(JSON.stringify(k));return{define:q}}}}
@@ -0,0 +1,3 @@
1
+ export * from './plugin';
2
+ export { devupApi as default } from './plugin';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{join as B}from"node:path";import{createUrlMap as C,generateInterface as E}from"@devup-api/generator";import{createTmpDirAsync as F,readOpenapiAsync as z,writeInterfaceAsync as G}from"@devup-api/utils";function H(x){return{name:"devup-api",async configResolved(){let k=await F(x?.tempDir),b=await z(x?.openapiFile);await G(B(k,"api.d.ts"),E(b,x))},async config(){let k=await z(x?.openapiFile),b=C(k,x),q={};if(b)q["process.env.DEVUP_API_URL_MAP"]=JSON.stringify(JSON.stringify(b));return{define:q}}}}export{H as devupApi,H as default};
@@ -0,0 +1,4 @@
1
+ import type { DevupApiOptions } from '@devup-api/core';
2
+ import type { Plugin } from 'vite';
3
+ export declare function devupApi(options?: DevupApiOptions): Plugin;
4
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAOtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAA;AAElC,wBAAgB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CA2B1D"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@devup-api/vite-plugin",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/index.js",
8
+ "require": "./dist/index.cjs",
9
+ "types": "./dist/index.d.ts"
10
+ }
11
+ },
12
+ "scripts": {
13
+ "build": "tsc && bun build --target node --outfile=dist/index.js src/index.ts --production --packages=external && bun build --target node --outfile=dist/index.cjs --format=cjs src/index.ts --production --packages=external"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "dependencies": {
19
+ "@devup-api/utils": "0.1.0",
20
+ "@devup-api/core": "0.1.0",
21
+ "@devup-api/generator": "0.1.0"
22
+ },
23
+ "peerDependencies": {
24
+ "vite": "*",
25
+ "@devup-api/core": "*"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^24.10",
29
+ "typescript": "^5.9"
30
+ }
31
+ }
@@ -0,0 +1,9 @@
1
+ import { expect, test } from 'bun:test'
2
+ import * as indexModule from '../index'
3
+
4
+ test('index.ts exports', () => {
5
+ expect({ ...indexModule }).toEqual({
6
+ devupApi: expect.any(Function),
7
+ default: expect.any(Function),
8
+ })
9
+ })
@@ -0,0 +1,170 @@
1
+ import { beforeEach, expect, spyOn, test } from 'bun:test'
2
+ import { join } from 'node:path'
3
+ import type { DevupApiOptions } from '@devup-api/core'
4
+ import * as generator from '@devup-api/generator'
5
+ import * as utils from '@devup-api/utils'
6
+ import { devupApi } from '../plugin'
7
+
8
+ let mockCreateTmpDirAsync: ReturnType<typeof spyOn>
9
+ let mockReadOpenapiAsync: ReturnType<typeof spyOn>
10
+ let mockWriteInterfaceAsync: ReturnType<typeof spyOn>
11
+ let mockCreateUrlMap: ReturnType<typeof spyOn>
12
+ let mockGenerateInterface: ReturnType<typeof spyOn>
13
+
14
+ const mockSchema = {
15
+ openapi: '3.1.0',
16
+ paths: {
17
+ '/users': {
18
+ get: {
19
+ operationId: 'getUsers',
20
+ responses: {
21
+ '200': {
22
+ content: {
23
+ 'application/json': {
24
+ schema: {
25
+ type: 'array',
26
+ items: { type: 'string' },
27
+ },
28
+ },
29
+ },
30
+ },
31
+ },
32
+ },
33
+ },
34
+ },
35
+ } as const
36
+
37
+ const mockUrlMap = {
38
+ getUsers: {
39
+ method: 'GET' as const,
40
+ url: '/users',
41
+ },
42
+ '/users': {
43
+ method: 'GET' as const,
44
+ url: '/users',
45
+ },
46
+ }
47
+
48
+ const mockInterfaceContent = 'export interface Test {}'
49
+
50
+ beforeEach(() => {
51
+ mockCreateTmpDirAsync = spyOn(utils, 'createTmpDirAsync').mockResolvedValue(
52
+ 'df',
53
+ )
54
+ mockReadOpenapiAsync = spyOn(utils, 'readOpenapiAsync').mockResolvedValue(
55
+ mockSchema as never,
56
+ )
57
+ mockWriteInterfaceAsync = spyOn(
58
+ utils,
59
+ 'writeInterfaceAsync',
60
+ ).mockResolvedValue(undefined)
61
+ mockCreateUrlMap = spyOn(generator, 'createUrlMap').mockReturnValue(
62
+ mockUrlMap as never,
63
+ )
64
+ mockGenerateInterface = spyOn(generator, 'generateInterface').mockReturnValue(
65
+ mockInterfaceContent,
66
+ )
67
+ })
68
+
69
+ test('devupApi returns plugin with correct name', () => {
70
+ const plugin = devupApi()
71
+ expect(plugin.name).toBe('devup-api')
72
+ })
73
+
74
+ test.each([
75
+ [undefined],
76
+ [{ tempDir: 'custom-dir' }],
77
+ [{ openapiFile: 'custom-openapi.json' }],
78
+ [
79
+ {
80
+ tempDir: 'custom-dir',
81
+ openapiFile: 'custom-openapi.json',
82
+ convertCase: 'snake' as const,
83
+ },
84
+ ],
85
+ ] as const)('devupApi returns plugin with config hook: %s', async (options:
86
+ | DevupApiOptions
87
+ | undefined) => {
88
+ const plugin = devupApi(options)
89
+ expect(plugin.config).toBeDefined()
90
+ expect(typeof plugin.config).toBe('function')
91
+
92
+ const result = await (
93
+ plugin as unknown as {
94
+ config?: () => Promise<{ define: Record<string, string> }>
95
+ }
96
+ ).config?.()
97
+ expect(mockReadOpenapiAsync).toHaveBeenCalledWith(options?.openapiFile)
98
+ expect(mockCreateUrlMap).toHaveBeenCalledWith(mockSchema, options)
99
+ expect(result).toEqual({
100
+ define: {
101
+ 'process.env.DEVUP_API_URL_MAP': JSON.stringify(
102
+ JSON.stringify(mockUrlMap),
103
+ ),
104
+ },
105
+ })
106
+ })
107
+
108
+ test('devupApi config hook returns empty define when urlMap is null', async () => {
109
+ mockCreateUrlMap.mockReturnValue(null as never)
110
+ const plugin = devupApi()
111
+ const result = await (
112
+ plugin as unknown as {
113
+ config?: () => Promise<{ define: Record<string, string> }>
114
+ }
115
+ ).config?.()
116
+ expect(result).toEqual({
117
+ define: {},
118
+ })
119
+ })
120
+
121
+ test('devupApi config hook returns empty define when urlMap is undefined', async () => {
122
+ mockCreateUrlMap.mockReturnValue(undefined as never)
123
+ const plugin = devupApi()
124
+ const result = await (
125
+ plugin as unknown as {
126
+ config?: () => Promise<{ define: Record<string, string> }>
127
+ }
128
+ ).config?.()
129
+ expect(result).toEqual({
130
+ define: {},
131
+ })
132
+ })
133
+
134
+ test.each([
135
+ [undefined],
136
+ [{ tempDir: 'custom-dir' }],
137
+ [{ openapiFile: 'custom-openapi.json' }],
138
+ [
139
+ {
140
+ tempDir: 'custom-dir',
141
+ openapiFile: 'custom-openapi.json',
142
+ convertCase: 'pascal' as const,
143
+ },
144
+ ],
145
+ ] as const)('devupApi returns plugin with configResolved hook: %s', async (options:
146
+ | DevupApiOptions
147
+ | undefined) => {
148
+ const plugin = devupApi(options)
149
+ expect(plugin.configResolved).toBeDefined()
150
+ expect(typeof plugin.configResolved).toBe('function')
151
+
152
+ await (
153
+ plugin as unknown as { configResolved?: () => Promise<void> }
154
+ ).configResolved?.()
155
+ expect(mockCreateTmpDirAsync).toHaveBeenCalledWith(options?.tempDir)
156
+ expect(mockReadOpenapiAsync).toHaveBeenCalledWith(options?.openapiFile)
157
+ expect(mockGenerateInterface).toHaveBeenCalledWith(mockSchema, options)
158
+ expect(mockWriteInterfaceAsync).toHaveBeenCalledWith(
159
+ join('df', 'api.d.ts'),
160
+ mockInterfaceContent,
161
+ )
162
+ })
163
+
164
+ test('devupApi plugin has both config and configResolved hooks', () => {
165
+ const plugin = devupApi()
166
+ expect(plugin.config).toBeDefined()
167
+ expect(plugin.configResolved).toBeDefined()
168
+ expect(typeof plugin.config).toBe('function')
169
+ expect(typeof plugin.configResolved).toBe('function')
170
+ })
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './plugin'
2
+ export { devupApi as default } from './plugin'
package/src/plugin.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { join } from 'node:path'
2
+ import type { DevupApiOptions } from '@devup-api/core'
3
+ import { createUrlMap, generateInterface } from '@devup-api/generator'
4
+ import {
5
+ createTmpDirAsync,
6
+ readOpenapiAsync,
7
+ writeInterfaceAsync,
8
+ } from '@devup-api/utils'
9
+ import type { Plugin } from 'vite'
10
+
11
+ export function devupApi(options?: DevupApiOptions): Plugin {
12
+ return {
13
+ name: 'devup-api',
14
+ // Vite plugin implementation
15
+ async configResolved() {
16
+ const tempDir = await createTmpDirAsync(options?.tempDir)
17
+ const schema = await readOpenapiAsync(options?.openapiFile)
18
+ await writeInterfaceAsync(
19
+ join(tempDir, 'api.d.ts'),
20
+ generateInterface(schema, options),
21
+ )
22
+ },
23
+ async config() {
24
+ const schema = await readOpenapiAsync(options?.openapiFile)
25
+ const urlMap = createUrlMap(schema, options)
26
+ const define: Record<string, string> = {}
27
+ if (urlMap) {
28
+ // json stringify twice to avoid JSON.parse error
29
+ define['process.env.DEVUP_API_URL_MAP'] = JSON.stringify(
30
+ JSON.stringify(urlMap),
31
+ )
32
+ }
33
+ return {
34
+ define,
35
+ }
36
+ },
37
+ }
38
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Environment setup & latest features
4
+ "lib": ["ESNext"],
5
+ "target": "ESNext",
6
+ "module": "Preserve",
7
+ "moduleDetection": "force",
8
+ "jsx": "react-jsx",
9
+ "allowJs": true,
10
+
11
+ // Bundler mode
12
+ "moduleResolution": "bundler",
13
+ "verbatimModuleSyntax": true,
14
+ "emitDeclarationOnly": true,
15
+
16
+ // Best practices
17
+ "strict": true,
18
+ "skipLibCheck": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noUncheckedIndexedAccess": true,
21
+ "noImplicitOverride": true,
22
+
23
+ // Some stricter flags (disabled by default)
24
+ "noUnusedLocals": false,
25
+ "noUnusedParameters": false,
26
+ "noPropertyAccessFromIndexSignature": false,
27
+ "declaration": true,
28
+ "declarationMap": true,
29
+ "outDir": "dist",
30
+ "rootDir": "src"
31
+ },
32
+ "include": ["src/**/*.ts"],
33
+ "exclude": ["dist", "node_modules"]
34
+ }