shiftapi 0.0.15 → 0.0.16

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 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 plugin for dev proxy) |
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
 
@@ -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
  };
@@ -80,6 +80,23 @@ export const client = createClient({
80
80
  baseUrl: ${JSON.stringify(baseUrl)},
81
81
  });
82
82
 
83
+ export { createClient };
84
+ `;
85
+ }
86
+ function nextClientJsTemplate(port, baseUrl) {
87
+ const devServerUrl = `http://localhost:${port}`;
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 ||
93
+ (typeof window !== "undefined"
94
+ ? ${JSON.stringify("/__shiftapi")}
95
+ : ${JSON.stringify(devServerUrl)});
96
+
97
+ /** Pre-configured, fully-typed API client. */
98
+ export const client = createClient({ baseUrl });
99
+
83
100
  export { createClient };
84
101
  `;
85
102
  }
@@ -111,13 +128,13 @@ async function regenerateTypes(serverEntry, goRoot, baseUrl, isDev, previousType
111
128
  );
112
129
  return { types, virtualModuleSource, changed };
113
130
  }
114
- function writeGeneratedFiles(typesRoot, generatedDts, baseUrl) {
131
+ function writeGeneratedFiles(typesRoot, generatedDts, baseUrl, options) {
115
132
  const outDir = resolve(typesRoot, ".shiftapi");
116
133
  if (!existsSync(outDir)) {
117
134
  mkdirSync(outDir, { recursive: true });
118
135
  }
119
136
  writeFileSync(resolve(outDir, "client.d.ts"), dtsTemplate(generatedDts));
120
- writeFileSync(resolve(outDir, "client.js"), clientJsTemplate(baseUrl));
137
+ writeFileSync(resolve(outDir, "client.js"), options?.clientJsContent ?? clientJsTemplate(baseUrl));
121
138
  writeFileSync(
122
139
  resolve(outDir, "tsconfig.json"),
123
140
  JSON.stringify(
@@ -165,6 +182,7 @@ export {
165
182
  DEV_API_PREFIX,
166
183
  dtsTemplate,
167
184
  clientJsTemplate,
185
+ nextClientJsTemplate,
168
186
  virtualModuleTemplate,
169
187
  regenerateTypes,
170
188
  writeGeneratedFiles,
@@ -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-PUAivaXi.js';
1
+ export { S as ShiftAPIConfig, d as defineConfig } from './index-BG8_bsaE.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  defineConfig
3
- } from "./chunk-QBXBYTBE.js";
3
+ } from "./chunk-EQN44FQG.js";
4
4
  export {
5
5
  defineConfig
6
6
  };
@@ -1,11 +1,13 @@
1
- export { S as ShiftAPIConfig, d as defineConfig, l as loadConfig } from './index-PUAivaXi.js';
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): void;
8
+ declare function writeGeneratedFiles(typesRoot: string, generatedDts: string, baseUrl: string, options?: {
9
+ clientJsContent?: string;
10
+ }): void;
9
11
  declare function patchTsConfig(tsconfigDir: string, typesRoot: string): void;
10
12
 
11
13
  /**
@@ -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): 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
- export { DEV_API_PREFIX, MODULE_ID, RESOLVED_MODULE_ID, clientJsTemplate, dtsTemplate, extractSpec, generateTypes, patchTsConfig, regenerateTypes, virtualModuleTemplate, writeGeneratedFiles };
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, patchTsConfig, regenerateTypes, virtualModuleTemplate, writeGeneratedFiles };
package/dist/internal.js CHANGED
@@ -6,25 +6,138 @@ import {
6
6
  dtsTemplate,
7
7
  extractSpec,
8
8
  generateTypes,
9
+ nextClientJsTemplate,
9
10
  patchTsConfig,
10
11
  regenerateTypes,
11
12
  virtualModuleTemplate,
12
13
  writeGeneratedFiles
13
- } from "./chunk-M6SOET3R.js";
14
+ } from "./chunk-TE7E7CKV.js";
14
15
  import {
15
16
  defineConfig,
17
+ findConfigDir,
16
18
  loadConfig
17
- } from "./chunk-QBXBYTBE.js";
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,
140
+ nextClientJsTemplate,
28
141
  patchTsConfig,
29
142
  regenerateTypes,
30
143
  virtualModuleTemplate,
package/dist/prepare.js CHANGED
@@ -4,10 +4,10 @@ import {
4
4
  generateTypes,
5
5
  patchTsConfig,
6
6
  writeGeneratedFiles
7
- } from "./chunk-M6SOET3R.js";
7
+ } from "./chunk-TE7E7CKV.js";
8
8
  import {
9
9
  loadConfig
10
- } from "./chunk-QBXBYTBE.js";
10
+ } from "./chunk-EQN44FQG.js";
11
11
 
12
12
  // src/prepare.ts
13
13
  import { resolve } from "path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shiftapi",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "CLI and codegen for shiftapi – fully-typed TypeScript clients from Go servers",
5
5
  "author": "Frank Chiarulli Jr. <frank@frankchiarulli.com>",
6
6
  "license": "MIT",