Setting the file. One moment.
Seed Members · Wix Headless Fast · wix/skills · Skills Docs
ContentsBack to the top of the page references/members/seed/seed-members.mjs
references/members/seed/ seed-members.mjs
JavaScript · 94 lines · 4 KB
// Seeding is ADDITIVE — never deletes or overwrites existing content. Authoritative source:
15 // wix-headless/references/SETUP.md § members (the appDefId and the identity/profile split).
16 import { execFileSync } from "node:child_process" ;
17 import { readFileSync } from "node:fs" ;
18
19 const API = "https://www.wixapis.com" ;
20 // The Wix Members Area app (the profile layer). Not in the "Apps Created by Wix" table —
21 // the GUID comes from the App Market listing; recorded in wix-headless/references/SETUP.md.
22 // Installing it pulls in its Site-Members dependency automatically.
23 const MEMBERS_AREA_APP_ID = "14cc59bc-f0b7-15b8-e1c7-89ce41d0e0c9" ;
24
25 export function makeCtx ({ cwd = process. cwd () } = {}) {
26 const config = JSON . parse ( readFileSync ( `${ cwd }/wix.config.json` , "utf8" ));
27 const siteId = config.siteId ?? config.projectId;
28 if ( ! siteId) throw new Error ( "wix.config.json has no siteId — is this a Wix CLI project?" );
29 const token = execFileSync ( "npx" , [ "@wix/cli@latest" , "token" , "--site" , siteId], {
30 encoding: "utf8" ,
31 cwd,
32 }). trim ();
33 if ( ! token) throw new Error ( "The Wix CLI returned no token — run `npx @wix/cli@latest login` first." );
34 return { token, siteId };
35 }
36
37 async function req ( ctx , path , { method = "POST" , body } = {}) {
38 const res = await fetch ( API + path, {
39 method,
40 headers: {
41 Authorization: `Bearer ${ ctx . token }` ,
42 "wix-site-id" : ctx.siteId,
43 "Content-Type" : "application/json" ,
44 },
45 body: body ? JSON . stringify (body) : undefined ,
46 });
47 const json = await res. json (). catch (() => ({}));
48 if ( ! res.ok) throw new Error ( `${ method } ${ path } -> ${ res . status }: ${ JSON . stringify ( json ). slice ( 0 , 400 ) }` );
49 return json;
50 }
51
52 // ---- operations ----------------------------------------------------------------------------------
53
54 /**
55 * Install the Wix Members Area app (idempotent in effect: re-running against a site that
56 * already has it errors — recorded in the result, not thrown, since "already installed" and
57 * a real failure aren't distinguishable from the response).
58 * docs: https://dev.wix.com/docs/api-reference/articles/work-with-wix-apis/platform/about-apps-created-by-wix.md
59 */
60 export async function installMembersAreaApp ( ctx ) {
61 try {
62 await req (ctx, "/apps-installer-service/v1/app-instance/install" , { body: {
63 tenant: { tenantType: "SITE" , id: ctx.siteId },
64 appInstance: { appDefId: MEMBERS_AREA_APP_ID , enabled: true },
65 } });
66 return { requested: true , note: null };
67 } catch (e) {
68 return { requested: false , note: String (e.message). slice ( 0 , 300 ) };
69 }
70 }
71
72 /** ONE-CALL seed: install the Members Area app (the profile layer). The default path. */
73 export async function setupMembers ( ctx , { installMembersArea = true } = {}) {
74 return {
75 membersAreaAppId: MEMBERS_AREA_APP_ID ,
76 membersAreaInstall: installMembersArea ? await installMembersAreaApp (ctx) : { skipped: true },
77 membersCreated: 0 , // members self-register — never created at build time
78 };
79 }
80
81 // ---- CLI entry ----------------------------------------------------------------------------------
82
83 const invokedDirectly = process.argv[ 1 ] && import . meta .url. endsWith (process.argv[ 1 ]. split ( "/" ). pop ());
84 if (invokedDirectly) {
85 const planPath = process.argv[ 2 ];
86 const plan = planPath ? JSON . parse ( readFileSync (planPath, "utf8" )) : {};
87 const ctx = makeCtx ();
88 setupMembers (ctx, plan)
89 . then (( result ) => console. log ( JSON . stringify (result, null , 2 )))
90 . catch (( e ) => {
91 console. error (e.message);
92 process. exit ( 1 );
93 });
94 }