atmn 2.0.11 → 2.0.13
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/bin.js +725 -186
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/actions/init/runInit.ts +2 -0
- package/src/actions/pull/applyMappings.ts +100 -0
- package/src/actions/pull/locateFixture.ts +19 -4
- package/src/actions/pull.ts +22 -0
- package/src/actions/skills/ignoreBundledSkills.ts +32 -0
- package/src/cli.ts +5 -0
- package/src/generated/apiRoutes.ts +24 -24
- package/src/generated/emit.ts +42 -0
- package/src/generated/emitRuntime.ts +3 -5
- package/src/generated/mappingAssignments.ts +204 -0
- package/src/generated/skills.ts +10 -10
- package/src/surgery/appendPropertyEdit.ts +3 -1
- package/src/surgery/findFixture.ts +24 -12
- package/src/surgery/patchFixturePaths.ts +204 -0
- package/src/surgery/readFixtureValue.ts +99 -0
package/dist/bin.js
CHANGED
|
@@ -4,7 +4,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
4
4
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
7
|
-
import { join as
|
|
7
|
+
import { join as join14 } from "node:path";
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
|
|
10
10
|
// src/auth/oauthConfig.ts
|
|
@@ -375,6 +375,27 @@ var API_ROUTES = [
|
|
|
375
375
|
}
|
|
376
376
|
]
|
|
377
377
|
},
|
|
378
|
+
{
|
|
379
|
+
group: "customers",
|
|
380
|
+
method: "advance_test_clock",
|
|
381
|
+
path: "/v1/customers.advance_test_clock",
|
|
382
|
+
description: "Advance a customer's Stripe test clock to a future time in milliseconds. Only Stripe test-mode customers with a test clock are supported. Advancement is asynchronous; Stripe enforces clock status and advancement limits.",
|
|
383
|
+
body: "object",
|
|
384
|
+
fields: [
|
|
385
|
+
{
|
|
386
|
+
name: "customer_id",
|
|
387
|
+
type: "string",
|
|
388
|
+
required: true,
|
|
389
|
+
description: "The ID of the customer whose Stripe test clock to advance."
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
name: "frozen_time",
|
|
393
|
+
type: "number",
|
|
394
|
+
required: true,
|
|
395
|
+
description: "Target time as a Unix timestamp in milliseconds. Rounded down to whole seconds; must be later than the current clock time."
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
},
|
|
378
399
|
{
|
|
379
400
|
group: "plans",
|
|
380
401
|
method: "create",
|
|
@@ -1081,27 +1102,6 @@ var API_ROUTES = [
|
|
|
1081
1102
|
}
|
|
1082
1103
|
]
|
|
1083
1104
|
},
|
|
1084
|
-
{
|
|
1085
|
-
group: "billing",
|
|
1086
|
-
method: "advance_test_clock",
|
|
1087
|
-
path: "/v1/billing.advance_test_clock",
|
|
1088
|
-
description: "Advance a customer's Stripe test clock to a future time in milliseconds. Only Stripe test-mode customers with a test clock are supported. Advancement is asynchronous; Stripe enforces clock status and advancement limits.",
|
|
1089
|
-
body: "object",
|
|
1090
|
-
fields: [
|
|
1091
|
-
{
|
|
1092
|
-
name: "customer_id",
|
|
1093
|
-
type: "string",
|
|
1094
|
-
required: true,
|
|
1095
|
-
description: "The ID of the customer whose Stripe test clock to advance."
|
|
1096
|
-
},
|
|
1097
|
-
{
|
|
1098
|
-
name: "frozen_time",
|
|
1099
|
-
type: "number",
|
|
1100
|
-
required: true,
|
|
1101
|
-
description: "Target time as a Unix timestamp in milliseconds. Rounded down to whole seconds; must be later than the current clock time."
|
|
1102
|
-
}
|
|
1103
|
-
]
|
|
1104
|
-
},
|
|
1105
1105
|
{
|
|
1106
1106
|
group: "billing",
|
|
1107
1107
|
method: "create_schedule",
|
|
@@ -6787,7 +6787,7 @@ var createClient = (options) => ({
|
|
|
6787
6787
|
});
|
|
6788
6788
|
|
|
6789
6789
|
// src/version.ts
|
|
6790
|
-
var version = "2.0.
|
|
6790
|
+
var version = "2.0.13";
|
|
6791
6791
|
|
|
6792
6792
|
// src/http/autumnFetch.ts
|
|
6793
6793
|
var runtime = typeof Bun !== "undefined" ? `bun ${Bun.version}` : `node ${process.versions.node}`;
|
|
@@ -7183,8 +7183,8 @@ var fetchOrgInfo = async ({
|
|
|
7183
7183
|
};
|
|
7184
7184
|
|
|
7185
7185
|
// src/actions/init/runInit.ts
|
|
7186
|
-
import { existsSync as
|
|
7187
|
-
import { dirname as dirname5, join as
|
|
7186
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "node:fs";
|
|
7187
|
+
import { dirname as dirname5, join as join9, relative as relative3, resolve as resolve2 } from "node:path";
|
|
7188
7188
|
|
|
7189
7189
|
// src/config/configPackageName.ts
|
|
7190
7190
|
var PUBLISHED_PACKAGE = "atmn";
|
|
@@ -7723,6 +7723,7 @@ import { dirname as dirname3, join as join6 } from "node:path";
|
|
|
7723
7723
|
// src/generated/emit.ts
|
|
7724
7724
|
var COLLECTIONS = {
|
|
7725
7725
|
features: {
|
|
7726
|
+
wireKey: "features",
|
|
7726
7727
|
builder: "feature",
|
|
7727
7728
|
idField: "featureId",
|
|
7728
7729
|
responseIdField: "id",
|
|
@@ -7798,11 +7799,13 @@ var COLLECTIONS = {
|
|
|
7798
7799
|
"providerMarkups.*.markup",
|
|
7799
7800
|
"type"
|
|
7800
7801
|
],
|
|
7802
|
+
mappings: { properties: { processors: { mapping: true } } },
|
|
7801
7803
|
defaults: {},
|
|
7802
7804
|
pull: true,
|
|
7803
7805
|
deprecated: []
|
|
7804
7806
|
},
|
|
7805
7807
|
plans: {
|
|
7808
|
+
wireKey: "plans",
|
|
7806
7809
|
builder: "plan",
|
|
7807
7810
|
idField: "planId",
|
|
7808
7811
|
responseIdField: "id",
|
|
@@ -8583,6 +8586,43 @@ var COLLECTIONS = {
|
|
|
8583
8586
|
"variants.versionSlug",
|
|
8584
8587
|
"versionSlug"
|
|
8585
8588
|
],
|
|
8589
|
+
mappings: {
|
|
8590
|
+
properties: {
|
|
8591
|
+
processors: { mapping: true },
|
|
8592
|
+
price: { properties: { processors: { mapping: true } } },
|
|
8593
|
+
items: {
|
|
8594
|
+
items: {
|
|
8595
|
+
properties: {
|
|
8596
|
+
price: { properties: { processors: { mapping: true } } }
|
|
8597
|
+
}
|
|
8598
|
+
},
|
|
8599
|
+
identity: {
|
|
8600
|
+
responseField: "mappingIdentity",
|
|
8601
|
+
components: [
|
|
8602
|
+
{ paths: ["featureId"], default: "" },
|
|
8603
|
+
{ paths: ["price.billingMethod"], default: "" },
|
|
8604
|
+
{ paths: ["price.interval", "reset.interval"], default: "" },
|
|
8605
|
+
{
|
|
8606
|
+
paths: ["price.intervalCount", "reset.intervalCount"],
|
|
8607
|
+
default: "",
|
|
8608
|
+
defaultWhen: { component: 2, value: 1 }
|
|
8609
|
+
}
|
|
8610
|
+
]
|
|
8611
|
+
}
|
|
8612
|
+
},
|
|
8613
|
+
variants: {
|
|
8614
|
+
items: {
|
|
8615
|
+
properties: {
|
|
8616
|
+
processors: { mapping: true, sourcePath: ["plan", "processors"] }
|
|
8617
|
+
}
|
|
8618
|
+
},
|
|
8619
|
+
identity: {
|
|
8620
|
+
responseField: "mappingIdentity",
|
|
8621
|
+
components: [{ paths: ["variantPlanId"], default: "" }]
|
|
8622
|
+
}
|
|
8623
|
+
}
|
|
8624
|
+
}
|
|
8625
|
+
},
|
|
8586
8626
|
defaults: {
|
|
8587
8627
|
addOn: false,
|
|
8588
8628
|
autoEnable: false,
|
|
@@ -8678,6 +8718,7 @@ var COLLECTIONS = {
|
|
|
8678
8718
|
]
|
|
8679
8719
|
},
|
|
8680
8720
|
rewards: {
|
|
8721
|
+
wireKey: "rewards",
|
|
8681
8722
|
builder: "reward",
|
|
8682
8723
|
idField: "id",
|
|
8683
8724
|
responseIdField: "id",
|
|
@@ -8820,6 +8861,7 @@ var COLLECTIONS = {
|
|
|
8820
8861
|
]
|
|
8821
8862
|
},
|
|
8822
8863
|
referralPrograms: {
|
|
8864
|
+
wireKey: "referral_programs",
|
|
8823
8865
|
builder: "referralProgram",
|
|
8824
8866
|
idField: "id",
|
|
8825
8867
|
responseIdField: "id",
|
|
@@ -8974,6 +9016,10 @@ var scaffoldConfig = ({
|
|
|
8974
9016
|
return configPath;
|
|
8975
9017
|
};
|
|
8976
9018
|
|
|
9019
|
+
// src/actions/skills/ignoreBundledSkills.ts
|
|
9020
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "node:fs";
|
|
9021
|
+
import { isAbsolute as isAbsolute2, join as join8, relative as relative2, sep } from "node:path";
|
|
9022
|
+
|
|
8977
9023
|
// src/actions/skills/skills.ts
|
|
8978
9024
|
import { spawnSync } from "node:child_process";
|
|
8979
9025
|
import {
|
|
@@ -8988,16 +9034,16 @@ import { dirname as dirname4, join as join7 } from "node:path";
|
|
|
8988
9034
|
import chalk3 from "chalk";
|
|
8989
9035
|
|
|
8990
9036
|
// src/generated/skills.ts
|
|
8991
|
-
var SKILLS_VERSION = "2.0.
|
|
9037
|
+
var SKILLS_VERSION = "2.0.13";
|
|
8992
9038
|
var SKILLS = [
|
|
8993
9039
|
{
|
|
8994
9040
|
name: "autumn-setup",
|
|
8995
9041
|
description: "First-time Autumn setup — install the atmn CLI, connect to an org (sign in, or keyless with no account), turn the user's pricing into autumn.config.ts, and push it to a sandbox org. Use when the user is new to Autumn, pastes an Autumn setup prompt, or asks to set up Autumn, add billing, monetization, subscriptions, usage-based billing, pricing, or plans. If Autumn is already set up, use autumn-catalog instead.",
|
|
8996
|
-
version: "2.0.
|
|
9042
|
+
version: "2.0.13",
|
|
8997
9043
|
markdown: `---
|
|
8998
9044
|
name: autumn-setup
|
|
8999
9045
|
description: First-time Autumn setup — install the atmn CLI, connect to an org (sign in, or keyless with no account), turn the user's pricing into autumn.config.ts, and push it to a sandbox org. Use when the user is new to Autumn, pastes an Autumn setup prompt, or asks to set up Autumn, add billing, monetization, subscriptions, usage-based billing, pricing, or plans. If Autumn is already set up, use autumn-catalog instead.
|
|
9000
|
-
version: 2.0.
|
|
9046
|
+
version: 2.0.13
|
|
9001
9047
|
---
|
|
9002
9048
|
|
|
9003
9049
|
# Setup
|
|
@@ -9155,11 +9201,11 @@ Then stop. Don't keep building, don't tour the dashboard, don't deploy anything.
|
|
|
9155
9201
|
{
|
|
9156
9202
|
name: "autumn-catalog",
|
|
9157
9203
|
description: "Modeling a user's pricing into an Autumn catalog — deciding the structure (plans, variants, add-ons, licenses, credit systems, pooled balances) before writing config, then filling in the numbers. Use when the user describes their pricing or asks to model, change, or push a catalog.",
|
|
9158
|
-
version: "2.0.
|
|
9204
|
+
version: "2.0.13",
|
|
9159
9205
|
markdown: `---
|
|
9160
9206
|
name: autumn-catalog
|
|
9161
9207
|
description: Modeling a user's pricing into an Autumn catalog — deciding the structure (plans, variants, add-ons, licenses, credit systems, pooled balances) before writing config, then filling in the numbers. Use when the user describes their pricing or asks to model, change, or push a catalog.
|
|
9162
|
-
version: 2.0.
|
|
9208
|
+
version: 2.0.13
|
|
9163
9209
|
---
|
|
9164
9210
|
|
|
9165
9211
|
# Catalog
|
|
@@ -13041,11 +13087,11 @@ Pitch: "Pro $20/mo or $200/yr — 1,000 messages per month either way."
|
|
|
13041
13087
|
{
|
|
13042
13088
|
name: "autumn-integrate",
|
|
13043
13089
|
description: "Integrating Autumn into an app's backend — creating customers, billing flows (attach, checkout, upgrade, cancel), gating features with check, recording usage with track, and exposing billing data to the frontend. Use when the user asks to integrate Autumn, add billing/payments to their app, gate features, meter usage, or build checkout/upgrade flows. Requires a pushed catalog; use autumn-catalog first if plans don't exist yet.",
|
|
13044
|
-
version: "2.0.
|
|
13090
|
+
version: "2.0.13",
|
|
13045
13091
|
markdown: `---
|
|
13046
13092
|
name: autumn-integrate
|
|
13047
13093
|
description: Integrating Autumn into an app's backend — creating customers, billing flows (attach, checkout, upgrade, cancel), gating features with check, recording usage with track, and exposing billing data to the frontend. Use when the user asks to integrate Autumn, add billing/payments to their app, gate features, meter usage, or build checkout/upgrade flows. Requires a pushed catalog; use autumn-catalog first if plans don't exist yet.
|
|
13048
|
-
version: 2.0.
|
|
13094
|
+
version: 2.0.13
|
|
13049
13095
|
---
|
|
13050
13096
|
|
|
13051
13097
|
# Integrate
|
|
@@ -17569,7 +17615,8 @@ Fail-open is **enabled by default**. When Autumn is unreachable (network errors,
|
|
|
17569
17615
|
|--------|-----------------|--------|
|
|
17570
17616
|
| \`check()\` | \`{ allowed: true }\` | Users retain access to features |
|
|
17571
17617
|
| \`track()\` | \`{ value: 0, balance: null }\` | Usage event is silently dropped |
|
|
17572
|
-
|
|
17618
|
+
|
|
17619
|
+
Customer and entity operations, including \`customers.getOrCreate()\`, \`customers.get()\`, \`entities.get()\`, and \`entities.create()\`, propagate errors even when fail-open is enabled. Only \`check()\` and \`track()\` return fail-open defaults.
|
|
17573
17620
|
|
|
17574
17621
|
When fail-open triggers, the SDK logs a prominent error to your console so you're immediately aware of the issue.
|
|
17575
17622
|
|
|
@@ -17618,18 +17665,6 @@ const result = await autumn.check({
|
|
|
17618
17665
|
// Fail-open response: allowed is always true, customerId is ""
|
|
17619
17666
|
\`\`\`
|
|
17620
17667
|
|
|
17621
|
-
When \`customers.getOrCreate()\` fails open, the returned customer will have \`id: null\`:
|
|
17622
|
-
|
|
17623
|
-
\`\`\`typescript
|
|
17624
|
-
const customer = await autumn.customers.getOrCreate({
|
|
17625
|
-
customerId: "cus_123",
|
|
17626
|
-
});
|
|
17627
|
-
|
|
17628
|
-
if (customer.id === null) {
|
|
17629
|
-
// Autumn was unreachable, handle gracefully
|
|
17630
|
-
}
|
|
17631
|
-
\`\`\`
|
|
17632
|
-
|
|
17633
17668
|
## Console output
|
|
17634
17669
|
|
|
17635
17670
|
When fail-open triggers, you'll see this in your server logs:
|
|
@@ -17654,11 +17689,11 @@ Monitor your logs for this message. If you see it, check [status.useautumn.com](
|
|
|
17654
17689
|
{
|
|
17655
17690
|
name: "autumn-concepts",
|
|
17656
17691
|
description: "Understanding Autumn's billing objects before acting on them — what a plan version is and what active means, when a trial starts or ends billing, how entity- and seat-scoped subscriptions differ from the customer's own, what a customize diff actually changes, and how caps, overage, and top-ups behave. Load before versioning, editing, or drafting a plan, or when a customer's state does not match the plain reading of their plan.",
|
|
17657
|
-
version: "2.0.
|
|
17692
|
+
version: "2.0.13",
|
|
17658
17693
|
markdown: `---
|
|
17659
17694
|
name: autumn-concepts
|
|
17660
17695
|
description: Understanding Autumn's billing objects before acting on them — what a plan version is and what active means, when a trial starts or ends billing, how entity- and seat-scoped subscriptions differ from the customer's own, what a customize diff actually changes, and how caps, overage, and top-ups behave. Load before versioning, editing, or drafting a plan, or when a customer's state does not match the plain reading of their plan.
|
|
17661
|
-
version: 2.0.
|
|
17696
|
+
version: 2.0.13
|
|
17662
17697
|
---
|
|
17663
17698
|
|
|
17664
17699
|
# Concepts
|
|
@@ -18210,6 +18245,30 @@ var updateSkills = ({
|
|
|
18210
18245
|
return { updated };
|
|
18211
18246
|
};
|
|
18212
18247
|
|
|
18248
|
+
// src/actions/skills/ignoreBundledSkills.ts
|
|
18249
|
+
var ignoreBundledSkills = ({
|
|
18250
|
+
repoRoot,
|
|
18251
|
+
configDir
|
|
18252
|
+
}) => {
|
|
18253
|
+
const path = relative2(repoRoot, join8(configDir, SKILLS_DIR_NAME));
|
|
18254
|
+
if (isAbsolute2(path) || path === ".." || path.startsWith(`..${sep}`))
|
|
18255
|
+
return;
|
|
18256
|
+
if (/[\r\n]/.test(path))
|
|
18257
|
+
return;
|
|
18258
|
+
const pattern = `/${path.split(sep).join("/").replace(/[\\*?[\] ]/g, "\\$&")}/`;
|
|
18259
|
+
const ignorePath = join8(repoRoot, ".gitignore");
|
|
18260
|
+
const contents = existsSync8(ignorePath) ? readFileSync7(ignorePath, "utf8") : "";
|
|
18261
|
+
if (contents.split(/\r?\n/).includes(pattern))
|
|
18262
|
+
return;
|
|
18263
|
+
const newline = contents.includes(`\r
|
|
18264
|
+
`) ? `\r
|
|
18265
|
+
` : `
|
|
18266
|
+
`;
|
|
18267
|
+
const separator = contents.length > 0 && !contents.endsWith(`
|
|
18268
|
+
`) ? newline : "";
|
|
18269
|
+
writeFileSync5(ignorePath, `${contents}${separator}${pattern}${newline}`, "utf8");
|
|
18270
|
+
};
|
|
18271
|
+
|
|
18213
18272
|
// src/actions/init/runInit.ts
|
|
18214
18273
|
var DEFAULT_PACKAGE_DIR = "packages/autumn";
|
|
18215
18274
|
var DEFAULT_CONFIG_DIR = "autumn";
|
|
@@ -18294,8 +18353,8 @@ var authenticate = async ({
|
|
|
18294
18353
|
`);
|
|
18295
18354
|
return after.info;
|
|
18296
18355
|
};
|
|
18297
|
-
var readJson2 = (path) => JSON.parse(
|
|
18298
|
-
var writeJson2 = (path, value) =>
|
|
18356
|
+
var readJson2 = (path) => JSON.parse(readFileSync8(path, "utf8"));
|
|
18357
|
+
var writeJson2 = (path, value) => writeFileSync6(path, `${JSON.stringify(value, null, "\t")}
|
|
18299
18358
|
`, "utf8");
|
|
18300
18359
|
var packageJsonFor = ({
|
|
18301
18360
|
name,
|
|
@@ -18307,8 +18366,8 @@ var packageJsonFor = ({
|
|
|
18307
18366
|
dependencies: { [PACKAGE_NAME]: dependencySpec }
|
|
18308
18367
|
});
|
|
18309
18368
|
var ensureRootManifest = ({ repoRoot }) => {
|
|
18310
|
-
const manifestPath =
|
|
18311
|
-
if (!
|
|
18369
|
+
const manifestPath = join9(repoRoot, "package.json");
|
|
18370
|
+
if (!existsSync9(manifestPath))
|
|
18312
18371
|
writeJson2(manifestPath, { name: "autumn", private: true, type: "module" });
|
|
18313
18372
|
return manifestPath;
|
|
18314
18373
|
};
|
|
@@ -18316,7 +18375,7 @@ var addDependency = ({
|
|
|
18316
18375
|
manifestPath,
|
|
18317
18376
|
dependencySpec
|
|
18318
18377
|
}) => {
|
|
18319
|
-
if (!
|
|
18378
|
+
if (!existsSync9(manifestPath))
|
|
18320
18379
|
return false;
|
|
18321
18380
|
const manifest = readJson2(manifestPath);
|
|
18322
18381
|
const deps = manifest.dependencies ?? {};
|
|
@@ -18330,11 +18389,11 @@ var addDependency = ({
|
|
|
18330
18389
|
return true;
|
|
18331
18390
|
};
|
|
18332
18391
|
var packageManager = ({ repoRoot }) => {
|
|
18333
|
-
if (
|
|
18392
|
+
if (existsSync9(join9(repoRoot, "bun.lock")) || existsSync9(join9(repoRoot, "bun.lockb")))
|
|
18334
18393
|
return "bun";
|
|
18335
|
-
if (
|
|
18394
|
+
if (existsSync9(join9(repoRoot, "pnpm-lock.yaml")))
|
|
18336
18395
|
return "pnpm";
|
|
18337
|
-
if (
|
|
18396
|
+
if (existsSync9(join9(repoRoot, "yarn.lock")))
|
|
18338
18397
|
return "yarn";
|
|
18339
18398
|
return "npm";
|
|
18340
18399
|
};
|
|
@@ -18373,9 +18432,9 @@ var runInit = async ({
|
|
|
18373
18432
|
defaultValue: DEFAULT_PACKAGE_DIR
|
|
18374
18433
|
});
|
|
18375
18434
|
configDir = resolve2(repoRoot, chosen);
|
|
18376
|
-
prompter.write(`${done(`Path ${
|
|
18435
|
+
prompter.write(`${done(`Path ${relative3(repoRoot, configDir) || "."}`)}
|
|
18377
18436
|
`);
|
|
18378
|
-
const existingName =
|
|
18437
|
+
const existingName = existsSync9(join9(configDir, "package.json")) ? readJson2(join9(configDir, "package.json")).name : undefined;
|
|
18379
18438
|
packageName = await ask({
|
|
18380
18439
|
prompter,
|
|
18381
18440
|
value: name ?? existingName,
|
|
@@ -18389,27 +18448,27 @@ var runInit = async ({
|
|
|
18389
18448
|
} else {
|
|
18390
18449
|
const found = resolveProject({ cwd }).configPath;
|
|
18391
18450
|
configDir = resolve2(repoRoot, path ?? (found === null ? DEFAULT_CONFIG_DIR : dirname5(found)));
|
|
18392
|
-
prompter.write(`${done(`Path ${
|
|
18451
|
+
prompter.write(`${done(`Path ${relative3(repoRoot, configDir) || "."}`)}
|
|
18393
18452
|
`);
|
|
18394
18453
|
}
|
|
18395
|
-
const configPath =
|
|
18454
|
+
const configPath = join9(configDir, "autumn.config.ts");
|
|
18396
18455
|
mkdirSync3(configDir, { recursive: true });
|
|
18397
18456
|
const wrote = [];
|
|
18398
18457
|
let dependencyAdded = false;
|
|
18399
|
-
const manifestPath =
|
|
18400
|
-
if (packageName !== undefined && !
|
|
18458
|
+
const manifestPath = join9(configDir, "package.json");
|
|
18459
|
+
if (packageName !== undefined && !existsSync9(manifestPath)) {
|
|
18401
18460
|
writeJson2(manifestPath, packageJsonFor({ name: packageName, dependencySpec }));
|
|
18402
|
-
wrote.push(`${
|
|
18461
|
+
wrote.push(`${relative3(repoRoot, manifestPath)}`);
|
|
18403
18462
|
dependencyAdded = true;
|
|
18404
18463
|
} else if (addDependency({
|
|
18405
|
-
manifestPath:
|
|
18464
|
+
manifestPath: existsSync9(manifestPath) ? manifestPath : ensureRootManifest({ repoRoot }),
|
|
18406
18465
|
dependencySpec
|
|
18407
18466
|
})) {
|
|
18408
18467
|
dependencyAdded = true;
|
|
18409
18468
|
prompter.write(`${done(`Added ${PACKAGE_NAME} to package.json`)}
|
|
18410
18469
|
`);
|
|
18411
18470
|
}
|
|
18412
|
-
if (!
|
|
18471
|
+
if (!existsSync9(configPath)) {
|
|
18413
18472
|
scaffoldConfig({ directory: configDir });
|
|
18414
18473
|
wrote.push("autumn.config.ts", "features.ts", "plans.ts", "rewards.ts");
|
|
18415
18474
|
}
|
|
@@ -18432,16 +18491,17 @@ var runInit = async ({
|
|
|
18432
18491
|
const count = pulled.appended.length + pulled.replaced.length + pulled.deleted.length;
|
|
18433
18492
|
prompter.write(`${done(count === 0 ? "Sandbox matches the config; nothing to pull" : `Pulled ${count} ${count === 1 ? "entry" : "entries"}`)}
|
|
18434
18493
|
`);
|
|
18435
|
-
const skillsDir =
|
|
18494
|
+
const skillsDir = join9(configDir, SKILLS_DIR_NAME);
|
|
18436
18495
|
const { written } = installSkills({ dir: skillsDir, write: () => {} });
|
|
18437
|
-
|
|
18496
|
+
ignoreBundledSkills({ repoRoot, configDir });
|
|
18497
|
+
prompter.write(`${done(`Skills: ${relative3(repoRoot, skillsDir)}/${written.join(", ")}`)}
|
|
18438
18498
|
`);
|
|
18439
18499
|
prompter.write(`
|
|
18440
18500
|
Next:
|
|
18441
18501
|
`);
|
|
18442
18502
|
prompter.write(`${hint(`${runner} atmn push`)} preview your catalog against the sandbox
|
|
18443
18503
|
`);
|
|
18444
|
-
prompter.write(`${hint(`npx skills add ${
|
|
18504
|
+
prompter.write(`${hint(`npx skills add ${relative3(repoRoot, skillsDir)} -y`)} make the skills visible to your agent
|
|
18445
18505
|
`);
|
|
18446
18506
|
return { repoRoot, configDir, configPath, org };
|
|
18447
18507
|
};
|
|
@@ -18888,33 +18948,33 @@ Wrote ${writtenKeys.join(" and ")} to ${envPath}
|
|
|
18888
18948
|
|
|
18889
18949
|
// src/actions/pull.ts
|
|
18890
18950
|
import {
|
|
18891
|
-
existsSync as
|
|
18951
|
+
existsSync as existsSync12,
|
|
18892
18952
|
mkdirSync as mkdirSync4,
|
|
18893
|
-
readFileSync as
|
|
18953
|
+
readFileSync as readFileSync13,
|
|
18894
18954
|
unlinkSync,
|
|
18895
|
-
writeFileSync as
|
|
18955
|
+
writeFileSync as writeFileSync9
|
|
18896
18956
|
} from "node:fs";
|
|
18897
|
-
import { basename as basename3, dirname as dirname11, join as
|
|
18957
|
+
import { basename as basename3, dirname as dirname11, join as join13 } from "node:path";
|
|
18898
18958
|
|
|
18899
18959
|
// src/config/loadConfig.ts
|
|
18900
18960
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
18901
|
-
import { existsSync as
|
|
18902
|
-
import { dirname as dirname7, join as
|
|
18961
|
+
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "node:fs";
|
|
18962
|
+
import { dirname as dirname7, join as join11 } from "node:path";
|
|
18903
18963
|
|
|
18904
18964
|
// src/surgery/fixtureLocation.ts
|
|
18905
|
-
import { readFileSync as
|
|
18906
|
-
import { dirname as dirname6, relative as
|
|
18965
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
18966
|
+
import { dirname as dirname6, relative as relative4 } from "node:path";
|
|
18907
18967
|
|
|
18908
18968
|
// src/actions/pull/listSourceFiles.ts
|
|
18909
18969
|
import { readdirSync } from "node:fs";
|
|
18910
|
-
import { join as
|
|
18970
|
+
import { join as join10 } from "node:path";
|
|
18911
18971
|
var listSourceFiles = ({
|
|
18912
18972
|
directory
|
|
18913
18973
|
}) => {
|
|
18914
18974
|
const files = [];
|
|
18915
18975
|
const walk = (dir) => {
|
|
18916
18976
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
18917
|
-
const path =
|
|
18977
|
+
const path = join10(dir, entry.name);
|
|
18918
18978
|
if (entry.isDirectory()) {
|
|
18919
18979
|
if (entry.name === "node_modules" || entry.name.startsWith("."))
|
|
18920
18980
|
continue;
|
|
@@ -19092,7 +19152,7 @@ var candidateFixtures = ({
|
|
|
19092
19152
|
});
|
|
19093
19153
|
});
|
|
19094
19154
|
};
|
|
19095
|
-
var
|
|
19155
|
+
var findFixtures = ({
|
|
19096
19156
|
source,
|
|
19097
19157
|
builder,
|
|
19098
19158
|
idField,
|
|
@@ -19101,6 +19161,7 @@ var findFixture = ({
|
|
|
19101
19161
|
allowDynamic = false
|
|
19102
19162
|
}) => {
|
|
19103
19163
|
const root = parse3(Lang.TypeScript, source).root();
|
|
19164
|
+
const matches = [];
|
|
19104
19165
|
for (const { node, object } of candidateFixtures({ root, builder })) {
|
|
19105
19166
|
const idValue = topLevelPairValue({ object, key: idField });
|
|
19106
19167
|
if (idValue === null || stringLiteralValue(idValue) !== id)
|
|
@@ -19109,10 +19170,11 @@ var findFixture = ({
|
|
|
19109
19170
|
continue;
|
|
19110
19171
|
if (where !== undefined && !satisfiesFixtureConstraints({ object, where }))
|
|
19111
19172
|
continue;
|
|
19112
|
-
|
|
19173
|
+
matches.push(node);
|
|
19113
19174
|
}
|
|
19114
|
-
return
|
|
19175
|
+
return matches;
|
|
19115
19176
|
};
|
|
19177
|
+
var findFixture = (params) => findFixtures(params)[0] ?? null;
|
|
19116
19178
|
var SIMPLE_ESCAPES = {
|
|
19117
19179
|
n: `
|
|
19118
19180
|
`,
|
|
@@ -19170,7 +19232,7 @@ var topLevelPairValue = ({
|
|
|
19170
19232
|
if (member.kind() !== "pair")
|
|
19171
19233
|
continue;
|
|
19172
19234
|
const [name, value] = member.namedChildren();
|
|
19173
|
-
if (name
|
|
19235
|
+
if (name !== undefined && (name.text() === key || stringLiteralValue(name) === key) && value !== undefined)
|
|
19174
19236
|
return value;
|
|
19175
19237
|
}
|
|
19176
19238
|
return null;
|
|
@@ -19196,7 +19258,10 @@ var satisfiesConstraint = ({
|
|
|
19196
19258
|
object,
|
|
19197
19259
|
constraint
|
|
19198
19260
|
}) => {
|
|
19199
|
-
const pair = object.children().find((child) =>
|
|
19261
|
+
const pair = object.children().find((child) => {
|
|
19262
|
+
const key = child.field("key");
|
|
19263
|
+
return child.kind() === "pair" && key !== null && (key.text() === constraint.field || stringLiteralValue(key) === constraint.field);
|
|
19264
|
+
});
|
|
19200
19265
|
if (pair === undefined)
|
|
19201
19266
|
return constraint.absentMeans === constraint.equals;
|
|
19202
19267
|
const value = pair.namedChildren()[1];
|
|
@@ -19212,7 +19277,8 @@ var locateFixture = ({
|
|
|
19212
19277
|
id,
|
|
19213
19278
|
internalId,
|
|
19214
19279
|
where,
|
|
19215
|
-
allowDynamic = false
|
|
19280
|
+
allowDynamic = false,
|
|
19281
|
+
requireUnique = false
|
|
19216
19282
|
}) => {
|
|
19217
19283
|
const others = [...files.keys()].filter((file) => file !== configPath);
|
|
19218
19284
|
const ordered = [configPath, ...others];
|
|
@@ -19222,21 +19288,37 @@ var locateFixture = ({
|
|
|
19222
19288
|
];
|
|
19223
19289
|
const shapes = Array.isArray(builder) ? builder : [builder];
|
|
19224
19290
|
for (const attempt of attempts) {
|
|
19291
|
+
const matches = new Map;
|
|
19225
19292
|
for (const file of ordered) {
|
|
19226
19293
|
const source = files.get(file);
|
|
19227
19294
|
if (source === undefined)
|
|
19228
19295
|
continue;
|
|
19229
19296
|
for (const shape of shapes) {
|
|
19230
|
-
const
|
|
19297
|
+
const nodes = findFixtures({
|
|
19231
19298
|
source,
|
|
19232
19299
|
builder: shape,
|
|
19233
19300
|
allowDynamic,
|
|
19234
19301
|
...attempt
|
|
19235
19302
|
});
|
|
19236
|
-
|
|
19237
|
-
|
|
19303
|
+
for (const node of nodes) {
|
|
19304
|
+
const located = { file, source, node, builder: shape, ...attempt };
|
|
19305
|
+
if (!requireUnique)
|
|
19306
|
+
return located;
|
|
19307
|
+
const range = node.range();
|
|
19308
|
+
const key = JSON.stringify([
|
|
19309
|
+
file,
|
|
19310
|
+
range.start.index,
|
|
19311
|
+
range.end.index
|
|
19312
|
+
]);
|
|
19313
|
+
matches.set(key, located);
|
|
19314
|
+
if (matches.size > 1)
|
|
19315
|
+
return null;
|
|
19316
|
+
}
|
|
19238
19317
|
}
|
|
19239
19318
|
}
|
|
19319
|
+
const match = matches.values().next().value;
|
|
19320
|
+
if (match !== undefined)
|
|
19321
|
+
return match;
|
|
19240
19322
|
}
|
|
19241
19323
|
return null;
|
|
19242
19324
|
};
|
|
@@ -19250,16 +19332,16 @@ var fixtureLocation = ({
|
|
|
19250
19332
|
}) => {
|
|
19251
19333
|
const directory = dirname6(configPath);
|
|
19252
19334
|
const files = new Map;
|
|
19253
|
-
files.set(configPath,
|
|
19335
|
+
files.set(configPath, readFileSync9(configPath, "utf8"));
|
|
19254
19336
|
for (const file of listSourceFiles({ directory })) {
|
|
19255
19337
|
if (!files.has(file))
|
|
19256
|
-
files.set(file,
|
|
19338
|
+
files.set(file, readFileSync9(file, "utf8"));
|
|
19257
19339
|
}
|
|
19258
19340
|
const located = locateFixture({ configPath, files, builder, idField, id });
|
|
19259
19341
|
if (located === null)
|
|
19260
19342
|
return null;
|
|
19261
19343
|
return {
|
|
19262
|
-
file:
|
|
19344
|
+
file: relative4(directory, located.file),
|
|
19263
19345
|
line: located.node.range().start.line + 1
|
|
19264
19346
|
};
|
|
19265
19347
|
};
|
|
@@ -19300,8 +19382,8 @@ Run \`${configPackageName()} init\` to create one, or pass -c <dir>.`);
|
|
|
19300
19382
|
var findConfigPath = ({ dirs }) => {
|
|
19301
19383
|
for (const dir of dirs) {
|
|
19302
19384
|
for (const filename of CONFIG_FILENAMES2) {
|
|
19303
|
-
const path =
|
|
19304
|
-
if (
|
|
19385
|
+
const path = join11(dir, filename);
|
|
19386
|
+
if (existsSync10(path))
|
|
19305
19387
|
return path;
|
|
19306
19388
|
}
|
|
19307
19389
|
}
|
|
@@ -19364,10 +19446,10 @@ var loadConfig = async ({
|
|
|
19364
19446
|
dirs,
|
|
19365
19447
|
configPath
|
|
19366
19448
|
}) => {
|
|
19367
|
-
const path = configPath !== undefined ?
|
|
19449
|
+
const path = configPath !== undefined ? existsSync10(configPath) ? configPath : null : findConfigPath({ dirs });
|
|
19368
19450
|
if (!path)
|
|
19369
19451
|
throw new ConfigNotFoundError(configPath ? [configPath] : dirs);
|
|
19370
|
-
if (isLegacyConfigText({ text:
|
|
19452
|
+
if (isLegacyConfigText({ text: readFileSync10(path, "utf8") })) {
|
|
19371
19453
|
throw new LegacyConfigError({ path });
|
|
19372
19454
|
}
|
|
19373
19455
|
let module;
|
|
@@ -19417,7 +19499,7 @@ var looksLikeV2Config = ({
|
|
|
19417
19499
|
};
|
|
19418
19500
|
|
|
19419
19501
|
// src/project/chooseConfigDir.ts
|
|
19420
|
-
import { relative as
|
|
19502
|
+
import { relative as relative5, resolve as resolve3 } from "node:path";
|
|
19421
19503
|
var defaultConfigDirName = ({ cwd }) => findRepoLayout({ cwd }).hasWorkspaces ? "packages/autumn/" : "autumn/";
|
|
19422
19504
|
var configFiles = ["autumn.config.ts", ...Object.keys(COLLECTION_FILES)];
|
|
19423
19505
|
var chooseConfigDir = async ({
|
|
@@ -19438,7 +19520,7 @@ var chooseConfigDir = async ({
|
|
|
19438
19520
|
defaultValue: fallback
|
|
19439
19521
|
});
|
|
19440
19522
|
const configDir = resolve3(repoRoot, chosen);
|
|
19441
|
-
prompter.write(`${done(`Path ${
|
|
19523
|
+
prompter.write(`${done(`Path ${relative5(repoRoot, configDir) || "."}`)}
|
|
19442
19524
|
`);
|
|
19443
19525
|
return { configDir, repoRoot };
|
|
19444
19526
|
};
|
|
@@ -19784,9 +19866,496 @@ var emitFixture = ({
|
|
|
19784
19866
|
`);
|
|
19785
19867
|
};
|
|
19786
19868
|
|
|
19787
|
-
// src/
|
|
19869
|
+
// src/generated/mappingAssignments.ts
|
|
19870
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19871
|
+
var valueAt = ({
|
|
19872
|
+
value,
|
|
19873
|
+
path
|
|
19874
|
+
}) => {
|
|
19875
|
+
for (const key of path) {
|
|
19876
|
+
if (typeof value === "symbol")
|
|
19877
|
+
return value;
|
|
19878
|
+
value = isRecord(value) ? value[key] : undefined;
|
|
19879
|
+
}
|
|
19880
|
+
return value;
|
|
19881
|
+
};
|
|
19882
|
+
var mappingIdentityOf = ({
|
|
19883
|
+
value,
|
|
19884
|
+
identity
|
|
19885
|
+
}) => {
|
|
19886
|
+
const values = [];
|
|
19887
|
+
for (const component of identity.components) {
|
|
19888
|
+
let selected;
|
|
19889
|
+
for (const path of component.paths) {
|
|
19890
|
+
selected = valueAt({ value, path: path.split(".") });
|
|
19891
|
+
if (selected !== undefined && selected !== null)
|
|
19892
|
+
break;
|
|
19893
|
+
}
|
|
19894
|
+
if (selected === undefined || selected === null) {
|
|
19895
|
+
selected = component.defaultWhen && values[component.defaultWhen.component] ? component.defaultWhen.value : component.default;
|
|
19896
|
+
}
|
|
19897
|
+
if (typeof selected !== "string" && typeof selected !== "number")
|
|
19898
|
+
return;
|
|
19899
|
+
values.push(selected);
|
|
19900
|
+
}
|
|
19901
|
+
return JSON.stringify(values);
|
|
19902
|
+
};
|
|
19903
|
+
var hasMappings = ({
|
|
19904
|
+
node,
|
|
19905
|
+
value,
|
|
19906
|
+
local = false
|
|
19907
|
+
}) => {
|
|
19908
|
+
if (value === undefined || value === null)
|
|
19909
|
+
return false;
|
|
19910
|
+
if (node.mapping)
|
|
19911
|
+
return true;
|
|
19912
|
+
const items = node.items;
|
|
19913
|
+
if (items)
|
|
19914
|
+
return Array.isArray(value) && value.some((entry) => hasMappings({ node: items, value: entry, local }));
|
|
19915
|
+
return Object.entries(node.properties ?? {}).some(([key, child]) => hasMappings({
|
|
19916
|
+
node: child,
|
|
19917
|
+
value: valueAt({
|
|
19918
|
+
value,
|
|
19919
|
+
path: local ? [key] : child.sourcePath ?? [key]
|
|
19920
|
+
}),
|
|
19921
|
+
local
|
|
19922
|
+
}));
|
|
19923
|
+
};
|
|
19924
|
+
var mappingAssignments = ({
|
|
19925
|
+
projection,
|
|
19926
|
+
local,
|
|
19927
|
+
remote
|
|
19928
|
+
}) => {
|
|
19929
|
+
const assignments = [];
|
|
19930
|
+
const errors = [];
|
|
19931
|
+
const visit = ({
|
|
19932
|
+
node,
|
|
19933
|
+
localValue,
|
|
19934
|
+
remoteValue,
|
|
19935
|
+
path
|
|
19936
|
+
}) => {
|
|
19937
|
+
if (node.mapping) {
|
|
19938
|
+
if (remoteValue === undefined || remoteValue === null) {
|
|
19939
|
+
if (localValue !== undefined)
|
|
19940
|
+
assignments.push({ path, text: null });
|
|
19941
|
+
return;
|
|
19942
|
+
}
|
|
19943
|
+
assignments.push({ path, text: JSON.stringify(remoteValue) });
|
|
19944
|
+
return;
|
|
19945
|
+
}
|
|
19946
|
+
if (!hasMappings({ node, value: remoteValue }) && !hasMappings({ node, value: localValue, local: true }))
|
|
19947
|
+
return;
|
|
19948
|
+
if (remoteValue === undefined || remoteValue === null)
|
|
19949
|
+
return;
|
|
19950
|
+
if (typeof localValue === "symbol") {
|
|
19951
|
+
errors.push(`${path.join(".")}: cannot address a computed value`);
|
|
19952
|
+
return;
|
|
19953
|
+
}
|
|
19954
|
+
if (localValue === undefined || localValue === null) {
|
|
19955
|
+
errors.push(`${path.join(".")}: mapping container is not stated in the fixture`);
|
|
19956
|
+
return;
|
|
19957
|
+
}
|
|
19958
|
+
if (node.items) {
|
|
19959
|
+
if (!Array.isArray(localValue) || !Array.isArray(remoteValue) || !node.identity) {
|
|
19960
|
+
errors.push(`${path.join(".")}: array identity is unavailable`);
|
|
19961
|
+
return;
|
|
19962
|
+
}
|
|
19963
|
+
const identity = node.identity;
|
|
19964
|
+
const localKeys = localValue.map((value) => mappingIdentityOf({ value, identity }));
|
|
19965
|
+
const remoteKeys = remoteValue.map((value) => valueAt({ value, path: identity.responseField.split(".") }));
|
|
19966
|
+
for (const [index, value] of localValue.entries()) {
|
|
19967
|
+
const key = localKeys[index];
|
|
19968
|
+
const matches = remoteKeys.flatMap((candidate, position) => candidate === key ? [position] : []);
|
|
19969
|
+
const match = matches[0];
|
|
19970
|
+
if (key === undefined || match === undefined || localKeys.filter((candidate) => candidate === key).length !== 1 || matches.length !== 1) {
|
|
19971
|
+
errors.push(`${[...path, index].join(".")}: no unique server identity match`);
|
|
19972
|
+
continue;
|
|
19973
|
+
}
|
|
19974
|
+
visit({
|
|
19975
|
+
node: node.items,
|
|
19976
|
+
localValue: value,
|
|
19977
|
+
remoteValue: remoteValue[match],
|
|
19978
|
+
path: [...path, index]
|
|
19979
|
+
});
|
|
19980
|
+
}
|
|
19981
|
+
return;
|
|
19982
|
+
}
|
|
19983
|
+
for (const [key, child] of Object.entries(node.properties ?? {})) {
|
|
19984
|
+
visit({
|
|
19985
|
+
node: child,
|
|
19986
|
+
localValue: valueAt({ value: localValue, path: [key] }),
|
|
19987
|
+
remoteValue: valueAt({
|
|
19988
|
+
value: remoteValue,
|
|
19989
|
+
path: child.sourcePath ?? [key]
|
|
19990
|
+
}),
|
|
19991
|
+
path: [...path, key]
|
|
19992
|
+
});
|
|
19993
|
+
}
|
|
19994
|
+
};
|
|
19995
|
+
visit({ node: projection, localValue: local, remoteValue: remote, path: [] });
|
|
19996
|
+
return { assignments, errors };
|
|
19997
|
+
};
|
|
19998
|
+
|
|
19999
|
+
// src/surgery/patchFixturePaths.ts
|
|
20000
|
+
import { isDeepStrictEqual } from "node:util";
|
|
19788
20001
|
import { Lang as Lang2, parse as parse4 } from "@ast-grep/napi";
|
|
19789
20002
|
|
|
20003
|
+
// src/surgery/appendPropertyEdit.ts
|
|
20004
|
+
var isMember = (child) => child.kind() === "pair" || child.kind() === "spread_element" || child.kind() === "shorthand_property_identifier";
|
|
20005
|
+
var appendPropertyEdit = ({
|
|
20006
|
+
source,
|
|
20007
|
+
object,
|
|
20008
|
+
pair
|
|
20009
|
+
}) => {
|
|
20010
|
+
const closing = object.range().end.index - 1;
|
|
20011
|
+
const multiline = source.slice(object.range().start.index, closing).includes(`
|
|
20012
|
+
`);
|
|
20013
|
+
const members = object.children().filter(isMember);
|
|
20014
|
+
const last = members[members.length - 1];
|
|
20015
|
+
if (last === undefined) {
|
|
20016
|
+
return multiline ? {
|
|
20017
|
+
startPos: lineStartOf(source, closing),
|
|
20018
|
+
endPos: lineStartOf(source, closing),
|
|
20019
|
+
insertedText: `${leadingIndentOfLine(source, object.range().start.index)} ${pair},
|
|
20020
|
+
`
|
|
20021
|
+
} : {
|
|
20022
|
+
startPos: object.range().start.index + 1,
|
|
20023
|
+
endPos: closing,
|
|
20024
|
+
insertedText: ` ${pair} `
|
|
20025
|
+
};
|
|
20026
|
+
}
|
|
20027
|
+
const lastEnd = last.range().end.index;
|
|
20028
|
+
const between = source.slice(lastEnd, closing);
|
|
20029
|
+
const trailingComma = between.trimStart().startsWith(",");
|
|
20030
|
+
const afterComma = trailingComma ? lastEnd + between.indexOf(",") + 1 : lastEnd;
|
|
20031
|
+
if (multiline) {
|
|
20032
|
+
const indent = leadingIndentOfLine(source, last.range().start.index);
|
|
20033
|
+
return {
|
|
20034
|
+
startPos: afterComma,
|
|
20035
|
+
endPos: afterComma,
|
|
20036
|
+
insertedText: trailingComma ? `
|
|
20037
|
+
${indent}${pair},` : `,
|
|
20038
|
+
${indent}${pair},`
|
|
20039
|
+
};
|
|
20040
|
+
}
|
|
20041
|
+
return {
|
|
20042
|
+
startPos: afterComma,
|
|
20043
|
+
endPos: afterComma,
|
|
20044
|
+
insertedText: trailingComma ? ` ${pair},` : `, ${pair}`
|
|
20045
|
+
};
|
|
20046
|
+
};
|
|
20047
|
+
var holdsSpread = ({ object }) => object.children().some((child) => child.kind() === "spread_element");
|
|
20048
|
+
|
|
20049
|
+
// src/surgery/readFixtureValue.ts
|
|
20050
|
+
var DYNAMIC_VALUE = Symbol("dynamic-fixture-value");
|
|
20051
|
+
var fixtureKeyOf = ({ node }) => {
|
|
20052
|
+
if (node.kind() === "property_identifier" || node.kind() === "shorthand_property_identifier")
|
|
20053
|
+
return node.text();
|
|
20054
|
+
return stringLiteralValue(node);
|
|
20055
|
+
};
|
|
20056
|
+
var fixtureArrayElements = ({
|
|
20057
|
+
node
|
|
20058
|
+
}) => {
|
|
20059
|
+
const elements = [];
|
|
20060
|
+
let expectsElement = true;
|
|
20061
|
+
for (const child of node.children()) {
|
|
20062
|
+
const kind = child.kind();
|
|
20063
|
+
if (kind === "[" || kind === "]" || kind === "comment")
|
|
20064
|
+
continue;
|
|
20065
|
+
if (kind === ",") {
|
|
20066
|
+
if (expectsElement)
|
|
20067
|
+
return null;
|
|
20068
|
+
expectsElement = true;
|
|
20069
|
+
continue;
|
|
20070
|
+
}
|
|
20071
|
+
if (!expectsElement || kind === "spread_element")
|
|
20072
|
+
return null;
|
|
20073
|
+
elements.push(child);
|
|
20074
|
+
expectsElement = false;
|
|
20075
|
+
}
|
|
20076
|
+
return elements;
|
|
20077
|
+
};
|
|
20078
|
+
var readFixtureValue = ({
|
|
20079
|
+
node,
|
|
20080
|
+
builders = []
|
|
20081
|
+
}) => {
|
|
20082
|
+
const kind = node.kind();
|
|
20083
|
+
if (kind === "call_expression" && builders.includes(node.field("function")?.text() ?? "")) {
|
|
20084
|
+
const args = node.field("arguments")?.namedChildren().filter((child) => child.kind() !== "comment");
|
|
20085
|
+
return args?.length === 1 && args[0]?.kind() === "object" ? readFixtureValue({ node: args[0], builders }) : DYNAMIC_VALUE;
|
|
20086
|
+
}
|
|
20087
|
+
if (kind === "string")
|
|
20088
|
+
return stringLiteralValue(node) ?? DYNAMIC_VALUE;
|
|
20089
|
+
if (kind === "true")
|
|
20090
|
+
return true;
|
|
20091
|
+
if (kind === "false")
|
|
20092
|
+
return false;
|
|
20093
|
+
if (kind === "null")
|
|
20094
|
+
return null;
|
|
20095
|
+
if (kind === "number" || kind === "unary_expression" && /^[+-]\s*[\d.]/.test(node.text())) {
|
|
20096
|
+
const value2 = Number(node.text().replaceAll("_", "").replace(/\s/g, ""));
|
|
20097
|
+
return Number.isFinite(value2) ? value2 : DYNAMIC_VALUE;
|
|
20098
|
+
}
|
|
20099
|
+
if (kind === "array") {
|
|
20100
|
+
const elements = fixtureArrayElements({ node });
|
|
20101
|
+
return elements === null ? DYNAMIC_VALUE : elements.map((element) => readFixtureValue({ node: element, builders }));
|
|
20102
|
+
}
|
|
20103
|
+
if (kind !== "object")
|
|
20104
|
+
return DYNAMIC_VALUE;
|
|
20105
|
+
const value = {};
|
|
20106
|
+
for (const member of node.namedChildren()) {
|
|
20107
|
+
if (member.kind() === "comment")
|
|
20108
|
+
continue;
|
|
20109
|
+
const shorthand = member.kind() === "shorthand_property_identifier";
|
|
20110
|
+
if (member.kind() !== "pair" && !shorthand)
|
|
20111
|
+
return DYNAMIC_VALUE;
|
|
20112
|
+
const keyNode = shorthand ? member : member.field("key");
|
|
20113
|
+
const key = keyNode === null ? null : fixtureKeyOf({ node: keyNode });
|
|
20114
|
+
if (key === null || Object.getOwnPropertyDescriptor(value, key) !== undefined)
|
|
20115
|
+
return DYNAMIC_VALUE;
|
|
20116
|
+
const child = member.field("value");
|
|
20117
|
+
Object.defineProperty(value, key, {
|
|
20118
|
+
value: child === null ? DYNAMIC_VALUE : readFixtureValue({ node: child, builders }),
|
|
20119
|
+
enumerable: true
|
|
20120
|
+
});
|
|
20121
|
+
}
|
|
20122
|
+
return value;
|
|
20123
|
+
};
|
|
20124
|
+
|
|
20125
|
+
// src/surgery/patchFixturePaths.ts
|
|
20126
|
+
var isDynamic = (value) => {
|
|
20127
|
+
if (value === DYNAMIC_VALUE)
|
|
20128
|
+
return true;
|
|
20129
|
+
if (value === null || typeof value !== "object")
|
|
20130
|
+
return false;
|
|
20131
|
+
return Object.values(value).some(isDynamic);
|
|
20132
|
+
};
|
|
20133
|
+
var matchesLiteral = ({
|
|
20134
|
+
value,
|
|
20135
|
+
text
|
|
20136
|
+
}) => {
|
|
20137
|
+
const root = parse4(Lang2.TypeScript, `const value = (${text});`).root();
|
|
20138
|
+
if (root.find({ rule: { kind: "ERROR" } }) !== null)
|
|
20139
|
+
return false;
|
|
20140
|
+
const expression = root.find({ rule: { kind: "variable_declarator" } })?.field("value");
|
|
20141
|
+
if (expression?.kind() !== "parenthesized_expression")
|
|
20142
|
+
return false;
|
|
20143
|
+
const literal = expression.namedChildren().filter((node) => node.kind() !== "comment");
|
|
20144
|
+
if (literal.length !== 1 || literal[0] === undefined)
|
|
20145
|
+
return false;
|
|
20146
|
+
const proposed = readFixtureValue({ node: literal[0] });
|
|
20147
|
+
return !isDynamic(proposed) && isDeepStrictEqual(value, proposed);
|
|
20148
|
+
};
|
|
20149
|
+
var removeMemberEdits = ({ member }) => {
|
|
20150
|
+
const siblings = member.parent()?.children() ?? [];
|
|
20151
|
+
const index = siblings.findIndex((sibling) => sibling.range().start.index === member.range().start.index);
|
|
20152
|
+
const next = siblings.slice(index + 1).find((sibling) => sibling.kind() !== "comment");
|
|
20153
|
+
const previous = siblings.slice(0, index).reverse().find((sibling) => sibling.kind() !== "comment");
|
|
20154
|
+
const comma = next?.kind() === "," ? next : previous?.kind() === "," ? previous : null;
|
|
20155
|
+
return [member, ...comma === null ? [] : [comma]].map((node) => ({
|
|
20156
|
+
startPos: node.range().start.index,
|
|
20157
|
+
endPos: node.range().end.index,
|
|
20158
|
+
insertedText: ""
|
|
20159
|
+
}));
|
|
20160
|
+
};
|
|
20161
|
+
var pathEdits = ({
|
|
20162
|
+
source,
|
|
20163
|
+
object,
|
|
20164
|
+
path,
|
|
20165
|
+
text,
|
|
20166
|
+
builders
|
|
20167
|
+
}) => {
|
|
20168
|
+
let current = object;
|
|
20169
|
+
for (let index = 0;index < path.length; index += 1) {
|
|
20170
|
+
if (current.kind() === "call_expression" && builders.includes(current.field("function")?.text() ?? "")) {
|
|
20171
|
+
const args = current.field("arguments")?.namedChildren().filter((child) => child.kind() !== "comment");
|
|
20172
|
+
if (args?.length !== 1 || args[0]?.kind() !== "object")
|
|
20173
|
+
return "dynamic-value";
|
|
20174
|
+
current = args[0];
|
|
20175
|
+
}
|
|
20176
|
+
const segment = path[index];
|
|
20177
|
+
const last = index === path.length - 1;
|
|
20178
|
+
let member;
|
|
20179
|
+
let value;
|
|
20180
|
+
if (typeof segment === "number") {
|
|
20181
|
+
if (current.kind() !== "array" || !Number.isSafeInteger(segment) || segment < 0)
|
|
20182
|
+
return "invalid-array-path";
|
|
20183
|
+
const elements = fixtureArrayElements({ node: current });
|
|
20184
|
+
if (elements === null)
|
|
20185
|
+
return "dynamic-array";
|
|
20186
|
+
value = elements[segment];
|
|
20187
|
+
if (value === undefined)
|
|
20188
|
+
return "missing-array-element";
|
|
20189
|
+
if (last && text === null)
|
|
20190
|
+
return "array-element-removal";
|
|
20191
|
+
} else {
|
|
20192
|
+
if (current.kind() !== "object")
|
|
20193
|
+
return "non-object-container";
|
|
20194
|
+
if (readFixtureValue({ node: current }) === DYNAMIC_VALUE)
|
|
20195
|
+
return "ambiguous-object";
|
|
20196
|
+
member = current.namedChildren().find((child) => {
|
|
20197
|
+
const key = child.kind() === "pair" ? child.field("key") : child;
|
|
20198
|
+
return key !== null && fixtureKeyOf({ node: key }) === segment;
|
|
20199
|
+
});
|
|
20200
|
+
if (member === undefined) {
|
|
20201
|
+
if (text === null)
|
|
20202
|
+
return [];
|
|
20203
|
+
const remaining = path.slice(index + 1);
|
|
20204
|
+
if (remaining.some((key) => typeof key === "number"))
|
|
20205
|
+
return "missing-array-element";
|
|
20206
|
+
let inserted = text;
|
|
20207
|
+
for (const key of remaining.reverse())
|
|
20208
|
+
inserted = `{ ${JSON.stringify(key)}: ${inserted} }`;
|
|
20209
|
+
const pair = `${JSON.stringify(segment)}: ${inserted}`;
|
|
20210
|
+
const members = current.namedChildren().filter((child) => child.kind() !== "comment");
|
|
20211
|
+
if (members.length === 0) {
|
|
20212
|
+
const closing = current.range().end.index - 1;
|
|
20213
|
+
return [
|
|
20214
|
+
{ startPos: closing, endPos: closing, insertedText: ` ${pair} ` }
|
|
20215
|
+
];
|
|
20216
|
+
}
|
|
20217
|
+
return [appendPropertyEdit({ source, object: current, pair })];
|
|
20218
|
+
}
|
|
20219
|
+
value = member.field("value");
|
|
20220
|
+
}
|
|
20221
|
+
if (value == null)
|
|
20222
|
+
return "dynamic-value";
|
|
20223
|
+
if (!last) {
|
|
20224
|
+
current = value;
|
|
20225
|
+
continue;
|
|
20226
|
+
}
|
|
20227
|
+
const currentValue = readFixtureValue({ node: value });
|
|
20228
|
+
if (isDynamic(currentValue))
|
|
20229
|
+
return "dynamic-value";
|
|
20230
|
+
if (text === null)
|
|
20231
|
+
return member === undefined ? "array-element-removal" : removeMemberEdits({ member });
|
|
20232
|
+
if (matchesLiteral({ value: currentValue, text }))
|
|
20233
|
+
return [];
|
|
20234
|
+
return [
|
|
20235
|
+
{
|
|
20236
|
+
startPos: value.range().start.index,
|
|
20237
|
+
endPos: value.range().end.index,
|
|
20238
|
+
insertedText: text
|
|
20239
|
+
}
|
|
20240
|
+
];
|
|
20241
|
+
}
|
|
20242
|
+
return "empty-path";
|
|
20243
|
+
};
|
|
20244
|
+
var patchFixturePaths = ({
|
|
20245
|
+
source,
|
|
20246
|
+
builder,
|
|
20247
|
+
idField,
|
|
20248
|
+
id,
|
|
20249
|
+
where,
|
|
20250
|
+
assignments,
|
|
20251
|
+
builders = []
|
|
20252
|
+
}) => {
|
|
20253
|
+
const selector = { builder, idField, id, where, allowDynamic: true };
|
|
20254
|
+
const initial = findFixtures({ source, ...selector });
|
|
20255
|
+
if (initial.length === 0)
|
|
20256
|
+
return null;
|
|
20257
|
+
const skipped = [];
|
|
20258
|
+
for (const assignment of assignments) {
|
|
20259
|
+
const matches = findFixtures({ source, ...selector });
|
|
20260
|
+
const match = matches[0];
|
|
20261
|
+
const object = matches.length === 1 && match !== undefined ? fixtureObjectOf(match) : null;
|
|
20262
|
+
const edits = object === null ? "ambiguous-fixture" : pathEdits({ source, object, builders, ...assignment });
|
|
20263
|
+
if (typeof edits === "string") {
|
|
20264
|
+
skipped.push({ path: assignment.path, reason: edits });
|
|
20265
|
+
continue;
|
|
20266
|
+
}
|
|
20267
|
+
source = parse4(Lang2.TypeScript, source).root().commitEdits(edits);
|
|
20268
|
+
}
|
|
20269
|
+
return { source, skipped };
|
|
20270
|
+
};
|
|
20271
|
+
|
|
20272
|
+
// src/actions/pull/applyMappings.ts
|
|
20273
|
+
var applyMappings = ({
|
|
20274
|
+
catalog,
|
|
20275
|
+
configPath,
|
|
20276
|
+
files
|
|
20277
|
+
}) => {
|
|
20278
|
+
const replaced = [];
|
|
20279
|
+
const unlocated = [];
|
|
20280
|
+
const builders = Object.values(NESTED_FIXTURES).map(({ builder }) => builder);
|
|
20281
|
+
for (const [collection, collectionSpec] of Object.entries(COLLECTIONS)) {
|
|
20282
|
+
const rows = catalog[collection];
|
|
20283
|
+
if (!collectionSpec.pull || !Array.isArray(rows))
|
|
20284
|
+
continue;
|
|
20285
|
+
for (const entry of rows) {
|
|
20286
|
+
const { spec, row } = resolveBranch({ spec: collectionSpec, row: entry });
|
|
20287
|
+
const id = row[spec.responseIdField];
|
|
20288
|
+
if (!spec.mappings || typeof id !== "string" || row.archived === true)
|
|
20289
|
+
continue;
|
|
20290
|
+
const key = spec.versioned ? `${id}@${row.versionSlug ?? "v1"}` : id;
|
|
20291
|
+
const located = locateFixture({
|
|
20292
|
+
configPath,
|
|
20293
|
+
files,
|
|
20294
|
+
builder: spec.builder,
|
|
20295
|
+
idField: spec.idField,
|
|
20296
|
+
id,
|
|
20297
|
+
internalId: typeof row.internalId === "string" ? row.internalId : undefined,
|
|
20298
|
+
where: spec.versioned ? [
|
|
20299
|
+
{
|
|
20300
|
+
field: "versionSlug",
|
|
20301
|
+
equals: typeof row.versionSlug === "string" ? row.versionSlug : "v1",
|
|
20302
|
+
absentMeans: "v1"
|
|
20303
|
+
}
|
|
20304
|
+
] : undefined,
|
|
20305
|
+
allowDynamic: true,
|
|
20306
|
+
requireUnique: true
|
|
20307
|
+
});
|
|
20308
|
+
if (!located) {
|
|
20309
|
+
unlocated.push({
|
|
20310
|
+
collection,
|
|
20311
|
+
id: key,
|
|
20312
|
+
action: "cannot locate the fixture to write processor mappings"
|
|
20313
|
+
});
|
|
20314
|
+
continue;
|
|
20315
|
+
}
|
|
20316
|
+
const planned = mappingAssignments({
|
|
20317
|
+
projection: spec.mappings,
|
|
20318
|
+
local: readFixtureValue({
|
|
20319
|
+
node: located.node,
|
|
20320
|
+
builders: [spec.builder, ...builders]
|
|
20321
|
+
}),
|
|
20322
|
+
remote: row
|
|
20323
|
+
});
|
|
20324
|
+
if (planned.errors.length) {
|
|
20325
|
+
unlocated.push(...planned.errors.map((action) => ({ collection, id: key, action })));
|
|
20326
|
+
continue;
|
|
20327
|
+
}
|
|
20328
|
+
if (!planned.assignments.length)
|
|
20329
|
+
continue;
|
|
20330
|
+
const patched = patchFixturePaths({
|
|
20331
|
+
source: located.source,
|
|
20332
|
+
builder: located.builder,
|
|
20333
|
+
idField: located.idField,
|
|
20334
|
+
id: located.id,
|
|
20335
|
+
where: located.where,
|
|
20336
|
+
builders,
|
|
20337
|
+
assignments: planned.assignments
|
|
20338
|
+
});
|
|
20339
|
+
if (!patched || patched.skipped.length) {
|
|
20340
|
+
unlocated.push({
|
|
20341
|
+
collection,
|
|
20342
|
+
id: key,
|
|
20343
|
+
action: "cannot safely splice processor mappings into a computed or ambiguous value"
|
|
20344
|
+
});
|
|
20345
|
+
continue;
|
|
20346
|
+
}
|
|
20347
|
+
if (patched.source === located.source)
|
|
20348
|
+
continue;
|
|
20349
|
+
files.set(located.file, patched.source);
|
|
20350
|
+
replaced.push(key);
|
|
20351
|
+
}
|
|
20352
|
+
}
|
|
20353
|
+
return { replaced, unlocated };
|
|
20354
|
+
};
|
|
20355
|
+
|
|
20356
|
+
// src/surgery/appendToBinding.ts
|
|
20357
|
+
import { Lang as Lang3, parse as parse5 } from "@ast-grep/napi";
|
|
20358
|
+
|
|
19790
20359
|
// src/surgery/appendToArray.ts
|
|
19791
20360
|
var appendElementToArray = ({
|
|
19792
20361
|
source,
|
|
@@ -19887,7 +20456,7 @@ var appendToBinding = ({
|
|
|
19887
20456
|
name,
|
|
19888
20457
|
text
|
|
19889
20458
|
}) => {
|
|
19890
|
-
const root =
|
|
20459
|
+
const root = parse5(Lang3.TypeScript, source).root();
|
|
19891
20460
|
const array = findArrayBinding({ root, name });
|
|
19892
20461
|
if (array === null)
|
|
19893
20462
|
return null;
|
|
@@ -19895,13 +20464,13 @@ var appendToBinding = ({
|
|
|
19895
20464
|
};
|
|
19896
20465
|
|
|
19897
20466
|
// src/surgery/appendToCollection.ts
|
|
19898
|
-
import { Lang as
|
|
20467
|
+
import { Lang as Lang4, parse as parse6 } from "@ast-grep/napi";
|
|
19899
20468
|
var appendToCollection = ({
|
|
19900
20469
|
source,
|
|
19901
20470
|
collection,
|
|
19902
20471
|
text
|
|
19903
20472
|
}) => {
|
|
19904
|
-
const root =
|
|
20473
|
+
const root = parse6(Lang4.TypeScript, source).root();
|
|
19905
20474
|
const anchor = root.find(`atmn({ $$$, ${collection}: [$$$ITEMS], $$$ })`) ?? root.find(`atmn({ ${collection}: [$$$ITEMS] })`);
|
|
19906
20475
|
if (anchor === null)
|
|
19907
20476
|
return null;
|
|
@@ -19926,55 +20495,7 @@ var collectionArray = ({
|
|
|
19926
20495
|
};
|
|
19927
20496
|
|
|
19928
20497
|
// src/surgery/appendToFixtureArray.ts
|
|
19929
|
-
import { Lang as
|
|
19930
|
-
|
|
19931
|
-
// src/surgery/appendPropertyEdit.ts
|
|
19932
|
-
var isMember = (child) => child.kind() === "pair" || child.kind() === "spread_element";
|
|
19933
|
-
var appendPropertyEdit = ({
|
|
19934
|
-
source,
|
|
19935
|
-
object,
|
|
19936
|
-
pair
|
|
19937
|
-
}) => {
|
|
19938
|
-
const closing = object.range().end.index - 1;
|
|
19939
|
-
const multiline = source.slice(object.range().start.index, closing).includes(`
|
|
19940
|
-
`);
|
|
19941
|
-
const members = object.children().filter(isMember);
|
|
19942
|
-
const last = members[members.length - 1];
|
|
19943
|
-
if (last === undefined) {
|
|
19944
|
-
return multiline ? {
|
|
19945
|
-
startPos: lineStartOf(source, closing),
|
|
19946
|
-
endPos: lineStartOf(source, closing),
|
|
19947
|
-
insertedText: `${leadingIndentOfLine(source, object.range().start.index)} ${pair},
|
|
19948
|
-
`
|
|
19949
|
-
} : {
|
|
19950
|
-
startPos: object.range().start.index + 1,
|
|
19951
|
-
endPos: closing,
|
|
19952
|
-
insertedText: ` ${pair} `
|
|
19953
|
-
};
|
|
19954
|
-
}
|
|
19955
|
-
const lastEnd = last.range().end.index;
|
|
19956
|
-
const between = source.slice(lastEnd, closing);
|
|
19957
|
-
const trailingComma = between.trimStart().startsWith(",");
|
|
19958
|
-
const afterComma = trailingComma ? lastEnd + between.indexOf(",") + 1 : lastEnd;
|
|
19959
|
-
if (multiline) {
|
|
19960
|
-
const indent = leadingIndentOfLine(source, last.range().start.index);
|
|
19961
|
-
return {
|
|
19962
|
-
startPos: afterComma,
|
|
19963
|
-
endPos: afterComma,
|
|
19964
|
-
insertedText: trailingComma ? `
|
|
19965
|
-
${indent}${pair},` : `,
|
|
19966
|
-
${indent}${pair},`
|
|
19967
|
-
};
|
|
19968
|
-
}
|
|
19969
|
-
return {
|
|
19970
|
-
startPos: afterComma,
|
|
19971
|
-
endPos: afterComma,
|
|
19972
|
-
insertedText: trailingComma ? ` ${pair},` : `, ${pair}`
|
|
19973
|
-
};
|
|
19974
|
-
};
|
|
19975
|
-
var holdsSpread = ({ object }) => object.children().some((child) => child.kind() === "spread_element");
|
|
19976
|
-
|
|
19977
|
-
// src/surgery/appendToFixtureArray.ts
|
|
20498
|
+
import { Lang as Lang5, parse as parse7 } from "@ast-grep/napi";
|
|
19978
20499
|
var appendToFixtureArray = ({
|
|
19979
20500
|
source,
|
|
19980
20501
|
builder,
|
|
@@ -19997,7 +20518,7 @@ var appendToFixtureArray = ({
|
|
|
19997
20518
|
const object = fixtureObjectOf(call);
|
|
19998
20519
|
if (object === null)
|
|
19999
20520
|
return null;
|
|
20000
|
-
const root =
|
|
20521
|
+
const root = parse7(Lang5.TypeScript, source).root();
|
|
20001
20522
|
const pair = object.children().find((member) => member.kind() === "pair" && member.namedChildren()[0]?.text() === property);
|
|
20002
20523
|
if (pair === undefined) {
|
|
20003
20524
|
const seeded = root.commitEdits([
|
|
@@ -20085,12 +20606,12 @@ var exportRemovalEdit = ({
|
|
|
20085
20606
|
};
|
|
20086
20607
|
|
|
20087
20608
|
// src/surgery/deleteReference.ts
|
|
20088
|
-
import { Lang as
|
|
20609
|
+
import { Lang as Lang6, parse as parse8 } from "@ast-grep/napi";
|
|
20089
20610
|
var deleteReference = ({
|
|
20090
20611
|
source,
|
|
20091
20612
|
name
|
|
20092
20613
|
}) => {
|
|
20093
|
-
const root =
|
|
20614
|
+
const root = parse8(Lang6.TypeScript, source).root();
|
|
20094
20615
|
const edits = [];
|
|
20095
20616
|
for (const identifier of root.findAll({
|
|
20096
20617
|
rule: { kind: "identifier", pattern: name }
|
|
@@ -20124,7 +20645,7 @@ var deleteReference = ({
|
|
|
20124
20645
|
};
|
|
20125
20646
|
|
|
20126
20647
|
// src/surgery/ensureBuilderImport.ts
|
|
20127
|
-
import { Lang as
|
|
20648
|
+
import { Lang as Lang7, parse as parse9 } from "@ast-grep/napi";
|
|
20128
20649
|
var NAMED_IMPORT = /^import\s+\{([^}]*)\}\s*from\s*["']([^"']+)["']/;
|
|
20129
20650
|
var GENERATED_MODULE = /\/generated\/[A-Za-z]+$/;
|
|
20130
20651
|
var ensureBuilderImport = ({
|
|
@@ -20132,7 +20653,7 @@ var ensureBuilderImport = ({
|
|
|
20132
20653
|
builder,
|
|
20133
20654
|
collection
|
|
20134
20655
|
}) => {
|
|
20135
|
-
const root =
|
|
20656
|
+
const root = parse9(Lang7.TypeScript, source).root();
|
|
20136
20657
|
const statements = root.findAll({ rule: { kind: "import_statement" } });
|
|
20137
20658
|
const parsed = statements.flatMap((statement) => {
|
|
20138
20659
|
const match = NAMED_IMPORT.exec(statement.text());
|
|
@@ -20170,9 +20691,9 @@ var ensureBuilderImport = ({
|
|
|
20170
20691
|
};
|
|
20171
20692
|
|
|
20172
20693
|
// src/surgery/insertCollection.ts
|
|
20173
|
-
import { Lang as
|
|
20694
|
+
import { Lang as Lang8, parse as parse10 } from "@ast-grep/napi";
|
|
20174
20695
|
var rootSpreadNames = ({ source }) => {
|
|
20175
|
-
const root =
|
|
20696
|
+
const root = parse10(Lang8.TypeScript, source).root();
|
|
20176
20697
|
const call = root.find("atmn($ARG)");
|
|
20177
20698
|
const object = call?.getMatch("ARG");
|
|
20178
20699
|
if (object === null || object === undefined || object.kind() !== "object")
|
|
@@ -20183,7 +20704,7 @@ var insertCollection = ({
|
|
|
20183
20704
|
source,
|
|
20184
20705
|
collection
|
|
20185
20706
|
}) => {
|
|
20186
|
-
const root =
|
|
20707
|
+
const root = parse10(Lang8.TypeScript, source).root();
|
|
20187
20708
|
const call = root.find("atmn($ARG)");
|
|
20188
20709
|
if (call === null)
|
|
20189
20710
|
return null;
|
|
@@ -20237,7 +20758,7 @@ ${indent}${collection}: [],`
|
|
|
20237
20758
|
};
|
|
20238
20759
|
|
|
20239
20760
|
// src/surgery/patchFixtureProperty.ts
|
|
20240
|
-
import { Lang as
|
|
20761
|
+
import { Lang as Lang9, parse as parse11 } from "@ast-grep/napi";
|
|
20241
20762
|
var pairFor = ({
|
|
20242
20763
|
object,
|
|
20243
20764
|
property
|
|
@@ -20328,7 +20849,7 @@ var patchFixtureProperty = ({
|
|
|
20328
20849
|
const object = fixtureObjectOf(call);
|
|
20329
20850
|
if (object === null)
|
|
20330
20851
|
return null;
|
|
20331
|
-
const root =
|
|
20852
|
+
const root = parse11(Lang9.TypeScript, source).root();
|
|
20332
20853
|
const pair = pairFor({ object, property });
|
|
20333
20854
|
if (text === null) {
|
|
20334
20855
|
if (pair === null)
|
|
@@ -20433,7 +20954,7 @@ var changedFixtureKeys = ({
|
|
|
20433
20954
|
|
|
20434
20955
|
// src/actions/pull/resolveCollectionTarget.ts
|
|
20435
20956
|
import { dirname as dirname8, resolve as resolve4 } from "node:path";
|
|
20436
|
-
import { Lang as
|
|
20957
|
+
import { Lang as Lang10, parse as parse12 } from "@ast-grep/napi";
|
|
20437
20958
|
var NAMED_IMPORT2 = /import\s+(?:type\s+)?\{([^}]*)\}\s*from\s*["']([^"']+)["']/;
|
|
20438
20959
|
var resolveCollectionTarget = ({
|
|
20439
20960
|
configPath,
|
|
@@ -20444,7 +20965,7 @@ var resolveCollectionTarget = ({
|
|
|
20444
20965
|
const source = files.get(configPath);
|
|
20445
20966
|
if (source === undefined)
|
|
20446
20967
|
return null;
|
|
20447
|
-
const root =
|
|
20968
|
+
const root = parse12(Lang10.TypeScript, source).root();
|
|
20448
20969
|
const value = collectionValue({ root, collection });
|
|
20449
20970
|
if (value === null)
|
|
20450
20971
|
return null;
|
|
@@ -20484,7 +21005,7 @@ var resolveBinding = ({
|
|
|
20484
21005
|
});
|
|
20485
21006
|
if (file === null)
|
|
20486
21007
|
return null;
|
|
20487
|
-
const module =
|
|
21008
|
+
const module = parse12(Lang10.TypeScript, files.get(file) ?? "").root();
|
|
20488
21009
|
return findLiteralBinding({
|
|
20489
21010
|
root: module,
|
|
20490
21011
|
name: imported.exportedName,
|
|
@@ -20956,7 +21477,7 @@ var applyPreview = ({
|
|
|
20956
21477
|
};
|
|
20957
21478
|
|
|
20958
21479
|
// src/surgery/patchSingletonProperty.ts
|
|
20959
|
-
import { Lang as
|
|
21480
|
+
import { Lang as Lang11, parse as parse13 } from "@ast-grep/napi";
|
|
20960
21481
|
var atmnObject = (root) => {
|
|
20961
21482
|
const object = root.find("atmn($ARG)")?.getMatch("ARG") ?? null;
|
|
20962
21483
|
return object !== null && object.kind() === "object" ? object : null;
|
|
@@ -21030,7 +21551,7 @@ var patchSingletonProperty = ({
|
|
|
21030
21551
|
block,
|
|
21031
21552
|
edit
|
|
21032
21553
|
}) => {
|
|
21033
|
-
const root =
|
|
21554
|
+
const root = parse13(Lang11.TypeScript, source).root();
|
|
21034
21555
|
const object = blockObject({ root, block });
|
|
21035
21556
|
if (object === null)
|
|
21036
21557
|
return null;
|
|
@@ -21067,7 +21588,7 @@ var insertSingleton = ({
|
|
|
21067
21588
|
source,
|
|
21068
21589
|
singleton
|
|
21069
21590
|
}) => {
|
|
21070
|
-
const root =
|
|
21591
|
+
const root = parse13(Lang11.TypeScript, source).root();
|
|
21071
21592
|
const object = atmnObject(root);
|
|
21072
21593
|
if (object === null)
|
|
21073
21594
|
return null;
|
|
@@ -21080,7 +21601,7 @@ var insertSingleton = ({
|
|
|
21080
21601
|
const withArray = insertCollection({ source, collection: singleton });
|
|
21081
21602
|
if (withArray === null || withArray === source)
|
|
21082
21603
|
return withArray;
|
|
21083
|
-
const seededRoot =
|
|
21604
|
+
const seededRoot = parse13(Lang11.TypeScript, withArray).root();
|
|
21084
21605
|
const seeded = atmnObject(seededRoot);
|
|
21085
21606
|
const pair = seeded === null ? null : pairFor2({ object: seeded, key: singleton });
|
|
21086
21607
|
const value = pair?.namedChildren()[1];
|
|
@@ -21170,8 +21691,8 @@ var applySettingsPreview = ({
|
|
|
21170
21691
|
};
|
|
21171
21692
|
|
|
21172
21693
|
// src/actions/pull/rewriteConfig.ts
|
|
21173
|
-
import { existsSync as
|
|
21174
|
-
import { dirname as dirname9, join as
|
|
21694
|
+
import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "node:fs";
|
|
21695
|
+
import { dirname as dirname9, join as join12 } from "node:path";
|
|
21175
21696
|
var PACKAGE_NAMES = ["atmn", "atmn-nightly"];
|
|
21176
21697
|
var importsConfigPackage = ({
|
|
21177
21698
|
text,
|
|
@@ -21186,17 +21707,17 @@ var rewriteConfig = ({
|
|
|
21186
21707
|
const rewritten = [];
|
|
21187
21708
|
const kept = [];
|
|
21188
21709
|
for (const [file, collections] of Object.entries(COLLECTION_FILES)) {
|
|
21189
|
-
const path =
|
|
21190
|
-
const isUsers =
|
|
21710
|
+
const path = join12(configDir, file);
|
|
21711
|
+
const isUsers = existsSync11(path) && !importsConfigPackage({ text: readFileSync11(path, "utf8"), imports });
|
|
21191
21712
|
if (isUsers) {
|
|
21192
21713
|
kept.push(path);
|
|
21193
21714
|
continue;
|
|
21194
21715
|
}
|
|
21195
|
-
|
|
21716
|
+
writeFileSync7(path, collectionFileSource({ collections, imports }), "utf8");
|
|
21196
21717
|
importedFiles.add(file);
|
|
21197
21718
|
rewritten.push(path);
|
|
21198
21719
|
}
|
|
21199
|
-
|
|
21720
|
+
writeFileSync7(configPath, rootSource({ imports, importedFiles }), "utf8");
|
|
21200
21721
|
return { rewritten: [configPath, ...rewritten], kept };
|
|
21201
21722
|
};
|
|
21202
21723
|
|
|
@@ -21733,7 +22254,7 @@ var previewIsEmpty = ({
|
|
|
21733
22254
|
}) => !(preview.features ?? []).some(rowHasWork) && !(preview.plans ?? []).some(rowHasWork) && !(preview.rewards ?? []).some(rowHasWork) && !(preview.referralPrograms ?? []).some(rowHasWork) && !settingsHaveWork({ settings: preview.settings });
|
|
21734
22255
|
|
|
21735
22256
|
// src/actions/push/backfillInternalIds.ts
|
|
21736
|
-
import { readFileSync as
|
|
22257
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync8 } from "node:fs";
|
|
21737
22258
|
import { dirname as dirname10 } from "node:path";
|
|
21738
22259
|
|
|
21739
22260
|
// src/surgery/insertFirstProperty.ts
|
|
@@ -21784,7 +22305,7 @@ ${indent}`
|
|
|
21784
22305
|
};
|
|
21785
22306
|
|
|
21786
22307
|
// src/surgery/setFixtureProperty.ts
|
|
21787
|
-
import { Lang as
|
|
22308
|
+
import { Lang as Lang12, parse as parse14 } from "@ast-grep/napi";
|
|
21788
22309
|
var setFixtureProperty = ({
|
|
21789
22310
|
source,
|
|
21790
22311
|
builder,
|
|
@@ -21813,7 +22334,7 @@ var setFixtureProperty = ({
|
|
|
21813
22334
|
const [key, current] = member.namedChildren();
|
|
21814
22335
|
if (key?.text() !== property || current === undefined)
|
|
21815
22336
|
continue;
|
|
21816
|
-
const root =
|
|
22337
|
+
const root = parse14(Lang12.TypeScript, source).root();
|
|
21817
22338
|
return root.commitEdits([
|
|
21818
22339
|
{
|
|
21819
22340
|
startPos: current.range().start.index,
|
|
@@ -21863,10 +22384,10 @@ var backfillInternalIds = ({
|
|
|
21863
22384
|
configPath
|
|
21864
22385
|
}) => {
|
|
21865
22386
|
const files = new Map;
|
|
21866
|
-
files.set(configPath,
|
|
22387
|
+
files.set(configPath, readFileSync12(configPath, "utf8"));
|
|
21867
22388
|
for (const file of listSourceFiles({ directory: dirname10(configPath) })) {
|
|
21868
22389
|
if (!files.has(file))
|
|
21869
|
-
files.set(file,
|
|
22390
|
+
files.set(file, readFileSync12(file, "utf8"));
|
|
21870
22391
|
}
|
|
21871
22392
|
const originals = new Map(files);
|
|
21872
22393
|
const backfilled = [];
|
|
@@ -22100,7 +22621,7 @@ var backfillInternalIds = ({
|
|
|
22100
22621
|
}
|
|
22101
22622
|
for (const [file, source] of files) {
|
|
22102
22623
|
if (source !== originals.get(file))
|
|
22103
|
-
|
|
22624
|
+
writeFileSync8(file, source, "utf8");
|
|
22104
22625
|
}
|
|
22105
22626
|
return { backfilled, slugged };
|
|
22106
22627
|
};
|
|
@@ -22426,7 +22947,7 @@ var runPull = async ({
|
|
|
22426
22947
|
write(`This rewrites autumn.config.ts and the features.ts, plans.ts and rewards.ts beside it from your org's catalog. Other files are left alone. Re-run with --yes to overwrite.
|
|
22427
22948
|
`);
|
|
22428
22949
|
return {
|
|
22429
|
-
configPath: project.configPath ??
|
|
22950
|
+
configPath: project.configPath ?? join13(project.configDir, "autumn.config.ts"),
|
|
22430
22951
|
appended: [],
|
|
22431
22952
|
replaced: [],
|
|
22432
22953
|
deleted: []
|
|
@@ -22439,7 +22960,7 @@ var runPull = async ({
|
|
|
22439
22960
|
if (project.configPath === null) {
|
|
22440
22961
|
const chosen = await chooseConfigDir({ cwd, prompter });
|
|
22441
22962
|
scaffoldDir = chosen.configDir;
|
|
22442
|
-
scaffoldPath =
|
|
22963
|
+
scaffoldPath = join13(scaffoldDir, "autumn.config.ts");
|
|
22443
22964
|
if (scaffoldDir !== cwd && writeRootMarker({ repoRoot: chosen.repoRoot, configPath: scaffoldPath }))
|
|
22444
22965
|
prompter.write(`${done("Recorded in package.json so atmn finds it from anywhere")}
|
|
22445
22966
|
`);
|
|
@@ -22460,11 +22981,11 @@ var runPull = async ({
|
|
|
22460
22981
|
client.previewUpdateOrganization(singletons.settings ?? { config: {} })
|
|
22461
22982
|
]);
|
|
22462
22983
|
const files = new Map;
|
|
22463
|
-
files.set(configPath,
|
|
22984
|
+
files.set(configPath, readFileSync13(configPath, "utf8"));
|
|
22464
22985
|
for (const file of listSourceFiles({ directory: dirname11(configPath) })) {
|
|
22465
22986
|
if (file === configPath || files.has(file))
|
|
22466
22987
|
continue;
|
|
22467
|
-
files.set(file,
|
|
22988
|
+
files.set(file, readFileSync13(file, "utf8"));
|
|
22468
22989
|
}
|
|
22469
22990
|
const originals = new Map(files);
|
|
22470
22991
|
const appended = [];
|
|
@@ -22512,16 +23033,30 @@ var runPull = async ({
|
|
|
22512
23033
|
action: `set by hand: \`${singleton}\` is not an object literal`
|
|
22513
23034
|
})));
|
|
22514
23035
|
}
|
|
23036
|
+
if (includeMappings) {
|
|
23037
|
+
const managedCatalog = Object.fromEntries(Object.entries(COLLECTIONS).filter(([, spec]) => spec.wireKey !== undefined && wire[spec.wireKey] !== undefined).map(([collection]) => [collection, catalogRows[collection]]));
|
|
23038
|
+
const mapped = applyMappings({
|
|
23039
|
+
catalog: managedCatalog,
|
|
23040
|
+
configPath,
|
|
23041
|
+
files
|
|
23042
|
+
});
|
|
23043
|
+
unlocated.push(...mapped.unlocated);
|
|
23044
|
+
for (const id of mapped.replaced) {
|
|
23045
|
+
if (!replaced.includes(id) && !appended.includes(id))
|
|
23046
|
+
replaced.push(id);
|
|
23047
|
+
lines.push(`↳ wrote processor mappings into ${id}`);
|
|
23048
|
+
}
|
|
23049
|
+
}
|
|
22515
23050
|
if (unlocated.length > 0)
|
|
22516
23051
|
throw new UnlocatableFixturesError({ unlocated });
|
|
22517
23052
|
for (const [file, source] of files) {
|
|
22518
23053
|
if (source === originals.get(file))
|
|
22519
23054
|
continue;
|
|
22520
23055
|
mkdirSync4(dirname11(file), { recursive: true });
|
|
22521
|
-
|
|
23056
|
+
writeFileSync9(file, source, "utf8");
|
|
22522
23057
|
if (!originals.has(file)) {
|
|
22523
|
-
const keep =
|
|
22524
|
-
if (
|
|
23058
|
+
const keep = join13(dirname11(file), ".gitkeep");
|
|
23059
|
+
if (existsSync12(keep))
|
|
22525
23060
|
unlinkSync(keep);
|
|
22526
23061
|
}
|
|
22527
23062
|
}
|
|
@@ -23008,11 +23543,11 @@ ${hint(flagHint)}
|
|
|
23008
23543
|
`);
|
|
23009
23544
|
throw new NeedsInputError(flagHint);
|
|
23010
23545
|
}
|
|
23011
|
-
return
|
|
23546
|
+
return join14(project.configDir, SKILLS_DIR_NAME);
|
|
23012
23547
|
};
|
|
23013
23548
|
var writeStaleSkillsHint = ({ command }) => {
|
|
23014
23549
|
const stale = staleSkillsHint({
|
|
23015
|
-
dir:
|
|
23550
|
+
dir: join14(projectOf({ command }).configDir, SKILLS_DIR_NAME)
|
|
23016
23551
|
});
|
|
23017
23552
|
if (stale !== null)
|
|
23018
23553
|
process.stdout.write(`${stale}
|
|
@@ -23196,6 +23731,8 @@ Nothing applied. Re-run with --yes to apply these changes.
|
|
|
23196
23731
|
skills.command("install").description("write the skills next to your config; --link runs npx skills add").option("--dir <dir>", "write here instead of <config folder>/skills").option("--link", "run `npx skills add <dir> --all` afterwards").action(async (options, command) => {
|
|
23197
23732
|
const dir = skillsDirOf({ command, dir: options.dir });
|
|
23198
23733
|
installSkills({ dir, write: (text) => process.stdout.write(text) });
|
|
23734
|
+
if (options.dir === undefined)
|
|
23735
|
+
ignoreBundledSkills(projectOf({ command }));
|
|
23199
23736
|
if (options.link === true)
|
|
23200
23737
|
await linkSkills({
|
|
23201
23738
|
dir,
|
|
@@ -23205,6 +23742,8 @@ Nothing applied. Re-run with --yes to apply these changes.
|
|
|
23205
23742
|
skills.command("update").description("rewrite installed skills older than this CLI's").option("--dir <dir>", "the install to update; <config folder>/skills by default").action((options, command) => {
|
|
23206
23743
|
const dir = skillsDirOf({ command, dir: options.dir });
|
|
23207
23744
|
updateSkills({ dir, write: (text) => process.stdout.write(text) });
|
|
23745
|
+
if (options.dir === undefined)
|
|
23746
|
+
ignoreBundledSkills(projectOf({ command }));
|
|
23208
23747
|
});
|
|
23209
23748
|
program.command("pull").description("write your remote catalog back into autumn.config.ts").option("--include-mappings", "keep processor mappings in pulled fixtures").option("--overwrite", "rewrite the config from your org's catalog (e.g. after switching orgs)").option("-y, --yes", "overwrite it").action(async (options, command) => {
|
|
23210
23749
|
const target = prepareTarget({ command });
|