@apps-in-toss/web-framework 2.6.1 → 3.0.0-beta.0c56009

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.js ADDED
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli/index.ts
4
+ import { Cli } from "clipanion";
5
+
6
+ // src/cli/commands/build/index.ts
7
+ import * as p from "@clack/prompts";
8
+ import { Command } from "clipanion";
9
+ import path3 from "path";
10
+
11
+ // src/cli/commands/build/buildArtifact.ts
12
+ import { AppsInTossBundle, PlatformType } from "@apps-in-toss/ait-format";
13
+ import { cosmiconfig } from "cosmiconfig";
14
+ import { TypeScriptLoader } from "cosmiconfig-typescript-loader";
15
+ import path2 from "path";
16
+ import { readdir, readFile, writeFile } from "fs/promises";
17
+ import { uuidv7 } from "uuidv7";
18
+
19
+ // src/cli/utils/getPackageRoot.ts
20
+ import fs from "fs";
21
+ import path from "path";
22
+ function getPackageRoot(base) {
23
+ let dirPath = base;
24
+ const root = path.parse(dirPath).root;
25
+ while (dirPath !== root) {
26
+ if (fs.existsSync(path.join(dirPath, "package.json"))) {
27
+ return dirPath;
28
+ }
29
+ dirPath = path.dirname(dirPath);
30
+ }
31
+ return dirPath;
32
+ }
33
+
34
+ // src/cli/commands/build/buildArtifact.ts
35
+ async function buildArtifact() {
36
+ const projectRoot = getPackageRoot(process.cwd());
37
+ const projectPackageJsonData = await readFile(
38
+ path2.resolve(projectRoot, "package.json")
39
+ );
40
+ const projectPackageJson = JSON.parse(projectPackageJsonData.toString());
41
+ const sdkPackageJson = await getSDKPackageJson();
42
+ const appsInTossConfig = await getAppsInTossConfig();
43
+ const deploymentId = uuidv7();
44
+ const writer = AppsInTossBundle.writer({
45
+ deploymentId,
46
+ appName: appsInTossConfig.appName,
47
+ createdBy: sdkPackageJson.name
48
+ });
49
+ const unityMetadata = getUnityMetadata();
50
+ writer.setMetadata({
51
+ platform: PlatformType.WEB,
52
+ sdkVersion: sdkPackageJson.version,
53
+ packageJson: projectPackageJson,
54
+ extra: { unityMetadata, appsInTossConfig }
55
+ });
56
+ appsInTossConfig.permissions.forEach(
57
+ ({ name, access }) => writer.addPermission(name, access)
58
+ );
59
+ const webBundleDir = path2.resolve(
60
+ projectRoot,
61
+ appsInTossConfig.webBundleDir
62
+ );
63
+ const webBundleFiles = await getWebBundleFiles(webBundleDir);
64
+ for (const file of webBundleFiles) {
65
+ writer.addFile("sources/" + file.name, file.data);
66
+ }
67
+ const bundleJson = {
68
+ deploymentId,
69
+ byteLength: webBundleFiles.reduce(
70
+ (acc, cur) => acc + cur.data.byteLength,
71
+ 0
72
+ ),
73
+ sdk: { name: sdkPackageJson.name, version: sdkPackageJson.version },
74
+ config: appsInTossConfig
75
+ };
76
+ writer.addFile(
77
+ "bundle.json",
78
+ new Uint8Array(Buffer.from(JSON.stringify(bundleJson), "utf-8"))
79
+ );
80
+ writer.addFile(
81
+ "project-package.json",
82
+ new Uint8Array(projectPackageJsonData)
83
+ );
84
+ const artifactBuffer = await writer.toBuffer();
85
+ const outPath = path2.resolve(projectRoot, `${appsInTossConfig.appName}.ait`);
86
+ await writeFile(outPath, artifactBuffer);
87
+ return { deploymentId, outPath };
88
+ }
89
+ async function getSDKPackageJson() {
90
+ const packageJsonPath = path2.resolve(
91
+ getPackageRoot(import.meta.dirname),
92
+ "package.json"
93
+ );
94
+ const packageJsonString = (await readFile(packageJsonPath)).toString();
95
+ return JSON.parse(packageJsonString);
96
+ }
97
+ async function getAppsInTossConfig() {
98
+ const result = await cosmiconfig("apps-in-toss", {
99
+ loaders: {
100
+ ".ts": TypeScriptLoader(),
101
+ ".cts": TypeScriptLoader(),
102
+ ".mts": TypeScriptLoader()
103
+ },
104
+ searchPlaces: [
105
+ "apps-in-toss.config.ts",
106
+ "apps-in-toss.config.cts",
107
+ "apps-in-toss.config.mts",
108
+ "apps-in-toss.config.js",
109
+ "apps-in-toss.config.cjs",
110
+ "apps-in-toss.config.mjs"
111
+ ]
112
+ }).search(getPackageRoot(process.cwd()));
113
+ if (result == null) {
114
+ throw new Error("Config \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
115
+ }
116
+ return result.config;
117
+ }
118
+ function getUnityMetadata() {
119
+ const unityMetadataString = process.env.UNITY_METADATA;
120
+ if (typeof unityMetadataString !== "string") {
121
+ return null;
122
+ }
123
+ try {
124
+ return JSON.parse(unityMetadataString);
125
+ } catch (error) {
126
+ console.warn("UNITY_METADATA is not a valid JSON:", error);
127
+ return null;
128
+ }
129
+ }
130
+ async function getWebBundleFiles(webBundleDir) {
131
+ const filePaths = await getFilePathsInDir(webBundleDir);
132
+ const files = [];
133
+ for (const filePath of filePaths) {
134
+ const name = filePath.replace(webBundleDir + "/", "");
135
+ const data = new Uint8Array(await readFile(filePath));
136
+ files.push({ name, data });
137
+ }
138
+ return files;
139
+ }
140
+ async function getFilePathsInDir(dir) {
141
+ const entries = await readdir(dir, { withFileTypes: true });
142
+ const files = await Promise.all(
143
+ entries.map((entry) => {
144
+ const filePath = path2.resolve(dir, entry.name);
145
+ return entry.isDirectory() ? getFilePathsInDir(filePath) : filePath;
146
+ })
147
+ );
148
+ return files.flat();
149
+ }
150
+
151
+ // src/cli/commands/build/index.ts
152
+ var BuildCommand = class extends Command {
153
+ static paths = [["build"]];
154
+ static usage = Command.Usage({
155
+ category: "Build",
156
+ description: "\uC571\uC778\uD1A0\uC2A4 \uBC30\uD3EC\uC6A9 .ait \uC544\uD2F0\uD329\uD2B8\uB97C \uBE4C\uB4DC\uD569\uB2C8\uB2E4.",
157
+ examples: [["Build artifact", "apps-in-toss build"]]
158
+ });
159
+ async execute() {
160
+ const buildResult = await buildArtifact();
161
+ p.log.success(
162
+ `\uC571\uC778\uD1A0\uC2A4 \uBE4C\uB4DC\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. (${path3.basename(buildResult.outPath)})`
163
+ );
164
+ p.log.info(`deploymentId: ${buildResult.deploymentId}`);
165
+ }
166
+ };
167
+
168
+ // src/cli/commands/migration/index.ts
169
+ import * as p3 from "@clack/prompts";
170
+ import { Command as Command2, Option } from "clipanion";
171
+
172
+ // src/cli/commands/migration/web-framework-v3.ts
173
+ import * as p2 from "@clack/prompts";
174
+ import { cosmiconfig as cosmiconfig2 } from "cosmiconfig";
175
+ import { TypeScriptLoader as TypeScriptLoader2 } from "cosmiconfig-typescript-loader";
176
+ import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
177
+ import { resolve } from "path";
178
+ import jscodeshift from "jscodeshift";
179
+ async function migrateWebFrameworkV3() {
180
+ const projectRoot = getPackageRoot(process.cwd());
181
+ p2.log.info("@apps-in-toss/web-framework V3 \uC790\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC744 \uC2DC\uC791\uD569\uB2C8\uB2E4.");
182
+ p2.log.info(
183
+ "\uC790\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC5D0 \uC2E4\uD328\uD560 \uACBD\uC6B0, \uCEE4\uBBA4\uB2C8\uD2F0\uC5D0\uC11C \uC218\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uAC00\uC774\uB4DC\uB97C \uCC38\uACE0\uD574\uC8FC\uC138\uC694.\nhttps://techchat-apps-in-toss.toss.im"
184
+ );
185
+ const { config: graniteConfig, filepath: graniteConfigPath } = await getGraniteConfig(projectRoot);
186
+ await migrateAppsInTossConfig(
187
+ graniteConfigPath,
188
+ resolve(
189
+ projectRoot,
190
+ "apps-in-toss.config." + graniteConfigPath.split(".").pop()
191
+ )
192
+ );
193
+ await migratePackageJsonScripts(
194
+ resolve(projectRoot, "package.json"),
195
+ graniteConfig.web.commands.dev,
196
+ graniteConfig.web.commands.build
197
+ );
198
+ p2.log.success("\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
199
+ }
200
+ async function getGraniteConfig(projectRoot) {
201
+ p2.log.info("granite.config \uD30C\uC77C \uCC3E\uB294 \uC911..");
202
+ const result = await cosmiconfig2("granite", {
203
+ loaders: {
204
+ ".ts": TypeScriptLoader2(),
205
+ ".cts": TypeScriptLoader2(),
206
+ ".mts": TypeScriptLoader2()
207
+ },
208
+ searchPlaces: [
209
+ "granite.config.ts",
210
+ "granite.config.cts",
211
+ "granite.config.mts",
212
+ "granite.config.js",
213
+ "granite.config.cjs",
214
+ "granite.config.mjs"
215
+ ]
216
+ }).search(projectRoot);
217
+ if (result == null) {
218
+ p2.log.error("granite.config \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
219
+ process.exit(1);
220
+ }
221
+ return result;
222
+ }
223
+ async function migrateAppsInTossConfig(configPath, outputPath) {
224
+ p2.log.info("granite.config\uB97C apps-in-toss.config\uB85C \uB9C8\uC774\uADF8\uB808\uC774\uC158\uD569\uB2C8\uB2E4.");
225
+ const root = jscodeshift((await readFile2(configPath)).toString());
226
+ root.find(jscodeshift.ObjectExpression).forEach((path4) => {
227
+ const obj = path4.value;
228
+ for (const prop of obj.properties) {
229
+ if (jscodeshift.Property.check(prop) && jscodeshift.Identifier.check(prop.key) && prop.key.name === "brand" && jscodeshift.ObjectExpression.check(prop.value)) {
230
+ prop.value.properties = prop.value.properties.filter(
231
+ (prop2) => jscodeshift.Property.check(prop2) && jscodeshift.Identifier.check(prop2.key) && prop2.key.name === "primaryColor"
232
+ );
233
+ }
234
+ if (jscodeshift.Property.check(prop) && jscodeshift.Identifier.check(prop.key) && prop.key.name === "webViewProps") {
235
+ prop.key = jscodeshift.identifier("webView");
236
+ if (prop.value.type === "ObjectExpression") {
237
+ prop.value.properties = prop.value.properties.filter(
238
+ (prop2) => jscodeshift.Property.check(prop2) && jscodeshift.Identifier.check(prop2.key) && prop2.key.name !== "type"
239
+ );
240
+ }
241
+ }
242
+ if (jscodeshift.Property.check(prop) && jscodeshift.Identifier.check(prop.key) && prop.key.name === "outdir") {
243
+ prop.key = jscodeshift.identifier("webBundleDir");
244
+ }
245
+ }
246
+ obj.properties = obj.properties.filter((prop) => {
247
+ if (jscodeshift.Property.check(prop) && jscodeshift.Identifier.check(prop.key) && prop.key.name === "web" && jscodeshift.ObjectExpression.check(prop.value) && prop.value.properties.filter(
248
+ (prop2) => jscodeshift.Property.check(prop2) && jscodeshift.Identifier.check(prop2.key) && ["host", "port", "commands"].includes(prop2.key.name)
249
+ ).length > 0) {
250
+ return false;
251
+ }
252
+ return true;
253
+ });
254
+ });
255
+ await writeFile2(outputPath, root.toSource());
256
+ p2.log.info("apps-in-toss.config\uAC00 \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
257
+ }
258
+ async function migratePackageJsonScripts(packageJsonPath, dev, build) {
259
+ p2.log.info("package.json\uC758 dev, build \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uC218\uC815\uD569\uB2C8\uB2E4.");
260
+ const packageJson = JSON.parse((await readFile2(packageJsonPath)).toString());
261
+ if (packageJson.scripts == null) {
262
+ packageJson.scripts = {};
263
+ }
264
+ packageJson.scripts["dev"] = dev;
265
+ packageJson.scripts["build"] = `${build} && ait build`;
266
+ await writeFile2(packageJsonPath, JSON.stringify(packageJson, null, 2));
267
+ p2.log.info("package.json \uC218\uC815\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
268
+ }
269
+
270
+ // src/cli/commands/migration/index.ts
271
+ var MIGRATION_TARGETS = {
272
+ v3: migrateWebFrameworkV3
273
+ };
274
+ var MigrationCommand = class extends Command2 {
275
+ static paths = [["migrate"]];
276
+ static usage = Command2.Usage({
277
+ category: "Migration",
278
+ description: "\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC744 \uC2E4\uD589\uD569\uB2C8\uB2E4.",
279
+ examples: [["Run migration", "apps-in-toss migrate <target>"]]
280
+ });
281
+ target = Option.String({ required: true });
282
+ async execute() {
283
+ const target = MIGRATION_TARGETS[this.target];
284
+ if (target != null) {
285
+ await target();
286
+ } else {
287
+ p3.log.error(
288
+ [
289
+ "\uC798\uBABB\uB41C \uB9C8\uC774\uADF8\uB808\uC774\uC158 target \uC785\uB2C8\uB2E4. \uC544\uB798 \uC911 \uD558\uB098\uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694.\n",
290
+ ...Object.keys(MIGRATION_TARGETS)
291
+ ].join("\n")
292
+ );
293
+ process.exit(1);
294
+ }
295
+ }
296
+ };
297
+
298
+ // src/cli/index.ts
299
+ var cli = new Cli({
300
+ binaryLabel: "appsintoss",
301
+ binaryName: "appsintoss",
302
+ enableCapture: true
303
+ });
304
+ cli.register(BuildCommand);
305
+ cli.register(MigrationCommand);
306
+ cli.runExit(process.argv.slice(2));
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/config/index.ts
21
+ var config_exports = {};
22
+ __export(config_exports, {
23
+ defineConfig: () => defineConfig
24
+ });
25
+ module.exports = __toCommonJS(config_exports);
26
+ function defineConfig(config) {
27
+ return {
28
+ ...config,
29
+ appName: config.appName,
30
+ brand: config.brand,
31
+ permissions: config.permissions,
32
+ webView: {
33
+ mediaPlaybackRequiresUserAction: true,
34
+ allowsInlineMediaPlayback: false,
35
+ bounces: true,
36
+ allowsBackForwardNavigationGestures: true,
37
+ pullToRefreshEnabled: true,
38
+ overScrollMode: "always",
39
+ ...config.webView
40
+ },
41
+ navigationBar: {
42
+ withBackButton: true,
43
+ withHomeButton: false,
44
+ ...config.navigationBar
45
+ },
46
+ webBundleDir: config.webBundleDir ?? "dist"
47
+ };
48
+ }
49
+ // Annotate the CommonJS export names for ESM import in node:
50
+ 0 && (module.exports = {
51
+ defineConfig
52
+ });
@@ -0,0 +1,54 @@
1
+ interface AppsInTossConfig {
2
+ appName: string;
3
+ brand: {
4
+ primaryColor: string;
5
+ };
6
+ permissions: ({
7
+ name: "clipboard";
8
+ access: "read" | "write";
9
+ } | {
10
+ name: "geolocation";
11
+ access: "access";
12
+ } | {
13
+ name: "contacts";
14
+ access: "read" | "write";
15
+ } | {
16
+ name: "photos";
17
+ access: "read" | "write";
18
+ } | {
19
+ name: "camera";
20
+ access: "access";
21
+ } | {
22
+ name: "microphone";
23
+ access: "access";
24
+ })[];
25
+ navigationBar?: {
26
+ withBackButton?: boolean;
27
+ withHomeButton?: boolean;
28
+ initialAccessoryButton?: {
29
+ id: string;
30
+ title: string;
31
+ icon: {
32
+ source: {
33
+ uri: string;
34
+ };
35
+ name?: never;
36
+ } | {
37
+ name: string;
38
+ source?: never;
39
+ };
40
+ };
41
+ };
42
+ webView?: {
43
+ allowsInlineMediaPlayback?: boolean;
44
+ bounces?: boolean;
45
+ pullToRefreshEnabled?: boolean;
46
+ overScrollMode?: "always" | "content" | "never";
47
+ mediaPlaybackRequiresUserAction?: boolean;
48
+ allowsBackForwardNavigationGestures?: boolean;
49
+ };
50
+ webBundleDir?: string;
51
+ }
52
+ declare function defineConfig(config: AppsInTossConfig): AppsInTossConfig;
53
+
54
+ export { type AppsInTossConfig, defineConfig };
@@ -0,0 +1,54 @@
1
+ interface AppsInTossConfig {
2
+ appName: string;
3
+ brand: {
4
+ primaryColor: string;
5
+ };
6
+ permissions: ({
7
+ name: "clipboard";
8
+ access: "read" | "write";
9
+ } | {
10
+ name: "geolocation";
11
+ access: "access";
12
+ } | {
13
+ name: "contacts";
14
+ access: "read" | "write";
15
+ } | {
16
+ name: "photos";
17
+ access: "read" | "write";
18
+ } | {
19
+ name: "camera";
20
+ access: "access";
21
+ } | {
22
+ name: "microphone";
23
+ access: "access";
24
+ })[];
25
+ navigationBar?: {
26
+ withBackButton?: boolean;
27
+ withHomeButton?: boolean;
28
+ initialAccessoryButton?: {
29
+ id: string;
30
+ title: string;
31
+ icon: {
32
+ source: {
33
+ uri: string;
34
+ };
35
+ name?: never;
36
+ } | {
37
+ name: string;
38
+ source?: never;
39
+ };
40
+ };
41
+ };
42
+ webView?: {
43
+ allowsInlineMediaPlayback?: boolean;
44
+ bounces?: boolean;
45
+ pullToRefreshEnabled?: boolean;
46
+ overScrollMode?: "always" | "content" | "never";
47
+ mediaPlaybackRequiresUserAction?: boolean;
48
+ allowsBackForwardNavigationGestures?: boolean;
49
+ };
50
+ webBundleDir?: string;
51
+ }
52
+ declare function defineConfig(config: AppsInTossConfig): AppsInTossConfig;
53
+
54
+ export { type AppsInTossConfig, defineConfig };
package/dist/config.js ADDED
@@ -0,0 +1,27 @@
1
+ // src/config/index.ts
2
+ function defineConfig(config) {
3
+ return {
4
+ ...config,
5
+ appName: config.appName,
6
+ brand: config.brand,
7
+ permissions: config.permissions,
8
+ webView: {
9
+ mediaPlaybackRequiresUserAction: true,
10
+ allowsInlineMediaPlayback: false,
11
+ bounces: true,
12
+ allowsBackForwardNavigationGestures: true,
13
+ pullToRefreshEnabled: true,
14
+ overScrollMode: "always",
15
+ ...config.webView
16
+ },
17
+ navigationBar: {
18
+ withBackButton: true,
19
+ withHomeButton: false,
20
+ ...config.navigationBar
21
+ },
22
+ webBundleDir: config.webBundleDir ?? "dist"
23
+ };
24
+ }
25
+ export {
26
+ defineConfig
27
+ };