saasfunnels 0.3.2 → 0.3.3
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/README.md +2 -0
- package/dist/library.js +6 -1
- package/dist/saasfunnels.js +69 -13
- package/dist/types/identity.d.ts +1 -1
- package/dist/types/mcp.d.ts +1 -1
- package/dist/types/source-scope.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -108,4 +108,6 @@ Static pricing supports literal spreads, capability/quota maps, unlimited limits
|
|
|
108
108
|
|
|
109
109
|
If extraction is unsupported, `.saasfunnels/setup-review.json` lists the files and reasons. Correct those declarations or review a `.saasfunnels/setup-pricing.json` file with `{ "plans": [{ "key": "pro", "name": "Pro", "features": { "export": true }, "prices": [{ "key": "price_ACTUAL_ID" }] }] }`, then resume. Use real identifiers from the connected merchant. Raw source files are never uploaded by guided setup or the pricing handoff.
|
|
110
110
|
|
|
111
|
+
Discovery follows Git ignore rules (including custom build folders) while keeping tracked application sources and new, non-ignored source files. Standalone folders without Git use the standard source filters.
|
|
112
|
+
|
|
111
113
|
The command does not implement arbitrary payment code, approve feature access, or verify transactions. Complete **Review and verify** in Setup after deploying the runtime and payment integration. Requires the server's guided setup API release.
|
package/dist/library.js
CHANGED
|
@@ -24187,6 +24187,11 @@ function agentCapabilityAllowedAtBoundary(id, boundary, { mutationsEnabled = fal
|
|
|
24187
24187
|
return true;
|
|
24188
24188
|
}
|
|
24189
24189
|
|
|
24190
|
+
// src/source-scope.ts
|
|
24191
|
+
import { execFile } from "node:child_process";
|
|
24192
|
+
import { promisify } from "node:util";
|
|
24193
|
+
var exec = promisify(execFile);
|
|
24194
|
+
|
|
24190
24195
|
// src/feature-setup.ts
|
|
24191
24196
|
var import_yaml = __toESM(require_dist(), 1);
|
|
24192
24197
|
var schemaVersion = 1;
|
|
@@ -24264,7 +24269,7 @@ function validateFeatureCatalogManifest(value) {
|
|
|
24264
24269
|
|
|
24265
24270
|
// src/identity.ts
|
|
24266
24271
|
var SAASFUNNELS_CLI_NAME = "saasfunnels";
|
|
24267
|
-
var SAASFUNNELS_CLI_VERSION = "0.3.
|
|
24272
|
+
var SAASFUNNELS_CLI_VERSION = "0.3.3";
|
|
24268
24273
|
var SAASFUNNELS_PRODUCT_NAME = "SaaSFunnels";
|
|
24269
24274
|
var SAASFUNNELS_DEFAULT_API_BASE_URL = "https://app.saasfunnels.ai";
|
|
24270
24275
|
var SAASFUNNELS_ENV = Object.freeze({
|
package/dist/saasfunnels.js
CHANGED
|
@@ -219160,8 +219160,8 @@ function extractSetupPricing(source, kind, catalogPrices = []) {
|
|
|
219160
219160
|
|
|
219161
219161
|
// src/setup-run.ts
|
|
219162
219162
|
import { createHash as createHash3 } from "node:crypto";
|
|
219163
|
-
import { execFile as
|
|
219164
|
-
import { promisify as
|
|
219163
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
219164
|
+
import { promisify as promisify3 } from "node:util";
|
|
219165
219165
|
import { readFile as readFile5, writeFile as writeFile3, mkdir as mkdir3 } from "node:fs/promises";
|
|
219166
219166
|
import { join as join4 } from "node:path";
|
|
219167
219167
|
|
|
@@ -233679,6 +233679,56 @@ function date4(params) {
|
|
|
233679
233679
|
// node_modules/zod/v4/classic/external.js
|
|
233680
233680
|
config(en_default());
|
|
233681
233681
|
|
|
233682
|
+
// src/source-scope.ts
|
|
233683
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
233684
|
+
import { promisify as promisify2 } from "node:util";
|
|
233685
|
+
var exec2 = promisify2(execFile2);
|
|
233686
|
+
async function repositorySourceScope(cwd2) {
|
|
233687
|
+
try {
|
|
233688
|
+
await exec2("git", ["rev-parse", "--is-inside-work-tree"], { cwd: cwd2 });
|
|
233689
|
+
} catch (error51) {
|
|
233690
|
+
const failure = error51;
|
|
233691
|
+
if (failure.code === "ENOENT" || failure.stderr?.includes("not a git repository"))
|
|
233692
|
+
return (_path) => true;
|
|
233693
|
+
throw new Error(
|
|
233694
|
+
"Cannot read repository source scope. Check Git access and retry."
|
|
233695
|
+
);
|
|
233696
|
+
}
|
|
233697
|
+
let stdout;
|
|
233698
|
+
try {
|
|
233699
|
+
({ stdout } = await exec2(
|
|
233700
|
+
"git",
|
|
233701
|
+
[
|
|
233702
|
+
"ls-files",
|
|
233703
|
+
"--cached",
|
|
233704
|
+
"--others",
|
|
233705
|
+
"--exclude-standard",
|
|
233706
|
+
"-z",
|
|
233707
|
+
"--",
|
|
233708
|
+
"."
|
|
233709
|
+
],
|
|
233710
|
+
{
|
|
233711
|
+
cwd: cwd2,
|
|
233712
|
+
maxBuffer: 32 * 1024 * 1024
|
|
233713
|
+
}
|
|
233714
|
+
));
|
|
233715
|
+
} catch {
|
|
233716
|
+
throw new Error(
|
|
233717
|
+
"Cannot list repository sources. Check Git access and retry."
|
|
233718
|
+
);
|
|
233719
|
+
}
|
|
233720
|
+
const included = /* @__PURE__ */ new Set([""]);
|
|
233721
|
+
for (const path of stdout.split("\0").filter(Boolean)) {
|
|
233722
|
+
included.add(path);
|
|
233723
|
+
let end = path.lastIndexOf("/");
|
|
233724
|
+
while (end > 0) {
|
|
233725
|
+
included.add(path.slice(0, end));
|
|
233726
|
+
end = path.lastIndexOf("/", end - 1);
|
|
233727
|
+
}
|
|
233728
|
+
}
|
|
233729
|
+
return (path) => included.has(path);
|
|
233730
|
+
}
|
|
233731
|
+
|
|
233682
233732
|
// src/feature-setup.ts
|
|
233683
233733
|
var import_yaml2 = __toESM(require_dist(), 1);
|
|
233684
233734
|
import { createHash as createHash2, randomUUID } from "node:crypto";
|
|
@@ -235973,6 +236023,7 @@ function allowedPath(path, excludes) {
|
|
|
235973
236023
|
);
|
|
235974
236024
|
}
|
|
235975
236025
|
async function walkFiles(input) {
|
|
236026
|
+
const inRepository = await repositorySourceScope(input.cwd);
|
|
235976
236027
|
const files = [];
|
|
235977
236028
|
const queue = input.roots.map((root) => resolve2(input.cwd, root));
|
|
235978
236029
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -235982,7 +236033,8 @@ async function walkFiles(input) {
|
|
|
235982
236033
|
if (seen.has(current)) continue;
|
|
235983
236034
|
seen.add(current);
|
|
235984
236035
|
const relativePath = safeRelative(input.cwd, current);
|
|
235985
|
-
if (!relativePath || !allowedPath(relativePath, input.excludes))
|
|
236036
|
+
if (!relativePath || !inRepository(relativePath) || !allowedPath(relativePath, input.excludes))
|
|
236037
|
+
continue;
|
|
235986
236038
|
let currentStat;
|
|
235987
236039
|
try {
|
|
235988
236040
|
currentStat = await lstat(current);
|
|
@@ -236709,13 +236761,15 @@ async function discoverPlanSourceCandidates(input) {
|
|
|
236709
236761
|
const roots = input.roots ?? [".", "config", ...defaultRoots];
|
|
236710
236762
|
const seen = /* @__PURE__ */ new Set();
|
|
236711
236763
|
const candidates = [];
|
|
236764
|
+
const inRepository = await repositorySourceScope(input.cwd);
|
|
236712
236765
|
const queue = roots.map((root) => resolve3(input.cwd, root));
|
|
236713
236766
|
while (queue.length) {
|
|
236714
236767
|
const current = queue.shift();
|
|
236715
236768
|
if (seen.has(current)) continue;
|
|
236716
236769
|
seen.add(current);
|
|
236717
236770
|
const relativePath = normalize(relative2(input.cwd, current));
|
|
236718
|
-
if (relativePath && !allowed(relativePath, excludes))
|
|
236771
|
+
if (!inRepository(relativePath) || relativePath && !allowed(relativePath, excludes))
|
|
236772
|
+
continue;
|
|
236719
236773
|
let entryStat;
|
|
236720
236774
|
try {
|
|
236721
236775
|
entryStat = await lstat2(current);
|
|
@@ -236979,13 +237033,15 @@ async function discoverPlanBranches(input) {
|
|
|
236979
237033
|
const branches = [];
|
|
236980
237034
|
const constants = /* @__PURE__ */ new Map();
|
|
236981
237035
|
const pending = [];
|
|
237036
|
+
const inRepository = await repositorySourceScope(input.cwd);
|
|
236982
237037
|
const queue = roots.map((root) => resolve4(input.cwd, root));
|
|
236983
237038
|
while (queue.length) {
|
|
236984
237039
|
const current = queue.shift();
|
|
236985
237040
|
if (seen.has(current)) continue;
|
|
236986
237041
|
seen.add(current);
|
|
236987
237042
|
const relativePath = normalize2(relative3(input.cwd, current));
|
|
236988
|
-
if (relativePath && !allowed2(relativePath, excludes))
|
|
237043
|
+
if (!inRepository(relativePath) || relativePath && !allowed2(relativePath, excludes))
|
|
237044
|
+
continue;
|
|
236989
237045
|
let entryStat;
|
|
236990
237046
|
try {
|
|
236991
237047
|
entryStat = await lstat3(current);
|
|
@@ -237048,7 +237104,7 @@ async function discoverPlanBranches(input) {
|
|
|
237048
237104
|
}
|
|
237049
237105
|
|
|
237050
237106
|
// src/setup-run.ts
|
|
237051
|
-
var
|
|
237107
|
+
var exec3 = promisify3(execFile3);
|
|
237052
237108
|
var hash2 = (text) => createHash3("sha256").update(text).digest("hex");
|
|
237053
237109
|
var contextSchema = external_exports.object({
|
|
237054
237110
|
workspaceId: external_exports.string(),
|
|
@@ -237121,15 +237177,15 @@ async function runGuidedSetup(options) {
|
|
|
237121
237177
|
"Connect Stripe and create app credentials in Setup first."
|
|
237122
237178
|
);
|
|
237123
237179
|
try {
|
|
237124
|
-
await
|
|
237125
|
-
await
|
|
237180
|
+
await exec3("git", ["rev-parse", "HEAD"], { cwd: options.cwd });
|
|
237181
|
+
await exec3("git", ["remote", "get-url", "origin"], { cwd: options.cwd });
|
|
237126
237182
|
} catch {
|
|
237127
237183
|
throw new Error(
|
|
237128
237184
|
"Repository setup needed: run this command inside your app\u2019s Git repository with an initial commit and an origin remote. No push or production deploy is required for discovery."
|
|
237129
237185
|
);
|
|
237130
237186
|
}
|
|
237131
|
-
const head = (await
|
|
237132
|
-
const diff = (await
|
|
237187
|
+
const head = (await exec3("git", ["rev-parse", "HEAD"], { cwd: options.cwd })).stdout.trim();
|
|
237188
|
+
const diff = (await exec3(
|
|
237133
237189
|
"git",
|
|
237134
237190
|
[
|
|
237135
237191
|
"diff",
|
|
@@ -237142,7 +237198,7 @@ async function runGuidedSetup(options) {
|
|
|
237142
237198
|
],
|
|
237143
237199
|
{ cwd: options.cwd, maxBuffer: 8e6 }
|
|
237144
237200
|
)).stdout;
|
|
237145
|
-
const untracked = (await
|
|
237201
|
+
const untracked = (await exec3("git", ["ls-files", "--others", "--exclude-standard", "-z"], {
|
|
237146
237202
|
cwd: options.cwd
|
|
237147
237203
|
})).stdout.split("\0").filter(
|
|
237148
237204
|
(path) => path && !path.startsWith(".saasfunnels/") && !/(^|\/)(\.env|node_modules|dist|\.next)(\/|$|\.)/i.test(path)
|
|
@@ -237158,7 +237214,7 @@ async function runGuidedSetup(options) {
|
|
|
237158
237214
|
])
|
|
237159
237215
|
);
|
|
237160
237216
|
const revision = `${head}:${hash2(JSON.stringify([diff, sourceHashes]))}`;
|
|
237161
|
-
const remote = (await
|
|
237217
|
+
const remote = (await exec3("git", ["remote", "get-url", "origin"], { cwd: options.cwd })).stdout.trim();
|
|
237162
237218
|
const repositoryKey = safeRepositoryKey(remote);
|
|
237163
237219
|
const statePath = join4(options.cwd, ".saasfunnels", "setup-run.json");
|
|
237164
237220
|
if (options.resume) {
|
|
@@ -237477,7 +237533,7 @@ import { mkdir as mkdir4, readFile as readFile6, writeFile as writeFile4 } from
|
|
|
237477
237533
|
|
|
237478
237534
|
// src/identity.ts
|
|
237479
237535
|
var SAASFUNNELS_CLI_NAME = "saasfunnels";
|
|
237480
|
-
var SAASFUNNELS_CLI_VERSION = "0.3.
|
|
237536
|
+
var SAASFUNNELS_CLI_VERSION = "0.3.3";
|
|
237481
237537
|
var SAASFUNNELS_PRODUCT_NAME = "SaaSFunnels";
|
|
237482
237538
|
var SAASFUNNELS_DEFAULT_API_BASE_URL = "https://app.saasfunnels.ai";
|
|
237483
237539
|
var SAASFUNNELS_ENV = Object.freeze({
|
package/dist/types/identity.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const SAASFUNNELS_CLI_NAME = "saasfunnels";
|
|
2
|
-
export declare const SAASFUNNELS_CLI_VERSION = "0.3.
|
|
2
|
+
export declare const SAASFUNNELS_CLI_VERSION = "0.3.3";
|
|
3
3
|
export declare const SAASFUNNELS_PRODUCT_NAME = "SaaSFunnels";
|
|
4
4
|
export declare const SAASFUNNELS_DEFAULT_API_BASE_URL = "https://app.saasfunnels.ai";
|
|
5
5
|
export declare const SAASFUNNELS_ENV: Readonly<{
|
package/dist/types/mcp.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export type SaaSFunnelsMcpOptions = {
|
|
|
77
77
|
output?: Pick<NodeJS.WritableStream, "write">;
|
|
78
78
|
};
|
|
79
79
|
declare const mcpProtocolVersion = "2025-06-18";
|
|
80
|
-
declare const mcpServerVersion = "0.3.
|
|
80
|
+
declare const mcpServerVersion = "0.3.3";
|
|
81
81
|
export declare function saasFunnelsMcpResources(): McpResourceDefinition[];
|
|
82
82
|
export declare function readSaaSFunnelsMcpResource(uri: string, options?: SaaSFunnelsMcpOptions): string;
|
|
83
83
|
export declare function saasFunnelsMcpToolDefinitions({ allowFunnelTests, allowFunnelWrites, allowTestWrites, includeHostedAccountTools, }?: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function repositorySourceScope(cwd: string): Promise<(_path: string) => boolean>;
|