@adhd/apigen-python-env 0.1.5 → 0.2.1

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/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.2.1 (2026-07-27)
2
+
3
+
4
+ ### 🩹 Fixes
5
+
6
+ - **apigen-python-env:** ship the `apigen_python` sources into `dist/python/` via a vite `writeBundle` copy plugin and resolve them co-located-first, so `py-grpc`/`py-flask` work for consumers installing from npm outside the monorepo (BUG-015). `project.json` `build.options.assets` was a no-op under `@nx/vite:build`.
7
+
8
+
1
9
  ## 0.1.5 (2026-07-25)
2
10
 
3
11
 
package/index.js CHANGED
@@ -1,10 +1,10 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("node:fs"),I=require("node:os"),q=require("node:path"),F=require("node:crypto"),h=require("node:child_process");function P(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const o=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(e,n,o.get?o:{enumerable:!0,get:()=>t[n]})}}return e.default=t,Object.freeze(e)}const r=P(D),b=P(I),i=P(q);function k(t){const e=t??__dirname,n=i.resolve(e,"..","..","..","python");if(r.existsSync(i.join(n,"apigen_python")))return n;let o=e;for(let u=0;u<20;u++){const c=i.join(o,"packages","apigen","python");if(r.existsSync(i.join(c,"apigen_python")))return c;const a=i.dirname(o);if(a===o)break;o=a}return n}const H=["python3.13","python3.12","python3.11","python3"],m=[3,11];function J(t){const e=h.spawnSync(t,["-c",'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}")'],{encoding:"utf8",timeout:15e3});if(e.status!==0||!e.stdout)return;const[n,o]=e.stdout.trim().split(".").map(Number);if(!(!Number.isFinite(n)||!Number.isFinite(o)))return[n,o]}function M(){for(const t of H){const e=J(t);if(e&&(e[0]>m[0]||e[0]===m[0]&&e[1]>=m[1]))return t}throw new Error(`apigen-python-env: no Python >= ${m.join(".")} found on PATH (tried: ${H.join(", ")}). Install Python ${m.join(".")}+ or set APIGEN_PYTHON to a provisioned interpreter.`)}function Y(t){return process.platform==="win32"?i.join(t,"Scripts","python.exe"):i.join(t,"bin","python3")}function G(t){const e=r.readFileSync(i.join(t,"pyproject.toml"));return F.createHash("sha256").update(e).digest("hex")}function O(t){try{const e=JSON.parse(r.readFileSync(t,"utf8"));if(typeof e.pyprojectHash=="string"&&Array.isArray(e.extras))return e}catch{}}function B(t,e,n){const o=Date.now()+e;for(;;)try{r.mkdirSync(t,{recursive:!1});break}catch{if(Date.now()>o){try{r.rmdirSync(t)}catch{}continue}h.spawnSync(process.execPath,["-e","setTimeout(()=>{}, 250)"],{timeout:5e3})}try{return n()}finally{try{r.rmdirSync(t)}catch{}}}function V(t={}){const e=k(),n=process.env.APIGEN_PYTHON;if(n){if(!r.existsSync(n))throw new Error(`apigen-python-env: APIGEN_PYTHON points to a missing file: ${n}`);return{python:n,venvDir:"",pythonPkgDir:e}}const o=[...new Set(t.extras??[])].sort(),u=t.envHome??process.env.APIGEN_PYENV_HOME??i.join(b.homedir(),".adhd","apigen"),c=i.join(u,"pyvenv"),a=i.join(c,".apigen-stamp"),d=G(e),p=Y(c),l=()=>{if(!r.existsSync(p))return!1;const s=O(a);return!s||s.pyprojectHash!==d?!1:o.every(y=>s.extras.includes(y))};if(l())return{python:p,venvDir:c,pythonPkgDir:e};r.mkdirSync(u,{recursive:!0});const v=i.join(u,"pyvenv.lock"),w=t.lockTimeoutMs??3e5;return B(v,w,()=>{if(l())return{python:p,venvDir:c,pythonPkgDir:e};const s=O(a),y=[...new Set([...(s==null?void 0:s.extras)??[],...o])].sort();r.rmSync(c,{recursive:!0,force:!0});const _=M(),j=h.spawnSync(_,["-m","venv",c],{encoding:"utf8",timeout:12e4});if(j.status!==0)throw new Error(`apigen-python-env: "${_} -m venv" failed (exit ${j.status}):
2
- ${j.stderr}`);const x=i.join(e,"build");r.existsSync(x)&&r.rmSync(x,{recursive:!0,force:!0});for(const f of r.readdirSync(e))f.endsWith(".egg-info")&&r.rmSync(i.join(e,f),{recursive:!0,force:!0});const S=r.mkdtempSync(i.join(b.tmpdir(),"apigen-python-wheel-"));try{const f=h.spawnSync(p,["-m","pip","wheel","--no-deps","--wheel-dir",S,e],{encoding:"utf8",timeout:6e5});if(f.status!==0)throw new Error(`apigen-python-env: pip wheel failed (exit ${f.status}):
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const D=require("node:fs"),I=require("node:os"),q=require("node:path"),F=require("node:crypto"),h=require("node:child_process");function P(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const r in t)if(r!=="default"){const i=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(e,r,i.get?i:{enumerable:!0,get:()=>t[r]})}}return e.default=t,Object.freeze(e)}const n=P(D),b=P(I),o=P(q);function k(t){const e=t??__dirname,r=o.join(e,"python");if(n.existsSync(o.join(r,"apigen_python")))return r;const i=o.resolve(e,"..","..","..","python");if(n.existsSync(o.join(i,"apigen_python")))return i;let a=e;for(let c=0;c<20;c++){const p=o.join(a,"packages","apigen","python");if(n.existsSync(o.join(p,"apigen_python")))return p;const u=o.dirname(a);if(u===a)break;a=u}return i}const H=["python3.13","python3.12","python3.11","python3"],m=[3,11];function J(t){const e=h.spawnSync(t,["-c",'import sys; print(f"{sys.version_info[0]}.{sys.version_info[1]}")'],{encoding:"utf8",timeout:15e3});if(e.status!==0||!e.stdout)return;const[r,i]=e.stdout.trim().split(".").map(Number);if(!(!Number.isFinite(r)||!Number.isFinite(i)))return[r,i]}function M(){for(const t of H){const e=J(t);if(e&&(e[0]>m[0]||e[0]===m[0]&&e[1]>=m[1]))return t}throw new Error(`apigen-python-env: no Python >= ${m.join(".")} found on PATH (tried: ${H.join(", ")}). Install Python ${m.join(".")}+ or set APIGEN_PYTHON to a provisioned interpreter.`)}function Y(t){return process.platform==="win32"?o.join(t,"Scripts","python.exe"):o.join(t,"bin","python3")}function G(t){const e=n.readFileSync(o.join(t,"pyproject.toml"));return F.createHash("sha256").update(e).digest("hex")}function O(t){try{const e=JSON.parse(n.readFileSync(t,"utf8"));if(typeof e.pyprojectHash=="string"&&Array.isArray(e.extras))return e}catch{}}function B(t,e,r){const i=Date.now()+e;for(;;)try{n.mkdirSync(t,{recursive:!1});break}catch{if(Date.now()>i){try{n.rmdirSync(t)}catch{}continue}h.spawnSync(process.execPath,["-e","setTimeout(()=>{}, 250)"],{timeout:5e3})}try{return r()}finally{try{n.rmdirSync(t)}catch{}}}function V(t={}){const e=k(),r=process.env.APIGEN_PYTHON;if(r){if(!n.existsSync(r))throw new Error(`apigen-python-env: APIGEN_PYTHON points to a missing file: ${r}`);return{python:r,venvDir:"",pythonPkgDir:e}}const i=[...new Set(t.extras??[])].sort(),a=t.envHome??process.env.APIGEN_PYENV_HOME??o.join(b.homedir(),".adhd","apigen"),c=o.join(a,"pyvenv"),p=o.join(c,".apigen-stamp"),u=G(e),y=Y(c),l=()=>{if(!n.existsSync(y))return!1;const s=O(p);return!s||s.pyprojectHash!==u?!1:i.every(d=>s.extras.includes(d))};if(l())return{python:y,venvDir:c,pythonPkgDir:e};n.mkdirSync(a,{recursive:!0});const v=o.join(a,"pyvenv.lock"),w=t.lockTimeoutMs??3e5;return B(v,w,()=>{if(l())return{python:y,venvDir:c,pythonPkgDir:e};const s=O(p),d=[...new Set([...(s==null?void 0:s.extras)??[],...i])].sort();n.rmSync(c,{recursive:!0,force:!0});const _=M(),j=h.spawnSync(_,["-m","venv",c],{encoding:"utf8",timeout:12e4});if(j.status!==0)throw new Error(`apigen-python-env: "${_} -m venv" failed (exit ${j.status}):
2
+ ${j.stderr}`);const x=o.join(e,"build");n.existsSync(x)&&n.rmSync(x,{recursive:!0,force:!0});for(const f of n.readdirSync(e))f.endsWith(".egg-info")&&n.rmSync(o.join(e,f),{recursive:!0,force:!0});const S=n.mkdtempSync(o.join(b.tmpdir(),"apigen-python-wheel-"));try{const f=h.spawnSync(y,["-m","pip","wheel","--no-deps","--wheel-dir",S,e],{encoding:"utf8",timeout:6e5});if(f.status!==0)throw new Error(`apigen-python-env: pip wheel failed (exit ${f.status}):
3
3
  ${f.stderr}
4
4
  stdout:
5
- ${f.stdout}`);const E=r.readdirSync(S).filter(A=>A.endsWith(".whl"));if(E.length===0)throw new Error("apigen-python-env: pip wheel produced no .whl file");const $=i.join(S,E[0]),N=y.length?`${$}[${y.join(",")}]`:$,g=h.spawnSync(p,["-m","pip","install","--quiet","--disable-pip-version-check",N],{encoding:"utf8",timeout:6e5});if(g.status!==0)throw new Error(`apigen-python-env: pip install "${N}" failed (exit ${g.status}):
5
+ ${f.stdout}`);const E=n.readdirSync(S).filter(A=>A.endsWith(".whl"));if(E.length===0)throw new Error("apigen-python-env: pip wheel produced no .whl file");const $=o.join(S,E[0]),N=d.length?`${$}[${d.join(",")}]`:$,g=h.spawnSync(y,["-m","pip","install","--quiet","--disable-pip-version-check",N],{encoding:"utf8",timeout:6e5});if(g.status!==0)throw new Error(`apigen-python-env: pip install "${N}" failed (exit ${g.status}):
6
6
  ${g.stderr}
7
7
  stdout:
8
- ${g.stdout}`)}finally{r.rmSync(S,{recursive:!0,force:!0})}const T={pyprojectHash:d,extras:y};return r.writeFileSync(a,JSON.stringify(T)),{python:p,venvDir:c,pythonPkgDir:e}})}function W(t,e,n,o,u){return new Promise((c,a)=>{var v,w;const d=h.spawn(t,["-m","apigen_python.extractor",n,"--namespace",o,"--emit-json"],{cwd:e,env:{...process.env,PYTHONPATH:e},stdio:["ignore","pipe","pipe"]});let p="",l="";(v=d.stdout)==null||v.on("data",s=>{p+=s.toString("utf8")}),(w=d.stderr)==null||w.on("data",s=>{l+=s.toString("utf8")}),d.on("error",a),d.on("exit",s=>{if(s!==0){a(new Error(`${u}: extractor --emit-json exited with code ${s}:
9
- ${l}`));return}try{c(JSON.parse(p))}catch(y){a(new Error(`${u}: extractor --emit-json produced invalid JSON (${y.message}):
10
- ${p}`))}})})}exports.ensurePythonEnv=V;exports.resolvePythonPkgDir=k;exports.runExtractorEmitJson=W;
8
+ ${g.stdout}`)}finally{n.rmSync(S,{recursive:!0,force:!0})}const T={pyprojectHash:u,extras:d};return n.writeFileSync(p,JSON.stringify(T)),{python:y,venvDir:c,pythonPkgDir:e}})}function L(t,e,r,i,a){return new Promise((c,p)=>{var v,w;const u=h.spawn(t,["-m","apigen_python.extractor",r,"--namespace",i,"--emit-json"],{cwd:e,env:{...process.env,PYTHONPATH:e},stdio:["ignore","pipe","pipe"]});let y="",l="";(v=u.stdout)==null||v.on("data",s=>{y+=s.toString("utf8")}),(w=u.stderr)==null||w.on("data",s=>{l+=s.toString("utf8")}),u.on("error",p),u.on("exit",s=>{if(s!==0){p(new Error(`${a}: extractor --emit-json exited with code ${s}:
9
+ ${l}`));return}try{c(JSON.parse(y))}catch(d){p(new Error(`${a}: extractor --emit-json produced invalid JSON (${d.message}):
10
+ ${y}`))}})})}exports.ensurePythonEnv=V;exports.resolvePythonPkgDir=k;exports.runExtractorEmitJson=L;
package/index.mjs CHANGED
@@ -4,20 +4,23 @@ import * as r from "node:path";
4
4
  import { createHash as T } from "node:crypto";
