@whop/react-native 0.0.11 → 0.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/cli/index.js +360 -41
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +357 -38
- package/dist/cli/index.mjs.map +1 -1
- package/dist/lib/index.d.mts +18 -1
- package/dist/lib/index.d.ts +18 -1
- package/dist/lib/index.js +305 -5
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +295 -5
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/web.mjs +228 -0
- package/dist/lib/web.mjs.map +1 -0
- package/package.json +63 -5
package/dist/cli/index.js
CHANGED
|
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
27
|
var import_node_fs2 = require("fs");
|
|
28
|
-
var
|
|
28
|
+
var import_node_path4 = __toESM(require("path"));
|
|
29
29
|
var import_node_util = require("util");
|
|
30
30
|
var import_find_up2 = require("find-up");
|
|
31
31
|
var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
|
|
@@ -33,8 +33,8 @@ var import_rimraf = require("rimraf");
|
|
|
33
33
|
|
|
34
34
|
// src/cli/mobile.ts
|
|
35
35
|
var import_node_fs = require("fs");
|
|
36
|
-
var
|
|
37
|
-
var
|
|
36
|
+
var import_promises2 = require("fs/promises");
|
|
37
|
+
var import_node_path2 = __toESM(require("path"));
|
|
38
38
|
var import_metro_config = require("@react-native/metro-config");
|
|
39
39
|
var import_find_up = require("find-up");
|
|
40
40
|
var import_jszip = __toESM(require("jszip"));
|
|
@@ -85,7 +85,29 @@ async function getChecksum(data) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// src/cli/valid-view-type.ts
|
|
88
|
-
var
|
|
88
|
+
var import_promises = require("fs/promises");
|
|
89
|
+
var import_node_path = __toESM(require("path"));
|
|
90
|
+
var VALID_VIEW_TYPES = [
|
|
91
|
+
"experience-view",
|
|
92
|
+
"discover-view",
|
|
93
|
+
"dashboard-view"
|
|
94
|
+
];
|
|
95
|
+
async function getSupportedAppViewTypes(root) {
|
|
96
|
+
const views = await (0, import_promises.readdir)(import_node_path.default.join(root, "src", "views"), {
|
|
97
|
+
withFileTypes: true,
|
|
98
|
+
recursive: false
|
|
99
|
+
});
|
|
100
|
+
const files = views.filter((file) => file.isFile()).map((file) => file.name.split(".")[0]).filter((file) => !!file);
|
|
101
|
+
const validViews = files.filter(
|
|
102
|
+
(file) => VALID_VIEW_TYPES.includes(file)
|
|
103
|
+
);
|
|
104
|
+
if (validViews.length === 0) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`No valid views found, please create a view in the src/views folder and name it with a valid view type: ${VALID_VIEW_TYPES.join(", ")}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return validViews;
|
|
110
|
+
}
|
|
89
111
|
|
|
90
112
|
// src/cli/mobile.ts
|
|
91
113
|
async function buildAndPublish(root, platform, {
|
|
@@ -104,14 +126,14 @@ async function buildAndPublish(root, platform, {
|
|
|
104
126
|
}
|
|
105
127
|
async function bundle(root, platform) {
|
|
106
128
|
await makeEntrypoint(root, platform);
|
|
107
|
-
const outputFile =
|
|
129
|
+
const outputFile = import_node_path2.default.join(
|
|
108
130
|
root,
|
|
109
131
|
"build",
|
|
110
132
|
"output",
|
|
111
133
|
platform,
|
|
112
134
|
"main_js_bundle"
|
|
113
135
|
);
|
|
114
|
-
await (0,
|
|
136
|
+
await (0, import_promises2.mkdir)(import_node_path2.default.dirname(outputFile), { recursive: true });
|
|
115
137
|
const defaultConfig = (0, import_metro_config.getDefaultConfig)(root);
|
|
116
138
|
const babelLocation = require.resolve("@babel/runtime/package");
|
|
117
139
|
const bableNodeModules = await (0, import_find_up.findUp)("node_modules", {
|
|
@@ -131,7 +153,7 @@ async function bundle(root, platform) {
|
|
|
131
153
|
},
|
|
132
154
|
watchFolders: [
|
|
133
155
|
root,
|
|
134
|
-
|
|
156
|
+
import_node_path2.default.resolve(root, "node_modules"),
|
|
135
157
|
bableNodeModules
|
|
136
158
|
],
|
|
137
159
|
reporter: new CustomReporter(),
|
|
@@ -152,30 +174,14 @@ async function bundle(root, platform) {
|
|
|
152
174
|
out: outputFile
|
|
153
175
|
}
|
|
154
176
|
);
|
|
155
|
-
await (0,
|
|
177
|
+
await (0, import_promises2.rename)(
|
|
156
178
|
`${outputFile}.js`,
|
|
157
|
-
|
|
179
|
+
import_node_path2.default.join(root, "build", "output", platform, "main_js_bundle.hbc")
|
|
158
180
|
);
|
|
159
181
|
console.log(` \u2714\uFE0E [${platform}] bundle created`);
|
|
160
182
|
}
|
|
161
|
-
async function getSupportedAppViewTypes(root) {
|
|
162
|
-
const views = await (0, import_promises.readdir)(import_node_path.default.join(root, "src", "views"), {
|
|
163
|
-
withFileTypes: true,
|
|
164
|
-
recursive: false
|
|
165
|
-
});
|
|
166
|
-
const files = views.filter((file) => file.isFile()).map((file) => file.name.split(".")[0]).filter((file) => !!file);
|
|
167
|
-
const validViews = files.filter(
|
|
168
|
-
(file) => VALID_VIEW_TYPES.includes(file)
|
|
169
|
-
);
|
|
170
|
-
if (validViews.length === 0) {
|
|
171
|
-
throw new Error(
|
|
172
|
-
`No valid views found, please create a view in the src/views folder and name it with a valid view type: ${VALID_VIEW_TYPES.join(", ")}`
|
|
173
|
-
);
|
|
174
|
-
}
|
|
175
|
-
return validViews;
|
|
176
|
-
}
|
|
177
183
|
async function makeEntrypoint(root, platform) {
|
|
178
|
-
const entrypoint =
|
|
184
|
+
const entrypoint = import_node_path2.default.join(
|
|
179
185
|
root,
|
|
180
186
|
"build",
|
|
181
187
|
"entrypoints",
|
|
@@ -195,16 +201,16 @@ ${imports.join("\n")}
|
|
|
195
201
|
|
|
196
202
|
${registry.join("\n")}
|
|
197
203
|
`;
|
|
198
|
-
const entrypointDir =
|
|
199
|
-
await (0,
|
|
200
|
-
await (0,
|
|
204
|
+
const entrypointDir = import_node_path2.default.dirname(entrypoint);
|
|
205
|
+
await (0, import_promises2.mkdir)(entrypointDir, { recursive: true });
|
|
206
|
+
await (0, import_promises2.writeFile)(entrypoint, entrypointContent, "utf-8");
|
|
201
207
|
console.log(` \u2714\uFE0E [${platform}] entrypoint created`);
|
|
202
208
|
return entrypoint;
|
|
203
209
|
}
|
|
204
210
|
async function createMobileBuild(root, platform) {
|
|
205
211
|
const viewTypes = await getSupportedAppViewTypes(root);
|
|
206
|
-
const fullDirectory =
|
|
207
|
-
const mainJsBundle =
|
|
212
|
+
const fullDirectory = import_node_path2.default.join(root, "build", "output", platform);
|
|
213
|
+
const mainJsBundle = import_node_path2.default.join(fullDirectory, "main_js_bundle.hbc");
|
|
208
214
|
if (!(0, import_node_fs.existsSync)(mainJsBundle)) {
|
|
209
215
|
throw new Error(`main_js_bundle.hbc not found in ${fullDirectory}`);
|
|
210
216
|
}
|
|
@@ -227,7 +233,7 @@ async function createMobileBuild(root, platform) {
|
|
|
227
233
|
console.log(
|
|
228
234
|
` \u2714\uFE0E [${platform}] uploaded build: ${fileName} (${(zipData.length / 1024).toFixed(0)} KB)`
|
|
229
235
|
);
|
|
230
|
-
const
|
|
236
|
+
const build2 = await whopSdk.apps.createAppBuild({
|
|
231
237
|
attachment: { directUploadId: uploadedFile.directUploadId },
|
|
232
238
|
checksum,
|
|
233
239
|
platform,
|
|
@@ -238,25 +244,25 @@ async function createMobileBuild(root, platform) {
|
|
|
238
244
|
})[view]
|
|
239
245
|
)
|
|
240
246
|
});
|
|
241
|
-
if (!
|
|
247
|
+
if (!build2) {
|
|
242
248
|
throw new Error("Failed to create app build");
|
|
243
249
|
}
|
|
244
|
-
const dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds
|
|
250
|
+
const dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds/?platform=${platform}`;
|
|
245
251
|
console.log(`
|
|
246
252
|
\u2714\uFE0E [${platform}] deployed as development build \u2714\uFE0E
|
|
247
|
-
- build id: ${
|
|
253
|
+
- build id: ${build2.id}
|
|
248
254
|
- view types: ${viewTypes.join(", ")}
|
|
249
255
|
- promote to production here: ${dashboardUrl}
|
|
250
256
|
`);
|
|
251
|
-
return
|
|
257
|
+
return build2;
|
|
252
258
|
}
|
|
253
259
|
async function zipDirectory(directory) {
|
|
254
260
|
const zip = new import_jszip.default();
|
|
255
261
|
function addFilesToZip(currentPath, relativePath = "") {
|
|
256
262
|
const items = (0, import_node_fs.readdirSync)(currentPath);
|
|
257
263
|
for (const item of items) {
|
|
258
|
-
const fullPath =
|
|
259
|
-
const zipPath = relativePath ?
|
|
264
|
+
const fullPath = import_node_path2.default.join(currentPath, item);
|
|
265
|
+
const zipPath = relativePath ? import_node_path2.default.join(relativePath, item) : item;
|
|
260
266
|
const stats = (0, import_node_fs.statSync)(fullPath);
|
|
261
267
|
if (stats.isDirectory()) {
|
|
262
268
|
addFilesToZip(fullPath, zipPath);
|
|
@@ -275,6 +281,319 @@ var CustomReporter = class {
|
|
|
275
281
|
}
|
|
276
282
|
};
|
|
277
283
|
|
|
284
|
+
// src/cli/web.ts
|
|
285
|
+
var import_promises3 = require("fs/promises");
|
|
286
|
+
var import_node_path3 = __toESM(require("path"));
|
|
287
|
+
var import_esbuild = require("esbuild");
|
|
288
|
+
|
|
289
|
+
// src/cli/reanimated-bable.ts
|
|
290
|
+
var fs = __toESM(require("fs/promises"));
|
|
291
|
+
var path3 = __toESM(require("path"));
|
|
292
|
+
var babel = __toESM(require("@babel/core"));
|
|
293
|
+
var JS_RE = /\.(m|c)?(t|j)sx?$/;
|
|
294
|
+
function reanimatedBabelPlugin() {
|
|
295
|
+
const shouldTransform = (p) => {
|
|
296
|
+
if (!JS_RE.test(p)) return false;
|
|
297
|
+
if (p.includes(`${path3.sep}react-native-reanimated${path3.sep}`))
|
|
298
|
+
return true;
|
|
299
|
+
if (p.includes(`${path3.sep}node_modules${path3.sep}`)) return false;
|
|
300
|
+
return p.includes(`${path3.sep}src${path3.sep}`);
|
|
301
|
+
};
|
|
302
|
+
return {
|
|
303
|
+
name: "reanimated-babel",
|
|
304
|
+
setup(b) {
|
|
305
|
+
b.onLoad({ filter: JS_RE }, async (args) => {
|
|
306
|
+
if (!shouldTransform(args.path)) {
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
const code = await fs.readFile(args.path, "utf8");
|
|
310
|
+
const result = await babel.transformAsync(code, {
|
|
311
|
+
filename: args.path,
|
|
312
|
+
sourceMaps: false,
|
|
313
|
+
babelrc: false,
|
|
314
|
+
configFile: false,
|
|
315
|
+
// ORDER MATTERS: Reanimated plugin MUST BE LAST
|
|
316
|
+
plugins: [
|
|
317
|
+
// Needed by Reanimated on web per docs
|
|
318
|
+
"@babel/plugin-transform-export-namespace-from",
|
|
319
|
+
// Handle Flow types present in some RN libs
|
|
320
|
+
[
|
|
321
|
+
"@babel/plugin-transform-flow-strip-types",
|
|
322
|
+
{ allowDeclareFields: true }
|
|
323
|
+
],
|
|
324
|
+
// MUST be last
|
|
325
|
+
[
|
|
326
|
+
"react-native-reanimated/plugin",
|
|
327
|
+
{ relativeSourceLocation: true }
|
|
328
|
+
]
|
|
329
|
+
],
|
|
330
|
+
presets: [],
|
|
331
|
+
// esbuild handles TS/JSX syntax; no preset-env/preset-react
|
|
332
|
+
caller: { name: "esbuild" },
|
|
333
|
+
// Let Babel parse TS/JSX/Flow; keep it broad
|
|
334
|
+
parserOpts: { plugins: ["jsx", "typescript"] },
|
|
335
|
+
generatorOpts: { decoratorsBeforeExport: true }
|
|
336
|
+
});
|
|
337
|
+
return {
|
|
338
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
339
|
+
contents: result.code,
|
|
340
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
341
|
+
loader: pickLoader(args.path)
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function pickLoader(file) {
|
|
348
|
+
const ext = path3.extname(file).toLowerCase();
|
|
349
|
+
if (ext === ".tsx") return "tsx";
|
|
350
|
+
if (ext === ".ts") return "ts";
|
|
351
|
+
if (ext === ".jsx") return "jsx";
|
|
352
|
+
return "jsx";
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// src/cli/strip-flow.ts
|
|
356
|
+
var fs2 = __toESM(require("fs/promises"));
|
|
357
|
+
var babel2 = __toESM(require("@babel/core"));
|
|
358
|
+
function stripFlowWithBabel() {
|
|
359
|
+
const filter = /\.(m|c)?jsx?$/;
|
|
360
|
+
return {
|
|
361
|
+
name: "strip-flow-with-babel",
|
|
362
|
+
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
|
|
363
|
+
setup(b) {
|
|
364
|
+
b.onLoad({ filter }, async (args) => {
|
|
365
|
+
const code = await fs2.readFile(args.path, "utf8");
|
|
366
|
+
const out = await babel2.transformAsync(code, {
|
|
367
|
+
filename: args.path,
|
|
368
|
+
babelrc: false,
|
|
369
|
+
configFile: false,
|
|
370
|
+
plugins: [
|
|
371
|
+
[
|
|
372
|
+
"@babel/plugin-transform-flow-strip-types",
|
|
373
|
+
{ allowDeclareFields: true }
|
|
374
|
+
]
|
|
375
|
+
],
|
|
376
|
+
parserOpts: { plugins: ["jsx", "flow"] },
|
|
377
|
+
sourceMaps: false
|
|
378
|
+
});
|
|
379
|
+
return { contents: out.code, loader: "jsx" };
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// src/cli/web.ts
|
|
386
|
+
function aliasReactNativePlugin() {
|
|
387
|
+
return {
|
|
388
|
+
name: "alias-react-native",
|
|
389
|
+
setup(b) {
|
|
390
|
+
b.onResolve({ filter: /^react-native$/ }, () => ({
|
|
391
|
+
path: require.resolve("react-native-web")
|
|
392
|
+
}));
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
function forceSingleReact() {
|
|
397
|
+
const map = /* @__PURE__ */ new Map([
|
|
398
|
+
["react", require.resolve("react")],
|
|
399
|
+
["react/jsx-runtime", require.resolve("react/jsx-runtime")],
|
|
400
|
+
["react/jsx-dev-runtime", require.resolve("react/jsx-dev-runtime")],
|
|
401
|
+
["react-dom", require.resolve("react-dom")],
|
|
402
|
+
["react-dom/client", require.resolve("react-dom/client")]
|
|
403
|
+
]);
|
|
404
|
+
const rx = /^(react(?:\/jsx-(?:dev-)?runtime)?|react-dom(?:\/client)?)$/;
|
|
405
|
+
return {
|
|
406
|
+
name: "force-single-react",
|
|
407
|
+
setup(b) {
|
|
408
|
+
b.onResolve({ filter: rx }, (args) => ({ path: map.get(args.path) }));
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function toPascalCase(str) {
|
|
413
|
+
return str.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
414
|
+
}
|
|
415
|
+
async function makeWebEntrypoint(root) {
|
|
416
|
+
const files = await getSupportedAppViewTypes(root);
|
|
417
|
+
const packageJsonPath = import_node_path3.default.join(root, "package.json");
|
|
418
|
+
const packageJson = JSON.parse(await (0, import_promises3.readFile)(packageJsonPath, "utf-8"));
|
|
419
|
+
const hasReactNativeReanimated = packageJson.dependencies?.["react-native-reanimated"];
|
|
420
|
+
const imports = files.map(
|
|
421
|
+
(file) => `import { ${toPascalCase(file)} } from "../../../src/views/${file}";`
|
|
422
|
+
);
|
|
423
|
+
const registry = files.map(
|
|
424
|
+
(file) => `AppRegistry.registerComponent("${toPascalCase(file)}", () => WhopNavigationWrapper(React, "${toPascalCase(file)}", ${toPascalCase(file)}));`
|
|
425
|
+
);
|
|
426
|
+
const defaultKey = toPascalCase(files[0] ?? "experience-view");
|
|
427
|
+
const reanimatedImport = hasReactNativeReanimated ? `import "react-native-reanimated";` : "";
|
|
428
|
+
const entry = `import { AppRegistry } from "react-native";
|
|
429
|
+
import * as React from "react";
|
|
430
|
+
import { WhopNavigationWrapper } from "@whop/react-native/web";
|
|
431
|
+
${reanimatedImport}
|
|
432
|
+
|
|
433
|
+
${imports.join("\n")}
|
|
434
|
+
|
|
435
|
+
${registry.join("\n")}
|
|
436
|
+
|
|
437
|
+
const viewType = new URLSearchParams(window.location.search).get("app_view") ?? "${defaultKey}";
|
|
438
|
+
|
|
439
|
+
const root = document.getElementById("root") || (() => {
|
|
440
|
+
const d = document.createElement("div");
|
|
441
|
+
d.id = "root";
|
|
442
|
+
document.body.appendChild(d);
|
|
443
|
+
return d;
|
|
444
|
+
})();
|
|
445
|
+
AppRegistry.runApplication(viewType, { rootTag: root });
|
|
446
|
+
`;
|
|
447
|
+
const entryFile = import_node_path3.default.join(root, "build", "entrypoints", "web", "index.tsx");
|
|
448
|
+
await (0, import_promises3.mkdir)(import_node_path3.default.dirname(entryFile), { recursive: true });
|
|
449
|
+
await (0, import_promises3.writeFile)(entryFile, entry, "utf-8");
|
|
450
|
+
return entryFile;
|
|
451
|
+
}
|
|
452
|
+
async function bundleWeb(root) {
|
|
453
|
+
const entry = await makeWebEntrypoint(root);
|
|
454
|
+
const outDir = import_node_path3.default.join(root, "build", "output", "web");
|
|
455
|
+
await (0, import_promises3.mkdir)(outDir, { recursive: true });
|
|
456
|
+
await (0, import_esbuild.build)({
|
|
457
|
+
entryPoints: [entry],
|
|
458
|
+
outfile: import_node_path3.default.join(outDir, "main.js"),
|
|
459
|
+
bundle: true,
|
|
460
|
+
minify: false,
|
|
461
|
+
format: "esm",
|
|
462
|
+
platform: "browser",
|
|
463
|
+
sourcemap: false,
|
|
464
|
+
jsx: "automatic",
|
|
465
|
+
mainFields: ["browser", "module", "main"],
|
|
466
|
+
conditions: ["browser", "import", "default"],
|
|
467
|
+
define: {
|
|
468
|
+
process: "{}",
|
|
469
|
+
"process.env": "{}",
|
|
470
|
+
"process.env.NODE_ENV": '"production"',
|
|
471
|
+
__DEV__: "false",
|
|
472
|
+
"process.env.NEXT_PUBLIC_WHOP_APP_ID": `"${APP_ID}"`,
|
|
473
|
+
// Some RN libraries (e.g., RNGH) expect a Node-like global in the browser
|
|
474
|
+
global: "globalThis"
|
|
475
|
+
},
|
|
476
|
+
resolveExtensions: [
|
|
477
|
+
".web.tsx",
|
|
478
|
+
".web.ts",
|
|
479
|
+
".web.js",
|
|
480
|
+
".tsx",
|
|
481
|
+
".ts",
|
|
482
|
+
".jsx",
|
|
483
|
+
".js"
|
|
484
|
+
],
|
|
485
|
+
loader: {
|
|
486
|
+
".png": "dataurl",
|
|
487
|
+
".jpg": "dataurl",
|
|
488
|
+
".jpeg": "dataurl",
|
|
489
|
+
".svg": "dataurl",
|
|
490
|
+
".ttf": "dataurl",
|
|
491
|
+
".woff": "dataurl",
|
|
492
|
+
".woff2": "dataurl",
|
|
493
|
+
".js": "jsx",
|
|
494
|
+
".jsx": "jsx"
|
|
495
|
+
},
|
|
496
|
+
plugins: [
|
|
497
|
+
forceSingleReact(),
|
|
498
|
+
aliasReactNativePlugin(),
|
|
499
|
+
reanimatedBabelPlugin(),
|
|
500
|
+
stripFlowWithBabel(),
|
|
501
|
+
{
|
|
502
|
+
name: "force-native-web-stub",
|
|
503
|
+
setup(b) {
|
|
504
|
+
b.onResolve({ filter: /^\.\/native-whop-core$/ }, (args) => {
|
|
505
|
+
return {
|
|
506
|
+
path: import_node_path3.default.join(args.resolveDir, "native-whop-core"),
|
|
507
|
+
namespace: "file"
|
|
508
|
+
};
|
|
509
|
+
});
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
]
|
|
513
|
+
});
|
|
514
|
+
const html = `<!doctype html>
|
|
515
|
+
<html>
|
|
516
|
+
<head>
|
|
517
|
+
<meta charset="utf-8" />
|
|
518
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
519
|
+
<title>Whop App (Web)</title>
|
|
520
|
+
<style>
|
|
521
|
+
#root {
|
|
522
|
+
width: 100vw;
|
|
523
|
+
height: 100vh;
|
|
524
|
+
margin: 0;
|
|
525
|
+
padding: 0;
|
|
526
|
+
overflow: hidden;
|
|
527
|
+
display: flex;
|
|
528
|
+
flex-direction: column;
|
|
529
|
+
align-items: stretch;
|
|
530
|
+
justify-content: start;
|
|
531
|
+
}
|
|
532
|
+
</style>
|
|
533
|
+
</head>
|
|
534
|
+
<body>
|
|
535
|
+
<div id="root"></div>
|
|
536
|
+
<script type="module" src="./main.js"></script>
|
|
537
|
+
</body>
|
|
538
|
+
</html>`;
|
|
539
|
+
await (0, import_promises3.writeFile)(import_node_path3.default.join(outDir, "index.html"), html, "utf-8");
|
|
540
|
+
console.log(" \u2714\uFE0E [web] bundle created at build/output/web/main.js");
|
|
541
|
+
}
|
|
542
|
+
async function buildAndPublish2(root, {
|
|
543
|
+
shouldBuild = true,
|
|
544
|
+
shouldUpload = true
|
|
545
|
+
} = {
|
|
546
|
+
shouldBuild: true,
|
|
547
|
+
shouldUpload: true
|
|
548
|
+
}) {
|
|
549
|
+
if (shouldBuild) {
|
|
550
|
+
await bundleWeb(root);
|
|
551
|
+
}
|
|
552
|
+
if (shouldUpload) {
|
|
553
|
+
await createWebBuild(root);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
async function createWebBuild(root) {
|
|
557
|
+
const fullDirectory = import_node_path3.default.join(root, "build", "output", "web");
|
|
558
|
+
const mainJsFile = import_node_path3.default.join(fullDirectory, "main.js");
|
|
559
|
+
try {
|
|
560
|
+
await (0, import_promises3.readFile)(mainJsFile);
|
|
561
|
+
} catch {
|
|
562
|
+
throw new Error(`main.js not found in ${fullDirectory}`);
|
|
563
|
+
}
|
|
564
|
+
const buf = await (0, import_promises3.readFile)(mainJsFile);
|
|
565
|
+
const checksum = await getChecksum(buf);
|
|
566
|
+
console.log(` \u2714\uFE0E [web] build checksummed: ${checksum}`);
|
|
567
|
+
const fileName = `rnweb_${checksum}.js`;
|
|
568
|
+
const uploadedFile = await uploadFile(
|
|
569
|
+
buf,
|
|
570
|
+
fileName,
|
|
571
|
+
"application/javascript"
|
|
572
|
+
);
|
|
573
|
+
console.log(
|
|
574
|
+
` \u2714\uFE0E [web] uploaded build: ${fileName} (${(buf.length / 1024).toFixed(0)} KB)`
|
|
575
|
+
);
|
|
576
|
+
const build2 = await whopSdk.apps.createAppBuild({
|
|
577
|
+
attachment: { directUploadId: uploadedFile.directUploadId },
|
|
578
|
+
checksum,
|
|
579
|
+
platform: "web",
|
|
580
|
+
supportedAppViewTypes: ["hub"]
|
|
581
|
+
});
|
|
582
|
+
if (!build2) {
|
|
583
|
+
throw new Error("Failed to create app build");
|
|
584
|
+
}
|
|
585
|
+
const dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds/?platform=web`;
|
|
586
|
+
console.log(
|
|
587
|
+
`
|
|
588
|
+
\u2714\uFE0E [web] deployed as development build \u2714\uFE0E
|
|
589
|
+
- build id: ${build2.id}
|
|
590
|
+
- view types: hub
|
|
591
|
+
- promote to production here: ${dashboardUrl}
|
|
592
|
+
`
|
|
593
|
+
);
|
|
594
|
+
return build2;
|
|
595
|
+
}
|
|
596
|
+
|
|
278
597
|
// src/cli/index.ts
|
|
279
598
|
async function main() {
|
|
280
599
|
const args = (0, import_node_util.parseArgs)({
|
|
@@ -336,12 +655,12 @@ async function main() {
|
|
|
336
655
|
promises.push(buildAndPublish(root, "android", opts));
|
|
337
656
|
}
|
|
338
657
|
if (args.values.web || !didProvidePlatform) {
|
|
339
|
-
|
|
658
|
+
promises.push(buildAndPublish2(root, opts));
|
|
340
659
|
}
|
|
341
660
|
await Promise.all(promises);
|
|
342
661
|
}
|
|
343
662
|
async function cleanBuildDirectory(root) {
|
|
344
|
-
const buildDirectory =
|
|
663
|
+
const buildDirectory = import_node_path4.default.join(root, "build");
|
|
345
664
|
if ((0, import_node_fs2.existsSync)(buildDirectory)) {
|
|
346
665
|
await (0, import_rimraf.rimraf)(buildDirectory);
|
|
347
666
|
}
|
|
@@ -354,7 +673,7 @@ async function getRootProjectDirectory() {
|
|
|
354
673
|
"please run this command inside a whop react native project"
|
|
355
674
|
);
|
|
356
675
|
}
|
|
357
|
-
const root =
|
|
676
|
+
const root = import_node_path4.default.dirname(file);
|
|
358
677
|
return root;
|
|
359
678
|
}
|
|
360
679
|
async function handleInstall() {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/mobile.ts","../../src/cli/file.ts","../../src/cli/sdk.ts","../../src/cli/valid-view-type.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { findUp } from \"find-up\";\nimport qrcode from \"qrcode-terminal\";\nimport { rimraf } from \"rimraf\";\nimport { buildAndPublish } from \"./mobile\";\nimport { env } from \"./sdk\";\n\nasync function main() {\n\tconst args = parseArgs({\n\t\toptions: {\n\t\t\tios: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t\tandroid: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t\tweb: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t},\n\t\tstrict: true,\n\t\tallowPositionals: true,\n\t\targs: process.argv.slice(2),\n\t});\n\n\tconst [command] = args.positionals;\n\n\tif (command === \"install\") {\n\t\tawait handleInstall();\n\t\treturn;\n\t}\n\n\tlet shouldBuild = true;\n\tlet shouldUpload = true;\n\tlet shouldClean = true;\n\tif (command === \"build\") {\n\t\tshouldUpload = false;\n\t} else if (command === \"ship\") {\n\t\tshouldBuild = true;\n\t\tshouldUpload = true;\n\t} else if (command === \"upload\") {\n\t\tshouldBuild = false;\n\t\tshouldClean = false;\n\t} else if (command === \"clean\") {\n\t\tshouldBuild = false;\n\t\tshouldUpload = false;\n\t} else {\n\t\tconsole.error(\n\t\t\t`Usage:\n\twhop-react-native ship [--ios] [--android] [--web] # runs build and then publishes it as a dev build to whop.\n\twhop-react-native build [--ios] [--android] [--web] # builds your app into a distributable bundle in the build/ directory.\n\twhop-react-native upload [--ios] [--android] [--web] # uploads the existing build directory to whop.\n\twhop-react-native clean # cleans the build directory.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tconst root = await getRootProjectDirectory();\n\n\tif (shouldClean) {\n\t\tawait cleanBuildDirectory(root);\n\t}\n\n\tconst didProvidePlatform =\n\t\targs.values.ios || args.values.android || args.values.web;\n\n\tconst opts = { shouldBuild, shouldUpload };\n\tconst promises: Promise<void>[] = [];\n\n\tif (args.values.ios || !didProvidePlatform) {\n\t\tpromises.push(buildAndPublish(root, \"ios\", opts));\n\t}\n\tif (args.values.android || !didProvidePlatform) {\n\t\tpromises.push(buildAndPublish(root, \"android\", opts));\n\t}\n\tif (args.values.web || !didProvidePlatform) {\n\t\tconsole.warn(\" - [web] builds for web are not supported yet - coming soon\");\n\t}\n\n\tawait Promise.all(promises);\n}\n\nasync function cleanBuildDirectory(root: string) {\n\tconst buildDirectory = path.join(root, \"build\");\n\tif (existsSync(buildDirectory)) {\n\t\tawait rimraf(buildDirectory);\n\t}\n\tconsole.log(\" ✔︎ cleaned build directory\");\n}\n\nasync function getRootProjectDirectory() {\n\tconst file = await findUp(\"package.json\", { cwd: process.cwd() });\n\tif (!file) {\n\t\tthrow new Error(\n\t\t\t\"please run this command inside a whop react native project\",\n\t\t);\n\t}\n\tconst root = path.dirname(file);\n\treturn root;\n}\n\nasync function handleInstall() {\n\tconst appId = env(\"NEXT_PUBLIC_WHOP_APP_ID\");\n\tconst installLink = `https://whop.com/apps/${appId}/install`;\n\n\tconsole.log(`\nOpen this link in your browser to install the app into your whop.\n${installLink}\n\nOr scan the QR code with your iPhone:\n\t`);\n\n\tqrcode.generate(installLink, { small: true });\n}\n\nmain()\n\t.catch((err) => {\n\t\tconsole.error(err);\n\t\tprocess.exit(1);\n\t})\n\t.then(() => {\n\t\tprocess.exit(0);\n\t});\n","import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { mkdir, readdir, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getDefaultConfig } from \"@react-native/metro-config\";\nimport { findUp } from \"find-up\";\nimport JSZip from \"jszip\";\nimport { type ReportableEvent, type Reporter, runBuild } from \"metro\";\nimport { getChecksum, uploadFile } from \"./file\";\nimport { APP_ID, COMPANY_ID, whopSdk } from \"./sdk\";\nimport { VALID_VIEW_TYPES } from \"./valid-view-type\";\n\nexport async function buildAndPublish(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n\t{\n\t\tshouldBuild = true,\n\t\tshouldUpload = true,\n\t}: { shouldBuild: boolean; shouldUpload: boolean } = {\n\t\tshouldBuild: true,\n\t\tshouldUpload: true,\n\t},\n) {\n\tif (shouldBuild) {\n\t\tawait bundle(root, platform);\n\t}\n\tif (shouldUpload) {\n\t\tawait createMobileBuild(root, platform);\n\t}\n}\n\nexport async function bundle(root: string, platform: \"ios\" | \"android\") {\n\tawait makeEntrypoint(root, platform);\n\n\tconst outputFile = path.join(\n\t\troot,\n\t\t\"build\",\n\t\t\"output\",\n\t\tplatform,\n\t\t\"main_js_bundle\",\n\t);\n\tawait mkdir(path.dirname(outputFile), { recursive: true });\n\n\tconst defaultConfig = getDefaultConfig(root);\n\n\tconst babelLocation = require.resolve(\"@babel/runtime/package\");\n\n\tconst bableNodeModules = await findUp(\"node_modules\", {\n\t\tcwd: babelLocation,\n\t\ttype: \"directory\",\n\t});\n\tif (!bableNodeModules) {\n\t\tthrow new Error(\"babel node_modules parent folder not found\");\n\t}\n\n\tawait runBuild(\n\t\t{\n\t\t\t...defaultConfig,\n\t\t\tprojectRoot: root,\n\t\t\ttransformer: {\n\t\t\t\t...defaultConfig.transformer,\n\t\t\t\tbabelTransformerPath: require.resolve(\n\t\t\t\t\t\"./whop-react-native-babel-transformer.js\",\n\t\t\t\t),\n\t\t\t},\n\t\t\twatchFolders: [\n\t\t\t\troot,\n\t\t\t\tpath.resolve(root, \"node_modules\"),\n\t\t\t\tbableNodeModules,\n\t\t\t],\n\t\t\treporter: new CustomReporter(),\n\t\t\tresolver: {\n\t\t\t\t...defaultConfig.resolver,\n\t\t\t\tnodeModulesPaths: [\n\t\t\t\t\t...(defaultConfig.resolver?.nodeModulesPaths ?? []),\n\t\t\t\t\tbableNodeModules,\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdev: false,\n\t\t\tentry: `build/entrypoints/${platform}/index.js`,\n\t\t\tminify: false,\n\t\t\tplatform: platform,\n\t\t\tsourceMap: false,\n\t\t\tout: outputFile,\n\t\t},\n\t);\n\n\tawait rename(\n\t\t`${outputFile}.js`,\n\t\tpath.join(root, \"build\", \"output\", platform, \"main_js_bundle.hbc\"),\n\t);\n\n\tconsole.log(` ✔︎ [${platform}] bundle created`);\n}\n\nasync function getSupportedAppViewTypes(\n\troot: string,\n): Promise<(typeof VALID_VIEW_TYPES)[number][]> {\n\tconst views = await readdir(path.join(root, \"src\", \"views\"), {\n\t\twithFileTypes: true,\n\t\trecursive: false,\n\t});\n\tconst files = views\n\t\t.filter((file) => file.isFile())\n\t\t.map((file) => file.name.split(\".\")[0])\n\t\t.filter((file) => !!file);\n\n\tconst validViews = files.filter((file) =>\n\t\tVALID_VIEW_TYPES.includes(file as (typeof VALID_VIEW_TYPES)[number]),\n\t) as (typeof VALID_VIEW_TYPES)[number][];\n\n\tif (validViews.length === 0) {\n\t\tthrow new Error(\n\t\t\t`No valid views found, please create a view in the src/views folder and name it with a valid view type: ${VALID_VIEW_TYPES.join(\", \")}`,\n\t\t);\n\t}\n\n\treturn validViews;\n}\n\nasync function makeEntrypoint(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n): Promise<string> {\n\tconst entrypoint = path.join(\n\t\troot,\n\t\t\"build\",\n\t\t\"entrypoints\",\n\t\tplatform,\n\t\t\"index.js\",\n\t);\n\n\tconst files = await getSupportedAppViewTypes(root);\n\n\tconst pascalCase = (str: string) =>\n\t\tstr\n\t\t\t.split(\"-\")\n\t\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n\t\t\t.join(\"\");\n\n\tconst imports = files.map(\n\t\t(file) =>\n\t\t\t`import { ${pascalCase(file)} } from \"../../../src/views/${file}\";`,\n\t);\n\tconst registry = files.map(\n\t\t(file) =>\n\t\t\t`AppRegistry.registerComponent(\"${pascalCase(file)}\", () => ${pascalCase(file)});`,\n\t);\n\n\tconst entrypointContent = `import { AppRegistry } from \"react-native\";\n${imports.join(\"\\n\")}\n\n${registry.join(\"\\n\")}\n`;\n\n\tconst entrypointDir = path.dirname(entrypoint);\n\tawait mkdir(entrypointDir, { recursive: true });\n\tawait writeFile(entrypoint, entrypointContent, \"utf-8\");\n\n\tconsole.log(` ✔︎ [${platform}] entrypoint created`);\n\n\treturn entrypoint;\n}\n\nexport async function createMobileBuild(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n) {\n\tconst viewTypes = await getSupportedAppViewTypes(root);\n\n\tconst fullDirectory = path.join(root, \"build\", \"output\", platform);\n\n\t// Check if the directory contains a file called `main_js_bundle.hbc`\n\tconst mainJsBundle = path.join(fullDirectory, \"main_js_bundle.hbc\");\n\n\tif (!existsSync(mainJsBundle)) {\n\t\tthrow new Error(`main_js_bundle.hbc not found in ${fullDirectory}`);\n\t}\n\n\t// check that that folder only contains the main_js_bundle.hbc file and an optional `assets` folder\n\tconst files = readdirSync(fullDirectory);\n\tif (\n\t\tfiles.length > 2 ||\n\t\tfiles.length < 1 ||\n\t\t!files.includes(\"main_js_bundle.hbc\")\n\t) {\n\t\tthrow new Error(\n\t\t\t\"Directory must contain only the main_js_bundle.hbc file and an optional `assets` folder\",\n\t\t);\n\t}\n\tif (files.length === 2 && !files.includes(\"assets\")) {\n\t\tthrow new Error(\n\t\t\t\"Directory must contain only the main_js_bundle.hbc file and an optional `assets` folder\",\n\t\t);\n\t}\n\n\t// Zip the directory\n\tconst zipData = await zipDirectory(fullDirectory);\n\n\tconst checksum = await getChecksum(zipData);\n\n\tconsole.log(` ✔︎ [${platform}] build zipped with checksum: ${checksum}`);\n\n\tconst fileName = `app_build_${platform}.zip`;\n\tconst uploadedFile = await uploadFile(zipData, fileName, \"application/zip\");\n\n\tconsole.log(\n\t\t` ✔︎ [${platform}] uploaded build: ${fileName} (${(zipData.length / 1024).toFixed(0)} KB)`,\n\t);\n\n\tconst build = await whopSdk.apps.createAppBuild({\n\t\tattachment: { directUploadId: uploadedFile.directUploadId },\n\t\tchecksum,\n\t\tplatform,\n\t\tsupportedAppViewTypes: viewTypes.map(\n\t\t\t(view) =>\n\t\t\t\t({\n\t\t\t\t\t\"experience-view\": \"hub\" as const,\n\t\t\t\t\t\"discover-view\": \"discover\" as const,\n\t\t\t\t})[view],\n\t\t),\n\t});\n\n\tif (!build) {\n\t\tthrow new Error(\"Failed to create app build\");\n\t}\n\n\tconst dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds/`;\n\n\tconsole.log(`\\n ✔︎ [${platform}] deployed as development build ✔︎\n - build id: ${build.id}\n - view types: ${viewTypes.join(\", \")}\n - promote to production here: ${dashboardUrl}\\n`);\n\n\treturn build;\n}\n\nasync function zipDirectory(\n\tdirectory: string,\n): Promise<Buffer<ArrayBufferLike>> {\n\tconst zip = new JSZip();\n\n\t// Recursively add files to zip\n\tfunction addFilesToZip(currentPath: string, relativePath = \"\") {\n\t\tconst items = readdirSync(currentPath);\n\n\t\tfor (const item of items) {\n\t\t\tconst fullPath = path.join(currentPath, item);\n\t\t\tconst zipPath = relativePath ? path.join(relativePath, item) : item;\n\t\t\tconst stats = statSync(fullPath);\n\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddFilesToZip(fullPath, zipPath);\n\t\t\t} else {\n\t\t\t\tconst fileContent = readFileSync(fullPath);\n\t\t\t\tzip.file(zipPath, fileContent);\n\t\t\t}\n\t\t}\n\t}\n\n\taddFilesToZip(directory);\n\n\t// Generate zip file\n\tconst zipData = await zip.generateAsync({ type: \"nodebuffer\" });\n\n\treturn zipData;\n}\n\nclass CustomReporter implements Reporter {\n\tupdate(event: ReportableEvent) {\n\t\t// Do nothing.\n\t}\n}\n","import { createHash } from \"node:crypto\";\nimport { AGENT_USER_ID, APP_ID, whopSdk } from \"./sdk\";\n\nexport async function uploadFile(\n\tdata: Buffer<ArrayBufferLike>,\n\tname: string,\n\tcontentType: string,\n) {\n\tconst file = new File([data], name, {\n\t\ttype: contentType,\n\t});\n\n\tconst uploadedFile = await whopSdk\n\t\t.withUser(AGENT_USER_ID)\n\t\t.attachments.uploadAttachment({\n\t\t\tfile,\n\t\t\trecord: \"app\",\n\t\t\tid: APP_ID,\n\t\t});\n\n\treturn uploadedFile;\n}\n\nexport async function getChecksum(data: Buffer<ArrayBufferLike>) {\n\tconst hash = createHash(\"sha256\");\n\thash.update(data);\n\treturn hash.digest(\"hex\");\n}\n","import { WhopServerSdk } from \"@whop/api\";\nimport { config } from \"dotenv\";\n\nconfig({\n\tpath: [\".env\", \".env.local\", \".env.development\", \".env.production\"],\n});\n\nexport function env(key: string) {\n\tconst value = process.env[key];\n\tif (!value) {\n\t\tthrow new Error(`Missing environment variable: ${key}`);\n\t}\n\treturn value;\n}\n\nexport const AGENT_USER_ID = env(\"NEXT_PUBLIC_WHOP_AGENT_USER_ID\");\nexport const COMPANY_ID = env(\"NEXT_PUBLIC_WHOP_COMPANY_ID\");\nexport const APP_ID = env(\"NEXT_PUBLIC_WHOP_APP_ID\");\n\nexport const whopSdk: WhopServerSdk = WhopServerSdk({\n\tappApiKey: env(\"WHOP_API_KEY\"),\n\tappId: APP_ID,\n\tcompanyId: COMPANY_ID,\n\tonBehalfOfUserId: AGENT_USER_ID,\n});\n","export const VALID_VIEW_TYPES = [\"experience-view\", \"discover-view\"] as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,kBAA2B;AAC3B,IAAAC,oBAAiB;AACjB,uBAA0B;AAC1B,IAAAC,kBAAuB;AACvB,6BAAmB;AACnB,oBAAuB;;;ACLvB,qBAAgE;AAChE,sBAAkD;AAClD,uBAAiB;AACjB,0BAAiC;AACjC,qBAAuB;AACvB,mBAAkB;AAClB,mBAA8D;;;ACN9D,yBAA2B;;;ACA3B,iBAA8B;AAC9B,oBAAuB;AAAA,IAEvB,sBAAO;AAAA,EACN,MAAM,CAAC,QAAQ,cAAc,oBAAoB,iBAAiB;AACnE,CAAC;AAEM,SAAS,IAAI,KAAa;AAChC,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,MAAI,CAAC,OAAO;AACX,UAAM,IAAI,MAAM,iCAAiC,GAAG,EAAE;AAAA,EACvD;AACA,SAAO;AACR;AAEO,IAAM,gBAAgB,IAAI,gCAAgC;AAC1D,IAAM,aAAa,IAAI,6BAA6B;AACpD,IAAM,SAAS,IAAI,yBAAyB;AAE5C,IAAM,cAAyB,0BAAc;AAAA,EACnD,WAAW,IAAI,cAAc;AAAA,EAC7B,OAAO;AAAA,EACP,WAAW;AAAA,EACX,kBAAkB;AACnB,CAAC;;;ADrBD,eAAsB,WACrB,MACA,MACA,aACC;AACD,QAAM,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,MAAM;AAAA,IACnC,MAAM;AAAA,EACP,CAAC;AAED,QAAM,eAAe,MAAM,QACzB,SAAS,aAAa,EACtB,YAAY,iBAAiB;AAAA,IAC7B;AAAA,IACA,QAAQ;AAAA,IACR,IAAI;AAAA,EACL,CAAC;AAEF,SAAO;AACR;AAEA,eAAsB,YAAY,MAA+B;AAChE,QAAM,WAAO,+BAAW,QAAQ;AAChC,OAAK,OAAO,IAAI;AAChB,SAAO,KAAK,OAAO,KAAK;AACzB;;;AE3BO,IAAM,mBAAmB,CAAC,mBAAmB,eAAe;;;AHWnE,eAAsB,gBACrB,MACA,UACA;AAAA,EACC,cAAc;AAAA,EACd,eAAe;AAChB,IAAqD;AAAA,EACpD,aAAa;AAAA,EACb,cAAc;AACf,GACC;AACD,MAAI,aAAa;AAChB,UAAM,OAAO,MAAM,QAAQ;AAAA,EAC5B;AACA,MAAI,cAAc;AACjB,UAAM,kBAAkB,MAAM,QAAQ;AAAA,EACvC;AACD;AAEA,eAAsB,OAAO,MAAc,UAA6B;AACvE,QAAM,eAAe,MAAM,QAAQ;AAEnC,QAAM,aAAa,iBAAAC,QAAK;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACA,YAAM,uBAAM,iBAAAA,QAAK,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAEzD,QAAM,oBAAgB,sCAAiB,IAAI;AAE3C,QAAM,gBAAgB,gBAAgB,wBAAwB;AAE9D,QAAM,mBAAmB,UAAM,uBAAO,gBAAgB;AAAA,IACrD,KAAK;AAAA,IACL,MAAM;AAAA,EACP,CAAC;AACD,MAAI,CAAC,kBAAkB;AACtB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC7D;AAEA,YAAM;AAAA,IACL;AAAA,MACC,GAAG;AAAA,MACH,aAAa;AAAA,MACb,aAAa;AAAA,QACZ,GAAG,cAAc;AAAA,QACjB,sBAAsB,gBACrB,0CACD;AAAA,MACD;AAAA,MACA,cAAc;AAAA,QACb;AAAA,QACA,iBAAAA,QAAK,QAAQ,MAAM,cAAc;AAAA,QACjC;AAAA,MACD;AAAA,MACA,UAAU,IAAI,eAAe;AAAA,MAC7B,UAAU;AAAA,QACT,GAAG,cAAc;AAAA,QACjB,kBAAkB;AAAA,UACjB,GAAI,cAAc,UAAU,oBAAoB,CAAC;AAAA,UACjD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,KAAK;AAAA,MACL,OAAO,qBAAqB,QAAQ;AAAA,MACpC,QAAQ;AAAA,MACR;AAAA,MACA,WAAW;AAAA,MACX,KAAK;AAAA,IACN;AAAA,EACD;AAEA,YAAM;AAAA,IACL,GAAG,UAAU;AAAA,IACb,iBAAAA,QAAK,KAAK,MAAM,SAAS,UAAU,UAAU,oBAAoB;AAAA,EAClE;AAEA,UAAQ,IAAI,kBAAQ,QAAQ,kBAAkB;AAC/C;AAEA,eAAe,yBACd,MAC+C;AAC/C,QAAM,QAAQ,UAAM,yBAAQ,iBAAAA,QAAK,KAAK,MAAM,OAAO,OAAO,GAAG;AAAA,IAC5D,eAAe;AAAA,IACf,WAAW;AAAA,EACZ,CAAC;AACD,QAAM,QAAQ,MACZ,OAAO,CAAC,SAAS,KAAK,OAAO,CAAC,EAC9B,IAAI,CAAC,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,EACrC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI;AAEzB,QAAM,aAAa,MAAM;AAAA,IAAO,CAAC,SAChC,iBAAiB,SAAS,IAAyC;AAAA,EACpE;AAEA,MAAI,WAAW,WAAW,GAAG;AAC5B,UAAM,IAAI;AAAA,MACT,0GAA0G,iBAAiB,KAAK,IAAI,CAAC;AAAA,IACtI;AAAA,EACD;AAEA,SAAO;AACR;AAEA,eAAe,eACd,MACA,UACkB;AAClB,QAAM,aAAa,iBAAAA,QAAK;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD;AAEA,QAAM,QAAQ,MAAM,yBAAyB,IAAI;AAEjD,QAAM,aAAa,CAAC,QACnB,IACE,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,EAAE;AAEV,QAAM,UAAU,MAAM;AAAA,IACrB,CAAC,SACA,YAAY,WAAW,IAAI,CAAC,+BAA+B,IAAI;AAAA,EACjE;AACA,QAAM,WAAW,MAAM;AAAA,IACtB,CAAC,SACA,kCAAkC,WAAW,IAAI,CAAC,YAAY,WAAW,IAAI,CAAC;AAAA,EAChF;AAEA,QAAM,oBAAoB;AAAA,EACzB,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EAElB,SAAS,KAAK,IAAI,CAAC;AAAA;AAGpB,QAAM,gBAAgB,iBAAAA,QAAK,QAAQ,UAAU;AAC7C,YAAM,uBAAM,eAAe,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAM,2BAAU,YAAY,mBAAmB,OAAO;AAEtD,UAAQ,IAAI,kBAAQ,QAAQ,sBAAsB;AAElD,SAAO;AACR;AAEA,eAAsB,kBACrB,MACA,UACC;AACD,QAAM,YAAY,MAAM,yBAAyB,IAAI;AAErD,QAAM,gBAAgB,iBAAAA,QAAK,KAAK,MAAM,SAAS,UAAU,QAAQ;AAGjE,QAAM,eAAe,iBAAAA,QAAK,KAAK,eAAe,oBAAoB;AAElE,MAAI,KAAC,2BAAW,YAAY,GAAG;AAC9B,UAAM,IAAI,MAAM,mCAAmC,aAAa,EAAE;AAAA,EACnE;AAGA,QAAM,YAAQ,4BAAY,aAAa;AACvC,MACC,MAAM,SAAS,KACf,MAAM,SAAS,KACf,CAAC,MAAM,SAAS,oBAAoB,GACnC;AACD,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACA,MAAI,MAAM,WAAW,KAAK,CAAC,MAAM,SAAS,QAAQ,GAAG;AACpD,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAGA,QAAM,UAAU,MAAM,aAAa,aAAa;AAEhD,QAAM,WAAW,MAAM,YAAY,OAAO;AAE1C,UAAQ,IAAI,kBAAQ,QAAQ,iCAAiC,QAAQ,EAAE;AAEvE,QAAM,WAAW,aAAa,QAAQ;AACtC,QAAM,eAAe,MAAM,WAAW,SAAS,UAAU,iBAAiB;AAE1E,UAAQ;AAAA,IACP,kBAAQ,QAAQ,qBAAqB,QAAQ,MAAM,QAAQ,SAAS,MAAM,QAAQ,CAAC,CAAC;AAAA,EACrF;AAEA,QAAM,QAAQ,MAAM,QAAQ,KAAK,eAAe;AAAA,IAC/C,YAAY,EAAE,gBAAgB,aAAa,eAAe;AAAA,IAC1D;AAAA,IACA;AAAA,IACA,uBAAuB,UAAU;AAAA,MAChC,CAAC,UACC;AAAA,QACA,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,MAClB,GAAG,IAAI;AAAA,IACT;AAAA,EACD,CAAC;AAED,MAAI,CAAC,OAAO;AACX,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC7C;AAEA,QAAM,eAAe,8BAA8B,UAAU,mBAAmB,MAAM;AAEtF,UAAQ,IAAI;AAAA,iBAAU,QAAQ;AAAA,iBACd,MAAM,EAAE;AAAA,mBACN,UAAU,KAAK,IAAI,CAAC;AAAA,mCACJ,YAAY;AAAA,CAAI;AAElD,SAAO;AACR;AAEA,eAAe,aACd,WACmC;AACnC,QAAM,MAAM,IAAI,aAAAC,QAAM;AAGtB,WAAS,cAAc,aAAqB,eAAe,IAAI;AAC9D,UAAM,YAAQ,4BAAY,WAAW;AAErC,eAAW,QAAQ,OAAO;AACzB,YAAM,WAAW,iBAAAD,QAAK,KAAK,aAAa,IAAI;AAC5C,YAAM,UAAU,eAAe,iBAAAA,QAAK,KAAK,cAAc,IAAI,IAAI;AAC/D,YAAM,YAAQ,yBAAS,QAAQ;AAE/B,UAAI,MAAM,YAAY,GAAG;AACxB,sBAAc,UAAU,OAAO;AAAA,MAChC,OAAO;AACN,cAAM,kBAAc,6BAAa,QAAQ;AACzC,YAAI,KAAK,SAAS,WAAW;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAEA,gBAAc,SAAS;AAGvB,QAAM,UAAU,MAAM,IAAI,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9D,SAAO;AACR;AAEA,IAAM,iBAAN,MAAyC;AAAA,EACxC,OAAO,OAAwB;AAAA,EAE/B;AACD;;;ADxQA,eAAe,OAAO;AACrB,QAAM,WAAO,4BAAU;AAAA,IACtB,SAAS;AAAA,MACR,KAAK;AAAA,QACJ,MAAM;AAAA,MACP;AAAA,MACA,SAAS;AAAA,QACR,MAAM;AAAA,MACP;AAAA,MACA,KAAK;AAAA,QACJ,MAAM;AAAA,MACP;AAAA,IACD;AAAA,IACA,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,MAAM,QAAQ,KAAK,MAAM,CAAC;AAAA,EAC3B,CAAC;AAED,QAAM,CAAC,OAAO,IAAI,KAAK;AAEvB,MAAI,YAAY,WAAW;AAC1B,UAAM,cAAc;AACpB;AAAA,EACD;AAEA,MAAI,cAAc;AAClB,MAAI,eAAe;AACnB,MAAI,cAAc;AAClB,MAAI,YAAY,SAAS;AACxB,mBAAe;AAAA,EAChB,WAAW,YAAY,QAAQ;AAC9B,kBAAc;AACd,mBAAe;AAAA,EAChB,WAAW,YAAY,UAAU;AAChC,kBAAc;AACd,kBAAc;AAAA,EACf,WAAW,YAAY,SAAS;AAC/B,kBAAc;AACd,mBAAe;AAAA,EAChB,OAAO;AACN,YAAQ;AAAA,MACP;AAAA;AAAA;AAAA;AAAA;AAAA,IAKD;AACA,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,OAAO,MAAM,wBAAwB;AAE3C,MAAI,aAAa;AAChB,UAAM,oBAAoB,IAAI;AAAA,EAC/B;AAEA,QAAM,qBACL,KAAK,OAAO,OAAO,KAAK,OAAO,WAAW,KAAK,OAAO;AAEvD,QAAM,OAAO,EAAE,aAAa,aAAa;AACzC,QAAM,WAA4B,CAAC;AAEnC,MAAI,KAAK,OAAO,OAAO,CAAC,oBAAoB;AAC3C,aAAS,KAAK,gBAAgB,MAAM,OAAO,IAAI,CAAC;AAAA,EACjD;AACA,MAAI,KAAK,OAAO,WAAW,CAAC,oBAAoB;AAC/C,aAAS,KAAK,gBAAgB,MAAM,WAAW,IAAI,CAAC;AAAA,EACrD;AACA,MAAI,KAAK,OAAO,OAAO,CAAC,oBAAoB;AAC3C,YAAQ,KAAK,6DAA6D;AAAA,EAC3E;AAEA,QAAM,QAAQ,IAAI,QAAQ;AAC3B;AAEA,eAAe,oBAAoB,MAAc;AAChD,QAAM,iBAAiB,kBAAAE,QAAK,KAAK,MAAM,OAAO;AAC9C,UAAI,4BAAW,cAAc,GAAG;AAC/B,cAAM,sBAAO,cAAc;AAAA,EAC5B;AACA,UAAQ,IAAI,uCAA6B;AAC1C;AAEA,eAAe,0BAA0B;AACxC,QAAM,OAAO,UAAM,wBAAO,gBAAgB,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC;AAChE,MAAI,CAAC,MAAM;AACV,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AACA,QAAM,OAAO,kBAAAA,QAAK,QAAQ,IAAI;AAC9B,SAAO;AACR;AAEA,eAAe,gBAAgB;AAC9B,QAAM,QAAQ,IAAI,yBAAyB;AAC3C,QAAM,cAAc,yBAAyB,KAAK;AAElD,UAAQ,IAAI;AAAA;AAAA,EAEX,WAAW;AAAA;AAAA;AAAA,EAGX;AAED,yBAAAC,QAAO,SAAS,aAAa,EAAE,OAAO,KAAK,CAAC;AAC7C;AAEA,KAAK,EACH,MAAM,CAAC,QAAQ;AACf,UAAQ,MAAM,GAAG;AACjB,UAAQ,KAAK,CAAC;AACf,CAAC,EACA,KAAK,MAAM;AACX,UAAQ,KAAK,CAAC;AACf,CAAC;","names":["import_node_fs","import_node_path","import_find_up","path","JSZip","path","qrcode"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/mobile.ts","../../src/cli/file.ts","../../src/cli/sdk.ts","../../src/cli/valid-view-type.ts","../../src/cli/web.ts","../../src/cli/reanimated-bable.ts","../../src/cli/strip-flow.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport { findUp } from \"find-up\";\nimport qrcode from \"qrcode-terminal\";\nimport { rimraf } from \"rimraf\";\nimport { buildAndPublish } from \"./mobile\";\nimport { env } from \"./sdk\";\nimport { buildAndPublish as buildAndPublishWeb } from \"./web\";\n\nasync function main() {\n\tconst args = parseArgs({\n\t\toptions: {\n\t\t\tios: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t\tandroid: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t\tweb: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t},\n\t\t},\n\t\tstrict: true,\n\t\tallowPositionals: true,\n\t\targs: process.argv.slice(2),\n\t});\n\n\tconst [command] = args.positionals;\n\n\tif (command === \"install\") {\n\t\tawait handleInstall();\n\t\treturn;\n\t}\n\n\tlet shouldBuild = true;\n\tlet shouldUpload = true;\n\tlet shouldClean = true;\n\tif (command === \"build\") {\n\t\tshouldUpload = false;\n\t} else if (command === \"ship\") {\n\t\tshouldBuild = true;\n\t\tshouldUpload = true;\n\t} else if (command === \"upload\") {\n\t\tshouldBuild = false;\n\t\tshouldClean = false;\n\t} else if (command === \"clean\") {\n\t\tshouldBuild = false;\n\t\tshouldUpload = false;\n\t} else {\n\t\tconsole.error(\n\t\t\t`Usage:\n\twhop-react-native ship [--ios] [--android] [--web] # runs build and then publishes it as a dev build to whop.\n\twhop-react-native build [--ios] [--android] [--web] # builds your app into a distributable bundle in the build/ directory.\n\twhop-react-native upload [--ios] [--android] [--web] # uploads the existing build directory to whop.\n\twhop-react-native clean # cleans the build directory.`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tconst root = await getRootProjectDirectory();\n\n\tif (shouldClean) {\n\t\tawait cleanBuildDirectory(root);\n\t}\n\n\tconst didProvidePlatform =\n\t\targs.values.ios || args.values.android || args.values.web;\n\n\tconst opts = { shouldBuild, shouldUpload };\n\tconst promises: Promise<void>[] = [];\n\n\tif (args.values.ios || !didProvidePlatform) {\n\t\tpromises.push(buildAndPublish(root, \"ios\", opts));\n\t}\n\tif (args.values.android || !didProvidePlatform) {\n\t\tpromises.push(buildAndPublish(root, \"android\", opts));\n\t}\n\tif (args.values.web || !didProvidePlatform) {\n\t\tpromises.push(buildAndPublishWeb(root, opts));\n\t}\n\n\tawait Promise.all(promises);\n}\n\nasync function cleanBuildDirectory(root: string) {\n\tconst buildDirectory = path.join(root, \"build\");\n\tif (existsSync(buildDirectory)) {\n\t\tawait rimraf(buildDirectory);\n\t}\n\tconsole.log(\" ✔︎ cleaned build directory\");\n}\n\nasync function getRootProjectDirectory() {\n\tconst file = await findUp(\"package.json\", { cwd: process.cwd() });\n\tif (!file) {\n\t\tthrow new Error(\n\t\t\t\"please run this command inside a whop react native project\",\n\t\t);\n\t}\n\tconst root = path.dirname(file);\n\treturn root;\n}\n\nasync function handleInstall() {\n\tconst appId = env(\"NEXT_PUBLIC_WHOP_APP_ID\");\n\tconst installLink = `https://whop.com/apps/${appId}/install`;\n\n\tconsole.log(`\nOpen this link in your browser to install the app into your whop.\n${installLink}\n\nOr scan the QR code with your iPhone:\n\t`);\n\n\tqrcode.generate(installLink, { small: true });\n}\n\nmain()\n\t.catch((err) => {\n\t\tconsole.error(err);\n\t\tprocess.exit(1);\n\t})\n\t.then(() => {\n\t\tprocess.exit(0);\n\t});\n","import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { mkdir, rename, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { getDefaultConfig } from \"@react-native/metro-config\";\nimport { findUp } from \"find-up\";\nimport JSZip from \"jszip\";\nimport { type ReportableEvent, type Reporter, runBuild } from \"metro\";\nimport { getChecksum, uploadFile } from \"./file\";\nimport { APP_ID, COMPANY_ID, whopSdk } from \"./sdk\";\nimport { getSupportedAppViewTypes } from \"./valid-view-type\";\n\nexport async function buildAndPublish(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n\t{\n\t\tshouldBuild = true,\n\t\tshouldUpload = true,\n\t}: { shouldBuild: boolean; shouldUpload: boolean } = {\n\t\tshouldBuild: true,\n\t\tshouldUpload: true,\n\t},\n) {\n\tif (shouldBuild) {\n\t\tawait bundle(root, platform);\n\t}\n\tif (shouldUpload) {\n\t\tawait createMobileBuild(root, platform);\n\t}\n}\n\nexport async function bundle(root: string, platform: \"ios\" | \"android\") {\n\tawait makeEntrypoint(root, platform);\n\n\tconst outputFile = path.join(\n\t\troot,\n\t\t\"build\",\n\t\t\"output\",\n\t\tplatform,\n\t\t\"main_js_bundle\",\n\t);\n\tawait mkdir(path.dirname(outputFile), { recursive: true });\n\n\tconst defaultConfig = getDefaultConfig(root);\n\n\tconst babelLocation = require.resolve(\"@babel/runtime/package\");\n\n\tconst bableNodeModules = await findUp(\"node_modules\", {\n\t\tcwd: babelLocation,\n\t\ttype: \"directory\",\n\t});\n\tif (!bableNodeModules) {\n\t\tthrow new Error(\"babel node_modules parent folder not found\");\n\t}\n\n\tawait runBuild(\n\t\t{\n\t\t\t...defaultConfig,\n\t\t\tprojectRoot: root,\n\t\t\ttransformer: {\n\t\t\t\t...defaultConfig.transformer,\n\t\t\t\tbabelTransformerPath: require.resolve(\n\t\t\t\t\t\"./whop-react-native-babel-transformer.js\",\n\t\t\t\t),\n\t\t\t},\n\t\t\twatchFolders: [\n\t\t\t\troot,\n\t\t\t\tpath.resolve(root, \"node_modules\"),\n\t\t\t\tbableNodeModules,\n\t\t\t],\n\t\t\treporter: new CustomReporter(),\n\t\t\tresolver: {\n\t\t\t\t...defaultConfig.resolver,\n\t\t\t\tnodeModulesPaths: [\n\t\t\t\t\t...(defaultConfig.resolver?.nodeModulesPaths ?? []),\n\t\t\t\t\tbableNodeModules,\n\t\t\t\t],\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tdev: false,\n\t\t\tentry: `build/entrypoints/${platform}/index.js`,\n\t\t\tminify: false,\n\t\t\tplatform: platform,\n\t\t\tsourceMap: false,\n\t\t\tout: outputFile,\n\t\t},\n\t);\n\n\tawait rename(\n\t\t`${outputFile}.js`,\n\t\tpath.join(root, \"build\", \"output\", platform, \"main_js_bundle.hbc\"),\n\t);\n\n\tconsole.log(` ✔︎ [${platform}] bundle created`);\n}\n\n// getSupportedAppViewTypes moved to valid-view-type.ts\n\nasync function makeEntrypoint(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n): Promise<string> {\n\tconst entrypoint = path.join(\n\t\troot,\n\t\t\"build\",\n\t\t\"entrypoints\",\n\t\tplatform,\n\t\t\"index.js\",\n\t);\n\n\tconst files = await getSupportedAppViewTypes(root);\n\n\tconst pascalCase = (str: string) =>\n\t\tstr\n\t\t\t.split(\"-\")\n\t\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n\t\t\t.join(\"\");\n\n\tconst imports = files.map(\n\t\t(file) =>\n\t\t\t`import { ${pascalCase(file)} } from \"../../../src/views/${file}\";`,\n\t);\n\tconst registry = files.map(\n\t\t(file) =>\n\t\t\t`AppRegistry.registerComponent(\"${pascalCase(file)}\", () => ${pascalCase(file)});`,\n\t);\n\n\tconst entrypointContent = `import { AppRegistry } from \"react-native\";\n${imports.join(\"\\n\")}\n\n${registry.join(\"\\n\")}\n`;\n\n\tconst entrypointDir = path.dirname(entrypoint);\n\tawait mkdir(entrypointDir, { recursive: true });\n\tawait writeFile(entrypoint, entrypointContent, \"utf-8\");\n\n\tconsole.log(` ✔︎ [${platform}] entrypoint created`);\n\n\treturn entrypoint;\n}\n\nexport async function createMobileBuild(\n\troot: string,\n\tplatform: \"ios\" | \"android\",\n) {\n\tconst viewTypes = await getSupportedAppViewTypes(root);\n\n\tconst fullDirectory = path.join(root, \"build\", \"output\", platform);\n\n\t// Check if the directory contains a file called `main_js_bundle.hbc`\n\tconst mainJsBundle = path.join(fullDirectory, \"main_js_bundle.hbc\");\n\n\tif (!existsSync(mainJsBundle)) {\n\t\tthrow new Error(`main_js_bundle.hbc not found in ${fullDirectory}`);\n\t}\n\n\t// check that that folder only contains the main_js_bundle.hbc file and an optional `assets` folder\n\tconst files = readdirSync(fullDirectory);\n\tif (\n\t\tfiles.length > 2 ||\n\t\tfiles.length < 1 ||\n\t\t!files.includes(\"main_js_bundle.hbc\")\n\t) {\n\t\tthrow new Error(\n\t\t\t\"Directory must contain only the main_js_bundle.hbc file and an optional `assets` folder\",\n\t\t);\n\t}\n\tif (files.length === 2 && !files.includes(\"assets\")) {\n\t\tthrow new Error(\n\t\t\t\"Directory must contain only the main_js_bundle.hbc file and an optional `assets` folder\",\n\t\t);\n\t}\n\n\t// Zip the directory\n\tconst zipData = await zipDirectory(fullDirectory);\n\n\tconst checksum = await getChecksum(zipData);\n\n\tconsole.log(` ✔︎ [${platform}] build zipped with checksum: ${checksum}`);\n\n\tconst fileName = `app_build_${platform}.zip`;\n\tconst uploadedFile = await uploadFile(zipData, fileName, \"application/zip\");\n\n\tconsole.log(\n\t\t` ✔︎ [${platform}] uploaded build: ${fileName} (${(zipData.length / 1024).toFixed(0)} KB)`,\n\t);\n\n\tconst build = await whopSdk.apps.createAppBuild({\n\t\tattachment: { directUploadId: uploadedFile.directUploadId },\n\t\tchecksum,\n\t\tplatform,\n\t\tsupportedAppViewTypes: viewTypes.map(\n\t\t\t(view) =>\n\t\t\t\t({\n\t\t\t\t\t\"experience-view\": \"hub\" as const,\n\t\t\t\t\t\"discover-view\": \"discover\" as const,\n\t\t\t\t})[view],\n\t\t),\n\t});\n\n\tif (!build) {\n\t\tthrow new Error(\"Failed to create app build\");\n\t}\n\n\tconst dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds/?platform=${platform}`;\n\n\tconsole.log(`\\n ✔︎ [${platform}] deployed as development build ✔︎\n - build id: ${build.id}\n - view types: ${viewTypes.join(\", \")}\n - promote to production here: ${dashboardUrl}\\n`);\n\n\treturn build;\n}\n\nasync function zipDirectory(\n\tdirectory: string,\n): Promise<Buffer<ArrayBufferLike>> {\n\tconst zip = new JSZip();\n\n\t// Recursively add files to zip\n\tfunction addFilesToZip(currentPath: string, relativePath = \"\") {\n\t\tconst items = readdirSync(currentPath);\n\n\t\tfor (const item of items) {\n\t\t\tconst fullPath = path.join(currentPath, item);\n\t\t\tconst zipPath = relativePath ? path.join(relativePath, item) : item;\n\t\t\tconst stats = statSync(fullPath);\n\n\t\t\tif (stats.isDirectory()) {\n\t\t\t\taddFilesToZip(fullPath, zipPath);\n\t\t\t} else {\n\t\t\t\tconst fileContent = readFileSync(fullPath);\n\t\t\t\tzip.file(zipPath, fileContent);\n\t\t\t}\n\t\t}\n\t}\n\n\taddFilesToZip(directory);\n\n\t// Generate zip file\n\tconst zipData = await zip.generateAsync({ type: \"nodebuffer\" });\n\n\treturn zipData;\n}\n\nclass CustomReporter implements Reporter {\n\tupdate(event: ReportableEvent) {\n\t\t// Do nothing.\n\t}\n}\n","import { createHash } from \"node:crypto\";\nimport { AGENT_USER_ID, APP_ID, whopSdk } from \"./sdk\";\n\nexport async function uploadFile(\n\tdata: Buffer<ArrayBufferLike>,\n\tname: string,\n\tcontentType: string,\n) {\n\tconst file = new File([data], name, {\n\t\ttype: contentType,\n\t});\n\n\tconst uploadedFile = await whopSdk\n\t\t.withUser(AGENT_USER_ID)\n\t\t.attachments.uploadAttachment({\n\t\t\tfile,\n\t\t\trecord: \"app\",\n\t\t\tid: APP_ID,\n\t\t});\n\n\treturn uploadedFile;\n}\n\nexport async function getChecksum(data: Buffer<ArrayBufferLike>) {\n\tconst hash = createHash(\"sha256\");\n\thash.update(data);\n\treturn hash.digest(\"hex\");\n}\n","import { WhopServerSdk } from \"@whop/api\";\nimport { config } from \"dotenv\";\n\nconfig({\n\tpath: [\".env\", \".env.local\", \".env.development\", \".env.production\"],\n});\n\nexport function env(key: string) {\n\tconst value = process.env[key];\n\tif (!value) {\n\t\tthrow new Error(`Missing environment variable: ${key}`);\n\t}\n\treturn value;\n}\n\nexport const AGENT_USER_ID = env(\"NEXT_PUBLIC_WHOP_AGENT_USER_ID\");\nexport const COMPANY_ID = env(\"NEXT_PUBLIC_WHOP_COMPANY_ID\");\nexport const APP_ID = env(\"NEXT_PUBLIC_WHOP_APP_ID\");\n\nexport const whopSdk: WhopServerSdk = WhopServerSdk({\n\tappApiKey: env(\"WHOP_API_KEY\"),\n\tappId: APP_ID,\n\tcompanyId: COMPANY_ID,\n\tonBehalfOfUserId: AGENT_USER_ID,\n});\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport const VALID_VIEW_TYPES = [\n\t\"experience-view\",\n\t\"discover-view\",\n\t\"dashboard-view\",\n] as const;\n\nexport async function getSupportedAppViewTypes(\n\troot: string,\n): Promise<(typeof VALID_VIEW_TYPES)[number][]> {\n\tconst views = await readdir(path.join(root, \"src\", \"views\"), {\n\t\twithFileTypes: true,\n\t\trecursive: false,\n\t});\n\tconst files = views\n\t\t.filter((file) => file.isFile())\n\t\t.map((file) => file.name.split(\".\")[0])\n\t\t.filter((file) => !!file);\n\n\tconst validViews = files.filter((file) =>\n\t\tVALID_VIEW_TYPES.includes(file as (typeof VALID_VIEW_TYPES)[number]),\n\t) as (typeof VALID_VIEW_TYPES)[number][];\n\n\tif (validViews.length === 0) {\n\t\tthrow new Error(\n\t\t\t`No valid views found, please create a view in the src/views folder and name it with a valid view type: ${VALID_VIEW_TYPES.join(\", \")}`,\n\t\t);\n\t}\n\n\treturn validViews;\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { build } from \"esbuild\";\nimport { getChecksum, uploadFile } from \"./file\";\nimport { reanimatedBabelPlugin } from \"./reanimated-bable\";\nimport { APP_ID, COMPANY_ID, whopSdk } from \"./sdk\";\nimport { stripFlowWithBabel } from \"./strip-flow\";\nimport { getSupportedAppViewTypes } from \"./valid-view-type\";\n\nfunction aliasReactNativePlugin() {\n\treturn {\n\t\tname: \"alias-react-native\",\n\t\tsetup(b: import(\"esbuild\").PluginBuild) {\n\t\t\tb.onResolve({ filter: /^react-native$/ }, () => ({\n\t\t\t\tpath: require.resolve(\"react-native-web\"),\n\t\t\t}));\n\t\t},\n\t} satisfies import(\"esbuild\").Plugin;\n}\n\nfunction forceSingleReact() {\n\tconst map = new Map<string, string>([\n\t\t[\"react\", require.resolve(\"react\")],\n\t\t[\"react/jsx-runtime\", require.resolve(\"react/jsx-runtime\")],\n\t\t[\"react/jsx-dev-runtime\", require.resolve(\"react/jsx-dev-runtime\")],\n\t\t[\"react-dom\", require.resolve(\"react-dom\")],\n\t\t[\"react-dom/client\", require.resolve(\"react-dom/client\")],\n\t]);\n\n\tconst rx = /^(react(?:\\/jsx-(?:dev-)?runtime)?|react-dom(?:\\/client)?)$/;\n\n\treturn {\n\t\tname: \"force-single-react\",\n\t\tsetup(b: import(\"esbuild\").PluginBuild) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: <explanation>\n\t\t\tb.onResolve({ filter: rx }, (args) => ({ path: map.get(args.path)! }));\n\t\t},\n\t} satisfies import(\"esbuild\").Plugin;\n}\n\nfunction toPascalCase(str: string) {\n\treturn str\n\t\t.split(\"-\")\n\t\t.map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n\t\t.join(\"\");\n}\n\nasync function makeWebEntrypoint(root: string) {\n\tconst files = await getSupportedAppViewTypes(root);\n\n\tconst packageJsonPath = path.join(root, \"package.json\");\n\tconst packageJson = JSON.parse(await readFile(packageJsonPath, \"utf-8\"));\n\tconst hasReactNativeReanimated =\n\t\tpackageJson.dependencies?.[\"react-native-reanimated\"];\n\n\tconst imports = files.map(\n\t\t(file) =>\n\t\t\t`import { ${toPascalCase(file)} } from \"../../../src/views/${file}\";`,\n\t);\n\tconst registry = files.map(\n\t\t(file) =>\n\t\t\t`AppRegistry.registerComponent(\"${toPascalCase(file)}\", () => WhopNavigationWrapper(React, \"${toPascalCase(file)}\", ${toPascalCase(file)}));`,\n\t);\n\n\tconst defaultKey = toPascalCase(files[0] ?? \"experience-view\");\n\tconst reanimatedImport = hasReactNativeReanimated\n\t\t? `import \"react-native-reanimated\";`\n\t\t: \"\";\n\n\tconst entry = `import { AppRegistry } from \"react-native\";\nimport * as React from \"react\";\nimport { WhopNavigationWrapper } from \"@whop/react-native/web\";\n${reanimatedImport}\n\n${imports.join(\"\\n\")} \n\n${registry.join(\"\\n\")} \n\nconst viewType = new URLSearchParams(window.location.search).get(\"app_view\") ?? \"${defaultKey}\"; \n\nconst root = document.getElementById(\"root\") || (() => {\n\tconst d = document.createElement(\"div\");\n\td.id = \"root\";\n\tdocument.body.appendChild(d);\n\treturn d;\n})();\nAppRegistry.runApplication(viewType, { rootTag: root });\n`;\n\n\tconst entryFile = path.join(root, \"build\", \"entrypoints\", \"web\", \"index.tsx\");\n\tawait mkdir(path.dirname(entryFile), { recursive: true });\n\tawait writeFile(entryFile, entry, \"utf-8\");\n\n\treturn entryFile;\n}\n\nexport async function bundleWeb(root: string) {\n\tconst entry = await makeWebEntrypoint(root);\n\n\tconst outDir = path.join(root, \"build\", \"output\", \"web\");\n\tawait mkdir(outDir, { recursive: true });\n\n\tawait build({\n\t\tentryPoints: [entry],\n\t\toutfile: path.join(outDir, \"main.js\"),\n\t\tbundle: true,\n\t\tminify: false,\n\t\tformat: \"esm\",\n\t\tplatform: \"browser\",\n\t\tsourcemap: false,\n\t\tjsx: \"automatic\",\n\t\tmainFields: [\"browser\", \"module\", \"main\"],\n\t\tconditions: [\"browser\", \"import\", \"default\"],\n\t\tdefine: {\n\t\t\tprocess: \"{}\",\n\t\t\t\"process.env\": \"{}\",\n\t\t\t\"process.env.NODE_ENV\": '\"production\"',\n\t\t\t__DEV__: \"false\",\n\t\t\t\"process.env.NEXT_PUBLIC_WHOP_APP_ID\": `\"${APP_ID}\"`,\n\t\t\t// Some RN libraries (e.g., RNGH) expect a Node-like global in the browser\n\t\t\tglobal: \"globalThis\",\n\t\t},\n\t\tresolveExtensions: [\n\t\t\t\".web.tsx\",\n\t\t\t\".web.ts\",\n\t\t\t\".web.js\",\n\t\t\t\".tsx\",\n\t\t\t\".ts\",\n\t\t\t\".jsx\",\n\t\t\t\".js\",\n\t\t],\n\t\tloader: {\n\t\t\t\".png\": \"dataurl\",\n\t\t\t\".jpg\": \"dataurl\",\n\t\t\t\".jpeg\": \"dataurl\",\n\t\t\t\".svg\": \"dataurl\",\n\t\t\t\".ttf\": \"dataurl\",\n\t\t\t\".woff\": \"dataurl\",\n\t\t\t\".woff2\": \"dataurl\",\n\t\t\t\".js\": \"jsx\",\n\t\t\t\".jsx\": \"jsx\",\n\t\t},\n\t\tplugins: [\n\t\t\tforceSingleReact(),\n\t\t\taliasReactNativePlugin(),\n\t\t\treanimatedBabelPlugin(),\n\t\t\tstripFlowWithBabel(),\n\t\t\t{\n\t\t\t\tname: \"force-native-web-stub\",\n\t\t\t\tsetup(b) {\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: <explanation>\n\t\t\t\t\tb.onResolve({ filter: /^\\.\\/native-whop-core$/ }, (args: any) => {\n\t\t\t\t\t\t// Always resolve the local source file so extension resolution (.web.ts) applies\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tpath: path.join(args.resolveDir, \"native-whop-core\"),\n\t\t\t\t\t\t\tnamespace: \"file\",\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t});\n\n\tconst html = `<!doctype html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n\t\t<title>Whop App (Web)</title>\n\t\t<style>\n\t\t\t#root {\n\t\t\t\twidth: 100vw;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t\tpadding: 0;\n\t\t\t\toverflow: hidden;\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-direction: column;\n\t\t\t\talign-items: stretch;\n\t\t\t\tjustify-content: start;\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div id=\"root\"></div>\n\t\t<script type=\"module\" src=\"./main.js\"></script>\n\t</body>\n</html>`;\n\tawait writeFile(path.join(outDir, \"index.html\"), html, \"utf-8\");\n\n\tconsole.log(\" ✔︎ [web] bundle created at build/output/web/main.js\");\n}\n\nexport async function buildAndPublish(\n\troot: string,\n\t{\n\t\tshouldBuild = true,\n\t\tshouldUpload = true,\n\t}: { shouldBuild: boolean; shouldUpload: boolean } = {\n\t\tshouldBuild: true,\n\t\tshouldUpload: true,\n\t},\n) {\n\tif (shouldBuild) {\n\t\tawait bundleWeb(root);\n\t}\n\tif (shouldUpload) {\n\t\tawait createWebBuild(root);\n\t}\n}\n\nexport async function createWebBuild(root: string) {\n\tconst fullDirectory = path.join(root, \"build\", \"output\", \"web\");\n\tconst mainJsFile = path.join(fullDirectory, \"main.js\");\n\n\t// Verify bundle exists\n\ttry {\n\t\tawait readFile(mainJsFile);\n\t} catch {\n\t\tthrow new Error(`main.js not found in ${fullDirectory}`);\n\t}\n\n\tconst buf = await readFile(mainJsFile);\n\tconst checksum = await getChecksum(buf);\n\n\tconsole.log(` ✔︎ [web] build checksummed: ${checksum}`);\n\n\tconst fileName = `rnweb_${checksum}.js`;\n\tconst uploadedFile = await uploadFile(\n\t\tbuf,\n\t\tfileName,\n\t\t\"application/javascript\",\n\t);\n\n\tconsole.log(\n\t\t` ✔︎ [web] uploaded build: ${fileName} (${(buf.length / 1024).toFixed(0)} KB)`,\n\t);\n\n\tconst build = await whopSdk.apps.createAppBuild({\n\t\tattachment: { directUploadId: uploadedFile.directUploadId },\n\t\tchecksum,\n\t\tplatform: \"web\",\n\t\tsupportedAppViewTypes: [\"hub\"],\n\t});\n\n\tif (!build) {\n\t\tthrow new Error(\"Failed to create app build\");\n\t}\n\n\tconst dashboardUrl = `https://whop.com/dashboard/${COMPANY_ID}/developer/apps/${APP_ID}/builds/?platform=web`;\n\n\tconsole.log(\n\t\t`\\n ✔︎ [web] deployed as development build ✔︎\\n - build id: ${build.id}\\n - view types: hub\\n - promote to production here: ${dashboardUrl}\\n`,\n\t);\n\n\treturn build;\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n// build/plugins/reanimatedBabel.ts\nimport * as babel from \"@babel/core\";\n\nconst JS_RE = /\\.(m|c)?(t|j)sx?$/;\n\nexport function reanimatedBabelPlugin() {\n\t// Transform only: your app source (outside node_modules) and reanimated itself.\n\tconst shouldTransform = (p: string) => {\n\t\tif (!JS_RE.test(p)) return false;\n\t\t// Always run on reanimated’s files\n\t\tif (p.includes(`${path.sep}react-native-reanimated${path.sep}`))\n\t\t\treturn true;\n\t\t// Never touch third-party deps\n\t\tif (p.includes(`${path.sep}node_modules${path.sep}`)) return false;\n\t\t// Run on app code under src/\n\t\treturn p.includes(`${path.sep}src${path.sep}`);\n\t};\n\n\treturn {\n\t\tname: \"reanimated-babel\",\n\t\tsetup(b: import(\"esbuild\").PluginBuild) {\n\t\t\tb.onLoad({ filter: JS_RE }, async (args) => {\n\t\t\t\tif (!shouldTransform(args.path)) {\n\t\t\t\t\t// Skip non-target files so other plugins (and esbuild) can process them\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst code = await fs.readFile(args.path, \"utf8\");\n\t\t\t\tconst result = await babel.transformAsync(code, {\n\t\t\t\t\tfilename: args.path,\n\t\t\t\t\tsourceMaps: false,\n\t\t\t\t\tbabelrc: false,\n\t\t\t\t\tconfigFile: false,\n\t\t\t\t\t// ORDER MATTERS: Reanimated plugin MUST BE LAST\n\t\t\t\t\tplugins: [\n\t\t\t\t\t\t// Needed by Reanimated on web per docs\n\t\t\t\t\t\t\"@babel/plugin-transform-export-namespace-from\",\n\t\t\t\t\t\t// Handle Flow types present in some RN libs\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\"@babel/plugin-transform-flow-strip-types\",\n\t\t\t\t\t\t\t{ allowDeclareFields: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t\t// MUST be last\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\"react-native-reanimated/plugin\",\n\t\t\t\t\t\t\t{ relativeSourceLocation: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\tpresets: [], // esbuild handles TS/JSX syntax; no preset-env/preset-react\n\t\t\t\t\tcaller: { name: \"esbuild\" },\n\t\t\t\t\t// Let Babel parse TS/JSX/Flow; keep it broad\n\t\t\t\t\tparserOpts: { plugins: [\"jsx\", \"typescript\"] },\n\t\t\t\t\tgeneratorOpts: { decoratorsBeforeExport: true },\n\t\t\t\t});\n\n\t\t\t\treturn {\n\t\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: <explanation>\n\t\t\t\t\tcontents: result!.code!,\n\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: <explanation>\n\t\t\t\t\tloader: pickLoader(args.path) as any,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t};\n}\n\nfunction pickLoader(file: string) {\n\tconst ext = path.extname(file).toLowerCase();\n\tif (ext === \".tsx\") return \"tsx\";\n\tif (ext === \".ts\") return \"ts\";\n\tif (ext === \".jsx\") return \"jsx\";\n\t// For .js: many RN libs contain JSX; be permissive\n\treturn \"jsx\";\n}\n","import * as fs from \"node:fs/promises\";\n// stripFlowWithBabel.ts\nimport * as babel from \"@babel/core\";\n\nexport function stripFlowWithBabel() {\n\tconst filter = /\\.(m|c)?jsx?$/;\n\treturn {\n\t\tname: \"strip-flow-with-babel\",\n\t\t// biome-ignore lint/suspicious/noExplicitAny: <explanation>\n\t\tsetup(b: any) {\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: <explanation>\n\t\t\tb.onLoad({ filter }, async (args: any) => {\n\t\t\t\tconst code = await fs.readFile(args.path, \"utf8\");\n\t\t\t\tconst out = await babel.transformAsync(code, {\n\t\t\t\t\tfilename: args.path,\n\t\t\t\t\tbabelrc: false,\n\t\t\t\t\tconfigFile: false,\n\t\t\t\t\tplugins: [\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\"@babel/plugin-transform-flow-strip-types\",\n\t\t\t\t\t\t\t{ allowDeclareFields: true },\n\t\t\t\t\t\t],\n\t\t\t\t\t],\n\t\t\t\t\tparserOpts: { plugins: [\"jsx\", \"flow\"] },\n\t\t\t\t\tsourceMaps: false,\n\t\t\t\t});\n\t\t\t\t// biome-ignore lint/style/noNonNullAssertion: <explanation>\n\t\t\t\treturn { contents: out!.code!, loader: \"jsx\" };\n\t\t\t});\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_find_up","import_promises","import_node_path","path","path","build","JSZip","import_promises","import_node_path","path","fs","babel","path","buildAndPublish","build","buildAndPublish","path","qrcode"]}
|