@channel.io/app-sdk 0.17.1 → 0.18.0
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 +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/create.d.ts +7 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +201 -391
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/create.test.d.ts +2 -0
- package/dist/commands/create.test.d.ts.map +1 -0
- package/dist/commands/create.test.js +34 -0
- package/dist/commands/create.test.js.map +1 -0
- package/dist/package-version.d.ts +5 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +11 -0
- package/dist/package-version.js.map +1 -0
- package/package.json +6 -5
package/dist/cli.js
CHANGED
|
@@ -5,8 +5,9 @@ import { addCommand } from "./commands/add.js";
|
|
|
5
5
|
import { devCommand } from "./commands/dev.js";
|
|
6
6
|
import { buildCommand } from "./commands/build.js";
|
|
7
7
|
import { generateCommand } from "./commands/generate.js";
|
|
8
|
+
import { packageVersion } from "./package-version.js";
|
|
8
9
|
const program = new Command();
|
|
9
|
-
program.name("channel-app").description("CLI for Channel.io App SDK").version(
|
|
10
|
+
program.name("channel-app").description("CLI for Channel.io App SDK").version(packageVersion);
|
|
10
11
|
// Register commands
|
|
11
12
|
program.addCommand(createCommand);
|
|
12
13
|
program.addCommand(addCommand);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;AAE9F,oBAAoB;AACpB,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AAEpC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
+
interface CreateAppOptions {
|
|
3
|
+
cwd?: string;
|
|
4
|
+
sdkVersion?: string;
|
|
5
|
+
}
|
|
2
6
|
export declare const createCommand: Command;
|
|
7
|
+
/** Create the same starter used by the CLI. Exported for smoke tests and integrations. */
|
|
8
|
+
export declare function createApp(name: string, options?: CreateAppOptions): Promise<string>;
|
|
9
|
+
export {};
|
|
3
10
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,UAAU,gBAAgB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,SAmBtB,CAAC;AAEL,0FAA0F;AAC1F,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmL7F"}
|
package/dist/commands/create.js
CHANGED
|
@@ -1,417 +1,227 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import pc from "picocolors";
|
|
3
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
|
-
import { join } from "node:path";
|
|
4
|
+
import { basename, join, resolve } from "node:path";
|
|
5
|
+
import { packageVersion, wamUiVersion } from "../package-version.js";
|
|
6
|
+
const BEZIER_VERSION = "4.0.0-next.14";
|
|
5
7
|
export const createCommand = new Command("create")
|
|
6
|
-
.description("Create a
|
|
7
|
-
.argument("<name>", "
|
|
8
|
-
.
|
|
9
|
-
.action(async (name, options) => {
|
|
8
|
+
.description("Create a secure TypeScript Channel.io app starter")
|
|
9
|
+
.argument("<name>", "Directory and package name for the app")
|
|
10
|
+
.action(async (name) => {
|
|
10
11
|
console.log(pc.cyan(`\nCreating Channel.io app: ${pc.bold(name)}\n`));
|
|
11
|
-
const targetDir = join(process.cwd(), name);
|
|
12
12
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
const targetDir = await createApp(name);
|
|
14
|
+
console.log(pc.green(`\n✓ Created ${basename(targetDir)} successfully!\n`));
|
|
15
|
+
console.log("Next steps:\n");
|
|
16
|
+
console.log(` cd ${name}`);
|
|
17
|
+
console.log(" corepack pnpm install");
|
|
18
|
+
console.log(" cp apps/server/.env.example apps/server/.env");
|
|
19
|
+
console.log(" corepack pnpm build");
|
|
20
|
+
console.log(" corepack pnpm dev\n");
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
console.error(pc.red(`\nError creating app: ${String(error)}`));
|
|
24
|
+
process.exitCode = 1;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
/** Create the same starter used by the CLI. Exported for smoke tests and integrations. */
|
|
28
|
+
export async function createApp(name, options = {}) {
|
|
29
|
+
if (!/^[a-z0-9][a-z0-9._-]*$/.test(name)) {
|
|
30
|
+
throw new Error("App name must use lowercase letters, numbers, dots, underscores, or hyphens");
|
|
31
|
+
}
|
|
32
|
+
const targetDir = resolve(options.cwd ?? process.cwd(), name);
|
|
33
|
+
const sdkVersion = options.sdkVersion ?? packageVersion;
|
|
34
|
+
await mkdir(targetDir);
|
|
35
|
+
const directories = ["apps/server/src", "apps/wam/src", "packages/shared/src"];
|
|
36
|
+
await Promise.all(directories.map((directory) => mkdir(join(targetDir, directory), { recursive: true })));
|
|
37
|
+
const files = {
|
|
38
|
+
"package.json": json({
|
|
39
|
+
name,
|
|
21
40
|
version: "0.0.1",
|
|
22
41
|
private: true,
|
|
42
|
+
packageManager: "pnpm@9.15.4",
|
|
43
|
+
engines: { node: ">=20.11.0" },
|
|
23
44
|
scripts: {
|
|
24
|
-
dev: "turbo run dev",
|
|
25
45
|
build: "turbo run build",
|
|
26
|
-
|
|
46
|
+
dev: "turbo run dev",
|
|
47
|
+
typecheck: "turbo run typecheck",
|
|
27
48
|
},
|
|
28
49
|
devDependencies: {
|
|
29
|
-
turbo: "^2.
|
|
50
|
+
turbo: "^2.10.5",
|
|
30
51
|
typescript: "^5.7.2",
|
|
31
52
|
},
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await writeFile(join(targetDir, "pnpm-workspace.yaml"), `packages:
|
|
36
|
-
- "apps/*"
|
|
37
|
-
- "packages/*"
|
|
38
|
-
`);
|
|
39
|
-
// Create turbo.json
|
|
40
|
-
await writeFile(join(targetDir, "turbo.json"), JSON.stringify({
|
|
53
|
+
}),
|
|
54
|
+
"pnpm-workspace.yaml": `packages:\n - "apps/*"\n - "packages/*"\n`,
|
|
55
|
+
"turbo.json": json({
|
|
41
56
|
$schema: "https://turbo.build/schema.json",
|
|
42
57
|
tasks: {
|
|
43
|
-
build: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
},
|
|
47
|
-
dev: {
|
|
48
|
-
cache: false,
|
|
49
|
-
persistent: true,
|
|
50
|
-
},
|
|
51
|
-
lint: {
|
|
52
|
-
outputs: [],
|
|
53
|
-
},
|
|
58
|
+
build: { dependsOn: ["^build"], outputs: ["dist/**"] },
|
|
59
|
+
dev: { dependsOn: ["^build"], cache: false, persistent: true },
|
|
60
|
+
typecheck: { dependsOn: ["^build"], outputs: [] },
|
|
54
61
|
},
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
type: "module",
|
|
86
|
-
scripts: {
|
|
87
|
-
build: "nest build",
|
|
88
|
-
dev: "nest start --watch",
|
|
89
|
-
start: "node dist/main.js",
|
|
90
|
-
lint: "eslint src/",
|
|
91
|
-
},
|
|
92
|
-
dependencies: {
|
|
93
|
-
"@channel.io/app-sdk": "^0.0.1",
|
|
94
|
-
"@nestjs/common": "^10.4.15",
|
|
95
|
-
"@nestjs/core": "^10.4.15",
|
|
96
|
-
"@nestjs/platform-express": "^10.4.15",
|
|
97
|
-
"reflect-metadata": "^0.2.2",
|
|
98
|
-
rxjs: "^7.8.1",
|
|
99
|
-
zod: "^3.24.1",
|
|
100
|
-
},
|
|
101
|
-
devDependencies: {
|
|
102
|
-
"@nestjs/cli": "^10.4.9",
|
|
103
|
-
"@types/node": "^22.10.5",
|
|
104
|
-
typescript: "^5.7.2",
|
|
105
|
-
},
|
|
106
|
-
}, null, 2));
|
|
107
|
-
// tsconfig.json
|
|
108
|
-
await writeFile(join(serverDir, "tsconfig.json"), JSON.stringify({
|
|
109
|
-
compilerOptions: {
|
|
110
|
-
target: "ES2022",
|
|
111
|
-
module: "NodeNext",
|
|
112
|
-
moduleResolution: "NodeNext",
|
|
113
|
-
strict: true,
|
|
114
|
-
esModuleInterop: true,
|
|
115
|
-
skipLibCheck: true,
|
|
116
|
-
experimentalDecorators: true,
|
|
117
|
-
emitDecoratorMetadata: true,
|
|
118
|
-
outDir: "./dist",
|
|
119
|
-
rootDir: "./src",
|
|
120
|
-
},
|
|
121
|
-
include: ["src/**/*"],
|
|
122
|
-
}, null, 2));
|
|
123
|
-
// nest-cli.json
|
|
124
|
-
await writeFile(join(serverDir, "nest-cli.json"), JSON.stringify({
|
|
125
|
-
$schema: "https://json.schemastore.org/nest-cli",
|
|
126
|
-
collection: "@nestjs/schematics",
|
|
127
|
-
sourceRoot: "src",
|
|
128
|
-
compilerOptions: {
|
|
129
|
-
builder: "tsc",
|
|
130
|
-
},
|
|
131
|
-
}, null, 2));
|
|
132
|
-
// main.ts
|
|
133
|
-
await writeFile(join(serverDir, "src", "main.ts"), `import { NestFactory } from "@nestjs/core";
|
|
134
|
-
import { AppModule } from "./app.module.js";
|
|
135
|
-
|
|
136
|
-
async function bootstrap() {
|
|
137
|
-
const app = await NestFactory.create(AppModule);
|
|
138
|
-
|
|
139
|
-
const port = process.env.PORT ?? 3000;
|
|
140
|
-
await app.listen(port);
|
|
141
|
-
|
|
142
|
-
console.log(\`Server running on http://localhost:\${port}\`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
bootstrap();
|
|
146
|
-
`);
|
|
147
|
-
// app.module.ts
|
|
148
|
-
await writeFile(join(serverDir, "src", "app.module.ts"), `import { Module } from "@nestjs/common";
|
|
149
|
-
import { ConfigModule, ConfigService } from "@nestjs/config";
|
|
150
|
-
import { ChannelAppModule } from "@channel.io/app-sdk";
|
|
151
|
-
import { commandExtension } from "./extensions/command.extension.js";
|
|
152
|
-
|
|
153
|
-
@Module({
|
|
154
|
-
imports: [
|
|
155
|
-
ConfigModule.forRoot(),
|
|
156
|
-
ChannelAppModule.forRootAsync({
|
|
157
|
-
imports: [ConfigModule],
|
|
158
|
-
inject: [ConfigService],
|
|
159
|
-
useFactory: (config: ConfigService) => ({
|
|
160
|
-
appId: config.get("APP_ID") ?? "",
|
|
161
|
-
appSecret: config.get("APP_SECRET") ?? "",
|
|
162
|
-
extensions: [commandExtension],
|
|
163
|
-
debug: true,
|
|
164
|
-
}),
|
|
165
|
-
}),
|
|
166
|
-
],
|
|
167
|
-
})
|
|
168
|
-
export class AppModule {}
|
|
169
|
-
`);
|
|
170
|
-
// Sample extension
|
|
171
|
-
await writeFile(join(serverDir, "src", "extensions", "command.extension.ts"), `import {
|
|
172
|
-
createExtension,
|
|
173
|
-
defineFunction,
|
|
174
|
-
GetCommandsOutputSchema,
|
|
175
|
-
CommandResultSchema,
|
|
176
|
-
} from "@channel.io/app-sdk";
|
|
177
|
-
import { z } from "zod";
|
|
178
|
-
|
|
179
|
-
const CommandActionInput = z.object({
|
|
180
|
-
chat: z.object({
|
|
181
|
-
type: z.string(),
|
|
182
|
-
id: z.string(),
|
|
183
|
-
}),
|
|
184
|
-
trigger: z.object({
|
|
185
|
-
type: z.string(),
|
|
186
|
-
attributes: z.record(z.string()),
|
|
187
|
-
}),
|
|
188
|
-
input: z.record(z.unknown()),
|
|
189
|
-
language: z.string(),
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
export const commandExtension = createExtension({
|
|
193
|
-
name: "command",
|
|
194
|
-
systemVersion: "v1",
|
|
195
|
-
groups: {
|
|
196
|
-
metadata: {
|
|
197
|
-
getCommands: defineFunction({
|
|
198
|
-
description: "Return command definitions for AppStore registration",
|
|
199
|
-
input: z.object({}),
|
|
200
|
-
output: GetCommandsOutputSchema,
|
|
201
|
-
handler: async () => ({
|
|
202
|
-
commands: [
|
|
203
|
-
{
|
|
204
|
-
name: "hello",
|
|
205
|
-
scope: "desk",
|
|
206
|
-
actionFunctionName: "extension.command.command.execute",
|
|
207
|
-
alfMode: "disable",
|
|
62
|
+
}),
|
|
63
|
+
".gitignore": "node_modules\ndist\n.env\n*.log\n",
|
|
64
|
+
"README.md": starterReadme(name),
|
|
65
|
+
"apps/server/.env.example": `APP_ID=your-app-id\nAPP_SECRET=your-app-secret\nSIGNING_KEY=your-64-character-hex-signing-key\nPORT=3000\n`,
|
|
66
|
+
"apps/server/package.json": json({
|
|
67
|
+
name: `@${name}/server`,
|
|
68
|
+
version: "0.0.1",
|
|
69
|
+
private: true,
|
|
70
|
+
type: "module",
|
|
71
|
+
scripts: {
|
|
72
|
+
build: "nest build",
|
|
73
|
+
dev: "nest start --watch",
|
|
74
|
+
start: "node dist/main.js",
|
|
75
|
+
typecheck: "tsc --noEmit",
|
|
76
|
+
},
|
|
77
|
+
dependencies: {
|
|
78
|
+
"@channel.io/app-sdk-server": sdkVersion,
|
|
79
|
+
[`@${name}/shared`]: "workspace:*",
|
|
80
|
+
"@nestjs/common": "^11.1.28",
|
|
81
|
+
"@nestjs/core": "^11.1.28",
|
|
82
|
+
"@nestjs/platform-express": "^11.1.28",
|
|
83
|
+
dotenv: "^17.2.3",
|
|
84
|
+
"reflect-metadata": "^0.2.2",
|
|
85
|
+
rxjs: "^7.8.2",
|
|
86
|
+
zod: "^3.25.76",
|
|
87
|
+
},
|
|
88
|
+
devDependencies: {
|
|
89
|
+
"@nestjs/cli": "^11.0.23",
|
|
90
|
+
"@types/node": "^22.18.6",
|
|
91
|
+
typescript: "^5.9.3",
|
|
208
92
|
},
|
|
209
|
-
],
|
|
210
93
|
}),
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
message: \`Hello, \${target}!\`,
|
|
94
|
+
"apps/server/nest-cli.json": json({
|
|
95
|
+
$schema: "https://json.schemastore.org/nest-cli",
|
|
96
|
+
collection: "@nestjs/schematics",
|
|
97
|
+
sourceRoot: "src",
|
|
98
|
+
compilerOptions: { builder: "tsc" },
|
|
99
|
+
}),
|
|
100
|
+
"apps/server/tsconfig.json": json({
|
|
101
|
+
compilerOptions: {
|
|
102
|
+
target: "ES2022",
|
|
103
|
+
module: "NodeNext",
|
|
104
|
+
moduleResolution: "NodeNext",
|
|
105
|
+
outDir: "./dist",
|
|
106
|
+
rootDir: "./src",
|
|
107
|
+
strict: true,
|
|
108
|
+
esModuleInterop: true,
|
|
109
|
+
skipLibCheck: true,
|
|
110
|
+
experimentalDecorators: true,
|
|
111
|
+
emitDecoratorMetadata: true,
|
|
230
112
|
},
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
113
|
+
include: ["src/**/*.ts"],
|
|
114
|
+
exclude: ["node_modules"],
|
|
115
|
+
}),
|
|
116
|
+
"apps/server/src/config.ts": serverConfig(),
|
|
117
|
+
"apps/server/src/app.module.ts": serverModule(),
|
|
118
|
+
"apps/server/src/main.ts": serverMain(),
|
|
119
|
+
"apps/server/src/command.extension.ts": commandExtension(name),
|
|
120
|
+
"packages/shared/package.json": json({
|
|
121
|
+
name: `@${name}/shared`,
|
|
122
|
+
version: "0.0.1",
|
|
123
|
+
private: true,
|
|
124
|
+
type: "module",
|
|
125
|
+
main: "./dist/index.js",
|
|
126
|
+
types: "./dist/index.d.ts",
|
|
127
|
+
exports: { ".": { types: "./dist/index.d.ts", import: "./dist/index.js" } },
|
|
128
|
+
scripts: { build: "tsc", typecheck: "tsc --noEmit" },
|
|
129
|
+
dependencies: { zod: "^3.25.76" },
|
|
130
|
+
devDependencies: { typescript: "^5.9.3" },
|
|
131
|
+
}),
|
|
132
|
+
"packages/shared/tsconfig.json": json({
|
|
133
|
+
compilerOptions: {
|
|
134
|
+
target: "ES2022",
|
|
135
|
+
module: "NodeNext",
|
|
136
|
+
moduleResolution: "NodeNext",
|
|
137
|
+
outDir: "./dist",
|
|
138
|
+
rootDir: "./src",
|
|
139
|
+
strict: true,
|
|
140
|
+
declaration: true,
|
|
141
|
+
skipLibCheck: true,
|
|
142
|
+
},
|
|
143
|
+
include: ["src/**/*.ts"],
|
|
144
|
+
exclude: ["dist", "node_modules"],
|
|
145
|
+
}),
|
|
146
|
+
"packages/shared/src/index.ts": sharedContract(),
|
|
147
|
+
"apps/wam/package.json": json({
|
|
148
|
+
name: `@${name}/wam`,
|
|
149
|
+
version: "0.0.1",
|
|
150
|
+
private: true,
|
|
151
|
+
type: "module",
|
|
152
|
+
scripts: {
|
|
153
|
+
build: "tsc && vite build",
|
|
154
|
+
dev: "vite",
|
|
155
|
+
typecheck: "tsc --noEmit",
|
|
156
|
+
preview: "vite preview",
|
|
157
|
+
},
|
|
158
|
+
dependencies: {
|
|
159
|
+
"@channel.io/app-sdk-wam": sdkVersion,
|
|
160
|
+
"@channel.io/app-sdk-wam-ui": wamUiVersion,
|
|
161
|
+
"@channel.io/bezier-icons": "0.60.0",
|
|
162
|
+
"@channel.io/bezier-react": BEZIER_VERSION,
|
|
163
|
+
[`@${name}/shared`]: "workspace:*",
|
|
164
|
+
react: "^18.3.1",
|
|
165
|
+
"react-dom": "^18.3.1",
|
|
166
|
+
"styled-components": "^6.4.3",
|
|
167
|
+
},
|
|
168
|
+
devDependencies: {
|
|
169
|
+
"@types/react": "^18.3.18",
|
|
170
|
+
"@types/react-dom": "^18.3.5",
|
|
171
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
172
|
+
typescript: "^5.9.3",
|
|
173
|
+
vite: "^6.0.7",
|
|
174
|
+
},
|
|
175
|
+
}),
|
|
176
|
+
"apps/wam/tsconfig.json": json({
|
|
177
|
+
compilerOptions: {
|
|
178
|
+
target: "ES2020",
|
|
179
|
+
useDefineForClassFields: true,
|
|
180
|
+
lib: ["ES2020", "DOM", "DOM.Iterable"],
|
|
181
|
+
module: "ESNext",
|
|
182
|
+
moduleResolution: "bundler",
|
|
183
|
+
allowImportingTsExtensions: true,
|
|
184
|
+
isolatedModules: true,
|
|
185
|
+
noEmit: true,
|
|
186
|
+
jsx: "react-jsx",
|
|
187
|
+
strict: true,
|
|
188
|
+
skipLibCheck: true,
|
|
189
|
+
},
|
|
190
|
+
include: ["src"],
|
|
191
|
+
}),
|
|
192
|
+
"apps/wam/vite.config.ts": `import { defineConfig } from "vite";\nimport react from "@vitejs/plugin-react";\n\nexport default defineConfig({\n base: "",\n plugins: [react()],\n build: { outDir: "dist" },\n});\n`,
|
|
193
|
+
"apps/wam/index.html": `<!doctype html>\n<html lang="en">\n <head>\n <meta charset="UTF-8" />\n <meta name="viewport" content="width=device-width, initial-scale=1.0" />\n <title>${name}</title>\n </head>\n <body>\n <div id="root"></div>\n <script type="module" src="/src/main.tsx"></script>\n </body>\n</html>\n`,
|
|
194
|
+
"apps/wam/src/main.tsx": wamMain(),
|
|
195
|
+
"apps/wam/src/App.tsx": wamApp(name),
|
|
196
|
+
};
|
|
197
|
+
await Promise.all(Object.entries(files).map(([path, content]) => writeFile(join(targetDir, path), content)));
|
|
198
|
+
return targetDir;
|
|
242
199
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
"react-dom": "^18.3.1",
|
|
261
|
-
},
|
|
262
|
-
devDependencies: {
|
|
263
|
-
"@types/react": "^18.3.18",
|
|
264
|
-
"@types/react-dom": "^18.3.5",
|
|
265
|
-
"@vitejs/plugin-react": "^4.3.4",
|
|
266
|
-
typescript: "^5.7.2",
|
|
267
|
-
vite: "^6.0.7",
|
|
268
|
-
},
|
|
269
|
-
}, null, 2));
|
|
270
|
-
// vite.config.ts
|
|
271
|
-
await writeFile(join(wamDir, "vite.config.ts"), `import { defineConfig } from "vite";
|
|
272
|
-
import react from "@vitejs/plugin-react";
|
|
273
|
-
|
|
274
|
-
export default defineConfig({
|
|
275
|
-
plugins: [react()],
|
|
276
|
-
build: {
|
|
277
|
-
outDir: "dist",
|
|
278
|
-
},
|
|
279
|
-
});
|
|
280
|
-
`);
|
|
281
|
-
// tsconfig.json
|
|
282
|
-
await writeFile(join(wamDir, "tsconfig.json"), JSON.stringify({
|
|
283
|
-
compilerOptions: {
|
|
284
|
-
target: "ES2022",
|
|
285
|
-
module: "ESNext",
|
|
286
|
-
moduleResolution: "bundler",
|
|
287
|
-
strict: true,
|
|
288
|
-
esModuleInterop: true,
|
|
289
|
-
skipLibCheck: true,
|
|
290
|
-
jsx: "react-jsx",
|
|
291
|
-
lib: ["ES2022", "DOM"],
|
|
292
|
-
},
|
|
293
|
-
include: ["src/**/*"],
|
|
294
|
-
}, null, 2));
|
|
295
|
-
// index.html
|
|
296
|
-
await writeFile(join(wamDir, "index.html"), `<!DOCTYPE html>
|
|
297
|
-
<html lang="en">
|
|
298
|
-
<head>
|
|
299
|
-
<meta charset="UTF-8" />
|
|
300
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
301
|
-
<title>${name} WAM</title>
|
|
302
|
-
</head>
|
|
303
|
-
<body>
|
|
304
|
-
<div id="root"></div>
|
|
305
|
-
<script type="module" src="/src/main.tsx"></script>
|
|
306
|
-
</body>
|
|
307
|
-
</html>
|
|
308
|
-
`);
|
|
309
|
-
// main.tsx
|
|
310
|
-
await writeFile(join(wamDir, "src", "main.tsx"), `import React from "react";
|
|
311
|
-
import ReactDOM from "react-dom/client";
|
|
312
|
-
import { WamProvider } from "@channel.io/app-sdk";
|
|
313
|
-
import App from "./App";
|
|
314
|
-
|
|
315
|
-
ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
316
|
-
<React.StrictMode>
|
|
317
|
-
<WamProvider>
|
|
318
|
-
<App />
|
|
319
|
-
</WamProvider>
|
|
320
|
-
</React.StrictMode>
|
|
321
|
-
);
|
|
322
|
-
`);
|
|
323
|
-
// App.tsx
|
|
324
|
-
await writeFile(join(wamDir, "src", "App.tsx"), `import { useEffect } from "react";
|
|
325
|
-
import { useWamData, useWamSize, useCallFunction } from "@channel.io/app-sdk";
|
|
326
|
-
|
|
327
|
-
export default function App() {
|
|
328
|
-
const appId = useWamData<string>("appId") ?? "";
|
|
329
|
-
const channelId = useWamData<string>("channelId");
|
|
330
|
-
const { setSize } = useWamSize();
|
|
331
|
-
|
|
332
|
-
const { call, loading, data } = useCallFunction<{
|
|
333
|
-
type: string;
|
|
334
|
-
attributes?: { message?: string };
|
|
335
|
-
}>({
|
|
336
|
-
appId,
|
|
337
|
-
name: "extension.command.command.execute",
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
useEffect(() => {
|
|
341
|
-
setSize({ height: 300 });
|
|
342
|
-
}, [setSize]);
|
|
343
|
-
|
|
344
|
-
const handleClick = async () => {
|
|
345
|
-
try {
|
|
346
|
-
await call({
|
|
347
|
-
chat: { type: "direct", id: channelId ?? "demo-chat" },
|
|
348
|
-
trigger: { type: "wam-demo", attributes: {} },
|
|
349
|
-
input: { target: "world" },
|
|
350
|
-
language: "en",
|
|
351
|
-
});
|
|
352
|
-
} catch (error) {
|
|
353
|
-
console.error("Failed to execute command:", error);
|
|
354
|
-
}
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
return (
|
|
358
|
-
<div style={{ padding: 20 }}>
|
|
359
|
-
<h1>Channel.io App</h1>
|
|
360
|
-
<p>Channel ID: {channelId}</p>
|
|
361
|
-
|
|
362
|
-
<button onClick={handleClick} disabled={loading}>
|
|
363
|
-
{loading ? "Executing..." : "Execute Command"}
|
|
364
|
-
</button>
|
|
365
|
-
|
|
366
|
-
{data && (
|
|
367
|
-
<p style={{ color: "green" }}>
|
|
368
|
-
{data.attributes?.message ?? data.type}
|
|
369
|
-
</p>
|
|
370
|
-
)}
|
|
371
|
-
</div>
|
|
372
|
-
);
|
|
200
|
+
function json(value) {
|
|
201
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
202
|
+
}
|
|
203
|
+
function serverConfig() {
|
|
204
|
+
return `import "dotenv/config";\nimport type { ChannelAppModuleOptions } from "@channel.io/app-sdk-server";\n\nfunction required(name: string): string {\n const value = process.env[name]?.trim();\n if (!value) throw new Error(\`\${name} is required\`);\n return value;\n}\n\nexport const appId = required("APP_ID");\nexport const channelAppOptions: ChannelAppModuleOptions = {\n appId,\n appSecret: required("APP_SECRET"),\n signingKey: required("SIGNING_KEY"),\n autoRegister: true,\n};\n`;
|
|
205
|
+
}
|
|
206
|
+
function serverModule() {
|
|
207
|
+
return `import { Module } from "@nestjs/common";\nimport { APP_GUARD } from "@nestjs/core";\nimport { ChannelAppModule, SignatureGuard } from "@channel.io/app-sdk-server";\nimport { channelAppOptions } from "./config.js";\nimport { CommandExtension, HelloFunctions } from "./command.extension.js";\n\n@Module({\n imports: [ChannelAppModule.forRoot(channelAppOptions)],\n providers: [CommandExtension, HelloFunctions, { provide: APP_GUARD, useClass: SignatureGuard }],\n})\nexport class AppModule {}\n`;
|
|
208
|
+
}
|
|
209
|
+
function serverMain() {
|
|
210
|
+
return `import "reflect-metadata";\nimport { existsSync } from "node:fs";\nimport { resolve } from "node:path";\nimport { NestFactory } from "@nestjs/core";\nimport type { NestExpressApplication } from "@nestjs/platform-express";\nimport { AppModule } from "./app.module.js";\n\nasync function bootstrap() {\n const app = await NestFactory.create<NestExpressApplication>(AppModule, { rawBody: true });\n app.enableShutdownHooks();\n app.use((request: { method: string; url: string }, _response: unknown, next: () => void) => {\n const [path, query] = request.url.split("?", 2);\n if (request.method === "PUT" && path === "/functions") {\n request.url = "/functions/v1" + (query ? "?" + query : "");\n }\n next();\n });\n\n const wamDist = resolve(process.cwd(), "../wam/dist");\n if (existsSync(wamDist)) {\n app.useStaticAssets(wamDist, { prefix: "/resource/wam/hello" });\n }\n\n const port = Number(process.env.PORT ?? 3000);\n await app.listen(port);\n}\n\nvoid bootstrap();\n`;
|
|
211
|
+
}
|
|
212
|
+
function commandExtension(name) {
|
|
213
|
+
return `import { Injectable } from "@nestjs/common";\nimport { z } from "zod";\nimport { HELLO_FUNCTION, HELLO_WAM_NAME, CommandActionInputSchema } from "@${name}/shared";\nimport {\n CommandResultSchema,\n Extension,\n Func,\n GetCommandsOutputSchema,\n Input,\n InputSchema,\n OutputSchema,\n} from "@channel.io/app-sdk-server";\nimport { appId } from "./config.js";\n\n@Extension({ name: "command", systemVersion: "v1" })\nexport class CommandExtension {\n @Func("metadata.getCommands")\n @InputSchema(z.object({}))\n @OutputSchema(GetCommandsOutputSchema)\n getCommands(): z.infer<typeof GetCommandsOutputSchema> {\n return { commands: [{\n name: "hello",\n scope: "desk",\n description: "Open the starter WAM",\n actionFunctionName: HELLO_FUNCTION,\n alfMode: "disable",\n enabledByDefault: true,\n }] };\n }\n}\n\n@Injectable()\nexport class HelloFunctions {\n @Func(HELLO_FUNCTION)\n @InputSchema(CommandActionInputSchema)\n @OutputSchema(CommandResultSchema)\n open(@Input() input: z.infer<typeof CommandActionInputSchema>): z.infer<typeof CommandResultSchema> {\n return {\n type: "wam",\n attributes: {\n appId,\n name: HELLO_WAM_NAME,\n wamArgs: { message: \`Hello from ${name}!\`, language: input.language ?? "en" },\n },\n };\n }\n}\n`;
|
|
214
|
+
}
|
|
215
|
+
function sharedContract() {
|
|
216
|
+
return `import { z } from "zod";\n\nexport const HELLO_FUNCTION = "hello.open";\nexport const HELLO_WAM_NAME = "hello";\n\nexport const CommandActionInputSchema = z.object({\n chat: z.object({ type: z.string(), id: z.string() }).optional(),\n trigger: z.object({ type: z.string(), attributes: z.record(z.string()).nullish() }).optional(),\n input: z.record(z.unknown()).nullish().transform((value) => value ?? {}),\n language: z.string().optional(),\n});\n\nexport const HelloWamDataSchema = z.object({\n appId: z.string(),\n channelId: z.string(),\n message: z.string(),\n language: z.string(),\n});\n`;
|
|
373
217
|
}
|
|
374
|
-
|
|
218
|
+
function wamMain() {
|
|
219
|
+
return `import ReactDOM from "react-dom/client";\nimport { WamProvider } from "@channel.io/app-sdk-wam";\nimport App from "./App";\nimport "@channel.io/bezier-react/styles.css";\n\nReactDOM.createRoot(document.getElementById("root")!).render(\n <WamProvider><App /></WamProvider>\n);\n`;
|
|
375
220
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
// package.json
|
|
379
|
-
await writeFile(join(sharedDir, "package.json"), JSON.stringify({
|
|
380
|
-
name: `@${name}/shared`,
|
|
381
|
-
version: "0.0.1",
|
|
382
|
-
private: true,
|
|
383
|
-
type: "module",
|
|
384
|
-
main: "./dist/index.js",
|
|
385
|
-
types: "./dist/index.d.ts",
|
|
386
|
-
scripts: {
|
|
387
|
-
build: "tsc",
|
|
388
|
-
dev: "tsc --watch",
|
|
389
|
-
},
|
|
390
|
-
devDependencies: {
|
|
391
|
-
typescript: "^5.7.2",
|
|
392
|
-
},
|
|
393
|
-
}, null, 2));
|
|
394
|
-
// tsconfig.json
|
|
395
|
-
await writeFile(join(sharedDir, "tsconfig.json"), JSON.stringify({
|
|
396
|
-
compilerOptions: {
|
|
397
|
-
target: "ES2022",
|
|
398
|
-
module: "NodeNext",
|
|
399
|
-
moduleResolution: "NodeNext",
|
|
400
|
-
strict: true,
|
|
401
|
-
esModuleInterop: true,
|
|
402
|
-
skipLibCheck: true,
|
|
403
|
-
declaration: true,
|
|
404
|
-
outDir: "./dist",
|
|
405
|
-
rootDir: "./src",
|
|
406
|
-
},
|
|
407
|
-
include: ["src/**/*"],
|
|
408
|
-
}, null, 2));
|
|
409
|
-
// index.ts
|
|
410
|
-
await writeFile(join(sharedDir, "src", "index.ts"), `// Shared types and utilities
|
|
411
|
-
export interface AppConfig {
|
|
412
|
-
appId: string;
|
|
413
|
-
channelId: string;
|
|
221
|
+
function wamApp(name) {
|
|
222
|
+
return `import { Button, Text, VStack } from "@channel.io/bezier-react/beta";\nimport { useTypedWamData, useWamClose } from "@channel.io/app-sdk-wam";\nimport { HeightSynchronizer, WamHeader, WamThemeProvider } from "@channel.io/app-sdk-wam-ui";\nimport { HelloWamDataSchema } from "@${name}/shared";\n\nexport default function App() {\n const { close } = useWamClose();\n const parsed = HelloWamDataSchema.safeParse({\n appId: useTypedWamData("appId"),\n channelId: useTypedWamData("channelId"),\n message: useTypedWamData("message"),\n language: useTypedWamData("language"),\n });\n\n return (\n <WamThemeProvider>\n <HeightSynchronizer maxHeight={480}>\n <WamHeader title="Hello" onClose={close} />\n <VStack spacing={16} style={{ padding: "0 24px 24px" }}>\n <Text>{parsed.success ? parsed.data.message : "WAM data is unavailable."}</Text>\n <Button label="Close" variant="filled" semantic="primary" onClick={close} />\n </VStack>\n </HeightSynchronizer>\n </WamThemeProvider>\n );\n}\n`;
|
|
414
223
|
}
|
|
415
|
-
|
|
224
|
+
function starterReadme(name) {
|
|
225
|
+
return `# ${name}\n\nA TypeScript Channel.io app starter generated by \`@channel.io/app-sdk\`. It includes a secure NestJS Function server, a command Extension, a shared Zod contract, and a React WAM using the WAM SDK and WAM UI package.\n\n## Run\n\n\`\`\`sh\ncorepack pnpm install\ncp apps/server/.env.example apps/server/.env\ncorepack pnpm build\ncorepack pnpm dev\n\`\`\`\n\nConfigure the public Function Endpoint as \`https://YOUR_HOST/functions\` and WAM Endpoint as \`https://YOUR_HOST/resource/wam\`. Keep App Secret and Signing Key server-side.\n\nStart with the [SDK Quickstart](https://github.com/channel-io/app-sdk/blob/main/docs/guides/en/quickstart.md), then use the [TypeScript reference](https://github.com/channel-io/app-sdk/blob/main/docs/reference/typescript/README.md). For a complete runnable app, see the [TypeScript tutorial](https://github.com/channel-io/app-tutorial-ts).\n`;
|
|
416
226
|
}
|
|
417
227
|
//# sourceMappingURL=create.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.test.d.ts","sourceRoot":"","sources":["../../src/commands/create.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { createApp } from "./create.js";
|
|
6
|
+
const temporaryDirectories = [];
|
|
7
|
+
afterEach(async () => {
|
|
8
|
+
await Promise.all(temporaryDirectories.splice(0).map((path) => rm(path, { recursive: true })));
|
|
9
|
+
});
|
|
10
|
+
describe("createApp", () => {
|
|
11
|
+
it("creates a current secure server, shared contract, and React WAM starter", async () => {
|
|
12
|
+
const cwd = await mkdtemp(join(tmpdir(), "channel-app-cli-"));
|
|
13
|
+
temporaryDirectories.push(cwd);
|
|
14
|
+
const target = await createApp("hello-app", { cwd, sdkVersion: "9.8.7" });
|
|
15
|
+
const serverPackage = JSON.parse(await readFile(join(target, "apps/server/package.json"), "utf8"));
|
|
16
|
+
const wamPackage = JSON.parse(await readFile(join(target, "apps/wam/package.json"), "utf8"));
|
|
17
|
+
const main = await readFile(join(target, "apps/server/src/main.ts"), "utf8");
|
|
18
|
+
const module = await readFile(join(target, "apps/server/src/app.module.ts"), "utf8");
|
|
19
|
+
const environment = await readFile(join(target, "apps/server/.env.example"), "utf8");
|
|
20
|
+
expect(serverPackage.dependencies["@channel.io/app-sdk-server"]).toBe("9.8.7");
|
|
21
|
+
expect(wamPackage.dependencies["@channel.io/app-sdk-wam"]).toBe("9.8.7");
|
|
22
|
+
expect(wamPackage.dependencies["@channel.io/app-sdk-wam-ui"]).toBe("0.4.1");
|
|
23
|
+
expect(wamPackage.dependencies["@channel.io/bezier-react"]).toBe("4.0.0-next.14");
|
|
24
|
+
expect(main).toContain("rawBody: true");
|
|
25
|
+
expect(module).toContain("SignatureGuard");
|
|
26
|
+
expect(environment).toContain("SIGNING_KEY=");
|
|
27
|
+
});
|
|
28
|
+
it("rejects names that cannot be used as package scopes", async () => {
|
|
29
|
+
const cwd = await mkdtemp(join(tmpdir(), "channel-app-cli-"));
|
|
30
|
+
temporaryDirectories.push(cwd);
|
|
31
|
+
await expect(createApp("Hello App", { cwd })).rejects.toThrow("App name must use lowercase");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=create.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create.test.js","sourceRoot":"","sources":["../../src/commands/create.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Version used by generated server and WAM SDK dependencies. */
|
|
2
|
+
export declare const packageVersion: string;
|
|
3
|
+
/** WAM UI version verified with the generated React starter. */
|
|
4
|
+
export declare const wamUiVersion: string;
|
|
5
|
+
//# sourceMappingURL=package-version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAQA,iEAAiE;AACjE,eAAO,MAAM,cAAc,QAAmB,CAAC;AAE/C,gEAAgE;AAChE,eAAO,MAAM,YAAY,QAAwB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const manifest = require("../package.json");
|
|
5
|
+
const wamUiEntry = require.resolve("@channel.io/app-sdk-wam-ui");
|
|
6
|
+
const wamUiManifest = require(join(dirname(wamUiEntry), "../package.json"));
|
|
7
|
+
/** Version used by generated server and WAM SDK dependencies. */
|
|
8
|
+
export const packageVersion = manifest.version;
|
|
9
|
+
/** WAM UI version verified with the generated React starter. */
|
|
10
|
+
export const wamUiVersion = wamUiManifest.version;
|
|
11
|
+
//# sourceMappingURL=package-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-version.js","sourceRoot":"","sources":["../src/package-version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;AACnE,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;AACjE,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,iBAAiB,CAAC,CAAwB,CAAC;AAEnG,iEAAiE;AACjE,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC;AAE/C,gEAAgE;AAChE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,OAAO,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@channel.io/app-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "CLI and main entry for Channel.io App SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
"commander": "^12.1.0",
|
|
23
23
|
"picocolors": "^1.1.1",
|
|
24
24
|
"prompts": "^2.4.2",
|
|
25
|
-
"@channel.io/app-sdk-core": "0.
|
|
26
|
-
"@channel.io/app-sdk-server": "0.
|
|
27
|
-
"@channel.io/app-sdk-wam": "0.
|
|
25
|
+
"@channel.io/app-sdk-core": "0.18.0",
|
|
26
|
+
"@channel.io/app-sdk-server": "0.18.0",
|
|
27
|
+
"@channel.io/app-sdk-wam": "0.18.0",
|
|
28
|
+
"@channel.io/app-sdk-wam-ui": "0.4.1"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"@types/prompts": "^2.4.9",
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
},
|
|
34
35
|
"repository": {
|
|
35
36
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/channel-io/
|
|
37
|
+
"url": "https://github.com/channel-io/app-sdk.git",
|
|
37
38
|
"directory": "ts/packages/cli"
|
|
38
39
|
},
|
|
39
40
|
"license": "MIT",
|