← Files WixARCHIVED FILE
skills/wix-headless-templates/members/seed/seed-members.mjs
4 KB · Oct 8, 2026 · 12:02 UTC
// Members seed — a BUILD-TIME script, never shipped in the app. Run from the project root
// (where wix.config.json lives); the plan file is optional:
//
// node <SKILL_ROOT>/templates/members/seed/seed-members.mjs [plan.json]
//
// Members SELF-REGISTER — there is no member content to create (see SEED.md). The one
// build-time setup this vertical needs is installing the Wix Members Area app, which serves
// member PROFILE data: without it getCurrentMember() returns nothing for a logged-in member,
// so the account page can't render who they are. Identity alone (log in / log out / gating)
// needs no install. Prints a JSON result to stdout.
//
// Plan shape (see SEED.md): { "installMembersArea": true } // default true
//
// Seeding is ADDITIVE — never deletes or overwrites existing content. The appDefId below is the
// Members Area app's App Market id; the identity/profile split is described beside it.
import { seedSiteId } from "../../shared/seed/site-context.mjs";
import { wixToken } from "../../shared/seed/wix-cli.mjs";
import { readFileSync } from "node:fs";
const API = "https://www.wixapis.com";
// The Wix Members Area app (the profile layer). Not in the "Apps Created by Wix" table —
// the GUID comes from the App Market listing.
// Installing it pulls in its Site-Members dependency automatically.
const MEMBERS_AREA_APP_ID = "14cc59bc-f0b7-15b8-e1c7-89ce41d0e0c9";
export function makeCtx({ cwd = process.cwd() } = {}) {
// The content site: the config's site, or the parent on a migration preview (site-context.mjs stops
// a seed there unless --allow-parent is passed after the user confirmed).
const siteId = seedSiteId({ cwd, argv: process.argv });
const token = wixToken(siteId, cwd);
return { token, siteId };
}
async function req(ctx, path, { method = "POST", body } = {}) {
const res = await fetch(API + path, {
method,
headers: {
Authorization: `Bearer ${ctx.token}`,
"wix-site-id": ctx.siteId,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
const json = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(`${method} ${path} -> ${res.status}: ${JSON.stringify(json).slice(0, 400)}`);
return json;
}
// ---- operations ----------------------------------------------------------------------------------
/**
* Install the Wix Members Area app (idempotent in effect: re-running against a site that
* already has it errors — recorded in the result, not thrown, since "already installed" and
* a real failure aren't distinguishable from the response).
* docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
*/
export async function installMembersAreaApp(ctx) {
try {
await req(ctx, "/apps-installer-service/v1/app-instance/install", { body: {
tenant: { tenantType: "SITE", id: ctx.siteId },
appInstance: { appDefId: MEMBERS_AREA_APP_ID, enabled: true },
} });
return { requested: true, note: null };
} catch (e) {
return { requested: false, note: String(e.message).slice(0, 300) };
}
}
/** ONE-CALL seed: install the Members Area app (the profile layer). The default path. */
export async function setupMembers(ctx, { installMembersArea = true } = {}) {
return {
membersAreaAppId: MEMBERS_AREA_APP_ID,
membersAreaInstall: installMembersArea ? await installMembersAreaApp(ctx) : { skipped: true },
membersCreated: 0, // members self-register — never created at build time
};
}
// ---- CLI entry ----------------------------------------------------------------------------------
const invokedDirectly = process.argv[1] && import.meta.url.endsWith(process.argv[1].split("/").pop());
if (invokedDirectly) {
const planPath = process.argv[2];
const plan = planPath ? JSON.parse(readFileSync(planPath, "utf8")) : {};
const ctx = makeCtx();
setupMembers(ctx, plan)
.then((result) => console.log(JSON.stringify(result, null, 2)))
.catch((e) => {
console.error(e.message);
process.exit(1);
});
}
SHA-256: b1980c9a4b9f777b083c9250dd6987f3da390d2d86700f1ab0d8e447c57c390e