5
5
  import { spawnSync as l, spawn as I } from "node:child_process";
6
6
  function O(e) {
7
- const t = e ?? __dirname, o = r.resolve(t, "..", "..", "..", "python");
7
+ const t = e ?? __dirname, o = r.join(t, "python");
8
8
  if (n.existsSync(r.join(o, "apigen_python")))
9
9
  return o;
10
- let i = t;
11
- for (let u = 0; u < 20; u++) {
12
- const c = r.join(i, "packages", "apigen", "python");
13
- if (n.existsSync(r.join(c, "apigen_python")))
14
- return c;
15
- const a = r.dirname(i);
16
- if (a === i)
10
+ const s = r.resolve(t, "..", "..", "..", "python");
11
+ if (n.existsSync(r.join(s, "apigen_python")))
12
+ return s;
13
+ let a = t;
14
+ for (let c = 0; c < 20; c++) {
15
+ const p = r.join(a, "packages", "apigen", "python");
16
+ if (n.existsSync(r.join(p, "apigen_python")))
17
+ return p;
18
+ const u = r.dirname(a);
19
+ if (u === a)
17
20
  break;
18
- i = a;
21
+ a = u;
19
22
  }
20
- return o;
23
+ return s;
21
24
  }
22
25
  const _ = ["python3.13", "python3.12", "python3.11", "python3"], m = [3, 11];
23
26
  function D(e) {
@@ -27,9 +30,9 @@ function D(e) {
27
30
  });
28
31
  if (t.status !== 0 || !t.stdout)
29
32
  return;
30
- const [o, i] = t.stdout.trim().split(".").map(Number);
31
- if (!(!Number.isFinite(o) || !Number.isFinite(i)))
32
- return [o, i];
33
+ const [o, s] = t.stdout.trim().split(".").map(Number);
34
+ if (!(!Number.isFinite(o) || !Number.isFinite(s)))
35
+ return [o, s];
33
36
  }
