siteplane 0.1.64 → 0.1.66
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 +13 -0
- package/dist/bin/siteplane.js +214 -258
- package/dist/index.js +134 -178
- package/dist/next.d.ts +10 -0
- package/dist/next.js +175 -108
- package/package.json +1 -1
package/dist/next.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// src/next.ts
|
|
2
2
|
import { execFile as execFile4 } from "child_process";
|
|
3
3
|
import { createHash as createHash5 } from "crypto";
|
|
4
|
-
import { readFile as readFile13 } from "fs/promises";
|
|
5
|
-
import { dirname as
|
|
4
|
+
import { access as access8, readFile as readFile13 } from "fs/promises";
|
|
5
|
+
import { dirname as dirname10, join as join14, resolve as resolve4 } from "path";
|
|
6
6
|
import { promisify as promisify4 } from "util";
|
|
7
7
|
|
|
8
8
|
// ../cli/dist/analytics/manifest.js
|
|
@@ -638,6 +638,7 @@ var bookingPublicConfigSchema = z9.object({
|
|
|
638
638
|
settings: z9.object({
|
|
639
639
|
slotIntervalMinutes: z9.number().int().positive(),
|
|
640
640
|
minLeadMinutes: z9.number().int().min(0),
|
|
641
|
+
minCancelLeadMinutes: z9.number().int().min(0),
|
|
641
642
|
maxAdvanceDays: z9.number().int().min(1),
|
|
642
643
|
requirePhone: z9.boolean(),
|
|
643
644
|
collectNote: z9.boolean(),
|
|
@@ -846,7 +847,7 @@ var bookingManifestSchema = z9.object({
|
|
|
846
847
|
siteId: z9.string().trim().min(1),
|
|
847
848
|
siteKeyPrefix: z9.string().startsWith("bk_pub_"),
|
|
848
849
|
bookingPageSlug: z9.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).min(2).max(64),
|
|
849
|
-
|
|
850
|
+
integration: z9.literal("rewrite").optional(),
|
|
850
851
|
productionOrigin: z9.string().url().optional()
|
|
851
852
|
}).passthrough();
|
|
852
853
|
|
|
@@ -2405,6 +2406,9 @@ import ts from "typescript";
|
|
|
2405
2406
|
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
2406
2407
|
import { dirname as dirname2 } from "path";
|
|
2407
2408
|
|
|
2409
|
+
// ../cli/dist/booking/static-scan.js
|
|
2410
|
+
import ts2 from "typescript";
|
|
2411
|
+
|
|
2408
2412
|
// ../cli/dist/commands/analytics/check.js
|
|
2409
2413
|
import { readFile as readFile3 } from "fs/promises";
|
|
2410
2414
|
|
|
@@ -2505,17 +2509,20 @@ var errorSchema = z30.object({
|
|
|
2505
2509
|
import { randomUUID } from "crypto";
|
|
2506
2510
|
|
|
2507
2511
|
// ../cli/dist/commands/booking/check.js
|
|
2508
|
-
import {
|
|
2512
|
+
import { dirname as dirname4, join as join2 } from "path";
|
|
2513
|
+
import { access, readFile as readFile4 } from "fs/promises";
|
|
2509
2514
|
|
|
2510
2515
|
// ../cli/dist/commands/booking/init.js
|
|
2511
2516
|
import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
|
|
2512
|
-
import { dirname as
|
|
2517
|
+
import { dirname as dirname5, join as join3 } from "path";
|
|
2513
2518
|
var bookingRulesTemplate = `# Siteplane Booking Rules
|
|
2514
2519
|
|
|
2515
2520
|
- Do not change layout, copy, styling, animation or business logic while adding Booking.
|
|
2516
|
-
-
|
|
2517
|
-
- Use
|
|
2518
|
-
-
|
|
2521
|
+
- Integrate /booking on the customer domain through withSiteplane(nextConfig, { booking: { site: "<site-id>" } }); use the immutable Site ID supplied by Siteplane.
|
|
2522
|
+
- Use a normal <a href="/booking"> link, not next/link, an iframe or an embed script.
|
|
2523
|
+
- Preserve existing rewrites. Booking-only must not require Editor setup or siteplane.config.json.
|
|
2524
|
+
- Configure the public booking address in Siteplane; register its origin and call https://siteplane.io/api/booking/* directly with CORS, without a raw public key.
|
|
2525
|
+
- Preserve customer CSP and middleware; explain required Siteplane/Stripe permissions and exclude /booking from customer middleware.
|
|
2519
2526
|
- Do not write setup tokens, project CLI tokens or private keys into source files.
|
|
2520
2527
|
- Run npx siteplane booking check, npx siteplane booking sync and npx siteplane booking test after setup.
|
|
2521
2528
|
- booking test stays in test_mode; live booking only starts after explicit dashboard activation.
|
|
@@ -2528,9 +2535,9 @@ alwaysApply: true
|
|
|
2528
2535
|
${bookingRulesTemplate}`;
|
|
2529
2536
|
|
|
2530
2537
|
// ../cli/dist/config/project-config.js
|
|
2531
|
-
import { access, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
|
|
2538
|
+
import { access as access2, chmod, open, readFile as readFile5, rename, rm } from "fs/promises";
|
|
2532
2539
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
2533
|
-
import { join as
|
|
2540
|
+
import { join as join4 } from "path";
|
|
2534
2541
|
import { z as z31 } from "zod";
|
|
2535
2542
|
var siteplaneProjectConfigSchema = z31.object({
|
|
2536
2543
|
version: z31.literal(2),
|
|
@@ -2546,14 +2553,14 @@ var siteplaneProjectConfigSchema = z31.object({
|
|
|
2546
2553
|
fieldContractHash: z31.string().regex(/^sha256:[0-9a-f]{64}$/iu).optional()
|
|
2547
2554
|
}).strict();
|
|
2548
2555
|
async function readProjectConfig(projectDir) {
|
|
2549
|
-
return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(
|
|
2556
|
+
return siteplaneProjectConfigSchema.parse(JSON.parse(await readFile5(join4(projectDir, "siteplane.config.json"), "utf8")));
|
|
2550
2557
|
}
|
|
2551
2558
|
|
|
2552
2559
|
// ../cli/dist/config/credentials.js
|
|
2553
2560
|
import { execFile } from "child_process";
|
|
2554
2561
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2555
2562
|
import { chmod as chmod2, lstat, mkdir as mkdir5, open as open2, readFile as readFile6, rename as rename2, rm as rm2 } from "fs/promises";
|
|
2556
|
-
import { dirname as
|
|
2563
|
+
import { dirname as dirname6, join as join5, relative } from "path";
|
|
2557
2564
|
import { promisify } from "util";
|
|
2558
2565
|
import { z as z32 } from "zod";
|
|
2559
2566
|
var localSetupInstallationSchema = z32.object({
|
|
@@ -2578,7 +2585,7 @@ var localSetupCredentialsSchema = z32.union([
|
|
|
2578
2585
|
z32.object({ installation: localSetupInstallationSchema }).strict()
|
|
2579
2586
|
]);
|
|
2580
2587
|
async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
|
|
2581
|
-
const path =
|
|
2588
|
+
const path = join5(projectDir, ".siteplane/credentials.json");
|
|
2582
2589
|
await assertCredentialFilesystemSafe(projectDir);
|
|
2583
2590
|
const isTrackedFile = options.isTrackedFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "ls-files"));
|
|
2584
2591
|
const isIgnoredFile = options.isIgnoredFile ?? ((targetPath) => gitPathMatches(projectDir, targetPath, "check-ignore"));
|
|
@@ -2593,8 +2600,8 @@ async function assertLocalCredentialsPathSafe(projectDir, options = {}) {
|
|
|
2593
2600
|
async function assertCredentialFilesystemSafe(projectDir) {
|
|
2594
2601
|
for (const [path, directory, mode] of [
|
|
2595
2602
|
[projectDir, true, null],
|
|
2596
|
-
[
|
|
2597
|
-
[
|
|
2603
|
+
[join5(projectDir, ".siteplane"), true, 448],
|
|
2604
|
+
[join5(projectDir, ".siteplane/credentials.json"), false, 384]
|
|
2598
2605
|
]) {
|
|
2599
2606
|
const stat = await lstat(path).catch((error) => {
|
|
2600
2607
|
if (error.code === "ENOENT")
|
|
@@ -2620,7 +2627,7 @@ async function readLocalCredentials(projectDir) {
|
|
|
2620
2627
|
}
|
|
2621
2628
|
async function readLocalSetupCredentials(projectDir) {
|
|
2622
2629
|
await assertCredentialFilesystemSafe(projectDir);
|
|
2623
|
-
return localSetupCredentialsSchema.parse(JSON.parse(await readFile6(
|
|
2630
|
+
return localSetupCredentialsSchema.parse(JSON.parse(await readFile6(join5(projectDir, ".siteplane/credentials.json"), "utf8")));
|
|
2624
2631
|
}
|
|
2625
2632
|
var execFileAsync = promisify(execFile);
|
|
2626
2633
|
async function gitPathMatches(projectDir, path, command) {
|
|
@@ -2634,8 +2641,8 @@ async function gitPathMatches(projectDir, path, command) {
|
|
|
2634
2641
|
}
|
|
2635
2642
|
|
|
2636
2643
|
// ../cli/dist/commands/init.js
|
|
2637
|
-
import { access as
|
|
2638
|
-
import { join as
|
|
2644
|
+
import { access as access4 } from "fs/promises";
|
|
2645
|
+
import { join as join8, relative as relative3 } from "path";
|
|
2639
2646
|
import { z as z35 } from "zod";
|
|
2640
2647
|
|
|
2641
2648
|
// ../cli/dist/commands/setup-preflight.js
|
|
@@ -2647,7 +2654,7 @@ import { parse as parseYaml } from "yaml";
|
|
|
2647
2654
|
// ../cli/dist/config/installed-package.js
|
|
2648
2655
|
import { createRequire } from "module";
|
|
2649
2656
|
import { readFile as readFile7 } from "fs/promises";
|
|
2650
|
-
import { join as
|
|
2657
|
+
import { join as join6 } from "path";
|
|
2651
2658
|
import { z as z33 } from "zod";
|
|
2652
2659
|
var packageSchema = z33.object({
|
|
2653
2660
|
name: z33.string().optional(),
|
|
@@ -2655,10 +2662,10 @@ var packageSchema = z33.object({
|
|
|
2655
2662
|
peerDependencies: z33.record(z33.string(), z33.string()).optional()
|
|
2656
2663
|
});
|
|
2657
2664
|
async function readInstalledPackage(projectDir, name2) {
|
|
2658
|
-
const require2 = createRequire(
|
|
2665
|
+
const require2 = createRequire(join6(projectDir, "package.json"));
|
|
2659
2666
|
for (const directory of require2.resolve.paths(name2) ?? []) {
|
|
2660
2667
|
try {
|
|
2661
|
-
return packageSchema.parse(JSON.parse(await readFile7(
|
|
2668
|
+
return packageSchema.parse(JSON.parse(await readFile7(join6(directory, name2, "package.json"), "utf8")));
|
|
2662
2669
|
} catch (error) {
|
|
2663
2670
|
if (error.code !== "ENOENT")
|
|
2664
2671
|
throw error;
|
|
@@ -2668,8 +2675,8 @@ async function readInstalledPackage(projectDir, name2) {
|
|
|
2668
2675
|
}
|
|
2669
2676
|
|
|
2670
2677
|
// ../cli/dist/commands/setup-preflight.js
|
|
2671
|
-
import { access as
|
|
2672
|
-
import { dirname as
|
|
2678
|
+
import { access as access3, readFile as readFile8, realpath, readdir, readlink } from "fs/promises";
|
|
2679
|
+
import { dirname as dirname7, join as join7, relative as relative2, resolve, sep } from "path";
|
|
2673
2680
|
import { z as z34 } from "zod";
|
|
2674
2681
|
|
|
2675
2682
|
// ../cli/dist/commands/setup-process.js
|
|
@@ -2796,15 +2803,15 @@ var vercelProjectSchema = z34.object({
|
|
|
2796
2803
|
productionBranch: z34.string().optional()
|
|
2797
2804
|
}).nullable().optional()
|
|
2798
2805
|
});
|
|
2799
|
-
var exists = async (path) =>
|
|
2806
|
+
var exists = async (path) => access3(path).then(() => true, () => false);
|
|
2800
2807
|
var fail = (code, message) => {
|
|
2801
2808
|
throw new SetupFailure(code, message);
|
|
2802
2809
|
};
|
|
2803
2810
|
var stable = (version2, major) => new RegExp(`^${major}\\.\\d+\\.\\d+$`, "u").test(version2);
|
|
2804
2811
|
async function inspectSetupLocalProject(projectDir) {
|
|
2805
2812
|
const projectDirectory = await realpath(resolve(projectDir));
|
|
2806
|
-
const manifest = manifestSchema.parse(JSON.parse(await readFile8(
|
|
2807
|
-
const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(
|
|
2813
|
+
const manifest = manifestSchema.parse(JSON.parse(await readFile8(join7(projectDirectory, "package.json"), "utf8")));
|
|
2814
|
+
const apps = (await Promise.all(["app", "src/app"].map(async (path) => await exists(join7(projectDirectory, path)) ? path : null))).filter((path) => path !== null);
|
|
2808
2815
|
if (apps.length !== 1)
|
|
2809
2816
|
fail("ambiguous_app_directory", "Select one Next.js App Router application with exactly one app/ or src/app/ directory.");
|
|
2810
2817
|
const repositoryRoot = (await setupProcess("git", ["rev-parse", "--show-toplevel"], {
|
|
@@ -2818,8 +2825,8 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2818
2825
|
fail("git_submodule_conflict", "The repository contains Git submodules. Resolve the explicit deployment source boundary before setup; the CLI will not copy external repositories.");
|
|
2819
2826
|
if (!entry.startsWith("120000 "))
|
|
2820
2827
|
continue;
|
|
2821
|
-
const path =
|
|
2822
|
-
const target = resolve(
|
|
2828
|
+
const path = join7(repositoryRoot, entry.slice(entry.indexOf(" ") + 1));
|
|
2829
|
+
const target = resolve(dirname7(path), await readlink(path));
|
|
2823
2830
|
const bound = relative2(repositoryRoot, target);
|
|
2824
2831
|
if (bound.startsWith("..") || bound.startsWith(sep))
|
|
2825
2832
|
fail("external_symlink_conflict", "A tracked symbolic link points outside this repository. Resolve that source boundary before setup; local external files cannot enter a deployment.");
|
|
@@ -2835,10 +2842,10 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2835
2842
|
];
|
|
2836
2843
|
let locks = [];
|
|
2837
2844
|
for (; ; ) {
|
|
2838
|
-
locks = (await Promise.all(lockNames.map(async (name3) => await exists(
|
|
2839
|
-
if (locks.length || lockfileRoot === repositoryRoot ||
|
|
2845
|
+
locks = (await Promise.all(lockNames.map(async (name3) => await exists(join7(lockfileRoot, name3)) ? name3 : null))).filter((name3) => name3 !== null);
|
|
2846
|
+
if (locks.length || lockfileRoot === repositoryRoot || dirname7(lockfileRoot) === lockfileRoot)
|
|
2840
2847
|
break;
|
|
2841
|
-
lockfileRoot =
|
|
2848
|
+
lockfileRoot = dirname7(lockfileRoot);
|
|
2842
2849
|
}
|
|
2843
2850
|
if (locks.length > 1)
|
|
2844
2851
|
fail("conflicting_lockfiles", "Resolve conflicting package-manager lockfiles before setup; Siteplane does not replace them.");
|
|
@@ -2847,9 +2854,9 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2847
2854
|
const lockName = locks[0];
|
|
2848
2855
|
if (!["package-lock.json", "pnpm-lock.yaml"].includes(lockName))
|
|
2849
2856
|
fail("unsupported_package_manager", "This setup supports npm 10 or pnpm 9/10 with their canonical lockfile.");
|
|
2850
|
-
const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(
|
|
2857
|
+
const rootManifest = manifestSchema.parse(JSON.parse(await readFile8(join7(lockfileRoot, "package.json"), "utf8")));
|
|
2851
2858
|
if (lockfileRoot !== projectDirectory) {
|
|
2852
|
-
const workspaceFile =
|
|
2859
|
+
const workspaceFile = join7(lockfileRoot, "pnpm-workspace.yaml");
|
|
2853
2860
|
const workspace = lockName === "pnpm-lock.yaml" && await exists(workspaceFile) ? z34.object({ packages: z34.array(z34.string()) }).parse(parseYaml(await readFile8(workspaceFile, "utf8"))).packages : z34.union([
|
|
2854
2861
|
z34.array(z34.string()),
|
|
2855
2862
|
z34.object({ packages: z34.array(z34.string()) }).transform((value) => value.packages)
|
|
@@ -2858,14 +2865,14 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2858
2865
|
if (!workspace.some((pattern) => !pattern.startsWith("!") && minimatch(selected, pattern)) || workspace.some((pattern) => pattern.startsWith("!") && minimatch(selected, pattern.slice(1))))
|
|
2859
2866
|
fail("unbound_workspace_app", "The selected application is excluded from the canonical lockfile's workspace packages. Select its actual application root.");
|
|
2860
2867
|
}
|
|
2861
|
-
for (let ancestor =
|
|
2862
|
-
const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(
|
|
2868
|
+
for (let ancestor = dirname7(lockfileRoot); ancestor.startsWith(repositoryRoot + sep) || ancestor === repositoryRoot; ancestor = dirname7(ancestor)) {
|
|
2869
|
+
const ancestorLocks = await Promise.all(lockNames.map((name3) => exists(join7(ancestor, name3))));
|
|
2863
2870
|
if (ancestorLocks.some(Boolean))
|
|
2864
2871
|
fail("ambiguous_lockfile_root", "Both the selected package and its repository ancestors contain lockfiles. Select one canonical workspace resolution before setup.");
|
|
2865
2872
|
if (ancestor === repositoryRoot)
|
|
2866
2873
|
break;
|
|
2867
2874
|
}
|
|
2868
|
-
const lockText = await readFile8(
|
|
2875
|
+
const lockText = await readFile8(join7(lockfileRoot, lockName), "utf8");
|
|
2869
2876
|
const npmLock = lockName === "package-lock.json" ? z34.object({
|
|
2870
2877
|
lockfileVersion: z34.number(),
|
|
2871
2878
|
packages: z34.record(z34.string(), z34.object({
|
|
@@ -2918,9 +2925,9 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2918
2925
|
fail("lockfile_format_conflict", "The canonical lockfile format does not match npm 10 or pnpm 9/10.");
|
|
2919
2926
|
const sourceConflicts = [];
|
|
2920
2927
|
for (const file of ["next.config.js", "next.config.mjs", "next.config.ts"]) {
|
|
2921
|
-
if (!await exists(
|
|
2928
|
+
if (!await exists(join7(projectDirectory, file)))
|
|
2922
2929
|
continue;
|
|
2923
|
-
const source = await readFile8(
|
|
2930
|
+
const source = await readFile8(join7(projectDirectory, file), "utf8");
|
|
2924
2931
|
if (/output\s*:\s*['"]export['"]/u.test(source))
|
|
2925
2932
|
sourceConflicts.push("static_export");
|
|
2926
2933
|
if (/\bbasePath\s*:/u.test(source))
|
|
@@ -2940,11 +2947,11 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2940
2947
|
"src/proxy.ts",
|
|
2941
2948
|
"src/proxy.js"
|
|
2942
2949
|
]) {
|
|
2943
|
-
if (await exists(
|
|
2950
|
+
if (await exists(join7(projectDirectory, name3))) {
|
|
2944
2951
|
sourceConflicts.push(`inspect_routing:${name3}`);
|
|
2945
|
-
if (await readlink(
|
|
2952
|
+
if (await readlink(join7(projectDirectory, name3)).catch(() => null))
|
|
2946
2953
|
continue;
|
|
2947
|
-
const policySource = await readFile8(
|
|
2954
|
+
const policySource = await readFile8(join7(projectDirectory, name3), "utf8");
|
|
2948
2955
|
if (/Content-Security-Policy|img-src|default-src/iu.test(policySource))
|
|
2949
2956
|
sourceConflicts.push(`inspect_image_csp:${name3}`);
|
|
2950
2957
|
}
|
|
@@ -2953,7 +2960,7 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2953
2960
|
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
2954
2961
|
if (entry.isSymbolicLink() || ["node_modules", ".git", ".next", ".siteplane", ".vercel"].includes(entry.name))
|
|
2955
2962
|
continue;
|
|
2956
|
-
const path =
|
|
2963
|
+
const path = join7(directory, entry.name);
|
|
2957
2964
|
if (entry.isDirectory()) {
|
|
2958
2965
|
await inspectSource(path);
|
|
2959
2966
|
continue;
|
|
@@ -2973,7 +2980,7 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2973
2980
|
fail("next_security_advisory", `Next.js ${nextVersion} contains Server Actions affected by the July 2026 advisory. Review https://nextjs.org/blog/july-2026-security-release and explicitly update the affected dependency before setup.`);
|
|
2974
2981
|
}
|
|
2975
2982
|
}
|
|
2976
|
-
await inspectSource(
|
|
2983
|
+
await inspectSource(join7(projectDirectory, apps[0]));
|
|
2977
2984
|
const gitRead = async (args) => setupProcess("git", args, { cwd: projectDirectory }).then((value) => value.trim(), () => null);
|
|
2978
2985
|
return {
|
|
2979
2986
|
projectDirectory,
|
|
@@ -2985,7 +2992,7 @@ async function inspectSetupLocalProject(projectDir) {
|
|
|
2985
2992
|
nodeVersion: process.versions.node,
|
|
2986
2993
|
packageManager: { name: name2, version: localVersion, declared },
|
|
2987
2994
|
lockfile: {
|
|
2988
|
-
path: relative2(repositoryRoot,
|
|
2995
|
+
path: relative2(repositoryRoot, join7(lockfileRoot, lockName)),
|
|
2989
2996
|
format,
|
|
2990
2997
|
sha256: createHash2("sha256").update(lockText).digest("hex")
|
|
2991
2998
|
},
|
|
@@ -3004,14 +3011,14 @@ async function setupPreflightCommand(input) {
|
|
|
3004
3011
|
local = await inspectSetupLocalProject(input.projectDir);
|
|
3005
3012
|
await assertLocalCredentialsPathSafe(input.projectDir);
|
|
3006
3013
|
let linkDirectory = local.projectDirectory;
|
|
3007
|
-
while (!await exists(
|
|
3008
|
-
linkDirectory =
|
|
3009
|
-
if (!await exists(
|
|
3014
|
+
while (!await exists(join7(linkDirectory, ".vercel/project.json")) && linkDirectory !== local.repositoryRoot && dirname7(linkDirectory) !== linkDirectory)
|
|
3015
|
+
linkDirectory = dirname7(linkDirectory);
|
|
3016
|
+
if (!await exists(join7(linkDirectory, ".vercel/project.json")))
|
|
3010
3017
|
fail("vercel_project_not_linked", "Link this application to its intended Vercel project before setup; Siteplane will not guess a target.");
|
|
3011
3018
|
const linked = z34.object({
|
|
3012
3019
|
projectId: z34.string().regex(/^prj_[A-Za-z0-9]+$/u),
|
|
3013
3020
|
orgId: z34.string().regex(/^(?:team|user)_[A-Za-z0-9]+$/u)
|
|
3014
|
-
}).parse(JSON.parse(await readFile8(
|
|
3021
|
+
}).parse(JSON.parse(await readFile8(join7(linkDirectory, ".vercel/project.json"), "utf8")));
|
|
3015
3022
|
const project = vercelProjectSchema.parse(await setupVercelApi(linkDirectory, `/v9/projects/${linked.projectId}?teamId=${linked.orgId}`));
|
|
3016
3023
|
if (project.id !== linked.projectId || project.accountId !== linked.orgId)
|
|
3017
3024
|
fail("vercel_identity_conflict", "The provider project does not match the locally linked project and team.");
|
|
@@ -3122,7 +3129,7 @@ var bootstrapResponseSchema = z35.object({
|
|
|
3122
3129
|
|
|
3123
3130
|
// ../cli/dist/commands/scan.js
|
|
3124
3131
|
import { readdir as readdir2 } from "fs/promises";
|
|
3125
|
-
import { extname, join as
|
|
3132
|
+
import { extname, join as join9 } from "path";
|
|
3126
3133
|
var defaultScanRoots = ["app", "src", "pages", "components", "lib"];
|
|
3127
3134
|
var excludedDirectories = /* @__PURE__ */ new Set([
|
|
3128
3135
|
".git",
|
|
@@ -3140,14 +3147,14 @@ async function resolveScanFilePaths(filePaths, options = {}) {
|
|
|
3140
3147
|
return filePaths;
|
|
3141
3148
|
}
|
|
3142
3149
|
const projectDir = options.projectDir ?? process.cwd();
|
|
3143
|
-
const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(
|
|
3150
|
+
const discovered = await Promise.all(defaultScanRoots.map((root) => collectSourceFiles(join9(projectDir, root))));
|
|
3144
3151
|
return [...new Set(discovered.flat())].sort();
|
|
3145
3152
|
}
|
|
3146
3153
|
async function collectSourceFiles(directory) {
|
|
3147
3154
|
const entries = await readdir2(directory, { withFileTypes: true }).catch(() => []);
|
|
3148
3155
|
const files = [];
|
|
3149
3156
|
for (const entry of entries) {
|
|
3150
|
-
const entryPath =
|
|
3157
|
+
const entryPath = join9(directory, entry.name);
|
|
3151
3158
|
if (entry.isDirectory()) {
|
|
3152
3159
|
if (!excludedDirectories.has(entry.name)) {
|
|
3153
3160
|
files.push(...await collectSourceFiles(entryPath));
|
|
@@ -3168,7 +3175,7 @@ import { promisify as promisify2 } from "util";
|
|
|
3168
3175
|
import { z as z36 } from "zod";
|
|
3169
3176
|
|
|
3170
3177
|
// ../cli/dist/scan/next-source-scan.js
|
|
3171
|
-
import
|
|
3178
|
+
import ts3 from "typescript";
|
|
3172
3179
|
import { isAbsolute, relative as relative4 } from "path";
|
|
3173
3180
|
var eventPreviewHandlerMissingMessage = "Event preview fields must consume preview values with useSiteplanePreviewText from @siteplane/runtime-next/client or a siteplane:preview-value-applied listener.";
|
|
3174
3181
|
var valueCallUnusedMessage = "Siteplane value calls must feed rendered content. Assign or await the returned value and render that value instead of ignoring the call.";
|
|
@@ -3324,10 +3331,10 @@ function scanSourceFile(file, fields, hardErrors) {
|
|
|
3324
3331
|
const eventPreviewComponentPropUsages = [];
|
|
3325
3332
|
const eventPreviewConsumerFieldIds = /* @__PURE__ */ new Set();
|
|
3326
3333
|
let hasGenericEventPreviewConsumer = false;
|
|
3327
|
-
const sourceFile =
|
|
3334
|
+
const sourceFile = ts3.createSourceFile(file.filePath, file.sourceText, ts3.ScriptTarget.Latest, true, ts3.ScriptKind.TSX);
|
|
3328
3335
|
function visit(node, currentComponentName) {
|
|
3329
3336
|
const nextComponentName = getFunctionComponentName(node) ?? currentComponentName;
|
|
3330
|
-
if (
|
|
3337
|
+
if (ts3.isJsxSelfClosingElement(node) || ts3.isJsxOpeningElement(node)) {
|
|
3331
3338
|
const componentName = getJsxTagName(node.tagName);
|
|
3332
3339
|
if (editableComponentNames.has(componentName)) {
|
|
3333
3340
|
hardErrors.push({
|
|
@@ -3338,7 +3345,7 @@ function scanSourceFile(file, fields, hardErrors) {
|
|
|
3338
3345
|
}
|
|
3339
3346
|
collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables, eventPreviewComponentPropUsages, file);
|
|
3340
3347
|
}
|
|
3341
|
-
if (
|
|
3348
|
+
if (ts3.isCallExpression(node)) {
|
|
3342
3349
|
collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs, eventPreviewAttrVariables, directAttrs, file);
|
|
3343
3350
|
collectUnusedValueCallError(node, hardErrors, file);
|
|
3344
3351
|
const extractedFields = extractFunctionFields(node, file);
|
|
@@ -3362,7 +3369,7 @@ function scanSourceFile(file, fields, hardErrors) {
|
|
|
3362
3369
|
if (isGenericEventPreviewConsumerReference(node)) {
|
|
3363
3370
|
hasGenericEventPreviewConsumer = true;
|
|
3364
3371
|
}
|
|
3365
|
-
|
|
3372
|
+
ts3.forEachChild(node, (child) => visit(child, nextComponentName));
|
|
3366
3373
|
}
|
|
3367
3374
|
visit(sourceFile);
|
|
3368
3375
|
markMissingAttrsWarnings(fieldsInFile, attrFieldIds, attrRouteRefs);
|
|
@@ -3389,7 +3396,7 @@ function collectUnusedValueCallError(node, hardErrors, file) {
|
|
|
3389
3396
|
});
|
|
3390
3397
|
}
|
|
3391
3398
|
function getSiteplaneValueFunctionName(node) {
|
|
3392
|
-
if (!
|
|
3399
|
+
if (!ts3.isPropertyAccessExpression(node.expression)) {
|
|
3393
3400
|
return void 0;
|
|
3394
3401
|
}
|
|
3395
3402
|
if (node.expression.expression.getText() !== "siteplane") {
|
|
@@ -3402,16 +3409,16 @@ function getSiteplaneValueFunctionName(node) {
|
|
|
3402
3409
|
return void 0;
|
|
3403
3410
|
}
|
|
3404
3411
|
function isIgnoredValueCall(node) {
|
|
3405
|
-
if (
|
|
3412
|
+
if (ts3.isVoidExpression(node.parent)) {
|
|
3406
3413
|
return true;
|
|
3407
3414
|
}
|
|
3408
|
-
if (
|
|
3415
|
+
if (ts3.isExpressionStatement(node.parent)) {
|
|
3409
3416
|
return true;
|
|
3410
3417
|
}
|
|
3411
|
-
return
|
|
3418
|
+
return ts3.isAwaitExpression(node.parent) && ts3.isExpressionStatement(node.parent.parent);
|
|
3412
3419
|
}
|
|
3413
3420
|
function extractFunctionFields(node, file) {
|
|
3414
|
-
if (!
|
|
3421
|
+
if (!ts3.isPropertyAccessExpression(node.expression)) {
|
|
3415
3422
|
return [];
|
|
3416
3423
|
}
|
|
3417
3424
|
if (node.expression.expression.getText() !== "siteplane") {
|
|
@@ -3549,7 +3556,7 @@ function createFallbackHash(fieldType, fallback) {
|
|
|
3549
3556
|
}
|
|
3550
3557
|
}
|
|
3551
3558
|
function collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs, eventPreviewAttrVariables, directAttrs, file) {
|
|
3552
|
-
if (!
|
|
3559
|
+
if (!ts3.isPropertyAccessExpression(node.expression)) {
|
|
3553
3560
|
return;
|
|
3554
3561
|
}
|
|
3555
3562
|
if (node.expression.expression.getText() !== "siteplane" || node.expression.name.text !== "attrs") {
|
|
@@ -3578,7 +3585,7 @@ function collectAttrsCall(node, attrFieldIds, attrRouteRefs, eventPreviewAttrs,
|
|
|
3578
3585
|
}
|
|
3579
3586
|
return;
|
|
3580
3587
|
}
|
|
3581
|
-
if (firstArg &&
|
|
3588
|
+
if (firstArg && ts3.isIdentifier(firstArg) && typeof secondArg === "string") {
|
|
3582
3589
|
attrRouteRefs.add(`${firstArg.text}:${secondArg}`);
|
|
3583
3590
|
}
|
|
3584
3591
|
}
|
|
@@ -3615,7 +3622,7 @@ function hasEventPreviewStrategy(options) {
|
|
|
3615
3622
|
return !!options && typeof options === "object" && !Array.isArray(options) && options.previewStrategy === "event";
|
|
3616
3623
|
}
|
|
3617
3624
|
function isGenericEventPreviewConsumerReference(node) {
|
|
3618
|
-
return (
|
|
3625
|
+
return (ts3.isStringLiteral(node) || ts3.isNoSubstitutionTemplateLiteral(node)) && node.text === "siteplane:preview-value-applied";
|
|
3619
3626
|
}
|
|
3620
3627
|
function getPreviewHookFieldId(node, eventPreviewAttrVariables) {
|
|
3621
3628
|
const firstArg = getUseSiteplanePreviewTextFirstArg(node);
|
|
@@ -3626,7 +3633,7 @@ function getPreviewHookFieldId(node, eventPreviewAttrVariables) {
|
|
|
3626
3633
|
if (typeof directFieldId === "string") {
|
|
3627
3634
|
return directFieldId;
|
|
3628
3635
|
}
|
|
3629
|
-
if (
|
|
3636
|
+
if (ts3.isIdentifier(firstArg)) {
|
|
3630
3637
|
return eventPreviewAttrVariables.get(firstArg.text);
|
|
3631
3638
|
}
|
|
3632
3639
|
return void 0;
|
|
@@ -3636,16 +3643,16 @@ function getPreviewHookPropName(node, eventPreviewAttrVariables) {
|
|
|
3636
3643
|
if (!firstArg) {
|
|
3637
3644
|
return void 0;
|
|
3638
3645
|
}
|
|
3639
|
-
if (
|
|
3646
|
+
if (ts3.isIdentifier(firstArg) && !eventPreviewAttrVariables.has(firstArg.text)) {
|
|
3640
3647
|
return firstArg.text;
|
|
3641
3648
|
}
|
|
3642
|
-
if (
|
|
3649
|
+
if (ts3.isPropertyAccessExpression(firstArg) && ts3.isIdentifier(firstArg.expression)) {
|
|
3643
3650
|
return firstArg.name.text;
|
|
3644
3651
|
}
|
|
3645
3652
|
return void 0;
|
|
3646
3653
|
}
|
|
3647
3654
|
function getUseSiteplanePreviewTextFirstArg(node) {
|
|
3648
|
-
if (
|
|
3655
|
+
if (ts3.isIdentifier(node.expression) && node.expression.text === "useSiteplanePreviewText") {
|
|
3649
3656
|
return node.arguments[0];
|
|
3650
3657
|
}
|
|
3651
3658
|
return void 0;
|
|
@@ -3726,19 +3733,19 @@ function staticExpressionValue(expression) {
|
|
|
3726
3733
|
if (!expression) {
|
|
3727
3734
|
return void 0;
|
|
3728
3735
|
}
|
|
3729
|
-
if (
|
|
3736
|
+
if (ts3.isStringLiteral(expression) || ts3.isNoSubstitutionTemplateLiteral(expression)) {
|
|
3730
3737
|
return expression.text;
|
|
3731
3738
|
}
|
|
3732
|
-
if (
|
|
3739
|
+
if (ts3.isNumericLiteral(expression)) {
|
|
3733
3740
|
return Number(expression.text);
|
|
3734
3741
|
}
|
|
3735
|
-
if (expression.kind ===
|
|
3742
|
+
if (expression.kind === ts3.SyntaxKind.TrueKeyword) {
|
|
3736
3743
|
return true;
|
|
3737
3744
|
}
|
|
3738
|
-
if (expression.kind ===
|
|
3745
|
+
if (expression.kind === ts3.SyntaxKind.FalseKeyword) {
|
|
3739
3746
|
return false;
|
|
3740
3747
|
}
|
|
3741
|
-
if (
|
|
3748
|
+
if (ts3.isObjectLiteralExpression(expression)) {
|
|
3742
3749
|
return readObjectLiteral(expression);
|
|
3743
3750
|
}
|
|
3744
3751
|
return void 0;
|
|
@@ -3746,7 +3753,7 @@ function staticExpressionValue(expression) {
|
|
|
3746
3753
|
function readObjectLiteral(expression) {
|
|
3747
3754
|
const value = {};
|
|
3748
3755
|
for (const property of expression.properties) {
|
|
3749
|
-
if (!
|
|
3756
|
+
if (!ts3.isPropertyAssignment(property)) {
|
|
3750
3757
|
continue;
|
|
3751
3758
|
}
|
|
3752
3759
|
const name2 = getPropertyName(property.name);
|
|
@@ -3758,7 +3765,7 @@ function readObjectLiteral(expression) {
|
|
|
3758
3765
|
return value;
|
|
3759
3766
|
}
|
|
3760
3767
|
function getPropertyName(name2) {
|
|
3761
|
-
if (
|
|
3768
|
+
if (ts3.isIdentifier(name2) || ts3.isStringLiteral(name2)) {
|
|
3762
3769
|
return name2.text;
|
|
3763
3770
|
}
|
|
3764
3771
|
return null;
|
|
@@ -3769,7 +3776,7 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
|
|
|
3769
3776
|
return;
|
|
3770
3777
|
}
|
|
3771
3778
|
for (const property of node.attributes.properties) {
|
|
3772
|
-
if (!
|
|
3779
|
+
if (!ts3.isJsxAttribute(property)) {
|
|
3773
3780
|
continue;
|
|
3774
3781
|
}
|
|
3775
3782
|
const propName = getJsxAttributeName(property.name);
|
|
@@ -3786,7 +3793,7 @@ function collectEventPreviewComponentPropUsages(node, eventPreviewAttrVariables,
|
|
|
3786
3793
|
}
|
|
3787
3794
|
}
|
|
3788
3795
|
function getJsxAttributeName(name2) {
|
|
3789
|
-
if (
|
|
3796
|
+
if (ts3.isIdentifier(name2)) {
|
|
3790
3797
|
return name2.text;
|
|
3791
3798
|
}
|
|
3792
3799
|
return void 0;
|
|
@@ -3795,19 +3802,19 @@ function getJsxFieldIdValue(initializer, eventPreviewAttrVariables) {
|
|
|
3795
3802
|
if (!initializer) {
|
|
3796
3803
|
return void 0;
|
|
3797
3804
|
}
|
|
3798
|
-
if (
|
|
3805
|
+
if (ts3.isStringLiteral(initializer)) {
|
|
3799
3806
|
return initializer.text;
|
|
3800
3807
|
}
|
|
3801
|
-
if (
|
|
3808
|
+
if (ts3.isJsxExpression(initializer) && initializer.expression && ts3.isIdentifier(initializer.expression)) {
|
|
3802
3809
|
return eventPreviewAttrVariables.get(initializer.expression.text);
|
|
3803
3810
|
}
|
|
3804
3811
|
return void 0;
|
|
3805
3812
|
}
|
|
3806
3813
|
function getFunctionComponentName(node) {
|
|
3807
|
-
if (
|
|
3814
|
+
if (ts3.isFunctionDeclaration(node) && node.name && isComponentName(node.name.text)) {
|
|
3808
3815
|
return node.name.text;
|
|
3809
3816
|
}
|
|
3810
|
-
if (
|
|
3817
|
+
if (ts3.isVariableDeclaration(node) && ts3.isIdentifier(node.name) && isComponentName(node.name.text) && node.initializer && (ts3.isArrowFunction(node.initializer) || ts3.isFunctionExpression(node.initializer))) {
|
|
3811
3818
|
return node.name.text;
|
|
3812
3819
|
}
|
|
3813
3820
|
return void 0;
|
|
@@ -3817,10 +3824,10 @@ function isComponentName(name2) {
|
|
|
3817
3824
|
}
|
|
3818
3825
|
function getAssignedVariableName(node) {
|
|
3819
3826
|
let current = node;
|
|
3820
|
-
while (
|
|
3827
|
+
while (ts3.isAwaitExpression(current.parent)) {
|
|
3821
3828
|
current = current.parent;
|
|
3822
3829
|
}
|
|
3823
|
-
if (
|
|
3830
|
+
if (ts3.isVariableDeclaration(current.parent) && ts3.isIdentifier(current.parent.name)) {
|
|
3824
3831
|
return current.parent.name.text;
|
|
3825
3832
|
}
|
|
3826
3833
|
return void 0;
|
|
@@ -3990,8 +3997,8 @@ async function readGitRevision(projectDir) {
|
|
|
3990
3997
|
|
|
3991
3998
|
// ../cli/dist/commands/setup-start.js
|
|
3992
3999
|
import { randomBytes, randomUUID as randomUUID4 } from "crypto";
|
|
3993
|
-
import { access as
|
|
3994
|
-
import { join as
|
|
4000
|
+
import { access as access5 } from "fs/promises";
|
|
4001
|
+
import { join as join10, relative as relative5 } from "path";
|
|
3995
4002
|
import { z as z37 } from "zod";
|
|
3996
4003
|
var bootstrapResponseSchema2 = z37.object({
|
|
3997
4004
|
ok: z37.literal(true),
|
|
@@ -4009,10 +4016,10 @@ var responseSchema2 = z38.object({
|
|
|
4009
4016
|
}).strict();
|
|
4010
4017
|
|
|
4011
4018
|
// ../cli/dist/commands/setup-prepare.js
|
|
4012
|
-
import { access as
|
|
4019
|
+
import { access as access6, lstat as lstat2, mkdir as mkdir6, open as open3, readFile as readFile10, rename as rename3, rm as rm3 } from "fs/promises";
|
|
4013
4020
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
4014
|
-
import { dirname as
|
|
4015
|
-
import
|
|
4021
|
+
import { dirname as dirname8, join as join11, relative as relative6, sep as sep2 } from "path";
|
|
4022
|
+
import ts4 from "typescript";
|
|
4016
4023
|
|
|
4017
4024
|
// ../cli/dist/commands/setup-lock.js
|
|
4018
4025
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
@@ -4025,7 +4032,7 @@ var ownerSchema = z39.object({ pid: z39.number().int().positive(), nonce: z39.st
|
|
|
4025
4032
|
import { createHash as createHash3 } from "crypto";
|
|
4026
4033
|
import { execFile as execFile3 } from "child_process";
|
|
4027
4034
|
import { lstat as lstat4, readFile as readFile12, writeFile as writeFile5, mkdir as mkdir8 } from "fs/promises";
|
|
4028
|
-
import { dirname as
|
|
4035
|
+
import { dirname as dirname9, isAbsolute as isAbsolute2, join as join12, relative as relative7, resolve as resolve3, sep as sep3 } from "path";
|
|
4029
4036
|
import { isDeepStrictEqual, promisify as promisify3 } from "util";
|
|
4030
4037
|
import { z as z40 } from "zod";
|
|
4031
4038
|
var execute = promisify3(execFile3);
|
|
@@ -4066,15 +4073,15 @@ async function writeBuildProvenance(checkout, revision) {
|
|
|
4066
4073
|
if (entry.mode !== "120000")
|
|
4067
4074
|
continue;
|
|
4068
4075
|
const { readlink: readlink2 } = await import("fs/promises");
|
|
4069
|
-
const path =
|
|
4070
|
-
const target2 = resolve3(
|
|
4076
|
+
const path = join12(checkout, entry.path);
|
|
4077
|
+
const target2 = resolve3(dirname9(path), await readlink2(path));
|
|
4071
4078
|
const bound = relative7(checkout, target2);
|
|
4072
4079
|
if (bound.startsWith("..") || isAbsolute2(bound))
|
|
4073
4080
|
throw new Error("A tracked symbolic link escapes the committed upload; resolve that source boundary before deployment.");
|
|
4074
4081
|
}
|
|
4075
4082
|
const providerConfigurations = await Promise.all(entries.filter((entry) => /(?:^|\/)vercel\.json$/u.test(entry.path)).map(async (entry) => ({
|
|
4076
4083
|
path: entry.path,
|
|
4077
|
-
source: await readFile12(
|
|
4084
|
+
source: await readFile12(join12(checkout, entry.path), "utf8")
|
|
4078
4085
|
})));
|
|
4079
4086
|
const record = schema.parse({
|
|
4080
4087
|
version: 2,
|
|
@@ -4083,22 +4090,22 @@ async function writeBuildProvenance(checkout, revision) {
|
|
|
4083
4090
|
entries,
|
|
4084
4091
|
providerConfigurations
|
|
4085
4092
|
});
|
|
4086
|
-
const target =
|
|
4087
|
-
await mkdir8(
|
|
4093
|
+
const target = join12(checkout, name);
|
|
4094
|
+
await mkdir8(dirname9(target), { recursive: true, mode: 448 });
|
|
4088
4095
|
await writeFile5(target, JSON.stringify(record), { flag: "wx", mode: 384 });
|
|
4089
4096
|
}
|
|
4090
4097
|
async function readBuildProvenance(projectDirectory) {
|
|
4091
4098
|
let root = resolve3(projectDirectory);
|
|
4092
4099
|
let raw = null;
|
|
4093
4100
|
for (; ; ) {
|
|
4094
|
-
raw = await readFile12(
|
|
4101
|
+
raw = await readFile12(join12(root, name), "utf8").catch((error) => {
|
|
4095
4102
|
if (error.code === "ENOENT")
|
|
4096
4103
|
return null;
|
|
4097
4104
|
throw error;
|
|
4098
4105
|
});
|
|
4099
|
-
if (raw !== null ||
|
|
4106
|
+
if (raw !== null || dirname9(root) === root)
|
|
4100
4107
|
break;
|
|
4101
|
-
root =
|
|
4108
|
+
root = dirname9(root);
|
|
4102
4109
|
}
|
|
4103
4110
|
if (raw === null)
|
|
4104
4111
|
return null;
|
|
@@ -4124,7 +4131,7 @@ async function readBuildProvenance(projectDirectory) {
|
|
|
4124
4131
|
if (!bound.has(appRelative ? `${appRelative}/package.json` : "package.json"))
|
|
4125
4132
|
throw new Error("The selected app is not part of the committed upload.");
|
|
4126
4133
|
for (const entry of record.entries) {
|
|
4127
|
-
const path =
|
|
4134
|
+
const path = join12(root, entry.path);
|
|
4128
4135
|
const stat = await lstat4(path).catch((error) => {
|
|
4129
4136
|
if (error.code === "ENOENT")
|
|
4130
4137
|
return null;
|
|
@@ -4194,9 +4201,9 @@ function treeHash(entries) {
|
|
|
4194
4201
|
|
|
4195
4202
|
// ../cli/dist/commands/setup-deploy.js
|
|
4196
4203
|
import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "crypto";
|
|
4197
|
-
import { access as
|
|
4204
|
+
import { access as access7, mkdir as mkdir9, mkdtemp, rm as rm5, writeFile as writeFile6 } from "fs/promises";
|
|
4198
4205
|
import { tmpdir } from "os";
|
|
4199
|
-
import { join as
|
|
4206
|
+
import { join as join13 } from "path";
|
|
4200
4207
|
import { z as z41 } from "zod";
|
|
4201
4208
|
var envSchema = z41.object({
|
|
4202
4209
|
id: z41.string(),
|
|
@@ -4282,6 +4289,54 @@ async function scanNextProjectFieldContract(projectDir) {
|
|
|
4282
4289
|
}
|
|
4283
4290
|
async function withSiteplane(nextConfig, options = {}) {
|
|
4284
4291
|
const projectDir = options.projectDir ?? process.cwd();
|
|
4292
|
+
const booking = options.booking;
|
|
4293
|
+
let integrated = nextConfig;
|
|
4294
|
+
if (booking) {
|
|
4295
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
|
|
4296
|
+
booking.site
|
|
4297
|
+
))
|
|
4298
|
+
throw new Error(
|
|
4299
|
+
"Siteplane booking.site must be the Site ID from Booking settings."
|
|
4300
|
+
);
|
|
4301
|
+
for (const folder of ["app/booking", "src/app/booking"]) {
|
|
4302
|
+
if (await access8(join14(projectDir, folder)).then(
|
|
4303
|
+
() => true,
|
|
4304
|
+
() => false
|
|
4305
|
+
))
|
|
4306
|
+
console.warn(
|
|
4307
|
+
"[Siteplane] An app/booking route exists. The Booking beforeFiles rewrite takes precedence; move that route or remove the Booking integration."
|
|
4308
|
+
);
|
|
4309
|
+
}
|
|
4310
|
+
integrated = {
|
|
4311
|
+
...nextConfig,
|
|
4312
|
+
rewrites: async () => {
|
|
4313
|
+
const existing = await nextConfig.rewrites?.() ?? [];
|
|
4314
|
+
const rules = Array.isArray(existing) ? { beforeFiles: [], afterFiles: existing, fallback: [] } : existing;
|
|
4315
|
+
return {
|
|
4316
|
+
beforeFiles: [
|
|
4317
|
+
{
|
|
4318
|
+
source: "/booking",
|
|
4319
|
+
destination: `https://siteplane.io/booking?site=${booking.site}`
|
|
4320
|
+
},
|
|
4321
|
+
{
|
|
4322
|
+
source: "/booking/:path*",
|
|
4323
|
+
destination: `https://siteplane.io/booking/:path*?site=${booking.site}`
|
|
4324
|
+
},
|
|
4325
|
+
...rules.beforeFiles ?? []
|
|
4326
|
+
],
|
|
4327
|
+
afterFiles: rules.afterFiles ?? [],
|
|
4328
|
+
fallback: rules.fallback ?? []
|
|
4329
|
+
};
|
|
4330
|
+
}
|
|
4331
|
+
};
|
|
4332
|
+
const hasEditor = await access8(
|
|
4333
|
+
join14(projectDir, "siteplane.config.json")
|
|
4334
|
+
).then(
|
|
4335
|
+
() => true,
|
|
4336
|
+
() => false
|
|
4337
|
+
);
|
|
4338
|
+
if (!hasEditor) return { ...integrated, env: { ...nextConfig.env } };
|
|
4339
|
+
}
|
|
4285
4340
|
const config = await readProjectConfig(projectDir);
|
|
4286
4341
|
const scan = await scanNextProjectFieldContract(projectDir);
|
|
4287
4342
|
const requestedRevision = options.buildRevision?.trim() || process.env.SITEPLANE_BUILD_REVISION?.trim();
|
|
@@ -4307,7 +4362,7 @@ async function withSiteplane(nextConfig, options = {}) {
|
|
|
4307
4362
|
);
|
|
4308
4363
|
const imageOrigin = hasImages ? readImageWebsiteOrigin() : null;
|
|
4309
4364
|
return {
|
|
4310
|
-
...
|
|
4365
|
+
...integrated,
|
|
4311
4366
|
...hasImages ? { images: prepareImagePatterns(nextConfig.images, imageOrigin) } : {},
|
|
4312
4367
|
headers: async () => frameHeaders(
|
|
4313
4368
|
await nextConfig.headers?.() ?? [],
|
|
@@ -4335,18 +4390,30 @@ async function readGitRevision2(projectDir) {
|
|
|
4335
4390
|
}
|
|
4336
4391
|
function frameHeaders(rules, adminOrigin, imageOrigin) {
|
|
4337
4392
|
const policy = `frame-ancestors 'self' ${adminOrigin}`;
|
|
4338
|
-
const hasFrameOptions = rules.some(
|
|
4393
|
+
const hasFrameOptions = rules.some(
|
|
4394
|
+
(rule) => rule.headers.some(
|
|
4395
|
+
(header) => header.key.toLowerCase() === "x-frame-options"
|
|
4396
|
+
)
|
|
4397
|
+
);
|
|
4339
4398
|
const prepared = rules.map((rule) => ({
|
|
4340
4399
|
...rule,
|
|
4341
4400
|
headers: rule.headers.map((header) => {
|
|
4342
4401
|
if (header.key.toLowerCase() !== "content-security-policy") return header;
|
|
4343
|
-
const ancestors = /(?:^|;)\s*frame-ancestors\s+([^;]+)/iu.test(
|
|
4402
|
+
const ancestors = /(?:^|;)\s*frame-ancestors\s+([^;]+)/iu.test(
|
|
4403
|
+
header.value
|
|
4404
|
+
);
|
|
4344
4405
|
const value = ancestors || hasFrameOptions ? header.value : `${header.value.replace(/;\s*$/u, "")}; ${policy}`;
|
|
4345
|
-
return {
|
|
4406
|
+
return {
|
|
4407
|
+
...header,
|
|
4408
|
+
value: imageOrigin ? prepareImageCsp(value, imageOrigin) : value
|
|
4409
|
+
};
|
|
4346
4410
|
})
|
|
4347
4411
|
}));
|
|
4348
4412
|
return hasFrameOptions ? prepared : [
|
|
4349
|
-
{
|
|
4413
|
+
{
|
|
4414
|
+
source: "/:path*",
|
|
4415
|
+
headers: [{ key: "Content-Security-Policy", value: policy }]
|
|
4416
|
+
},
|
|
4350
4417
|
...prepared
|
|
4351
4418
|
];
|
|
4352
4419
|
}
|
|
@@ -4451,7 +4518,7 @@ async function emitBuildProof(projectDir, packages, revision, fieldContractHash)
|
|
|
4451
4518
|
let lock = null;
|
|
4452
4519
|
while (true) {
|
|
4453
4520
|
lock = await readFile13(
|
|
4454
|
-
|
|
4521
|
+
join14(
|
|
4455
4522
|
directory,
|
|
4456
4523
|
packageManager === "npm" ? "package-lock.json" : "pnpm-lock.yaml"
|
|
4457
4524
|
),
|
|
@@ -4460,8 +4527,8 @@ async function emitBuildProof(projectDir, packages, revision, fieldContractHash)
|
|
|
4460
4527
|
if (error.code === "ENOENT") return null;
|
|
4461
4528
|
throw error;
|
|
4462
4529
|
});
|
|
4463
|
-
if (lock !== null ||
|
|
4464
|
-
directory =
|
|
4530
|
+
if (lock !== null || dirname10(directory) === directory) break;
|
|
4531
|
+
directory = dirname10(directory);
|
|
4465
4532
|
}
|
|
4466
4533
|
if (!lock)
|
|
4467
4534
|
throw new SiteplaneNextContractError(
|