shiftapi 0.0.15 → 0.0.17
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 +1 -1
- package/dist/{chunk-M6SOET3R.js → chunk-DQX3QC7F.js} +45 -9
- package/dist/{chunk-QBXBYTBE.js → chunk-EQN44FQG.js} +10 -1
- package/dist/{index-PUAivaXi.d.ts → index-BG8_bsaE.d.ts} +10 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal.d.ts +19 -4
- package/dist/internal.js +117 -4
- package/dist/prepare.js +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Typically used in a `postinstall` script:
|
|
|
59
59
|
|--------|------|---------|-------------|
|
|
60
60
|
| `server` | `string` | **(required)** | Path to the Go server entry point (e.g. `"./cmd/server"`) |
|
|
61
61
|
| `baseUrl` | `string` | `"/"` | Base URL for the generated API client |
|
|
62
|
-
| `url` | `string` | `"http://localhost:8080"` | Go server address (used by the Vite
|
|
62
|
+
| `url` | `string` | `"http://localhost:8080"` | Go server address (used by the Vite/Next.js plugins for dev proxy) |
|
|
63
63
|
|
|
64
64
|
## License
|
|
65
65
|
|
|
@@ -80,6 +80,36 @@ export const client = createClient({
|
|
|
80
80
|
baseUrl: ${JSON.stringify(baseUrl)},
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
+
export { createClient };
|
|
84
|
+
`;
|
|
85
|
+
}
|
|
86
|
+
function nextClientJsTemplate(port, baseUrl, devApiPrefix) {
|
|
87
|
+
if (!devApiPrefix) {
|
|
88
|
+
return `// Auto-generated by @shiftapi/next. Do not edit.
|
|
89
|
+
import createClient from "openapi-fetch";
|
|
90
|
+
|
|
91
|
+
const baseUrl =
|
|
92
|
+
process.env.NEXT_PUBLIC_SHIFTAPI_BASE_URL || ${JSON.stringify(baseUrl)};
|
|
93
|
+
|
|
94
|
+
/** Pre-configured, fully-typed API client. */
|
|
95
|
+
export const client = createClient({ baseUrl });
|
|
96
|
+
|
|
97
|
+
export { createClient };
|
|
98
|
+
`;
|
|
99
|
+
}
|
|
100
|
+
const devServerUrl = `http://localhost:${port}`;
|
|
101
|
+
return `// Auto-generated by @shiftapi/next. Do not edit.
|
|
102
|
+
import createClient from "openapi-fetch";
|
|
103
|
+
|
|
104
|
+
const baseUrl =
|
|
105
|
+
process.env.NEXT_PUBLIC_SHIFTAPI_BASE_URL ||
|
|
106
|
+
(typeof window !== "undefined"
|
|
107
|
+
? ${JSON.stringify(devApiPrefix)}
|
|
108
|
+
: ${JSON.stringify(devServerUrl)});
|
|
109
|
+
|
|
110
|
+
/** Pre-configured, fully-typed API client. */
|
|
111
|
+
export const client = createClient({ baseUrl });
|
|
112
|
+
|
|
83
113
|
export { createClient };
|
|
84
114
|
`;
|
|
85
115
|
}
|
|
@@ -111,13 +141,13 @@ async function regenerateTypes(serverEntry, goRoot, baseUrl, isDev, previousType
|
|
|
111
141
|
);
|
|
112
142
|
return { types, virtualModuleSource, changed };
|
|
113
143
|
}
|
|
114
|
-
function writeGeneratedFiles(typesRoot, generatedDts, baseUrl) {
|
|
144
|
+
function writeGeneratedFiles(typesRoot, generatedDts, baseUrl, options) {
|
|
115
145
|
const outDir = resolve(typesRoot, ".shiftapi");
|
|
116
146
|
if (!existsSync(outDir)) {
|
|
117
147
|
mkdirSync(outDir, { recursive: true });
|
|
118
148
|
}
|
|
119
149
|
writeFileSync(resolve(outDir, "client.d.ts"), dtsTemplate(generatedDts));
|
|
120
|
-
writeFileSync(resolve(outDir, "client.js"), clientJsTemplate(baseUrl));
|
|
150
|
+
writeFileSync(resolve(outDir, "client.js"), options?.clientJsContent ?? clientJsTemplate(baseUrl));
|
|
121
151
|
writeFileSync(
|
|
122
152
|
resolve(outDir, "tsconfig.json"),
|
|
123
153
|
JSON.stringify(
|
|
@@ -133,7 +163,7 @@ function writeGeneratedFiles(typesRoot, generatedDts, baseUrl) {
|
|
|
133
163
|
) + "\n"
|
|
134
164
|
);
|
|
135
165
|
}
|
|
136
|
-
function
|
|
166
|
+
function patchTsConfigPaths(tsconfigDir, typesRoot) {
|
|
137
167
|
const tsconfigPath = resolve(tsconfigDir, "tsconfig.json");
|
|
138
168
|
if (!existsSync(tsconfigPath)) return;
|
|
139
169
|
const raw = readFileSync2(tsconfigPath, "utf-8");
|
|
@@ -146,14 +176,19 @@ function patchTsConfig(tsconfigDir, typesRoot) {
|
|
|
146
176
|
);
|
|
147
177
|
return;
|
|
148
178
|
}
|
|
149
|
-
const
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
tsconfig.
|
|
179
|
+
const dtsRel = relative(tsconfigDir, resolve(typesRoot, ".shiftapi", "client.d.ts"));
|
|
180
|
+
const dtsPath = dtsRel.startsWith("..") ? dtsRel : `./${dtsRel}`;
|
|
181
|
+
tsconfig.compilerOptions = tsconfig.compilerOptions || {};
|
|
182
|
+
tsconfig.compilerOptions.paths = tsconfig.compilerOptions.paths || {};
|
|
183
|
+
const existing = tsconfig.compilerOptions.paths[MODULE_ID];
|
|
184
|
+
if (Array.isArray(existing) && existing.length === 1 && existing[0] === dtsPath) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
tsconfig.compilerOptions.paths[MODULE_ID] = [dtsPath];
|
|
153
188
|
const detectedIndent = raw.match(/^[ \t]+/m)?.[0] ?? " ";
|
|
154
189
|
writeFileSync(tsconfigPath, stringify(tsconfig, null, detectedIndent) + "\n");
|
|
155
190
|
console.log(
|
|
156
|
-
"[shiftapi] Updated tsconfig.json
|
|
191
|
+
"[shiftapi] Updated tsconfig.json with @shiftapi/client path mapping."
|
|
157
192
|
);
|
|
158
193
|
}
|
|
159
194
|
|
|
@@ -165,8 +200,9 @@ export {
|
|
|
165
200
|
DEV_API_PREFIX,
|
|
166
201
|
dtsTemplate,
|
|
167
202
|
clientJsTemplate,
|
|
203
|
+
nextClientJsTemplate,
|
|
168
204
|
virtualModuleTemplate,
|
|
169
205
|
regenerateTypes,
|
|
170
206
|
writeGeneratedFiles,
|
|
171
|
-
|
|
207
|
+
patchTsConfigPaths
|
|
172
208
|
};
|
|
@@ -37,6 +37,14 @@ async function loadConfig(startDir, configPath) {
|
|
|
37
37
|
}
|
|
38
38
|
return { config, configDir: dirname(resolvedPath) };
|
|
39
39
|
}
|
|
40
|
+
function findConfigDir(startDir, configPath) {
|
|
41
|
+
if (configPath) {
|
|
42
|
+
const resolved = resolve(startDir, configPath);
|
|
43
|
+
return existsSync(resolved) ? dirname(resolved) : void 0;
|
|
44
|
+
}
|
|
45
|
+
const file = findConfigFile(startDir);
|
|
46
|
+
return file ? dirname(file) : void 0;
|
|
47
|
+
}
|
|
40
48
|
function findConfigFile(startDir) {
|
|
41
49
|
let dir = resolve(startDir);
|
|
42
50
|
const root = resolve("/");
|
|
@@ -57,5 +65,6 @@ function findConfigFile(startDir) {
|
|
|
57
65
|
|
|
58
66
|
export {
|
|
59
67
|
defineConfig,
|
|
60
|
-
loadConfig
|
|
68
|
+
loadConfig,
|
|
69
|
+
findConfigDir
|
|
61
70
|
};
|
|
@@ -22,5 +22,14 @@ declare function loadConfig(startDir: string, configPath?: string): Promise<{
|
|
|
22
22
|
config: ShiftAPIConfig;
|
|
23
23
|
configDir: string;
|
|
24
24
|
}>;
|
|
25
|
+
interface ShiftAPIPluginOptions {
|
|
26
|
+
/** Explicit path to shiftapi.config.ts (for advanced use only) */
|
|
27
|
+
configPath?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Synchronously walk up from `startDir` to find the directory containing
|
|
31
|
+
* a shiftapi config file. Returns the directory path, or undefined.
|
|
32
|
+
*/
|
|
33
|
+
declare function findConfigDir(startDir: string, configPath?: string): string | undefined;
|
|
25
34
|
|
|
26
|
-
export { type ShiftAPIConfig as S, defineConfig as d, loadConfig as l };
|
|
35
|
+
export { type ShiftAPIConfig as S, type ShiftAPIPluginOptions as a, defineConfig as d, findConfigDir as f, loadConfig as l };
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { S as ShiftAPIConfig, d as defineConfig } from './index-
|
|
1
|
+
export { S as ShiftAPIConfig, d as defineConfig } from './index-BG8_bsaE.js';
|
package/dist/index.js
CHANGED
package/dist/internal.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
export { S as ShiftAPIConfig, d as defineConfig, l as loadConfig } from './index-
|
|
1
|
+
export { S as ShiftAPIConfig, a as ShiftAPIPluginOptions, d as defineConfig, f as findConfigDir, l as loadConfig } from './index-BG8_bsaE.js';
|
|
2
2
|
|
|
3
3
|
declare function regenerateTypes(serverEntry: string, goRoot: string, baseUrl: string, isDev: boolean, previousTypes: string): Promise<{
|
|
4
4
|
types: string;
|
|
5
5
|
virtualModuleSource: string;
|
|
6
6
|
changed: boolean;
|
|
7
7
|
}>;
|
|
8
|
-
declare function writeGeneratedFiles(typesRoot: string, generatedDts: string, baseUrl: string
|
|
9
|
-
|
|
8
|
+
declare function writeGeneratedFiles(typesRoot: string, generatedDts: string, baseUrl: string, options?: {
|
|
9
|
+
clientJsContent?: string;
|
|
10
|
+
}): void;
|
|
11
|
+
declare function patchTsConfigPaths(tsconfigDir: string, typesRoot: string): void;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Extracts the OpenAPI spec from a Go shiftapi server by running it with
|
|
@@ -23,10 +25,23 @@ declare function generateTypes(spec: object): Promise<string>;
|
|
|
23
25
|
|
|
24
26
|
declare function dtsTemplate(generatedTypes: string): string;
|
|
25
27
|
declare function clientJsTemplate(baseUrl: string): string;
|
|
28
|
+
declare function nextClientJsTemplate(port: number, baseUrl: string, devApiPrefix?: string): string;
|
|
26
29
|
declare function virtualModuleTemplate(baseUrl: string, devApiPrefix?: string): string;
|
|
27
30
|
|
|
28
31
|
declare const MODULE_ID = "@shiftapi/client";
|
|
29
32
|
declare const RESOLVED_MODULE_ID: string;
|
|
30
33
|
declare const DEV_API_PREFIX = "/__shiftapi";
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
declare class GoServerManager {
|
|
36
|
+
private readonly serverEntry;
|
|
37
|
+
private readonly goRoot;
|
|
38
|
+
private goProcess;
|
|
39
|
+
constructor(serverEntry: string, goRoot: string);
|
|
40
|
+
start(port: number): Promise<void>;
|
|
41
|
+
stop(): Promise<void>;
|
|
42
|
+
forceKill(): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
declare function findFreePort(startPort: number): Promise<number>;
|
|
46
|
+
|
|
47
|
+
export { DEV_API_PREFIX, GoServerManager, MODULE_ID, RESOLVED_MODULE_ID, clientJsTemplate, dtsTemplate, extractSpec, findFreePort, generateTypes, nextClientJsTemplate, patchTsConfigPaths, regenerateTypes, virtualModuleTemplate, writeGeneratedFiles };
|
package/dist/internal.js
CHANGED
|
@@ -6,26 +6,139 @@ import {
|
|
|
6
6
|
dtsTemplate,
|
|
7
7
|
extractSpec,
|
|
8
8
|
generateTypes,
|
|
9
|
-
|
|
9
|
+
nextClientJsTemplate,
|
|
10
|
+
patchTsConfigPaths,
|
|
10
11
|
regenerateTypes,
|
|
11
12
|
virtualModuleTemplate,
|
|
12
13
|
writeGeneratedFiles
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-DQX3QC7F.js";
|
|
14
15
|
import {
|
|
15
16
|
defineConfig,
|
|
17
|
+
findConfigDir,
|
|
16
18
|
loadConfig
|
|
17
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-EQN44FQG.js";
|
|
20
|
+
|
|
21
|
+
// src/goServer.ts
|
|
22
|
+
import { spawn } from "child_process";
|
|
23
|
+
import { resolve } from "path";
|
|
24
|
+
var GoServerManager = class {
|
|
25
|
+
constructor(serverEntry, goRoot) {
|
|
26
|
+
this.serverEntry = serverEntry;
|
|
27
|
+
this.goRoot = goRoot;
|
|
28
|
+
}
|
|
29
|
+
goProcess = null;
|
|
30
|
+
start(port) {
|
|
31
|
+
return new Promise((resolveStart, rejectStart) => {
|
|
32
|
+
const proc = spawn(
|
|
33
|
+
"go",
|
|
34
|
+
["run", "-tags", "shiftapidev", this.serverEntry],
|
|
35
|
+
{
|
|
36
|
+
cwd: resolve(this.goRoot),
|
|
37
|
+
stdio: ["ignore", "inherit", "inherit"],
|
|
38
|
+
detached: true,
|
|
39
|
+
env: {
|
|
40
|
+
...process.env,
|
|
41
|
+
SHIFTAPI_PORT: String(port)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
this.goProcess = proc;
|
|
46
|
+
let settled = false;
|
|
47
|
+
proc.on("error", (err) => {
|
|
48
|
+
console.error("[shiftapi] Failed to start Go server:", err.message);
|
|
49
|
+
if (!settled) {
|
|
50
|
+
settled = true;
|
|
51
|
+
rejectStart(err);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
proc.on("exit", (code) => {
|
|
55
|
+
if (code !== null && code !== 0) {
|
|
56
|
+
console.error(`[shiftapi] Go server exited with code ${code}`);
|
|
57
|
+
}
|
|
58
|
+
this.goProcess = null;
|
|
59
|
+
});
|
|
60
|
+
proc.on("spawn", () => {
|
|
61
|
+
if (!settled) {
|
|
62
|
+
settled = true;
|
|
63
|
+
resolveStart();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
console.log(
|
|
67
|
+
`[shiftapi] Go server starting on port ${port}: go run ${this.serverEntry}`
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
stop() {
|
|
72
|
+
const proc = this.goProcess;
|
|
73
|
+
if (!proc || !proc.pid) return Promise.resolve();
|
|
74
|
+
const pid = proc.pid;
|
|
75
|
+
this.goProcess = null;
|
|
76
|
+
return new Promise((resolve2) => {
|
|
77
|
+
const timeout = setTimeout(() => {
|
|
78
|
+
try {
|
|
79
|
+
process.kill(-pid, "SIGKILL");
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
resolve2();
|
|
83
|
+
}, 5e3);
|
|
84
|
+
proc.on("exit", () => {
|
|
85
|
+
clearTimeout(timeout);
|
|
86
|
+
resolve2();
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
process.kill(-pid, "SIGTERM");
|
|
90
|
+
} catch {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
resolve2();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
forceKill() {
|
|
97
|
+
if (this.goProcess?.pid) {
|
|
98
|
+
try {
|
|
99
|
+
process.kill(-this.goProcess.pid, "SIGTERM");
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// src/ports.ts
|
|
107
|
+
import { createServer as createTcpServer } from "net";
|
|
108
|
+
function isPortFree(port) {
|
|
109
|
+
return new Promise((resolve2) => {
|
|
110
|
+
const server = createTcpServer();
|
|
111
|
+
server.once("error", () => resolve2(false));
|
|
112
|
+
server.once("listening", () => {
|
|
113
|
+
server.close(() => resolve2(true));
|
|
114
|
+
});
|
|
115
|
+
server.listen(port);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
async function findFreePort(startPort) {
|
|
119
|
+
for (let port = startPort; port < startPort + 20; port++) {
|
|
120
|
+
if (await isPortFree(port)) return port;
|
|
121
|
+
}
|
|
122
|
+
console.warn(
|
|
123
|
+
`[shiftapi] No free port found in range ${startPort}-${startPort + 19}, falling back to ${startPort}`
|
|
124
|
+
);
|
|
125
|
+
return startPort;
|
|
126
|
+
}
|
|
18
127
|
export {
|
|
19
128
|
DEV_API_PREFIX,
|
|
129
|
+
GoServerManager,
|
|
20
130
|
MODULE_ID,
|
|
21
131
|
RESOLVED_MODULE_ID,
|
|
22
132
|
clientJsTemplate,
|
|
23
133
|
defineConfig,
|
|
24
134
|
dtsTemplate,
|
|
25
135
|
extractSpec,
|
|
136
|
+
findConfigDir,
|
|
137
|
+
findFreePort,
|
|
26
138
|
generateTypes,
|
|
27
139
|
loadConfig,
|
|
28
|
-
|
|
140
|
+
nextClientJsTemplate,
|
|
141
|
+
patchTsConfigPaths,
|
|
29
142
|
regenerateTypes,
|
|
30
143
|
virtualModuleTemplate,
|
|
31
144
|
writeGeneratedFiles
|
package/dist/prepare.js
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import {
|
|
3
3
|
extractSpec,
|
|
4
4
|
generateTypes,
|
|
5
|
-
|
|
5
|
+
patchTsConfigPaths,
|
|
6
6
|
writeGeneratedFiles
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DQX3QC7F.js";
|
|
8
8
|
import {
|
|
9
9
|
loadConfig
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-EQN44FQG.js";
|
|
11
11
|
|
|
12
12
|
// src/prepare.ts
|
|
13
13
|
import { resolve } from "path";
|
|
@@ -26,7 +26,7 @@ async function main() {
|
|
|
26
26
|
const spec = extractSpec(serverEntry, resolve(goRoot));
|
|
27
27
|
const types = await generateTypes(spec);
|
|
28
28
|
writeGeneratedFiles(configDir, types, baseUrl);
|
|
29
|
-
|
|
29
|
+
patchTsConfigPaths(cwd, configDir);
|
|
30
30
|
console.log("[shiftapi] Done. Generated .shiftapi/client.d.ts and .shiftapi/client.js");
|
|
31
31
|
}
|
|
32
32
|
main().catch((err) => {
|
package/package.json
CHANGED