lane-sdk 0.1.0 → 0.1.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/dist/cli/index.js +144 -210
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +604 -165
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -4
- package/dist/index.d.ts +136 -4
- package/dist/index.js +599 -166
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +334 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server-http.cjs +477 -169
- package/dist/server-http.cjs.map +1 -1
- package/dist/server-http.js +477 -169
- package/dist/server-http.js.map +1 -1
- package/dist/server-stdio.cjs +477 -169
- package/dist/server-stdio.cjs.map +1 -1
- package/dist/server-stdio.js +477 -169
- package/dist/server-stdio.js.map +1 -1
- package/package.json +3 -2
package/dist/cli/index.js
CHANGED
|
@@ -38,9 +38,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
38
38
|
mod
|
|
39
39
|
));
|
|
40
40
|
|
|
41
|
-
// node_modules
|
|
41
|
+
// node_modules/commander/lib/error.js
|
|
42
42
|
var require_error = __commonJS({
|
|
43
|
-
"node_modules
|
|
43
|
+
"node_modules/commander/lib/error.js"(exports) {
|
|
44
44
|
"use strict";
|
|
45
45
|
var CommanderError2 = class extends Error {
|
|
46
46
|
/**
|
|
@@ -74,9 +74,9 @@ var require_error = __commonJS({
|
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
// node_modules
|
|
77
|
+
// node_modules/commander/lib/argument.js
|
|
78
78
|
var require_argument = __commonJS({
|
|
79
|
-
"node_modules
|
|
79
|
+
"node_modules/commander/lib/argument.js"(exports) {
|
|
80
80
|
"use strict";
|
|
81
81
|
var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
|
|
82
82
|
var Argument2 = class {
|
|
@@ -203,9 +203,9 @@ var require_argument = __commonJS({
|
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
|
|
206
|
-
// node_modules
|
|
206
|
+
// node_modules/commander/lib/help.js
|
|
207
207
|
var require_help = __commonJS({
|
|
208
|
-
"node_modules
|
|
208
|
+
"node_modules/commander/lib/help.js"(exports) {
|
|
209
209
|
"use strict";
|
|
210
210
|
var { humanReadableArgName } = require_argument();
|
|
211
211
|
var Help2 = class {
|
|
@@ -806,9 +806,9 @@ ${itemIndentStr}`);
|
|
|
806
806
|
}
|
|
807
807
|
});
|
|
808
808
|
|
|
809
|
-
// node_modules
|
|
809
|
+
// node_modules/commander/lib/option.js
|
|
810
810
|
var require_option = __commonJS({
|
|
811
|
-
"node_modules
|
|
811
|
+
"node_modules/commander/lib/option.js"(exports) {
|
|
812
812
|
"use strict";
|
|
813
813
|
var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
|
|
814
814
|
var Option2 = class {
|
|
@@ -1120,9 +1120,9 @@ var require_option = __commonJS({
|
|
|
1120
1120
|
}
|
|
1121
1121
|
});
|
|
1122
1122
|
|
|
1123
|
-
// node_modules
|
|
1123
|
+
// node_modules/commander/lib/suggestSimilar.js
|
|
1124
1124
|
var require_suggestSimilar = __commonJS({
|
|
1125
|
-
"node_modules
|
|
1125
|
+
"node_modules/commander/lib/suggestSimilar.js"(exports) {
|
|
1126
1126
|
"use strict";
|
|
1127
1127
|
var maxDistance = 3;
|
|
1128
1128
|
function editDistance(a, b) {
|
|
@@ -1201,9 +1201,9 @@ var require_suggestSimilar = __commonJS({
|
|
|
1201
1201
|
}
|
|
1202
1202
|
});
|
|
1203
1203
|
|
|
1204
|
-
// node_modules
|
|
1204
|
+
// node_modules/commander/lib/command.js
|
|
1205
1205
|
var require_command = __commonJS({
|
|
1206
|
-
"node_modules
|
|
1206
|
+
"node_modules/commander/lib/command.js"(exports) {
|
|
1207
1207
|
"use strict";
|
|
1208
1208
|
var EventEmitter2 = __require("events").EventEmitter;
|
|
1209
1209
|
var childProcess4 = __require("child_process");
|
|
@@ -3448,9 +3448,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
3448
3448
|
}
|
|
3449
3449
|
});
|
|
3450
3450
|
|
|
3451
|
-
// node_modules
|
|
3451
|
+
// node_modules/commander/index.js
|
|
3452
3452
|
var require_commander = __commonJS({
|
|
3453
|
-
"node_modules
|
|
3453
|
+
"node_modules/commander/index.js"(exports) {
|
|
3454
3454
|
"use strict";
|
|
3455
3455
|
var { Argument: Argument2 } = require_argument();
|
|
3456
3456
|
var { Command: Command2 } = require_command();
|
|
@@ -3471,105 +3471,6 @@ var require_commander = __commonJS({
|
|
|
3471
3471
|
}
|
|
3472
3472
|
});
|
|
3473
3473
|
|
|
3474
|
-
// src/auth/token-store.ts
|
|
3475
|
-
import { readFile, writeFile, mkdir, stat, chmod } from "fs/promises";
|
|
3476
|
-
import { join } from "path";
|
|
3477
|
-
import { homedir } from "os";
|
|
3478
|
-
function isNodeError(err) {
|
|
3479
|
-
return err instanceof Error && "code" in err;
|
|
3480
|
-
}
|
|
3481
|
-
var LANE_DIR, CREDENTIALS_FILE, SECURE_FILE_MODE, SECURE_DIR_MODE, FileTokenStore;
|
|
3482
|
-
var init_token_store = __esm({
|
|
3483
|
-
"src/auth/token-store.ts"() {
|
|
3484
|
-
"use strict";
|
|
3485
|
-
LANE_DIR = ".lane";
|
|
3486
|
-
CREDENTIALS_FILE = "credentials.json";
|
|
3487
|
-
SECURE_FILE_MODE = 384;
|
|
3488
|
-
SECURE_DIR_MODE = 448;
|
|
3489
|
-
FileTokenStore = class {
|
|
3490
|
-
dirPath;
|
|
3491
|
-
filePath;
|
|
3492
|
-
constructor(basePath) {
|
|
3493
|
-
this.dirPath = basePath ?? join(homedir(), LANE_DIR);
|
|
3494
|
-
this.filePath = join(this.dirPath, CREDENTIALS_FILE);
|
|
3495
|
-
}
|
|
3496
|
-
/**
|
|
3497
|
-
* Read credentials from disk. Returns null if file doesn't exist.
|
|
3498
|
-
* Warns to stderr if file permissions are too permissive.
|
|
3499
|
-
*/
|
|
3500
|
-
async read() {
|
|
3501
|
-
try {
|
|
3502
|
-
await this.validatePermissions();
|
|
3503
|
-
const raw = await readFile(this.filePath, "utf-8");
|
|
3504
|
-
const parsed = JSON.parse(raw);
|
|
3505
|
-
return this.validateCredentials(parsed);
|
|
3506
|
-
} catch (err) {
|
|
3507
|
-
if (isNodeError(err) && err.code === "ENOENT") {
|
|
3508
|
-
return null;
|
|
3509
|
-
}
|
|
3510
|
-
throw err;
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
/**
|
|
3514
|
-
* Write credentials to disk with secure permissions.
|
|
3515
|
-
*/
|
|
3516
|
-
async write(credentials) {
|
|
3517
|
-
await this.ensureDirectory();
|
|
3518
|
-
const data = JSON.stringify(credentials, null, 2) + "\n";
|
|
3519
|
-
await writeFile(this.filePath, data, { mode: SECURE_FILE_MODE });
|
|
3520
|
-
}
|
|
3521
|
-
/**
|
|
3522
|
-
* Remove the credentials file.
|
|
3523
|
-
*/
|
|
3524
|
-
async clear() {
|
|
3525
|
-
try {
|
|
3526
|
-
const { unlink } = await import("fs/promises");
|
|
3527
|
-
await unlink(this.filePath);
|
|
3528
|
-
} catch (err) {
|
|
3529
|
-
if (isNodeError(err) && err.code === "ENOENT") {
|
|
3530
|
-
return;
|
|
3531
|
-
}
|
|
3532
|
-
throw err;
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
/** Return the path to the credentials file (for CLI display). */
|
|
3536
|
-
get path() {
|
|
3537
|
-
return this.filePath;
|
|
3538
|
-
}
|
|
3539
|
-
// -------------------------------------------------------------------------
|
|
3540
|
-
// Private
|
|
3541
|
-
// -------------------------------------------------------------------------
|
|
3542
|
-
async ensureDirectory() {
|
|
3543
|
-
await mkdir(this.dirPath, { recursive: true, mode: SECURE_DIR_MODE });
|
|
3544
|
-
}
|
|
3545
|
-
/**
|
|
3546
|
-
* Check file permissions and warn if too open.
|
|
3547
|
-
* SOC 2 control: credentials should only be readable by owner.
|
|
3548
|
-
*/
|
|
3549
|
-
async validatePermissions() {
|
|
3550
|
-
try {
|
|
3551
|
-
const stats = await stat(this.filePath);
|
|
3552
|
-
const mode = stats.mode & 511;
|
|
3553
|
-
if (mode !== SECURE_FILE_MODE) {
|
|
3554
|
-
process.stderr.write(
|
|
3555
|
-
`[lane] Warning: ${this.filePath} has permissions ${mode.toString(8)}. Expected ${SECURE_FILE_MODE.toString(8)}. Fixing...
|
|
3556
|
-
`
|
|
3557
|
-
);
|
|
3558
|
-
await chmod(this.filePath, SECURE_FILE_MODE);
|
|
3559
|
-
}
|
|
3560
|
-
} catch {
|
|
3561
|
-
}
|
|
3562
|
-
}
|
|
3563
|
-
validateCredentials(parsed) {
|
|
3564
|
-
if (typeof parsed !== "object" || parsed === null || !("apiKey" in parsed) || typeof parsed["apiKey"] !== "string") {
|
|
3565
|
-
return null;
|
|
3566
|
-
}
|
|
3567
|
-
return parsed;
|
|
3568
|
-
}
|
|
3569
|
-
};
|
|
3570
|
-
}
|
|
3571
|
-
});
|
|
3572
|
-
|
|
3573
3474
|
// src/crypto/signature.ts
|
|
3574
3475
|
import { createHmac, createHash, timingSafeEqual } from "crypto";
|
|
3575
3476
|
function verifyWebhookSignature(payload, signature, secret, timestamp) {
|
|
@@ -4210,51 +4111,6 @@ var init_client = __esm({
|
|
|
4210
4111
|
}
|
|
4211
4112
|
});
|
|
4212
4113
|
|
|
4213
|
-
// src/config.ts
|
|
4214
|
-
async function resolveConfig(options = {}, tokenStore) {
|
|
4215
|
-
let apiKey = options.apiKey;
|
|
4216
|
-
if (!apiKey) {
|
|
4217
|
-
apiKey = process.env["LANE_API_KEY"];
|
|
4218
|
-
}
|
|
4219
|
-
if (!apiKey) {
|
|
4220
|
-
const store = tokenStore ?? new FileTokenStore();
|
|
4221
|
-
const creds = await store.read();
|
|
4222
|
-
if (creds) {
|
|
4223
|
-
apiKey = creds.apiKey;
|
|
4224
|
-
}
|
|
4225
|
-
}
|
|
4226
|
-
if (!apiKey) {
|
|
4227
|
-
throw new Error(
|
|
4228
|
-
'No API key found. Provide one via:\n 1. new Lane({ apiKey: "lane_sk_..." })\n 2. LANE_API_KEY environment variable\n 3. Run `lane login` to authenticate'
|
|
4229
|
-
);
|
|
4230
|
-
}
|
|
4231
|
-
const testMode = options.testMode ?? (process.env["LANE_TEST_MODE"] === "true" || apiKey.startsWith("lane_sk_test_"));
|
|
4232
|
-
const baseUrl = options.baseUrl ?? process.env["LANE_BASE_URL"] ?? DEFAULT_BASE_URL;
|
|
4233
|
-
const timeout = options.timeout ?? (process.env["LANE_TIMEOUT"] ? parseInt(process.env["LANE_TIMEOUT"], 10) : DEFAULT_TIMEOUT);
|
|
4234
|
-
const maxRetries = options.maxRetries ?? (process.env["LANE_MAX_RETRIES"] ? parseInt(process.env["LANE_MAX_RETRIES"], 10) : DEFAULT_MAX_RETRIES);
|
|
4235
|
-
return Object.freeze({
|
|
4236
|
-
apiKey,
|
|
4237
|
-
baseUrl,
|
|
4238
|
-
testMode,
|
|
4239
|
-
timeout,
|
|
4240
|
-
maxRetries,
|
|
4241
|
-
circuitBreaker: options.circuitBreaker ? Object.freeze({
|
|
4242
|
-
failureThreshold: options.circuitBreaker.failureThreshold ?? 3,
|
|
4243
|
-
resetTimeoutMs: options.circuitBreaker.resetTimeoutMs ?? 3e4
|
|
4244
|
-
}) : void 0
|
|
4245
|
-
});
|
|
4246
|
-
}
|
|
4247
|
-
var DEFAULT_BASE_URL, DEFAULT_TIMEOUT, DEFAULT_MAX_RETRIES;
|
|
4248
|
-
var init_config = __esm({
|
|
4249
|
-
"src/config.ts"() {
|
|
4250
|
-
"use strict";
|
|
4251
|
-
init_token_store();
|
|
4252
|
-
DEFAULT_BASE_URL = "https://api.getonlane.com";
|
|
4253
|
-
DEFAULT_TIMEOUT = 3e4;
|
|
4254
|
-
DEFAULT_MAX_RETRIES = 2;
|
|
4255
|
-
}
|
|
4256
|
-
});
|
|
4257
|
-
|
|
4258
4114
|
// src/resources/base.ts
|
|
4259
4115
|
var Resource;
|
|
4260
4116
|
var init_base = __esm({
|
|
@@ -5294,7 +5150,6 @@ var init_lane = __esm({
|
|
|
5294
5150
|
"src/lane.ts"() {
|
|
5295
5151
|
"use strict";
|
|
5296
5152
|
init_client();
|
|
5297
|
-
init_config();
|
|
5298
5153
|
init_auth();
|
|
5299
5154
|
init_wallets();
|
|
5300
5155
|
init_pay();
|
|
@@ -5312,7 +5167,7 @@ var init_lane = __esm({
|
|
|
5312
5167
|
init_identity();
|
|
5313
5168
|
init_subscriptions();
|
|
5314
5169
|
init_merchants();
|
|
5315
|
-
Lane = class
|
|
5170
|
+
Lane = class {
|
|
5316
5171
|
client;
|
|
5317
5172
|
_config;
|
|
5318
5173
|
// Lazily initialized resources
|
|
@@ -5347,8 +5202,9 @@ var init_lane = __esm({
|
|
|
5347
5202
|
* Resolves API key from: constructor > env var > credentials file.
|
|
5348
5203
|
*/
|
|
5349
5204
|
static async create(options = {}) {
|
|
5350
|
-
|
|
5351
|
-
|
|
5205
|
+
throw new Error(
|
|
5206
|
+
"\n\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 \u2551\n\u2551 Lane SDK \u2014 Coming Soon \u2551\n\u2551 \u2551\n\u2551 The Lane SDK is not yet available for public use. \u2551\n\u2551 Join the waitlist: https://app.getonlane.com/agents \u2551\n\u2551 \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"
|
|
5207
|
+
);
|
|
5352
5208
|
}
|
|
5353
5209
|
/**
|
|
5354
5210
|
* Create a Lane SDK instance synchronously (requires explicit apiKey).
|
|
@@ -5356,20 +5212,10 @@ var init_lane = __esm({
|
|
|
5356
5212
|
* Use this when you already have the API key and don't need file-based
|
|
5357
5213
|
* credential resolution.
|
|
5358
5214
|
*/
|
|
5359
|
-
static fromApiKey(
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
baseUrl: options.baseUrl ?? process.env["LANE_BASE_URL"] ?? "https://api.getonlane.com",
|
|
5364
|
-
testMode,
|
|
5365
|
-
timeout: options.timeout ?? 3e4,
|
|
5366
|
-
maxRetries: options.maxRetries ?? 2,
|
|
5367
|
-
circuitBreaker: options.circuitBreaker ? Object.freeze({
|
|
5368
|
-
failureThreshold: options.circuitBreaker.failureThreshold ?? 3,
|
|
5369
|
-
resetTimeoutMs: options.circuitBreaker.resetTimeoutMs ?? 3e4
|
|
5370
|
-
}) : void 0
|
|
5371
|
-
});
|
|
5372
|
-
return new _Lane(config);
|
|
5215
|
+
static fromApiKey(_apiKey, _options = {}) {
|
|
5216
|
+
throw new Error(
|
|
5217
|
+
"\n\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551 \u2551\n\u2551 Lane SDK \u2014 Coming Soon \u2551\n\u2551 \u2551\n\u2551 The Lane SDK is not yet available for public use. \u2551\n\u2551 Join the waitlist: https://app.getonlane.com/agents \u2551\n\u2551 \u2551\n\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D\n"
|
|
5218
|
+
);
|
|
5373
5219
|
}
|
|
5374
5220
|
// -------------------------------------------------------------------------
|
|
5375
5221
|
// Resource Accessors (lazy initialization)
|
|
@@ -5465,7 +5311,7 @@ var init_lane = __esm({
|
|
|
5465
5311
|
}
|
|
5466
5312
|
});
|
|
5467
5313
|
|
|
5468
|
-
// node_modules
|
|
5314
|
+
// node_modules/commander/esm.mjs
|
|
5469
5315
|
var import_index = __toESM(require_commander(), 1);
|
|
5470
5316
|
var {
|
|
5471
5317
|
program,
|
|
@@ -5482,7 +5328,7 @@ var {
|
|
|
5482
5328
|
Help
|
|
5483
5329
|
} = import_index.default;
|
|
5484
5330
|
|
|
5485
|
-
// node_modules
|
|
5331
|
+
// node_modules/chalk/source/vendor/ansi-styles/index.js
|
|
5486
5332
|
var ANSI_BACKGROUND_OFFSET = 10;
|
|
5487
5333
|
var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
|
|
5488
5334
|
var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
|
|
@@ -5668,7 +5514,7 @@ function assembleStyles() {
|
|
|
5668
5514
|
var ansiStyles = assembleStyles();
|
|
5669
5515
|
var ansi_styles_default = ansiStyles;
|
|
5670
5516
|
|
|
5671
|
-
// node_modules
|
|
5517
|
+
// node_modules/chalk/source/vendor/supports-color/index.js
|
|
5672
5518
|
import process2 from "process";
|
|
5673
5519
|
import os from "os";
|
|
5674
5520
|
import tty from "tty";
|
|
@@ -5800,7 +5646,7 @@ var supportsColor = {
|
|
|
5800
5646
|
};
|
|
5801
5647
|
var supports_color_default = supportsColor;
|
|
5802
5648
|
|
|
5803
|
-
// node_modules
|
|
5649
|
+
// node_modules/chalk/source/utilities.js
|
|
5804
5650
|
function stringReplaceAll(string, substring, replacer) {
|
|
5805
5651
|
let index = string.indexOf(substring);
|
|
5806
5652
|
if (index === -1) {
|
|
@@ -5830,7 +5676,7 @@ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
|
|
|
5830
5676
|
return returnValue;
|
|
5831
5677
|
}
|
|
5832
5678
|
|
|
5833
|
-
// node_modules
|
|
5679
|
+
// node_modules/chalk/source/index.js
|
|
5834
5680
|
var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
|
|
5835
5681
|
var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
|
|
5836
5682
|
var STYLER = /* @__PURE__ */ Symbol("STYLER");
|
|
@@ -5977,33 +5823,123 @@ var chalk = createChalk();
|
|
|
5977
5823
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
5978
5824
|
var source_default = chalk;
|
|
5979
5825
|
|
|
5980
|
-
// src/
|
|
5981
|
-
|
|
5826
|
+
// src/auth/token-store.ts
|
|
5827
|
+
import { readFile, writeFile, mkdir, stat, chmod } from "fs/promises";
|
|
5828
|
+
import { join } from "path";
|
|
5829
|
+
import { homedir } from "os";
|
|
5830
|
+
var LANE_DIR = ".lane";
|
|
5831
|
+
var CREDENTIALS_FILE = "credentials.json";
|
|
5832
|
+
var SECURE_FILE_MODE = 384;
|
|
5833
|
+
var SECURE_DIR_MODE = 448;
|
|
5834
|
+
var FileTokenStore = class {
|
|
5835
|
+
dirPath;
|
|
5836
|
+
filePath;
|
|
5837
|
+
constructor(basePath) {
|
|
5838
|
+
this.dirPath = basePath ?? join(homedir(), LANE_DIR);
|
|
5839
|
+
this.filePath = join(this.dirPath, CREDENTIALS_FILE);
|
|
5840
|
+
}
|
|
5841
|
+
/**
|
|
5842
|
+
* Read credentials from disk. Returns null if file doesn't exist.
|
|
5843
|
+
* Warns to stderr if file permissions are too permissive.
|
|
5844
|
+
*/
|
|
5845
|
+
async read() {
|
|
5846
|
+
try {
|
|
5847
|
+
await this.validatePermissions();
|
|
5848
|
+
const raw = await readFile(this.filePath, "utf-8");
|
|
5849
|
+
const parsed = JSON.parse(raw);
|
|
5850
|
+
return this.validateCredentials(parsed);
|
|
5851
|
+
} catch (err) {
|
|
5852
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
5853
|
+
return null;
|
|
5854
|
+
}
|
|
5855
|
+
throw err;
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
/**
|
|
5859
|
+
* Write credentials to disk with secure permissions.
|
|
5860
|
+
*/
|
|
5861
|
+
async write(credentials) {
|
|
5862
|
+
await this.ensureDirectory();
|
|
5863
|
+
const data = JSON.stringify(credentials, null, 2) + "\n";
|
|
5864
|
+
await writeFile(this.filePath, data, { mode: SECURE_FILE_MODE });
|
|
5865
|
+
}
|
|
5866
|
+
/**
|
|
5867
|
+
* Remove the credentials file.
|
|
5868
|
+
*/
|
|
5869
|
+
async clear() {
|
|
5870
|
+
try {
|
|
5871
|
+
const { unlink } = await import("fs/promises");
|
|
5872
|
+
await unlink(this.filePath);
|
|
5873
|
+
} catch (err) {
|
|
5874
|
+
if (isNodeError(err) && err.code === "ENOENT") {
|
|
5875
|
+
return;
|
|
5876
|
+
}
|
|
5877
|
+
throw err;
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
/** Return the path to the credentials file (for CLI display). */
|
|
5881
|
+
get path() {
|
|
5882
|
+
return this.filePath;
|
|
5883
|
+
}
|
|
5884
|
+
// -------------------------------------------------------------------------
|
|
5885
|
+
// Private
|
|
5886
|
+
// -------------------------------------------------------------------------
|
|
5887
|
+
async ensureDirectory() {
|
|
5888
|
+
await mkdir(this.dirPath, { recursive: true, mode: SECURE_DIR_MODE });
|
|
5889
|
+
}
|
|
5890
|
+
/**
|
|
5891
|
+
* Check file permissions and warn if too open.
|
|
5892
|
+
* SOC 2 control: credentials should only be readable by owner.
|
|
5893
|
+
*/
|
|
5894
|
+
async validatePermissions() {
|
|
5895
|
+
try {
|
|
5896
|
+
const stats = await stat(this.filePath);
|
|
5897
|
+
const mode = stats.mode & 511;
|
|
5898
|
+
if (mode !== SECURE_FILE_MODE) {
|
|
5899
|
+
process.stderr.write(
|
|
5900
|
+
`[lane] Warning: ${this.filePath} has permissions ${mode.toString(8)}. Expected ${SECURE_FILE_MODE.toString(8)}. Fixing...
|
|
5901
|
+
`
|
|
5902
|
+
);
|
|
5903
|
+
await chmod(this.filePath, SECURE_FILE_MODE);
|
|
5904
|
+
}
|
|
5905
|
+
} catch {
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
validateCredentials(parsed) {
|
|
5909
|
+
if (typeof parsed !== "object" || parsed === null || !("apiKey" in parsed) || typeof parsed["apiKey"] !== "string") {
|
|
5910
|
+
return null;
|
|
5911
|
+
}
|
|
5912
|
+
return parsed;
|
|
5913
|
+
}
|
|
5914
|
+
};
|
|
5915
|
+
function isNodeError(err) {
|
|
5916
|
+
return err instanceof Error && "code" in err;
|
|
5917
|
+
}
|
|
5982
5918
|
|
|
5983
5919
|
// src/auth/browser-flow.ts
|
|
5984
5920
|
import { createServer } from "http";
|
|
5985
5921
|
|
|
5986
|
-
// node_modules
|
|
5922
|
+
// node_modules/open/index.js
|
|
5987
5923
|
import process9 from "process";
|
|
5988
5924
|
import path from "path";
|
|
5989
5925
|
import { fileURLToPath } from "url";
|
|
5990
5926
|
import childProcess3 from "child_process";
|
|
5991
5927
|
import fs6, { constants as fsConstants3 } from "fs/promises";
|
|
5992
5928
|
|
|
5993
|
-
// node_modules
|
|
5929
|
+
// node_modules/wsl-utils/index.js
|
|
5994
5930
|
import { promisify as promisify2 } from "util";
|
|
5995
5931
|
import childProcess2 from "child_process";
|
|
5996
5932
|
import fs5, { constants as fsConstants2 } from "fs/promises";
|
|
5997
5933
|
|
|
5998
|
-
// node_modules
|
|
5934
|
+
// node_modules/is-wsl/index.js
|
|
5999
5935
|
import process3 from "process";
|
|
6000
5936
|
import os2 from "os";
|
|
6001
5937
|
import fs3 from "fs";
|
|
6002
5938
|
|
|
6003
|
-
// node_modules
|
|
5939
|
+
// node_modules/is-inside-container/index.js
|
|
6004
5940
|
import fs2 from "fs";
|
|
6005
5941
|
|
|
6006
|
-
// node_modules
|
|
5942
|
+
// node_modules/is-docker/index.js
|
|
6007
5943
|
import fs from "fs";
|
|
6008
5944
|
var isDockerCached;
|
|
6009
5945
|
function hasDockerEnv() {
|
|
@@ -6028,7 +5964,7 @@ function isDocker() {
|
|
|
6028
5964
|
return isDockerCached;
|
|
6029
5965
|
}
|
|
6030
5966
|
|
|
6031
|
-
// node_modules
|
|
5967
|
+
// node_modules/is-inside-container/index.js
|
|
6032
5968
|
var cachedResult;
|
|
6033
5969
|
var hasContainerEnv = () => {
|
|
6034
5970
|
try {
|
|
@@ -6045,7 +5981,7 @@ function isInsideContainer() {
|
|
|
6045
5981
|
return cachedResult;
|
|
6046
5982
|
}
|
|
6047
5983
|
|
|
6048
|
-
// node_modules
|
|
5984
|
+
// node_modules/is-wsl/index.js
|
|
6049
5985
|
var isWsl = () => {
|
|
6050
5986
|
if (process3.platform !== "linux") {
|
|
6051
5987
|
return false;
|
|
@@ -6069,7 +6005,7 @@ var isWsl = () => {
|
|
|
6069
6005
|
};
|
|
6070
6006
|
var is_wsl_default = process3.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
6071
6007
|
|
|
6072
|
-
// node_modules
|
|
6008
|
+
// node_modules/powershell-utils/index.js
|
|
6073
6009
|
import process4 from "process";
|
|
6074
6010
|
import { Buffer as Buffer2 } from "buffer";
|
|
6075
6011
|
import { promisify } from "util";
|
|
@@ -6105,7 +6041,7 @@ executePowerShell.argumentsPrefix = [
|
|
|
6105
6041
|
executePowerShell.encodeCommand = (command) => Buffer2.from(command, "utf16le").toString("base64");
|
|
6106
6042
|
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
6107
6043
|
|
|
6108
|
-
// node_modules
|
|
6044
|
+
// node_modules/wsl-utils/utilities.js
|
|
6109
6045
|
function parseMountPointFromConfig(content) {
|
|
6110
6046
|
for (const line of content.split("\n")) {
|
|
6111
6047
|
if (/^\s*#/.test(line)) {
|
|
@@ -6119,7 +6055,7 @@ function parseMountPointFromConfig(content) {
|
|
|
6119
6055
|
}
|
|
6120
6056
|
}
|
|
6121
6057
|
|
|
6122
|
-
// node_modules
|
|
6058
|
+
// node_modules/wsl-utils/index.js
|
|
6123
6059
|
var execFile2 = promisify2(childProcess2.execFile);
|
|
6124
6060
|
var wslDrivesMountPoint = /* @__PURE__ */ (() => {
|
|
6125
6061
|
const defaultMountPoint = "/mnt/";
|
|
@@ -6184,7 +6120,7 @@ var convertWslPathToWindows = async (path2) => {
|
|
|
6184
6120
|
}
|
|
6185
6121
|
};
|
|
6186
6122
|
|
|
6187
|
-
// node_modules
|
|
6123
|
+
// node_modules/define-lazy-prop/index.js
|
|
6188
6124
|
function defineLazyProperty(object, propertyName, valueGetter) {
|
|
6189
6125
|
const define = (value) => Object.defineProperty(object, propertyName, { value, enumerable: true, writable: true });
|
|
6190
6126
|
Object.defineProperty(object, propertyName, {
|
|
@@ -6202,12 +6138,12 @@ function defineLazyProperty(object, propertyName, valueGetter) {
|
|
|
6202
6138
|
return object;
|
|
6203
6139
|
}
|
|
6204
6140
|
|
|
6205
|
-
// node_modules
|
|
6141
|
+
// node_modules/default-browser/index.js
|
|
6206
6142
|
import { promisify as promisify6 } from "util";
|
|
6207
6143
|
import process7 from "process";
|
|
6208
6144
|
import { execFile as execFile6 } from "child_process";
|
|
6209
6145
|
|
|
6210
|
-
// node_modules
|
|
6146
|
+
// node_modules/default-browser-id/index.js
|
|
6211
6147
|
import { promisify as promisify3 } from "util";
|
|
6212
6148
|
import process5 from "process";
|
|
6213
6149
|
import { execFile as execFile3 } from "child_process";
|
|
@@ -6225,7 +6161,7 @@ async function defaultBrowserId() {
|
|
|
6225
6161
|
return browserId;
|
|
6226
6162
|
}
|
|
6227
6163
|
|
|
6228
|
-
// node_modules
|
|
6164
|
+
// node_modules/run-applescript/index.js
|
|
6229
6165
|
import process6 from "process";
|
|
6230
6166
|
import { promisify as promisify4 } from "util";
|
|
6231
6167
|
import { execFile as execFile4, execFileSync } from "child_process";
|
|
@@ -6243,13 +6179,13 @@ async function runAppleScript(script, { humanReadableOutput = true, signal } = {
|
|
|
6243
6179
|
return stdout.trim();
|
|
6244
6180
|
}
|
|
6245
6181
|
|
|
6246
|
-
// node_modules
|
|
6182
|
+
// node_modules/bundle-name/index.js
|
|
6247
6183
|
async function bundleName(bundleId) {
|
|
6248
6184
|
return runAppleScript(`tell application "Finder" to set app_path to application file id "${bundleId}" as string
|
|
6249
6185
|
tell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`);
|
|
6250
6186
|
}
|
|
6251
6187
|
|
|
6252
|
-
// node_modules
|
|
6188
|
+
// node_modules/default-browser/windows.js
|
|
6253
6189
|
import { promisify as promisify5 } from "util";
|
|
6254
6190
|
import { execFile as execFile5 } from "child_process";
|
|
6255
6191
|
var execFileAsync3 = promisify5(execFile5);
|
|
@@ -6294,7 +6230,7 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
|
6294
6230
|
return windowsBrowserProgIds[id] ?? windowsBrowserProgIds[baseIdByDot] ?? windowsBrowserProgIds[baseIdByHyphen] ?? { name: id, id };
|
|
6295
6231
|
}
|
|
6296
6232
|
|
|
6297
|
-
// node_modules
|
|
6233
|
+
// node_modules/default-browser/index.js
|
|
6298
6234
|
var execFileAsync4 = promisify6(execFile6);
|
|
6299
6235
|
var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
6300
6236
|
async function defaultBrowser2() {
|
|
@@ -6315,12 +6251,12 @@ async function defaultBrowser2() {
|
|
|
6315
6251
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
6316
6252
|
}
|
|
6317
6253
|
|
|
6318
|
-
// node_modules
|
|
6254
|
+
// node_modules/is-in-ssh/index.js
|
|
6319
6255
|
import process8 from "process";
|
|
6320
6256
|
var isInSsh = Boolean(process8.env.SSH_CONNECTION || process8.env.SSH_CLIENT || process8.env.SSH_TTY);
|
|
6321
6257
|
var is_in_ssh_default = isInSsh;
|
|
6322
6258
|
|
|
6323
|
-
// node_modules
|
|
6259
|
+
// node_modules/open/index.js
|
|
6324
6260
|
var fallbackAttemptSymbol = /* @__PURE__ */ Symbol("fallbackAttempt");
|
|
6325
6261
|
var __dirname = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
|
|
6326
6262
|
var localXdgOpenPath = path.join(__dirname, "xdg-open");
|
|
@@ -6738,7 +6674,7 @@ var loginCommand = new Command("login").alias("signup").description("Authenticat
|
|
|
6738
6674
|
});
|
|
6739
6675
|
console.log(source_default.green("Authenticated successfully."));
|
|
6740
6676
|
console.log(` Credentials stored at: ${store.path}`);
|
|
6741
|
-
console.log(` Dashboard: ${source_default.underline("app.getonlane.com/
|
|
6677
|
+
console.log(` Dashboard: ${source_default.underline("app.getonlane.com/dashboard")}`);
|
|
6742
6678
|
} catch (err) {
|
|
6743
6679
|
console.error(source_default.red(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
6744
6680
|
process.exit(1);
|
|
@@ -6746,7 +6682,6 @@ var loginCommand = new Command("login").alias("signup").description("Authenticat
|
|
|
6746
6682
|
});
|
|
6747
6683
|
|
|
6748
6684
|
// src/cli/commands/logout.ts
|
|
6749
|
-
init_token_store();
|
|
6750
6685
|
var logoutCommand = new Command("logout").description("Clear local credentials").action(async () => {
|
|
6751
6686
|
const store = new FileTokenStore();
|
|
6752
6687
|
await store.clear();
|
|
@@ -6803,7 +6738,7 @@ var addCardCommand = new Command("add-card").description("Add a payment card via
|
|
|
6803
6738
|
const latest = cards[cards.length - 1];
|
|
6804
6739
|
console.log(source_default.green(`
|
|
6805
6740
|
Card ending in ${latest.last4} (${latest.brand}) saved.`));
|
|
6806
|
-
console.log(` Manage cards: ${source_default.underline("app.getonlane.com/
|
|
6741
|
+
console.log(` Manage cards: ${source_default.underline("app.getonlane.com/dashboard/cards")}`);
|
|
6807
6742
|
return;
|
|
6808
6743
|
}
|
|
6809
6744
|
}
|
|
@@ -6844,7 +6779,7 @@ var cardsCommand = new Command("cards").description("List all payment cards (las
|
|
|
6844
6779
|
console.log(` ${card.brand.padEnd(12)} **** ${card.last4}${defaultBadge}${statusBadge}`);
|
|
6845
6780
|
}
|
|
6846
6781
|
console.log(`
|
|
6847
|
-
Manage: ${source_default.underline("app.getonlane.com/
|
|
6782
|
+
Manage: ${source_default.underline("app.getonlane.com/dashboard/cards")}`);
|
|
6848
6783
|
} catch (err) {
|
|
6849
6784
|
console.error(source_default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
6850
6785
|
process.exit(1);
|
|
@@ -6882,7 +6817,7 @@ var balanceCommand = new Command("balance").description("Show spending limits an
|
|
|
6882
6817
|
console.log(` Monthly: $${(budget.monthlyLimit / 100).toFixed(2)}`);
|
|
6883
6818
|
}
|
|
6884
6819
|
console.log(`
|
|
6885
|
-
Adjust: ${source_default.underline("app.getonlane.com/
|
|
6820
|
+
Adjust: ${source_default.underline("app.getonlane.com/dashboard/budgets")}`);
|
|
6886
6821
|
} catch (err) {
|
|
6887
6822
|
console.error(source_default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
6888
6823
|
process.exit(1);
|
|
@@ -6951,7 +6886,7 @@ var transactionsCommand = new Command("transactions").description("View spending
|
|
|
6951
6886
|
}
|
|
6952
6887
|
console.log(`
|
|
6953
6888
|
Total: ${result.total} transactions`);
|
|
6954
|
-
console.log(` Full history: ${source_default.underline("app.getonlane.com/
|
|
6889
|
+
console.log(` Full history: ${source_default.underline("app.getonlane.com/dashboard/transactions")}`);
|
|
6955
6890
|
} catch (err) {
|
|
6956
6891
|
console.error(source_default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
6957
6892
|
process.exit(1);
|
|
@@ -7010,7 +6945,6 @@ var payCommand = new Command("pay").description("Execute a payment to a merchant
|
|
|
7010
6945
|
|
|
7011
6946
|
// src/cli/commands/rotate-key.ts
|
|
7012
6947
|
init_lane();
|
|
7013
|
-
init_token_store();
|
|
7014
6948
|
var rotateKeyCommand = new Command("rotate-key").description("Rotate your API key (old key remains valid for 15 minutes)").action(async () => {
|
|
7015
6949
|
try {
|
|
7016
6950
|
const lane = await Lane.create();
|
|
@@ -7076,7 +7010,7 @@ var setupMcpCommand = new Command("setup-mcp").description("Auto-configure Lane
|
|
|
7076
7010
|
});
|
|
7077
7011
|
|
|
7078
7012
|
// src/cli/commands/dashboard.ts
|
|
7079
|
-
var DASHBOARD_URL = "https://app.getonlane.com/
|
|
7013
|
+
var DASHBOARD_URL = "https://app.getonlane.com/dashboard";
|
|
7080
7014
|
var dashboardCommand = new Command("dashboard").description("Open the Lane dashboard in your browser").option("--page <page>", "Dashboard page (cards, budgets, transactions, agents, sell, team, settings)").action(async (options) => {
|
|
7081
7015
|
const page = options.page;
|
|
7082
7016
|
const url = page ? `${DASHBOARD_URL}/${page}` : DASHBOARD_URL;
|