learn-secrets-sdk 1.6.3 → 1.6.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.
@@ -298,54 +298,23 @@ Log in on ${this.baseUrl}`);
298
298
  if (!deviceAuthorized) {
299
299
  throw new SecretsSDKError("Device authorization timeout", 408);
300
300
  }
301
- console.log("\n\nDevice authorized! Sending 2FA code...");
302
- const tfaResponse = await fetch(`${this.baseUrl}/api/auth/2fa/send`, {
301
+ console.log("\n\nDevice authorized! Retrieving access token...");
302
+ const finalTokenResponse = await fetch(`${this.baseUrl}/api/auth/cli/token`, {
303
303
  method: "POST",
304
304
  headers: {
305
305
  "Content-Type": "application/json"
306
306
  },
307
307
  body: JSON.stringify({
308
- device_code: deviceData.device_code,
309
- sdk_name: SDK_NAME,
310
- machine_id: machineInfo.machineId
308
+ device_code: deviceData.device_code
311
309
  })
312
310
  });
313
- if (!tfaResponse.ok) {
314
- const errorData = await tfaResponse.json().catch(() => ({}));
311
+ if (!finalTokenResponse.ok) {
315
312
  throw new SecretsSDKError(
316
- errorData.message || "Failed to send 2FA code",
317
- tfaResponse.status
313
+ "Failed to retrieve access token",
314
+ finalTokenResponse.status
318
315
  );
319
316
  }
320
- console.log("2FA code sent to your email.\n");
321
- const rl2 = readline.createInterface({
322
- input: process.stdin,
323
- output: process.stdout
324
- });
325
- const tfaCode = await new Promise((resolve2) => {
326
- rl2.question("Enter 2FA code from email: ", (answer) => {
327
- rl2.close();
328
- resolve2(answer);
329
- });
330
- });
331
- const verifyResponse = await fetch(`${this.baseUrl}/api/auth/2fa/verify`, {
332
- method: "POST",
333
- headers: {
334
- "Content-Type": "application/json"
335
- },
336
- body: JSON.stringify({
337
- device_code: deviceData.device_code,
338
- code: tfaCode.trim()
339
- })
340
- });
341
- if (!verifyResponse.ok) {
342
- const errorData = await verifyResponse.json().catch(() => ({}));
343
- throw new SecretsSDKError(
344
- errorData.message || "2FA verification failed",
345
- verifyResponse.status
346
- );
347
- }
348
- const tokenData = await verifyResponse.json();
317
+ const tokenData = await finalTokenResponse.json();
349
318
  writeSDKCredentials(SDK_NAME, {
350
319
  access_token: tokenData.access_token,
351
320
  refresh_token: null,
@@ -1,11 +1,10 @@
1
- "use strict";var SecretsSDK=(()=>{var te=Object.create;var P=Object.defineProperty;var re=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var ne=Object.getPrototypeOf,ie=Object.prototype.hasOwnProperty;var d=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var oe=(t,e)=>()=>(t&&(e=t(t=0)),e);var W=(t,e)=>{for(var r in e)P(t,r,{get:e[r],enumerable:!0})},B=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of se(e))!ie.call(t,n)&&n!==r&&P(t,n,{get:()=>e[n],enumerable:!(s=re(e,n))||s.enumerable});return t};var y=(t,e,r)=>(r=t!=null?te(ne(t)):{},B(e||!t||!t.__esModule?P(r,"default",{value:t,enumerable:!0}):r,t)),ae=t=>B(P({},"__esModule",{value:!0}),t);var Y={};W(Y,{loadSecretsConfig:()=>J,resolveEnvInSecret:()=>j,resolveEnvInSecrets:()=>M,resolveEnvString:()=>p});function p(t){return t.replace(/\$\{([A-Z0-9_]+)\}|\$([A-Z0-9_]+)/g,(e,r,s)=>{let n=r||s,i=process.env[n];if(i===void 0)throw new Error(`Environment variable ${n} is not defined`);return i})}function j(t){let e={name:p(t.name),provider:p(t.provider),api_key:p(t.api_key)};return t.base_url&&(e.base_url=p(t.base_url)),t.auth_header&&(e.auth_header=p(t.auth_header)),t.auth_prefix&&(e.auth_prefix=p(t.auth_prefix)),e}function M(t){return t.map(j)}function J(t){let e=d("fs"),s=d("path").resolve(t);if(!e.existsSync(s))throw new Error(`Config file not found: ${s}`);let n=e.readFileSync(s,"utf-8"),i=JSON.parse(n);if(!i.version)throw new Error('Config file missing "version" field');if(!i.project)throw new Error('Config file missing "project" field');if(!Array.isArray(i.secrets))throw new Error('Config file missing "secrets" array');let a=M(i.secrets);return{version:i.version,project:i.project,secrets:a}}var H=oe(()=>{"use strict"});var pe={};W(pe,{InvalidTokenError:()=>v,OriginMismatchError:()=>b,RateLimitError:()=>x,SecretsManagement:()=>K,SecretsSDK:()=>O,SecretsSDKError:()=>o,deleteSDKCredentials:()=>G,getMachineId:()=>$,hasSDKCredentials:()=>V,loadSecretsConfig:()=>J,readAllCredentials:()=>I,readSDKCredentials:()=>k,resolveEnvInSecret:()=>j,resolveEnvInSecrets:()=>M,resolveEnvString:()=>p,writeAllCredentials:()=>L,writeSDKCredentials:()=>A});var o=class extends Error{constructor(r,s,n){super(r);this.status=s;this.response=n;this.name="SecretsSDKError"}},b=class extends o{constructor(e="Origin not allowed for this token"){super(e,403),this.name="OriginMismatchError"}},x=class extends o{constructor(e="Rate limit exceeded",r=60,s=0,n=100){super(e,429),this.name="RateLimitError",this.retryAfter=r,this.remaining=s,this.limit=n}},v=class extends o{constructor(e="Invalid or expired token"){super(e,401),this.name="InvalidTokenError"}};var O=class{constructor(e={}){this.rateLimitInfo=null;this.appId=e.appId||null,this.token=e.token||e.sessionToken||null,this.baseUrl=e.baseUrl||"https://ctklearn.carsontkempf.workers.dev",this.timeout=e.timeout||3e4,this.retryOn429=e.retryOn429!==void 0?e.retryOn429:!0,this.zeroConfigMode=!this.appId&&!this.token}getUsage(){return this.rateLimitInfo}parseRateLimitHeaders(e){let r=e.get("X-RateLimit-Limit"),s=e.get("X-RateLimit-Remaining"),n=e.get("X-RateLimit-Reset");r&&s&&n&&(this.rateLimitInfo={limit:parseInt(r),remaining:parseInt(s),reset:parseInt(n)})}sleep(e){return new Promise(r=>setTimeout(r,e))}async fetchWithTimeout(e,r,s){let n=new AbortController,i=setTimeout(()=>n.abort(),s);try{return await fetch(e,{...r,signal:n.signal})}finally{clearTimeout(i)}}async call(e,r,s={}){let n=0,i=this.retryOn429?3:0;for(;;)try{let a=this.zeroConfigMode?`${this.baseUrl}/api/sdk/proxy`:`${this.baseUrl}/api/sdk/${this.appId}/proxy`,m={"Content-Type":"application/json"};!this.zeroConfigMode&&this.token&&(m.Authorization=`Bearer ${this.token}`);let u=await this.fetchWithTimeout(a,{method:"POST",headers:m,body:JSON.stringify({keyName:e,endpoint:r,method:s.method||"GET",body:s.body,headers:s.headers})},this.timeout);this.parseRateLimitHeaders(u.headers);let w=await u.json();if(!u.ok){let h=w.data?.message||w?.message||`Request failed with status ${u.status}`;if(u.status===403&&h.includes("Origin"))throw new b(h);if(u.status===401)throw new v(h);if(u.status===429){let T=this.rateLimitInfo?this.rateLimitInfo.reset-Math.floor(Date.now()/1e3):60,C=new x(h,T,this.rateLimitInfo?.remaining||0,this.rateLimitInfo?.limit||100);if(this.retryOn429&&n<i){n++;let D=Math.min(1e3*Math.pow(2,n-1),8e3);await this.sleep(D);continue}throw C}throw new o(h,u.status,w)}return w.data}catch(a){throw a instanceof o?a:a instanceof Error&&a.name==="AbortError"?new o("Request timeout",408):new o(a instanceof Error?a.message:"Unknown error occurred",500)}}async get(e,r,s){return this.call(e,r,{method:"GET",headers:s})}async post(e,r,s,n){return this.call(e,r,{method:"POST",body:s,headers:n})}async put(e,r,s,n){return this.call(e,r,{method:"PUT",body:s,headers:n})}async delete(e,r,s){return this.call(e,r,{method:"DELETE",headers:s})}async patch(e,r,s,n){return this.call(e,r,{method:"PATCH",body:s,headers:n})}setAppId(e){this.appId=e}async secretsRequest(e,r){if(!this.appId)throw new o("App ID required for secrets management. Call setAppId() first.",400);let s=await this.fetchWithTimeout(`${this.baseUrl}/api/projects/${this.appId}/secrets/manage?action=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:r?JSON.stringify(r):void 0},this.timeout);if(!s.ok){let n=await s.json().catch(()=>({}));throw new o(n.message||`Secrets management failed: ${s.statusText}`,s.status,n)}return s.json()}async listSecrets(){return this.secretsRequest("list")}async createSecret(e){return this.secretsRequest("create",e)}async updateSecret(e){return this.secretsRequest("update",e)}async deleteSecret(e){return this.secretsRequest("delete",{name:e})}async syncEnv(e,r){return this.secretsRequest("sync",{secrets:e,provider:r})}};var l=y(d("fs")),E=y(d("path")),U=y(d("os"));function q(){let t=U.homedir(),e=E.join(t,".learn");return E.join(e,"credentials.json")}function ce(){let t=U.homedir(),e=E.join(t,".learn");l.existsSync(e)||l.mkdirSync(e,{recursive:!0,mode:448})}function I(){try{let t=q();if(!l.existsSync(t))return null;let e=l.readFileSync(t,"utf-8"),r=JSON.parse(e);return r.access_token&&!r["learn-secrets-sdk"]&&!r["learn-auth-sdk"]?{"learn-secrets-sdk":r}:r}catch{return null}}function L(t){ce();let e=q(),r=JSON.stringify(t,null,2);l.writeFileSync(e,r,{mode:384})}function k(t){let e=I();return e&&e[t]||null}function A(t,e){let r=I()||{};r[t]=e,L(r)}function G(t){let e=I();e&&(delete e[t],Object.keys(e).length===0?F():L(e))}function N(){return k("learn-secrets-sdk")}function F(){try{let t=q();l.existsSync(t)&&l.unlinkSync(t)}catch{}}function V(t){let e=k(t);return e!==null&&!!e.access_token}function X(){let t=N();return t?t.expires_at?new Date(t.expires_at)>new Date:!0:!1}var Z=d("child_process"),Q=d("util"),z=d("crypto"),g=y(d("os")),_=(0,Q.promisify)(Z.exec);async function $(){let t=process.platform;try{let e;if(t==="darwin")e=await de();else if(t==="linux")e=await le();else if(t==="win32")e=await ue();else throw new Error(`Unsupported platform: ${t}`);let r=(0,z.createHash)("sha256").update(e).digest("hex").substring(0,32),s=JSON.stringify({machineId:r,cpus:g.cpus().length,arch:g.arch(),platform:g.platform(),homedir:g.homedir()}),n=(0,z.createHash)("sha256").update(s).digest("hex");return{machineId:r,fingerprint:n}}catch(e){throw new Error(`Failed to get machine ID: ${e.message}`)}}async function de(){try{let{stdout:t}=await _(`ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | sed 's/"//g'`),{stdout:e}=await _("hostname"),r=t.trim(),s=e.trim();if(r&&s)return`${r}-${s}`;let{stdout:n}=await _(`ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk '{print $3}' | sed 's/"//g'`);return n.trim()}catch{throw new Error("Failed to get macOS machine ID")}}async function le(){try{let{stdout:t}=await _("cat /etc/machine-id 2>/dev/null || cat /var/lib/dbus/machine-id 2>/dev/null"),e=t.trim();if(e)return e;throw new Error("Machine ID file not found")}catch{throw new Error("Failed to get Linux machine ID")}}async function ue(){try{let{stdout:t}=await _("wmic csproduct get uuid"),r=t.split(`
2
- `).map(s=>s.trim()).find(s=>s&&s!=="UUID");if(r)return r;throw new Error("Failed to parse machine UUID from WMIC")}catch{throw new Error("Failed to get Windows machine ID")}}var K=class{constructor(e){this.appId=e.appId,this.baseUrl=e.baseUrl||"https://cloudprototype.org",this.timeout=e.timeout||3e4}async openBrowser(e){let{exec:r}=await import("child_process"),{promisify:s}=await import("util"),n=s(r),i=process.platform;try{i==="darwin"?await n(`open "${e}"`):i==="win32"?await n(`start "${e}"`):await n(`xdg-open "${e}"`)}catch(a){throw console.error("Failed to open browser:",a),new o("Failed to open browser",500)}}sleep(e){return new Promise(r=>setTimeout(r,e))}async login(){let e="learn-secrets-sdk";try{console.log(`Authenticating with Learn (${e})...
3
- `);let r=await $(),s=k(e);if(s&&s.access_token){let c=await fetch(`${this.baseUrl}/api/auth/cli/check-authorization`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({machine_id:r.machineId,sdk_name:e})});if(c.ok){let f=await c.json();if(f.authorized)return console.log("This machine is already authorized."),console.log(`Logged in as: ${f.user_email||f.user_id}`),{success:!0,user:f.user_email||f.user_id}}}let n=await fetch(`${this.baseUrl}/api/auth/cli/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!n.ok)throw new o("Failed to generate device code",n.status);let i=await n.json();console.log(`
1
+ "use strict";var SecretsSDK=(()=>{var Q=Object.create;var D=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var c=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var se=(t,e)=>()=>(t&&(e=t(t=0)),e);var J=(t,e)=>{for(var r in e)D(t,r,{get:e[r],enumerable:!0})},H=(t,e,r,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of ee(e))!re.call(t,n)&&n!==r&&D(t,n,{get:()=>e[n],enumerable:!(s=Y(e,n))||s.enumerable});return t};var y=(t,e,r)=>(r=t!=null?Q(te(t)):{},H(e||!t||!t.__esModule?D(r,"default",{value:t,enumerable:!0}):r,t)),ne=t=>H(D({},"__esModule",{value:!0}),t);var Z={};J(Z,{loadSecretsConfig:()=>z,resolveEnvInSecret:()=>$,resolveEnvInSecrets:()=>A,resolveEnvString:()=>u});function u(t){return t.replace(/\$\{([A-Z0-9_]+)\}|\$([A-Z0-9_]+)/g,(e,r,s)=>{let n=r||s,i=process.env[n];if(i===void 0)throw new Error(`Environment variable ${n} is not defined`);return i})}function $(t){let e={name:u(t.name),provider:u(t.provider),api_key:u(t.api_key)};return t.base_url&&(e.base_url=u(t.base_url)),t.auth_header&&(e.auth_header=u(t.auth_header)),t.auth_prefix&&(e.auth_prefix=u(t.auth_prefix)),e}function A(t){return t.map($)}function z(t){let e=c("fs"),s=c("path").resolve(t);if(!e.existsSync(s))throw new Error(`Config file not found: ${s}`);let n=e.readFileSync(s,"utf-8"),i=JSON.parse(n);if(!i.version)throw new Error('Config file missing "version" field');if(!i.project)throw new Error('Config file missing "project" field');if(!Array.isArray(i.secrets))throw new Error('Config file missing "secrets" array');let a=A(i.secrets);return{version:i.version,project:i.project,secrets:a}}var F=se(()=>{"use strict"});var de={};J(de,{InvalidTokenError:()=>b,OriginMismatchError:()=>S,RateLimitError:()=>x,SecretsManagement:()=>j,SecretsSDK:()=>R,SecretsSDKError:()=>o,deleteSDKCredentials:()=>W,getMachineId:()=>L,hasSDKCredentials:()=>B,loadSecretsConfig:()=>z,readAllCredentials:()=>I,readSDKCredentials:()=>v,resolveEnvInSecret:()=>$,resolveEnvInSecrets:()=>A,resolveEnvString:()=>u,writeAllCredentials:()=>O,writeSDKCredentials:()=>E});var o=class extends Error{constructor(r,s,n){super(r);this.status=s;this.response=n;this.name="SecretsSDKError"}},S=class extends o{constructor(e="Origin not allowed for this token"){super(e,403),this.name="OriginMismatchError"}},x=class extends o{constructor(e="Rate limit exceeded",r=60,s=0,n=100){super(e,429),this.name="RateLimitError",this.retryAfter=r,this.remaining=s,this.limit=n}},b=class extends o{constructor(e="Invalid or expired token"){super(e,401),this.name="InvalidTokenError"}};var R=class{constructor(e={}){this.rateLimitInfo=null;this.appId=e.appId||null,this.token=e.token||e.sessionToken||null,this.baseUrl=e.baseUrl||"https://ctklearn.carsontkempf.workers.dev",this.timeout=e.timeout||3e4,this.retryOn429=e.retryOn429!==void 0?e.retryOn429:!0,this.zeroConfigMode=!this.appId&&!this.token}getUsage(){return this.rateLimitInfo}parseRateLimitHeaders(e){let r=e.get("X-RateLimit-Limit"),s=e.get("X-RateLimit-Remaining"),n=e.get("X-RateLimit-Reset");r&&s&&n&&(this.rateLimitInfo={limit:parseInt(r),remaining:parseInt(s),reset:parseInt(n)})}sleep(e){return new Promise(r=>setTimeout(r,e))}async fetchWithTimeout(e,r,s){let n=new AbortController,i=setTimeout(()=>n.abort(),s);try{return await fetch(e,{...r,signal:n.signal})}finally{clearTimeout(i)}}async call(e,r,s={}){let n=0,i=this.retryOn429?3:0;for(;;)try{let a=this.zeroConfigMode?`${this.baseUrl}/api/sdk/proxy`:`${this.baseUrl}/api/sdk/${this.appId}/proxy`,p={"Content-Type":"application/json"};!this.zeroConfigMode&&this.token&&(p.Authorization=`Bearer ${this.token}`);let l=await this.fetchWithTimeout(a,{method:"POST",headers:p,body:JSON.stringify({keyName:e,endpoint:r,method:s.method||"GET",body:s.body,headers:s.headers})},this.timeout);this.parseRateLimitHeaders(l.headers);let w=await l.json();if(!l.ok){let h=w.data?.message||w?.message||`Request failed with status ${l.status}`;if(l.status===403&&h.includes("Origin"))throw new S(h);if(l.status===401)throw new b(h);if(l.status===429){let T=this.rateLimitInfo?this.rateLimitInfo.reset-Math.floor(Date.now()/1e3):60,k=new x(h,T,this.rateLimitInfo?.remaining||0,this.rateLimitInfo?.limit||100);if(this.retryOn429&&n<i){n++;let m=Math.min(1e3*Math.pow(2,n-1),8e3);await this.sleep(m);continue}throw k}throw new o(h,l.status,w)}return w.data}catch(a){throw a instanceof o?a:a instanceof Error&&a.name==="AbortError"?new o("Request timeout",408):new o(a instanceof Error?a.message:"Unknown error occurred",500)}}async get(e,r,s){return this.call(e,r,{method:"GET",headers:s})}async post(e,r,s,n){return this.call(e,r,{method:"POST",body:s,headers:n})}async put(e,r,s,n){return this.call(e,r,{method:"PUT",body:s,headers:n})}async delete(e,r,s){return this.call(e,r,{method:"DELETE",headers:s})}async patch(e,r,s,n){return this.call(e,r,{method:"PATCH",body:s,headers:n})}setAppId(e){this.appId=e}async secretsRequest(e,r){if(!this.appId)throw new o("App ID required for secrets management. Call setAppId() first.",400);let s=await this.fetchWithTimeout(`${this.baseUrl}/api/projects/${this.appId}/secrets/manage?action=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:r?JSON.stringify(r):void 0},this.timeout);if(!s.ok){let n=await s.json().catch(()=>({}));throw new o(n.message||`Secrets management failed: ${s.statusText}`,s.status,n)}return s.json()}async listSecrets(){return this.secretsRequest("list")}async createSecret(e){return this.secretsRequest("create",e)}async updateSecret(e){return this.secretsRequest("update",e)}async deleteSecret(e){return this.secretsRequest("delete",{name:e})}async syncEnv(e,r){return this.secretsRequest("sync",{secrets:e,provider:r})}};var d=y(c("fs")),P=y(c("path")),M=y(c("os"));function K(){let t=M.homedir(),e=P.join(t,".learn");return P.join(e,"credentials.json")}function ie(){let t=M.homedir(),e=P.join(t,".learn");d.existsSync(e)||d.mkdirSync(e,{recursive:!0,mode:448})}function I(){try{let t=K();if(!d.existsSync(t))return null;let e=d.readFileSync(t,"utf-8"),r=JSON.parse(e);return r.access_token&&!r["learn-secrets-sdk"]&&!r["learn-auth-sdk"]?{"learn-secrets-sdk":r}:r}catch{return null}}function O(t){ie();let e=K(),r=JSON.stringify(t,null,2);d.writeFileSync(e,r,{mode:384})}function v(t){let e=I();return e&&e[t]||null}function E(t,e){let r=I()||{};r[t]=e,O(r)}function W(t){let e=I();e&&(delete e[t],Object.keys(e).length===0?q():O(e))}function U(){return v("learn-secrets-sdk")}function q(){try{let t=K();d.existsSync(t)&&d.unlinkSync(t)}catch{}}function B(t){let e=v(t);return e!==null&&!!e.access_token}function G(){let t=U();return t?t.expires_at?new Date(t.expires_at)>new Date:!0:!1}var V=c("child_process"),X=c("util"),N=c("crypto"),g=y(c("os")),_=(0,X.promisify)(V.exec);async function L(){let t=process.platform;try{let e;if(t==="darwin")e=await oe();else if(t==="linux")e=await ae();else if(t==="win32")e=await ce();else throw new Error(`Unsupported platform: ${t}`);let r=(0,N.createHash)("sha256").update(e).digest("hex").substring(0,32),s=JSON.stringify({machineId:r,cpus:g.cpus().length,arch:g.arch(),platform:g.platform(),homedir:g.homedir()}),n=(0,N.createHash)("sha256").update(s).digest("hex");return{machineId:r,fingerprint:n}}catch(e){throw new Error(`Failed to get machine ID: ${e.message}`)}}async function oe(){try{let{stdout:t}=await _(`ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | sed 's/"//g'`),{stdout:e}=await _("hostname"),r=t.trim(),s=e.trim();if(r&&s)return`${r}-${s}`;let{stdout:n}=await _(`ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk '{print $3}' | sed 's/"//g'`);return n.trim()}catch{throw new Error("Failed to get macOS machine ID")}}async function ae(){try{let{stdout:t}=await _("cat /etc/machine-id 2>/dev/null || cat /var/lib/dbus/machine-id 2>/dev/null"),e=t.trim();if(e)return e;throw new Error("Machine ID file not found")}catch{throw new Error("Failed to get Linux machine ID")}}async function ce(){try{let{stdout:t}=await _("wmic csproduct get uuid"),r=t.split(`
2
+ `).map(s=>s.trim()).find(s=>s&&s!=="UUID");if(r)return r;throw new Error("Failed to parse machine UUID from WMIC")}catch{throw new Error("Failed to get Windows machine ID")}}var j=class{constructor(e){this.appId=e.appId,this.baseUrl=e.baseUrl||"https://cloudprototype.org",this.timeout=e.timeout||3e4}async openBrowser(e){let{exec:r}=await import("child_process"),{promisify:s}=await import("util"),n=s(r),i=process.platform;try{i==="darwin"?await n(`open "${e}"`):i==="win32"?await n(`start "${e}"`):await n(`xdg-open "${e}"`)}catch(a){throw console.error("Failed to open browser:",a),new o("Failed to open browser",500)}}sleep(e){return new Promise(r=>setTimeout(r,e))}async login(){let e="learn-secrets-sdk";try{console.log(`Authenticating with Learn (${e})...
3
+ `);let r=await L(),s=v(e);if(s&&s.access_token){let f=await fetch(`${this.baseUrl}/api/auth/cli/check-authorization`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({machine_id:r.machineId,sdk_name:e})});if(f.ok){let C=await f.json();if(C.authorized)return console.log("This machine is already authorized."),console.log(`Logged in as: ${C.user_email||C.user_id}`),{success:!0,user:C.user_email||C.user_id}}}let n=await fetch(`${this.baseUrl}/api/auth/cli/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!n.ok)throw new o("Failed to generate device code",n.status);let i=await n.json();console.log(`
4
4
  Log in on ${this.baseUrl}`),console.log("Login at:"),console.log(i.verification_uri_complete),console.log(`
5
- Press ENTER to open in the browser...`);let a=await import("readline"),m=a.createInterface({input:process.stdin,output:process.stdout});await new Promise(c=>{m.question("",()=>{m.close(),c()})}),console.log(`Opening browser...
6
- `),await this.openBrowser(i.verification_uri_complete);let u=!1,w=i.interval*1e3,h=Math.ceil(i.expires_in/i.interval),T=0;for(;T<h;){await this.sleep(w),T++;let c=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:i.device_code})});if(c.status===202){process.stdout.write(".");continue}if(c.ok){u=!0;break}}if(!u)throw new o("Device authorization timeout",408);console.log(`
5
+ Press ENTER to open in the browser...`);let p=(await import("readline")).createInterface({input:process.stdin,output:process.stdout});await new Promise(f=>{p.question("",()=>{p.close(),f()})}),console.log(`Opening browser...
6
+ `),await this.openBrowser(i.verification_uri_complete);let l=!1,w=i.interval*1e3,h=Math.ceil(i.expires_in/i.interval),T=0;for(;T<h;){await this.sleep(w),T++;let f=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:i.device_code})});if(f.status===202){process.stdout.write(".");continue}if(f.ok){l=!0;break}}if(!l)throw new o("Device authorization timeout",408);console.log(`
7
7
 
8
- Device authorized! Sending 2FA code...`);let C=await fetch(`${this.baseUrl}/api/auth/2fa/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:i.device_code,sdk_name:e,machine_id:r.machineId})});if(!C.ok){let c=await C.json().catch(()=>({}));throw new o(c.message||"Failed to send 2FA code",C.status)}console.log(`2FA code sent to your email.
9
- `);let D=a.createInterface({input:process.stdin,output:process.stdout}),ee=await new Promise(c=>{D.question("Enter 2FA code from email: ",f=>{D.close(),c(f)})}),R=await fetch(`${this.baseUrl}/api/auth/2fa/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:i.device_code,code:ee.trim()})});if(!R.ok){let c=await R.json().catch(()=>({}));throw new o(c.message||"2FA verification failed",R.status)}let S=await R.json();return A(e,{access_token:S.access_token,refresh_token:null,expires_at:null,user_id:S.user_id,machine_id:r.machineId,sdk_name:e,authorized_at:new Date().toISOString()}),console.log(`
10
- Authentication successful!`),console.log(`Logged in as: ${S.user_email||S.user_id}`),console.log(`This machine is now permanently authorized.
11
- `),{success:!0,user:S.user_email||S.user_id}}catch(r){throw r instanceof o?r:new o(r.message||"Login failed",r.status||500)}}async isAuthenticated(){return X()}logout(){F(),console.log("Logged out successfully")}getAccessToken(){let e=N();if(!e)throw new o("Not authenticated. Run login() first.",401);if(e.expires_at&&new Date(e.expires_at)<=new Date)throw new o("Token expired. Run login() again.",401);return e.access_token}async request(e,r,s){let n=this.getAccessToken(),i={method:e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}};s&&(i.body=JSON.stringify(s));let a=await fetch(`${this.baseUrl}${r}`,i);if(!a.ok){let m=await a.json().catch(()=>({}));throw new o(m.message||`Request failed: ${a.statusText}`,a.status,m)}return a.json()}async list(){return(await this.request("GET",`/api/projects/${this.appId}/secrets`)).secrets}async sync(e,r){return await this.request("POST",`/api/projects/${this.appId}/secrets/sync`,{secrets:e,options:{deleteMissing:r?.deleteMissing??!1,dryRun:r?.dryRun??!1}})}async importSecrets(e){return this.request("POST",`/api/projects/${this.appId}/import-secrets`,{version:e.version||"1.0",origins:e.origins,secrets:e.secrets})}async importFromFile(e){let{loadSecretsConfig:r}=await Promise.resolve().then(()=>(H(),Y)),s=r(e);return this.importSecrets(s)}};H();return ae(pe);})();
8
+ Device authorized! Retrieving access token...`);let k=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:i.device_code})});if(!k.ok)throw new o("Failed to retrieve access token",k.status);let m=await k.json();return E(e,{access_token:m.access_token,refresh_token:null,expires_at:null,user_id:m.user_id,machine_id:r.machineId,sdk_name:e,authorized_at:new Date().toISOString()}),console.log(`
9
+ Authentication successful!`),console.log(`Logged in as: ${m.user_email||m.user_id}`),console.log(`This machine is now permanently authorized.
10
+ `),{success:!0,user:m.user_email||m.user_id}}catch(r){throw r instanceof o?r:new o(r.message||"Login failed",r.status||500)}}async isAuthenticated(){return G()}logout(){q(),console.log("Logged out successfully")}getAccessToken(){let e=U();if(!e)throw new o("Not authenticated. Run login() first.",401);if(e.expires_at&&new Date(e.expires_at)<=new Date)throw new o("Token expired. Run login() again.",401);return e.access_token}async request(e,r,s){let n=this.getAccessToken(),i={method:e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}};s&&(i.body=JSON.stringify(s));let a=await fetch(`${this.baseUrl}${r}`,i);if(!a.ok){let p=await a.json().catch(()=>({}));throw new o(p.message||`Request failed: ${a.statusText}`,a.status,p)}return a.json()}async list(){return(await this.request("GET",`/api/projects/${this.appId}/secrets`)).secrets}async sync(e,r){return await this.request("POST",`/api/projects/${this.appId}/secrets/sync`,{secrets:e,options:{deleteMissing:r?.deleteMissing??!1,dryRun:r?.dryRun??!1}})}async importSecrets(e){return this.request("POST",`/api/projects/${this.appId}/import-secrets`,{version:e.version||"1.0",origins:e.origins,secrets:e.secrets})}async importFromFile(e){let{loadSecretsConfig:r}=await Promise.resolve().then(()=>(F(),Z)),s=r(e);return this.importSecrets(s)}};F();return ne(de);})();
package/dist/index.mjs CHANGED
@@ -1,11 +1,10 @@
1
- import{a as q,b as N,c as F,d as z}from"./chunk-AS6G7JYX.mjs";var i=class extends Error{constructor(t,r,n){super(t);this.status=r;this.response=n;this.name="SecretsSDKError"}},w=class extends i{constructor(e="Origin not allowed for this token"){super(e,403),this.name="OriginMismatchError"}},S=class extends i{constructor(e="Rate limit exceeded",t=60,r=0,n=100){super(e,429),this.name="RateLimitError",this.retryAfter=t,this.remaining=r,this.limit=n}},b=class extends i{constructor(e="Invalid or expired token"){super(e,401),this.name="InvalidTokenError"}};var D=class{constructor(e={}){this.rateLimitInfo=null;this.appId=e.appId||null,this.token=e.token||e.sessionToken||null,this.baseUrl=e.baseUrl||"https://ctklearn.carsontkempf.workers.dev",this.timeout=e.timeout||3e4,this.retryOn429=e.retryOn429!==void 0?e.retryOn429:!0,this.zeroConfigMode=!this.appId&&!this.token}getUsage(){return this.rateLimitInfo}parseRateLimitHeaders(e){let t=e.get("X-RateLimit-Limit"),r=e.get("X-RateLimit-Remaining"),n=e.get("X-RateLimit-Reset");t&&r&&n&&(this.rateLimitInfo={limit:parseInt(t),remaining:parseInt(r),reset:parseInt(n)})}sleep(e){return new Promise(t=>setTimeout(t,e))}async fetchWithTimeout(e,t,r){let n=new AbortController,a=setTimeout(()=>n.abort(),r);try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(a)}}async call(e,t,r={}){let n=0,a=this.retryOn429?3:0;for(;;)try{let o=this.zeroConfigMode?`${this.baseUrl}/api/sdk/proxy`:`${this.baseUrl}/api/sdk/${this.appId}/proxy`,u={"Content-Type":"application/json"};!this.zeroConfigMode&&this.token&&(u.Authorization=`Bearer ${this.token}`);let l=await this.fetchWithTimeout(o,{method:"POST",headers:u,body:JSON.stringify({keyName:e,endpoint:t,method:r.method||"GET",body:r.body,headers:r.headers})},this.timeout);this.parseRateLimitHeaders(l.headers);let g=await l.json();if(!l.ok){let m=g.data?.message||g?.message||`Request failed with status ${l.status}`;if(l.status===403&&m.includes("Origin"))throw new w(m);if(l.status===401)throw new b(m);if(l.status===429){let I=this.rateLimitInfo?this.rateLimitInfo.reset-Math.floor(Date.now()/1e3):60,y=new S(m,I,this.rateLimitInfo?.remaining||0,this.rateLimitInfo?.limit||100);if(this.retryOn429&&n<a){n++;let v=Math.min(1e3*Math.pow(2,n-1),8e3);await this.sleep(v);continue}throw y}throw new i(m,l.status,g)}return g.data}catch(o){throw o instanceof i?o:o instanceof Error&&o.name==="AbortError"?new i("Request timeout",408):new i(o instanceof Error?o.message:"Unknown error occurred",500)}}async get(e,t,r){return this.call(e,t,{method:"GET",headers:r})}async post(e,t,r,n){return this.call(e,t,{method:"POST",body:r,headers:n})}async put(e,t,r,n){return this.call(e,t,{method:"PUT",body:r,headers:n})}async delete(e,t,r){return this.call(e,t,{method:"DELETE",headers:r})}async patch(e,t,r,n){return this.call(e,t,{method:"PATCH",body:r,headers:n})}setAppId(e){this.appId=e}async secretsRequest(e,t){if(!this.appId)throw new i("App ID required for secrets management. Call setAppId() first.",400);let r=await this.fetchWithTimeout(`${this.baseUrl}/api/projects/${this.appId}/secrets/manage?action=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0},this.timeout);if(!r.ok){let n=await r.json().catch(()=>({}));throw new i(n.message||`Secrets management failed: ${r.statusText}`,r.status,n)}return r.json()}async listSecrets(){return this.secretsRequest("list")}async createSecret(e){return this.secretsRequest("create",e)}async updateSecret(e){return this.secretsRequest("update",e)}async deleteSecret(e){return this.secretsRequest("delete",{name:e})}async syncEnv(e,t){return this.secretsRequest("sync",{secrets:e,provider:t})}};import*as d from"fs";import*as T from"path";import*as R from"os";function P(){let s=R.homedir(),e=T.join(s,".learn");return T.join(e,"credentials.json")}function J(){let s=R.homedir(),e=T.join(s,".learn");d.existsSync(e)||d.mkdirSync(e,{recursive:!0,mode:448})}function _(){try{let s=P();if(!d.existsSync(s))return null;let e=d.readFileSync(s,"utf-8"),t=JSON.parse(e);return t.access_token&&!t["learn-secrets-sdk"]&&!t["learn-auth-sdk"]?{"learn-secrets-sdk":t}:t}catch{return null}}function O(s){J();let e=P(),t=JSON.stringify(s,null,2);d.writeFileSync(e,t,{mode:384})}function x(s){let e=_();return e&&e[s]||null}function L(s,e){let t=_()||{};t[s]=e,O(t)}function H(s){let e=_();e&&(delete e[s],Object.keys(e).length===0?A():O(e))}function E(){return x("learn-secrets-sdk")}function A(){try{let s=P();d.existsSync(s)&&d.unlinkSync(s)}catch{}}function W(s){let e=x(s);return e!==null&&!!e.access_token}function K(){let s=E();return s?s.expires_at?new Date(s.expires_at)>new Date:!0:!1}import{exec as B}from"child_process";import{promisify as G}from"util";import{createHash as j}from"crypto";import*as p from"os";var k=G(B);async function M(){let s=process.platform;try{let e;if(s==="darwin")e=await X();else if(s==="linux")e=await V();else if(s==="win32")e=await Q();else throw new Error(`Unsupported platform: ${s}`);let t=j("sha256").update(e).digest("hex").substring(0,32),r=JSON.stringify({machineId:t,cpus:p.cpus().length,arch:p.arch(),platform:p.platform(),homedir:p.homedir()}),n=j("sha256").update(r).digest("hex");return{machineId:t,fingerprint:n}}catch(e){throw new Error(`Failed to get machine ID: ${e.message}`)}}async function X(){try{let{stdout:s}=await k(`ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | sed 's/"//g'`),{stdout:e}=await k("hostname"),t=s.trim(),r=e.trim();if(t&&r)return`${t}-${r}`;let{stdout:n}=await k(`ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk '{print $3}' | sed 's/"//g'`);return n.trim()}catch{throw new Error("Failed to get macOS machine ID")}}async function V(){try{let{stdout:s}=await k("cat /etc/machine-id 2>/dev/null || cat /var/lib/dbus/machine-id 2>/dev/null"),e=s.trim();if(e)return e;throw new Error("Machine ID file not found")}catch{throw new Error("Failed to get Linux machine ID")}}async function Q(){try{let{stdout:s}=await k("wmic csproduct get uuid"),t=s.split(`
2
- `).map(r=>r.trim()).find(r=>r&&r!=="UUID");if(t)return t;throw new Error("Failed to parse machine UUID from WMIC")}catch{throw new Error("Failed to get Windows machine ID")}}var $=class{constructor(e){this.appId=e.appId,this.baseUrl=e.baseUrl||"https://cloudprototype.org",this.timeout=e.timeout||3e4}async openBrowser(e){let{exec:t}=await import("child_process"),{promisify:r}=await import("util"),n=r(t),a=process.platform;try{a==="darwin"?await n(`open "${e}"`):a==="win32"?await n(`start "${e}"`):await n(`xdg-open "${e}"`)}catch(o){throw console.error("Failed to open browser:",o),new i("Failed to open browser",500)}}sleep(e){return new Promise(t=>setTimeout(t,e))}async login(){let e="learn-secrets-sdk";try{console.log(`Authenticating with Learn (${e})...
3
- `);let t=await M(),r=x(e);if(r&&r.access_token){let c=await fetch(`${this.baseUrl}/api/auth/cli/check-authorization`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({machine_id:t.machineId,sdk_name:e})});if(c.ok){let h=await c.json();if(h.authorized)return console.log("This machine is already authorized."),console.log(`Logged in as: ${h.user_email||h.user_id}`),{success:!0,user:h.user_email||h.user_id}}}let n=await fetch(`${this.baseUrl}/api/auth/cli/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!n.ok)throw new i("Failed to generate device code",n.status);let a=await n.json();console.log(`
1
+ import{a as K,b as U,c as j,d as q}from"./chunk-AS6G7JYX.mjs";var i=class extends Error{constructor(t,r,n){super(t);this.status=r;this.response=n;this.name="SecretsSDKError"}},w=class extends i{constructor(e="Origin not allowed for this token"){super(e,403),this.name="OriginMismatchError"}},S=class extends i{constructor(e="Rate limit exceeded",t=60,r=0,n=100){super(e,429),this.name="RateLimitError",this.retryAfter=t,this.remaining=r,this.limit=n}},b=class extends i{constructor(e="Invalid or expired token"){super(e,401),this.name="InvalidTokenError"}};var T=class{constructor(e={}){this.rateLimitInfo=null;this.appId=e.appId||null,this.token=e.token||e.sessionToken||null,this.baseUrl=e.baseUrl||"https://ctklearn.carsontkempf.workers.dev",this.timeout=e.timeout||3e4,this.retryOn429=e.retryOn429!==void 0?e.retryOn429:!0,this.zeroConfigMode=!this.appId&&!this.token}getUsage(){return this.rateLimitInfo}parseRateLimitHeaders(e){let t=e.get("X-RateLimit-Limit"),r=e.get("X-RateLimit-Remaining"),n=e.get("X-RateLimit-Reset");t&&r&&n&&(this.rateLimitInfo={limit:parseInt(t),remaining:parseInt(r),reset:parseInt(n)})}sleep(e){return new Promise(t=>setTimeout(t,e))}async fetchWithTimeout(e,t,r){let n=new AbortController,a=setTimeout(()=>n.abort(),r);try{return await fetch(e,{...t,signal:n.signal})}finally{clearTimeout(a)}}async call(e,t,r={}){let n=0,a=this.retryOn429?3:0;for(;;)try{let o=this.zeroConfigMode?`${this.baseUrl}/api/sdk/proxy`:`${this.baseUrl}/api/sdk/${this.appId}/proxy`,l={"Content-Type":"application/json"};!this.zeroConfigMode&&this.token&&(l.Authorization=`Bearer ${this.token}`);let d=await this.fetchWithTimeout(o,{method:"POST",headers:l,body:JSON.stringify({keyName:e,endpoint:t,method:r.method||"GET",body:r.body,headers:r.headers})},this.timeout);this.parseRateLimitHeaders(d.headers);let h=await d.json();if(!d.ok){let m=h.data?.message||h?.message||`Request failed with status ${d.status}`;if(d.status===403&&m.includes("Origin"))throw new w(m);if(d.status===401)throw new b(m);if(d.status===429){let I=this.rateLimitInfo?this.rateLimitInfo.reset-Math.floor(Date.now()/1e3):60,f=new S(m,I,this.rateLimitInfo?.remaining||0,this.rateLimitInfo?.limit||100);if(this.retryOn429&&n<a){n++;let u=Math.min(1e3*Math.pow(2,n-1),8e3);await this.sleep(u);continue}throw f}throw new i(m,d.status,h)}return h.data}catch(o){throw o instanceof i?o:o instanceof Error&&o.name==="AbortError"?new i("Request timeout",408):new i(o instanceof Error?o.message:"Unknown error occurred",500)}}async get(e,t,r){return this.call(e,t,{method:"GET",headers:r})}async post(e,t,r,n){return this.call(e,t,{method:"POST",body:r,headers:n})}async put(e,t,r,n){return this.call(e,t,{method:"PUT",body:r,headers:n})}async delete(e,t,r){return this.call(e,t,{method:"DELETE",headers:r})}async patch(e,t,r,n){return this.call(e,t,{method:"PATCH",body:r,headers:n})}setAppId(e){this.appId=e}async secretsRequest(e,t){if(!this.appId)throw new i("App ID required for secrets management. Call setAppId() first.",400);let r=await this.fetchWithTimeout(`${this.baseUrl}/api/projects/${this.appId}/secrets/manage?action=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:t?JSON.stringify(t):void 0},this.timeout);if(!r.ok){let n=await r.json().catch(()=>({}));throw new i(n.message||`Secrets management failed: ${r.statusText}`,r.status,n)}return r.json()}async listSecrets(){return this.secretsRequest("list")}async createSecret(e){return this.secretsRequest("create",e)}async updateSecret(e){return this.secretsRequest("update",e)}async deleteSecret(e){return this.secretsRequest("delete",{name:e})}async syncEnv(e,t){return this.secretsRequest("sync",{secrets:e,provider:t})}};import*as c from"fs";import*as v from"path";import*as _ from"os";function D(){let s=_.homedir(),e=v.join(s,".learn");return v.join(e,"credentials.json")}function N(){let s=_.homedir(),e=v.join(s,".learn");c.existsSync(e)||c.mkdirSync(e,{recursive:!0,mode:448})}function C(){try{let s=D();if(!c.existsSync(s))return null;let e=c.readFileSync(s,"utf-8"),t=JSON.parse(e);return t.access_token&&!t["learn-secrets-sdk"]&&!t["learn-auth-sdk"]?{"learn-secrets-sdk":t}:t}catch{return null}}function R(s){N();let e=D(),t=JSON.stringify(s,null,2);c.writeFileSync(e,t,{mode:384})}function x(s){let e=C();return e&&e[s]||null}function P(s,e){let t=C()||{};t[s]=e,R(t)}function z(s){let e=C();e&&(delete e[s],Object.keys(e).length===0?L():R(e))}function O(){return x("learn-secrets-sdk")}function L(){try{let s=D();c.existsSync(s)&&c.unlinkSync(s)}catch{}}function F(s){let e=x(s);return e!==null&&!!e.access_token}function $(){let s=O();return s?s.expires_at?new Date(s.expires_at)>new Date:!0:!1}import{exec as J}from"child_process";import{promisify as H}from"util";import{createHash as A}from"crypto";import*as p from"os";var k=H(J);async function E(){let s=process.platform;try{let e;if(s==="darwin")e=await W();else if(s==="linux")e=await B();else if(s==="win32")e=await G();else throw new Error(`Unsupported platform: ${s}`);let t=A("sha256").update(e).digest("hex").substring(0,32),r=JSON.stringify({machineId:t,cpus:p.cpus().length,arch:p.arch(),platform:p.platform(),homedir:p.homedir()}),n=A("sha256").update(r).digest("hex");return{machineId:t,fingerprint:n}}catch(e){throw new Error(`Failed to get machine ID: ${e.message}`)}}async function W(){try{let{stdout:s}=await k(`ioreg -l | grep IOPlatformSerialNumber | awk '{print $4}' | sed 's/"//g'`),{stdout:e}=await k("hostname"),t=s.trim(),r=e.trim();if(t&&r)return`${t}-${r}`;let{stdout:n}=await k(`ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk '{print $3}' | sed 's/"//g'`);return n.trim()}catch{throw new Error("Failed to get macOS machine ID")}}async function B(){try{let{stdout:s}=await k("cat /etc/machine-id 2>/dev/null || cat /var/lib/dbus/machine-id 2>/dev/null"),e=s.trim();if(e)return e;throw new Error("Machine ID file not found")}catch{throw new Error("Failed to get Linux machine ID")}}async function G(){try{let{stdout:s}=await k("wmic csproduct get uuid"),t=s.split(`
2
+ `).map(r=>r.trim()).find(r=>r&&r!=="UUID");if(t)return t;throw new Error("Failed to parse machine UUID from WMIC")}catch{throw new Error("Failed to get Windows machine ID")}}var M=class{constructor(e){this.appId=e.appId,this.baseUrl=e.baseUrl||"https://cloudprototype.org",this.timeout=e.timeout||3e4}async openBrowser(e){let{exec:t}=await import("child_process"),{promisify:r}=await import("util"),n=r(t),a=process.platform;try{a==="darwin"?await n(`open "${e}"`):a==="win32"?await n(`start "${e}"`):await n(`xdg-open "${e}"`)}catch(o){throw console.error("Failed to open browser:",o),new i("Failed to open browser",500)}}sleep(e){return new Promise(t=>setTimeout(t,e))}async login(){let e="learn-secrets-sdk";try{console.log(`Authenticating with Learn (${e})...
3
+ `);let t=await E(),r=x(e);if(r&&r.access_token){let g=await fetch(`${this.baseUrl}/api/auth/cli/check-authorization`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({machine_id:t.machineId,sdk_name:e})});if(g.ok){let y=await g.json();if(y.authorized)return console.log("This machine is already authorized."),console.log(`Logged in as: ${y.user_email||y.user_id}`),{success:!0,user:y.user_email||y.user_id}}}let n=await fetch(`${this.baseUrl}/api/auth/cli/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!n.ok)throw new i("Failed to generate device code",n.status);let a=await n.json();console.log(`
4
4
  Log in on ${this.baseUrl}`),console.log("Login at:"),console.log(a.verification_uri_complete),console.log(`
5
- Press ENTER to open in the browser...`);let o=await import("readline"),u=o.createInterface({input:process.stdin,output:process.stdout});await new Promise(c=>{u.question("",()=>{u.close(),c()})}),console.log(`Opening browser...
6
- `),await this.openBrowser(a.verification_uri_complete);let l=!1,g=a.interval*1e3,m=Math.ceil(a.expires_in/a.interval),I=0;for(;I<m;){await this.sleep(g),I++;let c=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a.device_code})});if(c.status===202){process.stdout.write(".");continue}if(c.ok){l=!0;break}}if(!l)throw new i("Device authorization timeout",408);console.log(`
5
+ Press ENTER to open in the browser...`);let l=(await import("readline")).createInterface({input:process.stdin,output:process.stdout});await new Promise(g=>{l.question("",()=>{l.close(),g()})}),console.log(`Opening browser...
6
+ `),await this.openBrowser(a.verification_uri_complete);let d=!1,h=a.interval*1e3,m=Math.ceil(a.expires_in/a.interval),I=0;for(;I<m;){await this.sleep(h),I++;let g=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a.device_code})});if(g.status===202){process.stdout.write(".");continue}if(g.ok){d=!0;break}}if(!d)throw new i("Device authorization timeout",408);console.log(`
7
7
 
8
- Device authorized! Sending 2FA code...`);let y=await fetch(`${this.baseUrl}/api/auth/2fa/send`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a.device_code,sdk_name:e,machine_id:t.machineId})});if(!y.ok){let c=await y.json().catch(()=>({}));throw new i(c.message||"Failed to send 2FA code",y.status)}console.log(`2FA code sent to your email.
9
- `);let v=o.createInterface({input:process.stdin,output:process.stdout}),U=await new Promise(c=>{v.question("Enter 2FA code from email: ",h=>{v.close(),c(h)})}),C=await fetch(`${this.baseUrl}/api/auth/2fa/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a.device_code,code:U.trim()})});if(!C.ok){let c=await C.json().catch(()=>({}));throw new i(c.message||"2FA verification failed",C.status)}let f=await C.json();return L(e,{access_token:f.access_token,refresh_token:null,expires_at:null,user_id:f.user_id,machine_id:t.machineId,sdk_name:e,authorized_at:new Date().toISOString()}),console.log(`
10
- Authentication successful!`),console.log(`Logged in as: ${f.user_email||f.user_id}`),console.log(`This machine is now permanently authorized.
11
- `),{success:!0,user:f.user_email||f.user_id}}catch(t){throw t instanceof i?t:new i(t.message||"Login failed",t.status||500)}}async isAuthenticated(){return K()}logout(){A(),console.log("Logged out successfully")}getAccessToken(){let e=E();if(!e)throw new i("Not authenticated. Run login() first.",401);if(e.expires_at&&new Date(e.expires_at)<=new Date)throw new i("Token expired. Run login() again.",401);return e.access_token}async request(e,t,r){let n=this.getAccessToken(),a={method:e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}};r&&(a.body=JSON.stringify(r));let o=await fetch(`${this.baseUrl}${t}`,a);if(!o.ok){let u=await o.json().catch(()=>({}));throw new i(u.message||`Request failed: ${o.statusText}`,o.status,u)}return o.json()}async list(){return(await this.request("GET",`/api/projects/${this.appId}/secrets`)).secrets}async sync(e,t){return await this.request("POST",`/api/projects/${this.appId}/secrets/sync`,{secrets:e,options:{deleteMissing:t?.deleteMissing??!1,dryRun:t?.dryRun??!1}})}async importSecrets(e){return this.request("POST",`/api/projects/${this.appId}/import-secrets`,{version:e.version||"1.0",origins:e.origins,secrets:e.secrets})}async importFromFile(e){let{loadSecretsConfig:t}=await import("./env-resolver-Y4SFGOKB.mjs"),r=t(e);return this.importSecrets(r)}};export{b as InvalidTokenError,w as OriginMismatchError,S as RateLimitError,$ as SecretsManagement,D as SecretsSDK,i as SecretsSDKError,H as deleteSDKCredentials,M as getMachineId,W as hasSDKCredentials,z as loadSecretsConfig,_ as readAllCredentials,x as readSDKCredentials,N as resolveEnvInSecret,F as resolveEnvInSecrets,q as resolveEnvString,O as writeAllCredentials,L as writeSDKCredentials};
8
+ Device authorized! Retrieving access token...`);let f=await fetch(`${this.baseUrl}/api/auth/cli/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:a.device_code})});if(!f.ok)throw new i("Failed to retrieve access token",f.status);let u=await f.json();return P(e,{access_token:u.access_token,refresh_token:null,expires_at:null,user_id:u.user_id,machine_id:t.machineId,sdk_name:e,authorized_at:new Date().toISOString()}),console.log(`
9
+ Authentication successful!`),console.log(`Logged in as: ${u.user_email||u.user_id}`),console.log(`This machine is now permanently authorized.
10
+ `),{success:!0,user:u.user_email||u.user_id}}catch(t){throw t instanceof i?t:new i(t.message||"Login failed",t.status||500)}}async isAuthenticated(){return $()}logout(){L(),console.log("Logged out successfully")}getAccessToken(){let e=O();if(!e)throw new i("Not authenticated. Run login() first.",401);if(e.expires_at&&new Date(e.expires_at)<=new Date)throw new i("Token expired. Run login() again.",401);return e.access_token}async request(e,t,r){let n=this.getAccessToken(),a={method:e,headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`}};r&&(a.body=JSON.stringify(r));let o=await fetch(`${this.baseUrl}${t}`,a);if(!o.ok){let l=await o.json().catch(()=>({}));throw new i(l.message||`Request failed: ${o.statusText}`,o.status,l)}return o.json()}async list(){return(await this.request("GET",`/api/projects/${this.appId}/secrets`)).secrets}async sync(e,t){return await this.request("POST",`/api/projects/${this.appId}/secrets/sync`,{secrets:e,options:{deleteMissing:t?.deleteMissing??!1,dryRun:t?.dryRun??!1}})}async importSecrets(e){return this.request("POST",`/api/projects/${this.appId}/import-secrets`,{version:e.version||"1.0",origins:e.origins,secrets:e.secrets})}async importFromFile(e){let{loadSecretsConfig:t}=await import("./env-resolver-Y4SFGOKB.mjs"),r=t(e);return this.importSecrets(r)}};export{b as InvalidTokenError,w as OriginMismatchError,S as RateLimitError,M as SecretsManagement,T as SecretsSDK,i as SecretsSDKError,z as deleteSDKCredentials,E as getMachineId,F as hasSDKCredentials,q as loadSecretsConfig,C as readAllCredentials,x as readSDKCredentials,U as resolveEnvInSecret,j as resolveEnvInSecrets,K as resolveEnvString,R as writeAllCredentials,P as writeSDKCredentials};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "learn-secrets-sdk",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "description": "Secure API proxy SDK for static sites with domain-scoped tokens",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",