34
37
  function F() {
35
38
  for (const e of _) {
@@ -57,13 +60,13 @@ function k(e) {
57
60
  }
58
61
  }
59
62
  function G(e, t, o) {
60
- const i = Date.now() + t;
63
+ const s = Date.now() + t;
61
64
  for (; ; )
62
65
  try {
63
66
  n.mkdirSync(e, { recursive: !1 });
64
67
  break;
65
68
  } catch {
66
- if (Date.now() > i) {
69
+ if (Date.now() > s) {
67
70
  try {
68
71
  n.rmdirSync(e);
69
72
  } catch {
@@ -88,20 +91,20 @@ function V(e = {}) {
88
91
  throw new Error(`apigen-python-env: APIGEN_PYTHON points to a missing file: ${o}`);
89
92
  return { python: o, venvDir: "", pythonPkgDir: t };
90
93
  }
91
- const i = [...new Set(e.extras ?? [])].sort(), u = e.envHome ?? process.env.APIGEN_PYENV_HOME ?? r.join(H.homedir(), ".adhd", "apigen"), c = r.join(u, "pyvenv"), a = r.join(c, ".apigen-stamp"), d = J(t), p = Y(c), h = () => {
92
- if (!n.existsSync(p))
94
+ const s = [...new Set(e.extras ?? [])].sort(), a = e.envHome ?? process.env.APIGEN_PYENV_HOME ?? r.join(H.homedir(), ".adhd", "apigen"), c = r.join(a, "pyvenv"), p = r.join(c, ".apigen-stamp"), u = J(t), d = Y(c), h = () => {
95
+ if (!n.existsSync(d))
93
96
  return !1;
94
- const s = k(a);
95
- return !s || s.pyprojectHash !== d ? !1 : i.every((f) => s.extras.includes(f));
97
+ const i = k(p);
98
+ return !i || i.pyprojectHash !== u ? !1 : s.every((y) => i.extras.includes(y));
96
99
  };
97
100
  if (h())
98
- return { python: p, venvDir: c, pythonPkgDir: t };
99
- n.mkdirSync(u, { recursive: !0 });
100
- const v = r.join(u, "pyvenv.lock"), w = e.lockTimeoutMs ?? 3e5;
101
+ return { python: d, venvDir: c, pythonPkgDir: t };
102
+ n.mkdirSync(a, { recursive: !0 });
103
+ const v = r.join(a, "pyvenv.lock"), w = e.lockTimeoutMs ?? 3e5;
101
104
  return G(v, w, () => {
102
105
  if (h())
103
- return { python: p, venvDir: c, pythonPkgDir: t };
104
- const s = k(a), f = [.../* @__PURE__ */ new Set([...(s == null ? void 0 : s.extras) ?? [], ...i])].sort();
106
+ return { python: d, venvDir: c, pythonPkgDir: t };
107
+ const i = k(p), y = [.../* @__PURE__ */ new Set([...(i == null ? void 0 : i.extras) ?? [], ...s])].sort();
105
108
  n.rmSync(c, { recursive: !0, force: !0 });
106
109
  const x = F(), j = l(x, ["-m", "venv", c], { encoding: "utf8", timeout: 12e4 });
107
110
  if (j.status !== 0)
@@ -111,27 +114,27 @@ ${j.stderr}`
111
114
  );
112
115
  const $ = r.join(t, "build");
113
116
  n.existsSync($) && n.rmSync($, { recursive: !0, force: !0 });
114
- for (const y of n.readdirSync(t))
115
- y.endsWith(".egg-info") && n.rmSync(r.join(t, y), { recursive: !0, force: !0 });
117
+ for (const f of n.readdirSync(t))
118
+ f.endsWith(".egg-info") && n.rmSync(r.join(t, f), { recursive: !0, force: !0 });
116
119
  const S = n.mkdtempSync(r.join(H.tmpdir(), "apigen-python-wheel-"));
117
120
  try {
118
- const y = l(
119
- p,
121
+ const f = l(
122
+ d,
120
123
  ["-m", "pip", "wheel", "--no-deps", "--wheel-dir", S, t],
121
124
  { encoding: "utf8", timeout: 6e5 }
122
125
  );
123
- if (y.status !== 0)
126
+ if (f.status !== 0)
124
127
  throw new Error(
125
- `apigen-python-env: pip wheel failed (exit ${y.status}):
126
- ${y.stderr}
128
+ `apigen-python-env: pip wheel failed (exit ${f.status}):
129
+ ${f.stderr}
127
130
  stdout:
128
- ${y.stdout}`
131
+ ${f.stdout}`
129
132
  );
130
133
  const P = n.readdirSync(S).filter((b) => b.endsWith(".whl"));
131
134
  if (P.length === 0)
132
135
  throw new Error("apigen-python-env: pip wheel produced no .whl file");
133
- const E = r.join(S, P[0]), N = f.length ? `${E}[${f.join(",")}]` : E, g = l(
134
- p,
136
+ const E = r.join(S, P[0]), N = y.length ? `${E}[${y.join(",")}]` : E, g = l(
137
+ d,
135
138
  ["-m", "pip", "install", "--quiet", "--disable-pip-version-check", N],
136
139
  { encoding: "utf8", timeout: 6e5 }
137
140
  );
@@ -145,40 +148,40 @@ ${g.stdout}`
145
148
  } finally {
146
149
  n.rmSync(S, { recursive: !0, force: !0 });
147
150
  }
148
- const A = { pyprojectHash: d, extras: f };
149
- return n.writeFileSync(a, JSON.stringify(A)), { python: p, venvDir: c, pythonPkgDir: t };
151
+ const A = { pyprojectHash: u, extras: y };
152
+ return n.writeFileSync(p, JSON.stringify(A)), { python: d, venvDir: c, pythonPkgDir: t };
150
153
  });
151
154
  }
152
- function q(e, t, o, i, u) {
153
- return new Promise((c, a) => {
155
+ function q(e, t, o, s, a) {
156
+ return new Promise((c, p) => {
154
157
  var v, w;
155
- const d = I(
158
+ const u = I(
156
159
  e,
157
- ["-m", "apigen_python.extractor", o, "--namespace", i, "--emit-json"],
160
+ ["-m", "apigen_python.extractor", o, "--namespace", s, "--emit-json"],
158
161
  {
159
162
  cwd: t,
160
163
  env: { ...process.env, PYTHONPATH: t },
161
164
  stdio: ["ignore", "pipe", "pipe"]
162
165
  }
163
166
  );
164
- let p = "", h = "";
165
- (v = d.stdout) == null || v.on("data", (s) => {
166
- p += s.toString("utf8");
167
- }), (w = d.stderr) == null || w.on("data", (s) => {
168
- h += s.toString("utf8");
169
- }), d.on("error", a), d.on("exit", (s) => {
170
- if (s !== 0) {
171
- a(new Error(`${u}: extractor --emit-json exited with code ${s}:
167
+ let d = "", h = "";
168
+ (v = u.stdout) == null || v.on("data", (i) => {
169
+ d += i.toString("utf8");
170
+ }), (w = u.stderr) == null || w.on("data", (i) => {
171
+ h += i.toString("utf8");
172
+ }), u.on("error", p), u.on("exit", (i) => {
173
+ if (i !== 0) {
174
+ p(new Error(`${a}: extractor --emit-json exited with code ${i}:
172
175
  ${h}`));
173
176
  return;
174
177
  }
175
178
  try {
176
- c(JSON.parse(p));
177
- } catch (f) {
178
- a(
179
+ c(JSON.parse(d));
180
+ } catch (y) {
181
+ p(
179
182
  new Error(
180
- `${u}: extractor --emit-json produced invalid JSON (${f.message}):
181
- ${p}`
183
+ `${a}: extractor --emit-json produced invalid JSON (${y.message}):
184
+ ${d}`
182
185
  )
183
186
  );
184
187
  }
@@ -26,10 +26,20 @@ export interface IEnsurePythonEnvOptions {
26
26
  /**
27
27
  * Locate the directory containing the `apigen_python` package sources.
28
28
  *
29
- * Primary: `<this file>/../../../python` (source layout:
30
- * packages/apigen/python-env/src/lib → packages/apigen/python).
31
- * Fallback: walk up from __dirname looking for `packages/apigen/python`
32
- * (covers the vite-bundled CLI, where __dirname is the bundle output dir).
29
+ * Probed in order:
30
+ * 1. Co-located (SHIPPED) copy: `<this file's dir>/python`. This package's
31
+ * build copies `packages/apigen/python/apigen_python/**` into its own
32
+ * `dist/python/apigen_python/`, so for a consumer installed from npm
33
+ * OUTSIDE the monorepo (where __dirname is `node_modules/@adhd/
34
+ * apigen-python-env/dist`), the sources are bundled right next to the
35
+ * compiled code. This MUST be probed first so published consumers never
36
+ * fall through to a monorepo-only path that doesn't exist for them.
37
+ * 2. Monorepo source (dev-time fallback): `<this file>/../../../python`
38
+ * (source layout: packages/apigen/python-env/src/lib → packages/apigen/
39
+ * python). Keeps vitest/ts-node runs resolving the LIVE source instead
40
+ * of the copied snapshot.
41
+ * 3. Walk up from __dirname looking for `packages/apigen/python` (covers
42
+ * the vite-bundled CLI, where __dirname is the bundle output dir).
33
43
  * (Shared by py-grpc / py-flask — previously duplicated in each plugin.)
34
44
  */
35
45
  export declare function resolvePythonPkgDir(fromDir?: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhd/apigen-python-env",
3
- "version": "0.1.5",
3
+ "version": "0.2.1",
4
4
  "main": "./index.js",
5
5
  "module": "./index.mjs",
6
6
  "types": "./index.d.ts",
@@ -12,7 +12,7 @@
12
12
  "provisioning"
13
13
  ],
14
14
  "dependencies": {
15
- "@adhd/apigen-core-client": "^0.1.5"
15
+ "@adhd/apigen-core-client": "^0.2.1"
16
16
  },
17
17
  "publishConfig": {
18
18
  "access": "public"