@superglue/cli 1.1.13 → 1.1.14
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.js +125 -77
- package/dist/dist/cli.js +125 -77
- package/dist/dist/skills/superglue/SKILL.md +11 -11
- package/dist/dist/skills/superglue/references/databases.md +164 -3
- package/dist/dist/skills/superglue/references/transforms-and-output.md +2 -2
- package/dist/skills/superglue/SKILL.md +11 -11
- package/dist/skills/superglue/references/databases.md +164 -3
- package/dist/skills/superglue/references/transforms-and-output.md +2 -2
- package/package.json +6 -6
- package/skills/superglue/SKILL.md +11 -11
- package/skills/superglue/references/databases.md +164 -3
- package/skills/superglue/references/transforms-and-output.md +2 -2
package/dist/cli.js
CHANGED
|
@@ -9077,8 +9077,8 @@ var require_luxon = __commonJS({
|
|
|
9077
9077
|
let current = null, currentFull = "", bracketed = false;
|
|
9078
9078
|
const splits = [];
|
|
9079
9079
|
for (let i = 0; i < fmt.length; i++) {
|
|
9080
|
-
const
|
|
9081
|
-
if (
|
|
9080
|
+
const c2 = fmt.charAt(i);
|
|
9081
|
+
if (c2 === "'") {
|
|
9082
9082
|
if (currentFull.length > 0 || bracketed) {
|
|
9083
9083
|
splits.push({
|
|
9084
9084
|
literal: bracketed || /^\s+$/.test(currentFull),
|
|
@@ -9089,9 +9089,9 @@ var require_luxon = __commonJS({
|
|
|
9089
9089
|
currentFull = "";
|
|
9090
9090
|
bracketed = !bracketed;
|
|
9091
9091
|
} else if (bracketed) {
|
|
9092
|
-
currentFull +=
|
|
9093
|
-
} else if (
|
|
9094
|
-
currentFull +=
|
|
9092
|
+
currentFull += c2;
|
|
9093
|
+
} else if (c2 === current) {
|
|
9094
|
+
currentFull += c2;
|
|
9095
9095
|
} else {
|
|
9096
9096
|
if (currentFull.length > 0) {
|
|
9097
9097
|
splits.push({
|
|
@@ -9099,8 +9099,8 @@ var require_luxon = __commonJS({
|
|
|
9099
9099
|
val: currentFull
|
|
9100
9100
|
});
|
|
9101
9101
|
}
|
|
9102
|
-
currentFull =
|
|
9103
|
-
current =
|
|
9102
|
+
currentFull = c2;
|
|
9103
|
+
current = c2;
|
|
9104
9104
|
}
|
|
9105
9105
|
}
|
|
9106
9106
|
if (currentFull.length > 0) {
|
|
@@ -11782,7 +11782,7 @@ var require_luxon = __commonJS({
|
|
|
11782
11782
|
return fixOffset(objToLocalTS(obj), offset2, zone);
|
|
11783
11783
|
}
|
|
11784
11784
|
function adjustTime(inst, dur) {
|
|
11785
|
-
const oPre = inst.o, year = inst.c.year + Math.trunc(dur.years), month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3,
|
|
11785
|
+
const oPre = inst.o, year = inst.c.year + Math.trunc(dur.years), month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, c2 = {
|
|
11786
11786
|
...inst.c,
|
|
11787
11787
|
year,
|
|
11788
11788
|
month,
|
|
@@ -11797,7 +11797,7 @@ var require_luxon = __commonJS({
|
|
|
11797
11797
|
minutes: dur.minutes,
|
|
11798
11798
|
seconds: dur.seconds,
|
|
11799
11799
|
milliseconds: dur.milliseconds
|
|
11800
|
-
}).as("milliseconds"), localTS = objToLocalTS(
|
|
11800
|
+
}).as("milliseconds"), localTS = objToLocalTS(c2);
|
|
11801
11801
|
let [ts, o] = fixOffset(localTS, oPre, inst.zone);
|
|
11802
11802
|
if (millisToAdd !== 0) {
|
|
11803
11803
|
ts += millisToAdd;
|
|
@@ -11832,72 +11832,72 @@ var require_luxon = __commonJS({
|
|
|
11832
11832
|
}
|
|
11833
11833
|
function toISODate(o, extended, precision) {
|
|
11834
11834
|
const longFormat = o.c.year > 9999 || o.c.year < 0;
|
|
11835
|
-
let
|
|
11836
|
-
if (longFormat && o.c.year >= 0)
|
|
11837
|
-
|
|
11838
|
-
if (precision === "year") return
|
|
11835
|
+
let c2 = "";
|
|
11836
|
+
if (longFormat && o.c.year >= 0) c2 += "+";
|
|
11837
|
+
c2 += padStart(o.c.year, longFormat ? 6 : 4);
|
|
11838
|
+
if (precision === "year") return c2;
|
|
11839
11839
|
if (extended) {
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
if (precision === "month") return
|
|
11843
|
-
|
|
11840
|
+
c2 += "-";
|
|
11841
|
+
c2 += padStart(o.c.month);
|
|
11842
|
+
if (precision === "month") return c2;
|
|
11843
|
+
c2 += "-";
|
|
11844
11844
|
} else {
|
|
11845
|
-
|
|
11846
|
-
if (precision === "month") return
|
|
11845
|
+
c2 += padStart(o.c.month);
|
|
11846
|
+
if (precision === "month") return c2;
|
|
11847
11847
|
}
|
|
11848
|
-
|
|
11849
|
-
return
|
|
11848
|
+
c2 += padStart(o.c.day);
|
|
11849
|
+
return c2;
|
|
11850
11850
|
}
|
|
11851
11851
|
function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision) {
|
|
11852
|
-
let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0,
|
|
11852
|
+
let showSeconds = !suppressSeconds || o.c.millisecond !== 0 || o.c.second !== 0, c2 = "";
|
|
11853
11853
|
switch (precision) {
|
|
11854
11854
|
case "day":
|
|
11855
11855
|
case "month":
|
|
11856
11856
|
case "year":
|
|
11857
11857
|
break;
|
|
11858
11858
|
default:
|
|
11859
|
-
|
|
11859
|
+
c2 += padStart(o.c.hour);
|
|
11860
11860
|
if (precision === "hour") break;
|
|
11861
11861
|
if (extended) {
|
|
11862
|
-
|
|
11863
|
-
|
|
11862
|
+
c2 += ":";
|
|
11863
|
+
c2 += padStart(o.c.minute);
|
|
11864
11864
|
if (precision === "minute") break;
|
|
11865
11865
|
if (showSeconds) {
|
|
11866
|
-
|
|
11867
|
-
|
|
11866
|
+
c2 += ":";
|
|
11867
|
+
c2 += padStart(o.c.second);
|
|
11868
11868
|
}
|
|
11869
11869
|
} else {
|
|
11870
|
-
|
|
11870
|
+
c2 += padStart(o.c.minute);
|
|
11871
11871
|
if (precision === "minute") break;
|
|
11872
11872
|
if (showSeconds) {
|
|
11873
|
-
|
|
11873
|
+
c2 += padStart(o.c.second);
|
|
11874
11874
|
}
|
|
11875
11875
|
}
|
|
11876
11876
|
if (precision === "second") break;
|
|
11877
11877
|
if (showSeconds && (!suppressMilliseconds || o.c.millisecond !== 0)) {
|
|
11878
|
-
|
|
11879
|
-
|
|
11878
|
+
c2 += ".";
|
|
11879
|
+
c2 += padStart(o.c.millisecond, 3);
|
|
11880
11880
|
}
|
|
11881
11881
|
}
|
|
11882
11882
|
if (includeOffset) {
|
|
11883
11883
|
if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
|
|
11884
|
-
|
|
11884
|
+
c2 += "Z";
|
|
11885
11885
|
} else if (o.o < 0) {
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11886
|
+
c2 += "-";
|
|
11887
|
+
c2 += padStart(Math.trunc(-o.o / 60));
|
|
11888
|
+
c2 += ":";
|
|
11889
|
+
c2 += padStart(Math.trunc(-o.o % 60));
|
|
11890
11890
|
} else {
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11891
|
+
c2 += "+";
|
|
11892
|
+
c2 += padStart(Math.trunc(o.o / 60));
|
|
11893
|
+
c2 += ":";
|
|
11894
|
+
c2 += padStart(Math.trunc(o.o % 60));
|
|
11895
11895
|
}
|
|
11896
11896
|
}
|
|
11897
11897
|
if (extendedZone) {
|
|
11898
|
-
|
|
11898
|
+
c2 += "[" + o.zone.ianaName + "]";
|
|
11899
11899
|
}
|
|
11900
|
-
return
|
|
11900
|
+
return c2;
|
|
11901
11901
|
}
|
|
11902
11902
|
var defaultUnitValues = {
|
|
11903
11903
|
month: 1,
|
|
@@ -12015,10 +12015,10 @@ var require_luxon = __commonJS({
|
|
|
12015
12015
|
});
|
|
12016
12016
|
}
|
|
12017
12017
|
function diffRelative(start, end, opts) {
|
|
12018
|
-
const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (
|
|
12019
|
-
|
|
12018
|
+
const round = isUndefined(opts.round) ? true : opts.round, rounding = isUndefined(opts.rounding) ? "trunc" : opts.rounding, format = (c2, unit) => {
|
|
12019
|
+
c2 = roundTo(c2, round || opts.calendary ? 0 : 2, opts.calendary ? "round" : rounding);
|
|
12020
12020
|
const formatter = end.loc.clone(opts).relFormatter(opts);
|
|
12021
|
-
return formatter.format(
|
|
12021
|
+
return formatter.format(c2, unit);
|
|
12022
12022
|
}, differ = (unit) => {
|
|
12023
12023
|
if (opts.calendary) {
|
|
12024
12024
|
if (!end.hasSame(start, unit)) {
|
|
@@ -12059,16 +12059,16 @@ var require_luxon = __commonJS({
|
|
|
12059
12059
|
const zone = config.zone || Settings.defaultZone;
|
|
12060
12060
|
let invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
|
|
12061
12061
|
this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
|
|
12062
|
-
let
|
|
12062
|
+
let c2 = null, o = null;
|
|
12063
12063
|
if (!invalid) {
|
|
12064
12064
|
const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
|
|
12065
12065
|
if (unchanged) {
|
|
12066
|
-
[
|
|
12066
|
+
[c2, o] = [config.old.c, config.old.o];
|
|
12067
12067
|
} else {
|
|
12068
12068
|
const ot = isNumber(config.o) && !config.old ? config.o : zone.offset(this.ts);
|
|
12069
|
-
|
|
12070
|
-
invalid = Number.isNaN(
|
|
12071
|
-
|
|
12069
|
+
c2 = tsToObj(this.ts, ot);
|
|
12070
|
+
invalid = Number.isNaN(c2.year) ? new Invalid("invalid input") : null;
|
|
12071
|
+
c2 = invalid ? null : c2;
|
|
12072
12072
|
o = invalid ? null : ot;
|
|
12073
12073
|
}
|
|
12074
12074
|
}
|
|
@@ -12077,7 +12077,7 @@ var require_luxon = __commonJS({
|
|
|
12077
12077
|
this.invalid = invalid;
|
|
12078
12078
|
this.weekData = null;
|
|
12079
12079
|
this.localWeekData = null;
|
|
12080
|
-
this.c =
|
|
12080
|
+
this.c = c2;
|
|
12081
12081
|
this.o = o;
|
|
12082
12082
|
this.isLuxonDateTime = true;
|
|
12083
12083
|
}
|
|
@@ -12836,8 +12836,8 @@ var require_luxon = __commonJS({
|
|
|
12836
12836
|
const ts1 = localTS - o1 * minuteMs;
|
|
12837
12837
|
const ts2 = localTS - o2 * minuteMs;
|
|
12838
12838
|
const c1 = tsToObj(ts1, o1);
|
|
12839
|
-
const
|
|
12840
|
-
if (c1.hour ===
|
|
12839
|
+
const c2 = tsToObj(ts2, o2);
|
|
12840
|
+
if (c1.hour === c2.hour && c1.minute === c2.minute && c1.second === c2.second && c1.millisecond === c2.millisecond) {
|
|
12841
12841
|
return [clone2(this, {
|
|
12842
12842
|
ts: ts1
|
|
12843
12843
|
}), clone2(this, {
|
|
@@ -13235,10 +13235,10 @@ var require_luxon = __commonJS({
|
|
|
13235
13235
|
}
|
|
13236
13236
|
precision = normalizeUnit(precision);
|
|
13237
13237
|
const ext = format === "extended";
|
|
13238
|
-
let
|
|
13239
|
-
if (orderedUnits.indexOf(precision) >= 3)
|
|
13240
|
-
|
|
13241
|
-
return
|
|
13238
|
+
let c2 = toISODate(this, ext, precision);
|
|
13239
|
+
if (orderedUnits.indexOf(precision) >= 3) c2 += "T";
|
|
13240
|
+
c2 += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
|
|
13241
|
+
return c2;
|
|
13242
13242
|
}
|
|
13243
13243
|
/**
|
|
13244
13244
|
* Returns an ISO 8601-compliant string representation of this DateTime's date component
|
|
@@ -13297,8 +13297,8 @@ var require_luxon = __commonJS({
|
|
|
13297
13297
|
return null;
|
|
13298
13298
|
}
|
|
13299
13299
|
precision = normalizeUnit(precision);
|
|
13300
|
-
let
|
|
13301
|
-
return
|
|
13300
|
+
let c2 = includePrefix && orderedUnits.indexOf(precision) >= 3 ? "T" : "";
|
|
13301
|
+
return c2 + toISOTime(this, format === "extended", suppressSeconds, suppressMilliseconds, includeOffset, extendedZone, precision);
|
|
13302
13302
|
}
|
|
13303
13303
|
/**
|
|
13304
13304
|
* Returns an RFC 2822-compatible string representation of this DateTime
|
|
@@ -17883,7 +17883,7 @@ attempted value: ${formattedValue}
|
|
|
17883
17883
|
type: next.type,
|
|
17884
17884
|
oneOf: next._whitelist.describe(),
|
|
17885
17885
|
notOneOf: next._blacklist.describe(),
|
|
17886
|
-
tests: next.tests.filter((n, idx, list) => list.findIndex((
|
|
17886
|
+
tests: next.tests.filter((n, idx, list) => list.findIndex((c2) => c2.OPTIONS.name === n.OPTIONS.name) === idx).map((fn) => {
|
|
17887
17887
|
const params = fn.OPTIONS.params && options ? resolveParams(Object.assign({}, fn.OPTIONS.params), options) : fn.OPTIONS.params;
|
|
17888
17888
|
return {
|
|
17889
17889
|
name: fn.OPTIONS.name,
|
|
@@ -20164,6 +20164,8 @@ var require_utils = __commonJS({
|
|
|
20164
20164
|
var getConnectionProtocol2 = (url) => {
|
|
20165
20165
|
if (url.startsWith("postgres://") || url.startsWith("postgresql://"))
|
|
20166
20166
|
return "postgres";
|
|
20167
|
+
if (url.startsWith("mssql://") || url.startsWith("sqlserver://"))
|
|
20168
|
+
return "mssql";
|
|
20167
20169
|
if (url.startsWith("redis://") || url.startsWith("rediss://"))
|
|
20168
20170
|
return "redis";
|
|
20169
20171
|
if (url.startsWith("ftp://") || url.startsWith("ftps://") || url.startsWith("sftp://"))
|
|
@@ -21499,17 +21501,18 @@ var require_superglue_client = __commonJS({
|
|
|
21499
21501
|
options: params.options,
|
|
21500
21502
|
runId: params.runId
|
|
21501
21503
|
}, params.traceId ? { "X-Trace-Id": params.traceId } : void 0);
|
|
21504
|
+
const success3 = response.status ? response.status === "success" : response.success ?? false;
|
|
21502
21505
|
return {
|
|
21503
|
-
success:
|
|
21506
|
+
success: success3,
|
|
21504
21507
|
data: response.data,
|
|
21505
21508
|
error: response.error,
|
|
21506
|
-
tool: response.tool,
|
|
21509
|
+
tool: response.tool || params.tool,
|
|
21507
21510
|
stepResults: response.stepResults?.map((sr) => ({
|
|
21508
21511
|
stepId: sr.stepId,
|
|
21509
21512
|
success: sr.success,
|
|
21510
21513
|
data: sr.data,
|
|
21511
21514
|
error: sr.error
|
|
21512
|
-
}))
|
|
21515
|
+
})) || []
|
|
21513
21516
|
};
|
|
21514
21517
|
}
|
|
21515
21518
|
async abortToolExecution(runId) {
|
|
@@ -22014,14 +22017,14 @@ var package_default = {
|
|
|
22014
22017
|
"LICENSE"
|
|
22015
22018
|
],
|
|
22016
22019
|
dependencies: {
|
|
22017
|
-
commander: "
|
|
22018
|
-
"fast-json-patch": "
|
|
22020
|
+
commander: "15.0.0-0",
|
|
22021
|
+
"fast-json-patch": "3.1.1"
|
|
22019
22022
|
},
|
|
22020
22023
|
devDependencies: {
|
|
22021
22024
|
"@superglue/shared": "file:../shared",
|
|
22022
|
-
"@types/node": "
|
|
22023
|
-
tsup: "
|
|
22024
|
-
typescript: "
|
|
22025
|
+
"@types/node": "25.5.0",
|
|
22026
|
+
tsup: "8.5.1",
|
|
22027
|
+
typescript: "5.8.3"
|
|
22025
22028
|
},
|
|
22026
22029
|
scripts: {
|
|
22027
22030
|
build: "tsup && (cp -r skills dist/ 2>/dev/null || true)",
|
|
@@ -23432,13 +23435,18 @@ function registerFindCommand2(parent, getContext2) {
|
|
|
23432
23435
|
const mode = opts.mode === "dev" || opts.mode === "prod" ? opts.mode : "all";
|
|
23433
23436
|
const { items } = await client.listSystems(100, 1, { mode });
|
|
23434
23437
|
table(
|
|
23435
|
-
items.map((s) =>
|
|
23436
|
-
|
|
23437
|
-
|
|
23438
|
-
|
|
23439
|
-
|
|
23440
|
-
|
|
23441
|
-
|
|
23438
|
+
items.map((s) => {
|
|
23439
|
+
const credentialKeys = Object.keys(s.credentials || {});
|
|
23440
|
+
const credPlaceholders = credentialKeys.map((k) => `<<${s.id}_${k}>>`).join(", ");
|
|
23441
|
+
return {
|
|
23442
|
+
id: s.id,
|
|
23443
|
+
name: s.name || "",
|
|
23444
|
+
env: s.environment || "prod",
|
|
23445
|
+
url: (s.url || "").slice(0, 40),
|
|
23446
|
+
credentials: credPlaceholders || "(none)"
|
|
23447
|
+
};
|
|
23448
|
+
}),
|
|
23449
|
+
["id", "name", "env", "url", "credentials"]
|
|
23442
23450
|
);
|
|
23443
23451
|
} catch (err) {
|
|
23444
23452
|
error(err.message);
|
|
@@ -23471,7 +23479,7 @@ function registerFindCommand2(parent, getContext2) {
|
|
|
23471
23479
|
if (rawQuery === "*") {
|
|
23472
23480
|
output({
|
|
23473
23481
|
success: true,
|
|
23474
|
-
systems: items.map((s) => (
|
|
23482
|
+
systems: items.map((s) => filterSystemFields(s))
|
|
23475
23483
|
});
|
|
23476
23484
|
return;
|
|
23477
23485
|
}
|
|
@@ -23482,7 +23490,7 @@ function registerFindCommand2(parent, getContext2) {
|
|
|
23482
23490
|
});
|
|
23483
23491
|
output({
|
|
23484
23492
|
success: true,
|
|
23485
|
-
systems: filtered.map((s) => (
|
|
23493
|
+
systems: filtered.map((s) => filterSystemFields(s))
|
|
23486
23494
|
});
|
|
23487
23495
|
} catch (err) {
|
|
23488
23496
|
error(err.message);
|
|
@@ -23505,6 +23513,46 @@ function registerCallCommand(parent, getContext2) {
|
|
|
23505
23513
|
[]
|
|
23506
23514
|
).addOption(
|
|
23507
23515
|
new import_commander5.Option("--env <environment>", "Environment: dev or prod").choices(["dev", "prod"])
|
|
23516
|
+
).addHelpText(
|
|
23517
|
+
"after",
|
|
23518
|
+
`
|
|
23519
|
+
${c.bold}Discovering Credential Placeholders:${c.reset}
|
|
23520
|
+
Use 'sg system find <system-id>' to see available credential placeholders:
|
|
23521
|
+
|
|
23522
|
+
${c.dim}$${c.reset} sg system find my_postgres
|
|
23523
|
+
${c.green}\u2192 credentialPlaceholders:${c.reset} ["<<my_postgres_username>>", "<<my_postgres_password>>"]
|
|
23524
|
+
|
|
23525
|
+
Or use 'sg system list' to see credentials for all systems at once.
|
|
23526
|
+
|
|
23527
|
+
${c.bold}Examples:${c.reset}
|
|
23528
|
+
${c.dim}# HTTP API with API key${c.reset}
|
|
23529
|
+
sg system call --system-id stripe \\
|
|
23530
|
+
--url "https://api.stripe.com/v1/customers" \\
|
|
23531
|
+
--headers '{"Authorization": "Bearer <<stripe_api_key>>"}'
|
|
23532
|
+
|
|
23533
|
+
${c.dim}# PostgreSQL database query${c.reset}
|
|
23534
|
+
sg system call --system-id my_postgres \\
|
|
23535
|
+
--url "postgres://<<my_postgres_username>>:<<my_postgres_password>>@localhost:5432/mydb" \\
|
|
23536
|
+
--body '{"query": "SELECT * FROM users WHERE id = $1", "params": [123]}'
|
|
23537
|
+
|
|
23538
|
+
${c.dim}# Microsoft SQL Server with parameterized query${c.reset}
|
|
23539
|
+
sg system call --system-id azure_sql \\
|
|
23540
|
+
--url "mssql://<<azure_sql_username>>:<<azure_sql_password>>@server.database.windows.net:1433/mydb" \\
|
|
23541
|
+
--body '{"query": "SELECT * FROM orders WHERE status = @param1", "params": ["pending"]}'
|
|
23542
|
+
|
|
23543
|
+
${c.dim}# Redis command${c.reset}
|
|
23544
|
+
sg system call --system-id my_redis \\
|
|
23545
|
+
--url "redis://<<my_redis_password>>@localhost:6379" \\
|
|
23546
|
+
--body '{"command": "GET", "args": ["user:123"]}'
|
|
23547
|
+
|
|
23548
|
+
${c.dim}# SFTP list files${c.reset}
|
|
23549
|
+
sg system call --system-id sftp_server \\
|
|
23550
|
+
--url "sftp://<<sftp_server_username>>:<<sftp_server_password>>@files.example.com:22" \\
|
|
23551
|
+
--body '{"operation": "list", "path": "/uploads"}'
|
|
23552
|
+
|
|
23553
|
+
${c.bold}Supported Protocols:${c.reset}
|
|
23554
|
+
HTTP/HTTPS, PostgreSQL, MSSQL/SQL Server, Redis, SFTP/FTP/FTPS, SMB
|
|
23555
|
+
`
|
|
23508
23556
|
).action(async (opts) => {
|
|
23509
23557
|
const { client } = getContext2();
|
|
23510
23558
|
const method = opts.method || "GET";
|