primitive-admin 1.0.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/README.md +495 -0
- package/dist/bin/primitive.js +72 -0
- package/dist/bin/primitive.js.map +1 -0
- package/dist/src/commands/admins.js +268 -0
- package/dist/src/commands/admins.js.map +1 -0
- package/dist/src/commands/analytics.js +195 -0
- package/dist/src/commands/analytics.js.map +1 -0
- package/dist/src/commands/apps.js +238 -0
- package/dist/src/commands/apps.js.map +1 -0
- package/dist/src/commands/auth.js +178 -0
- package/dist/src/commands/auth.js.map +1 -0
- package/dist/src/commands/catalog.js +460 -0
- package/dist/src/commands/catalog.js.map +1 -0
- package/dist/src/commands/integrations.js +438 -0
- package/dist/src/commands/integrations.js.map +1 -0
- package/dist/src/commands/prompts.js +999 -0
- package/dist/src/commands/prompts.js.map +1 -0
- package/dist/src/commands/sync.js +598 -0
- package/dist/src/commands/sync.js.map +1 -0
- package/dist/src/commands/users.js +293 -0
- package/dist/src/commands/users.js.map +1 -0
- package/dist/src/commands/waitlist.js +176 -0
- package/dist/src/commands/waitlist.js.map +1 -0
- package/dist/src/commands/workflows.js +876 -0
- package/dist/src/commands/workflows.js.map +1 -0
- package/dist/src/lib/api-client.js +522 -0
- package/dist/src/lib/api-client.js.map +1 -0
- package/dist/src/lib/auth-flow.js +306 -0
- package/dist/src/lib/auth-flow.js.map +1 -0
- package/dist/src/lib/config.js +90 -0
- package/dist/src/lib/config.js.map +1 -0
- package/dist/src/lib/fetch.js +43 -0
- package/dist/src/lib/fetch.js.map +1 -0
- package/dist/src/lib/output.js +143 -0
- package/dist/src/lib/output.js.map +1 -0
- package/dist/src/types/index.js +2 -0
- package/dist/src/types/index.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { ApiClient } from "../lib/api-client.js";
|
|
2
|
+
import { loadCredentials, getCurrentAppId } from "../lib/config.js";
|
|
3
|
+
import { success, error, info, keyValue, formatTable, formatId, json, divider, } from "../lib/output.js";
|
|
4
|
+
export function registerAppsCommands(program) {
|
|
5
|
+
const apps = program
|
|
6
|
+
.command("apps")
|
|
7
|
+
.description("Create, update, and manage applications")
|
|
8
|
+
.addHelpText("after", `
|
|
9
|
+
Examples:
|
|
10
|
+
$ primitive apps list
|
|
11
|
+
$ primitive apps create "My New App"
|
|
12
|
+
$ primitive apps update 01HXY... --mode invite-only --passkey
|
|
13
|
+
`);
|
|
14
|
+
// List apps
|
|
15
|
+
apps
|
|
16
|
+
.command("list")
|
|
17
|
+
.description("List all apps you have access to")
|
|
18
|
+
.option("--json", "Output as JSON")
|
|
19
|
+
.action(async (options) => {
|
|
20
|
+
const client = new ApiClient();
|
|
21
|
+
try {
|
|
22
|
+
const { apps: appsList } = await client.listApps();
|
|
23
|
+
if (options.json) {
|
|
24
|
+
json(appsList);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!appsList || appsList.length === 0) {
|
|
28
|
+
info("No apps found.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.log(formatTable(appsList, [
|
|
32
|
+
{ header: "ID", key: "id", format: formatId },
|
|
33
|
+
{ header: "NAME", key: "name" },
|
|
34
|
+
{ header: "ROLE", key: "role" },
|
|
35
|
+
]));
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
error(err.message);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
// Create app
|
|
43
|
+
apps
|
|
44
|
+
.command("create")
|
|
45
|
+
.description("Create a new app (super-admin only)")
|
|
46
|
+
.argument("<name>", "App name")
|
|
47
|
+
.option("--admin-email <email>", "Initial admin email (defaults to your email)")
|
|
48
|
+
.option("--json", "Output as JSON")
|
|
49
|
+
.action(async (name, options) => {
|
|
50
|
+
const client = new ApiClient();
|
|
51
|
+
const credentials = loadCredentials();
|
|
52
|
+
try {
|
|
53
|
+
const payload = { name };
|
|
54
|
+
if (options.adminEmail) {
|
|
55
|
+
payload.initialAdminEmail = options.adminEmail;
|
|
56
|
+
}
|
|
57
|
+
else if (credentials?.email) {
|
|
58
|
+
payload.initialAdminEmail = credentials.email;
|
|
59
|
+
}
|
|
60
|
+
const result = await client.createApp(payload);
|
|
61
|
+
if (options.json) {
|
|
62
|
+
json(result);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
success(`App created: ${result.app?.name || name}`);
|
|
66
|
+
keyValue("App ID", result.app?.appId || result.appId);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
error(err.message);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
// Get app details
|
|
74
|
+
apps
|
|
75
|
+
.command("get")
|
|
76
|
+
.description("Get app details and settings")
|
|
77
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
78
|
+
.option("--json", "Output as JSON")
|
|
79
|
+
.action(async (appId, options) => {
|
|
80
|
+
const resolvedAppId = appId || getCurrentAppId();
|
|
81
|
+
if (!resolvedAppId) {
|
|
82
|
+
error("No app specified. Use --app or 'primitive use <app-id>' to set context.");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
const client = new ApiClient();
|
|
86
|
+
try {
|
|
87
|
+
const [appInfo, settings] = await Promise.all([
|
|
88
|
+
client.getApp(resolvedAppId),
|
|
89
|
+
client.getAppSettings(resolvedAppId).catch(() => null),
|
|
90
|
+
]);
|
|
91
|
+
if (options.json) {
|
|
92
|
+
json({ ...appInfo, settings });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
keyValue("App ID", appInfo.id || resolvedAppId);
|
|
96
|
+
keyValue("Name", appInfo.name);
|
|
97
|
+
if (settings) {
|
|
98
|
+
divider();
|
|
99
|
+
keyValue("Mode", settings.mode);
|
|
100
|
+
keyValue("Waitlist Enabled", settings.waitlistEnabled);
|
|
101
|
+
keyValue("Base URL", settings.baseUrl);
|
|
102
|
+
divider();
|
|
103
|
+
info("Authentication:");
|
|
104
|
+
keyValue(" Google OAuth", settings.googleOAuthEnabled);
|
|
105
|
+
keyValue(" Passkey", settings.passkeyEnabled);
|
|
106
|
+
keyValue(" Magic Link", settings.magicLinkEnabled);
|
|
107
|
+
if (settings.corsMode === "custom") {
|
|
108
|
+
divider();
|
|
109
|
+
info("CORS:");
|
|
110
|
+
keyValue(" Mode", settings.corsMode);
|
|
111
|
+
keyValue(" Allowed Origins", settings.corsAllowedOrigins?.join(", ") || "-");
|
|
112
|
+
keyValue(" Allow Credentials", settings.corsAllowCredentials);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
error(err.message);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
// Update app
|
|
122
|
+
apps
|
|
123
|
+
.command("update")
|
|
124
|
+
.description("Update app settings")
|
|
125
|
+
.argument("[app-id]", "App ID (uses current app if not specified)")
|
|
126
|
+
.option("--name <name>", "App name")
|
|
127
|
+
.option("--mode <mode>", "Access mode: public, invite-only, domain")
|
|
128
|
+
.option("--waitlist <bool>", "Enable/disable waitlist")
|
|
129
|
+
.option("--base-url <url>", "Base URL for the app")
|
|
130
|
+
.option("--google-oauth <bool>", "Enable/disable Google OAuth")
|
|
131
|
+
.option("--passkey <bool>", "Enable/disable passkey authentication")
|
|
132
|
+
.option("--magic-link <bool>", "Enable/disable magic link authentication")
|
|
133
|
+
.option("--cors-mode <mode>", "CORS mode: universal, custom")
|
|
134
|
+
.option("--cors-origins <origins>", "Comma-separated list of allowed origins")
|
|
135
|
+
.option("--cors-credentials <bool>", "Allow credentials in CORS")
|
|
136
|
+
.option("--json", "Output as JSON")
|
|
137
|
+
.action(async (appId, options) => {
|
|
138
|
+
const resolvedAppId = appId || getCurrentAppId();
|
|
139
|
+
if (!resolvedAppId) {
|
|
140
|
+
error("No app specified. Use --app or 'primitive use <app-id>' to set context.");
|
|
141
|
+
process.exit(1);
|
|
142
|
+
}
|
|
143
|
+
const client = new ApiClient();
|
|
144
|
+
// Build update payload from options
|
|
145
|
+
const payload = {};
|
|
146
|
+
if (options.name)
|
|
147
|
+
payload.name = options.name;
|
|
148
|
+
if (options.mode)
|
|
149
|
+
payload.mode = options.mode;
|
|
150
|
+
if (options.waitlist !== undefined)
|
|
151
|
+
payload.waitlistEnabled = options.waitlist === "true";
|
|
152
|
+
if (options.baseUrl)
|
|
153
|
+
payload.baseUrl = options.baseUrl;
|
|
154
|
+
if (options.googleOauth !== undefined)
|
|
155
|
+
payload.googleOAuthEnabled = options.googleOauth === "true";
|
|
156
|
+
if (options.passkey !== undefined)
|
|
157
|
+
payload.passkeyEnabled = options.passkey === "true";
|
|
158
|
+
if (options.magicLink !== undefined)
|
|
159
|
+
payload.magicLinkEnabled = options.magicLink === "true";
|
|
160
|
+
if (options.corsMode)
|
|
161
|
+
payload.corsMode = options.corsMode;
|
|
162
|
+
if (options.corsOrigins)
|
|
163
|
+
payload.corsAllowedOrigins = options.corsOrigins.split(",").map((s) => s.trim());
|
|
164
|
+
if (options.corsCredentials !== undefined)
|
|
165
|
+
payload.corsAllowCredentials = options.corsCredentials === "true";
|
|
166
|
+
if (Object.keys(payload).length === 0) {
|
|
167
|
+
error("No update options specified.");
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const result = await client.updateAppSettings(resolvedAppId, payload);
|
|
172
|
+
if (options.json) {
|
|
173
|
+
json(result);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
success("App settings updated.");
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
error(err.message);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
// Delete app
|
|
184
|
+
apps
|
|
185
|
+
.command("delete")
|
|
186
|
+
.description("Delete an app (super-admin only)")
|
|
187
|
+
.argument("<app-id>", "App ID to delete")
|
|
188
|
+
.option("--confirm <name>", "Skip interactive prompt by providing app name")
|
|
189
|
+
.action(async (appId, options) => {
|
|
190
|
+
const client = new ApiClient();
|
|
191
|
+
// Fetch app details first to get the name
|
|
192
|
+
let appName;
|
|
193
|
+
try {
|
|
194
|
+
const appInfo = await client.getApp(appId);
|
|
195
|
+
appName = appInfo.name;
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
error(`Failed to fetch app: ${err.message}`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
// Show app details
|
|
202
|
+
console.log();
|
|
203
|
+
keyValue("App ID", appId);
|
|
204
|
+
keyValue("App Name", appName);
|
|
205
|
+
console.log();
|
|
206
|
+
if (options.confirm) {
|
|
207
|
+
// Non-interactive: verify the provided name matches
|
|
208
|
+
if (options.confirm !== appName) {
|
|
209
|
+
error(`App name does not match. Expected "${appName}", got "${options.confirm}".`);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Interactive: require typing the app name
|
|
215
|
+
const inquirer = await import("inquirer");
|
|
216
|
+
const { typedName } = await inquirer.default.prompt([
|
|
217
|
+
{
|
|
218
|
+
type: "input",
|
|
219
|
+
name: "typedName",
|
|
220
|
+
message: `Type the app name to confirm deletion:`,
|
|
221
|
+
},
|
|
222
|
+
]);
|
|
223
|
+
if (typedName !== appName) {
|
|
224
|
+
error(`App name does not match. Deletion cancelled.`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
await client.deleteApp(appId);
|
|
230
|
+
success(`App "${appName}" (${appId}) deleted.`);
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
error(err.message);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apps.js","sourceRoot":"","sources":["../../../src/commands/apps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { loadCredentials, clearCredentials, setCurrentApp, clearCurrentApp, } from "../lib/config.js";
|
|
2
|
+
import { browserLogin } from "../lib/auth-flow.js";
|
|
3
|
+
import { ApiClient } from "../lib/api-client.js";
|
|
4
|
+
import { success, error, info, keyValue, formatId, json, } from "../lib/output.js";
|
|
5
|
+
const DEFAULT_SERVER_URL = process.env.PRIMITIVE_SERVER_URL || "https://primitiveapi.com";
|
|
6
|
+
export function registerAuthCommands(program) {
|
|
7
|
+
// Login command
|
|
8
|
+
program
|
|
9
|
+
.command("login")
|
|
10
|
+
.description("Authenticate with the Primitive admin API via browser OAuth")
|
|
11
|
+
.option("-s, --server <url>", "Server URL", DEFAULT_SERVER_URL)
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
const serverUrl = options.server.replace(/\/$/, ""); // Remove trailing slash
|
|
14
|
+
const result = await browserLogin(serverUrl);
|
|
15
|
+
if (result.success && result.credentials) {
|
|
16
|
+
success(`Logged in as ${result.credentials.email}`);
|
|
17
|
+
if (result.credentials.role === "super-admin") {
|
|
18
|
+
info("You have super-admin privileges.");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
error(`Login failed: ${result.error || "Unknown error"}`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
// Logout command
|
|
27
|
+
program
|
|
28
|
+
.command("logout")
|
|
29
|
+
.description("Clear stored credentials")
|
|
30
|
+
.action(() => {
|
|
31
|
+
clearCredentials();
|
|
32
|
+
success("Logged out successfully.");
|
|
33
|
+
});
|
|
34
|
+
// Whoami command
|
|
35
|
+
program
|
|
36
|
+
.command("whoami")
|
|
37
|
+
.description("Show current authenticated user")
|
|
38
|
+
.option("--json", "Output as JSON")
|
|
39
|
+
.action((options) => {
|
|
40
|
+
const credentials = loadCredentials();
|
|
41
|
+
if (!credentials) {
|
|
42
|
+
error("Not logged in. Run 'primitive login' first.");
|
|
43
|
+
process.exit(2);
|
|
44
|
+
}
|
|
45
|
+
if (options.json) {
|
|
46
|
+
json({
|
|
47
|
+
email: credentials.email,
|
|
48
|
+
adminId: credentials.adminId,
|
|
49
|
+
role: credentials.role,
|
|
50
|
+
serverUrl: credentials.serverUrl,
|
|
51
|
+
currentAppId: credentials.currentAppId,
|
|
52
|
+
currentAppName: credentials.currentAppName,
|
|
53
|
+
});
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
keyValue("Email", credentials.email);
|
|
57
|
+
keyValue("Admin ID", credentials.adminId);
|
|
58
|
+
keyValue("Role", credentials.role);
|
|
59
|
+
keyValue("Server", credentials.serverUrl);
|
|
60
|
+
if (credentials.currentAppId) {
|
|
61
|
+
keyValue("Current App", credentials.currentAppName || credentials.currentAppId);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Token command - print access token for scripting
|
|
65
|
+
program
|
|
66
|
+
.command("token")
|
|
67
|
+
.description("Print the current access token (for scripting)")
|
|
68
|
+
.action(() => {
|
|
69
|
+
const credentials = loadCredentials();
|
|
70
|
+
if (!credentials) {
|
|
71
|
+
error("Not logged in. Run 'primitive login' first.");
|
|
72
|
+
process.exit(2);
|
|
73
|
+
}
|
|
74
|
+
// Print only the token for easy piping
|
|
75
|
+
console.log(credentials.accessToken);
|
|
76
|
+
});
|
|
77
|
+
// Use command - set current app context
|
|
78
|
+
program
|
|
79
|
+
.command("use [app-id-or-name]")
|
|
80
|
+
.description("Set the current app context (interactive if no argument)")
|
|
81
|
+
.action(async (appIdOrName) => {
|
|
82
|
+
const credentials = loadCredentials();
|
|
83
|
+
if (!credentials) {
|
|
84
|
+
error("Not logged in. Run 'primitive login' first.");
|
|
85
|
+
process.exit(2);
|
|
86
|
+
}
|
|
87
|
+
const client = new ApiClient();
|
|
88
|
+
try {
|
|
89
|
+
const { apps } = await client.listApps();
|
|
90
|
+
if (!apps || apps.length === 0) {
|
|
91
|
+
error("No apps available.");
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
let selectedApp;
|
|
95
|
+
if (appIdOrName) {
|
|
96
|
+
// Try to find by ID or name
|
|
97
|
+
selectedApp = apps.find((app) => app.id === appIdOrName ||
|
|
98
|
+
app.name.toLowerCase() === appIdOrName.toLowerCase());
|
|
99
|
+
if (!selectedApp) {
|
|
100
|
+
// Try partial name match
|
|
101
|
+
const matches = apps.filter((app) => app.name.toLowerCase().includes(appIdOrName.toLowerCase()));
|
|
102
|
+
if (matches.length === 1) {
|
|
103
|
+
selectedApp = matches[0];
|
|
104
|
+
}
|
|
105
|
+
else if (matches.length > 1) {
|
|
106
|
+
error(`Multiple apps match "${appIdOrName}":`);
|
|
107
|
+
matches.forEach((app) => {
|
|
108
|
+
console.log(` - ${app.name} (${app.id})`);
|
|
109
|
+
});
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
error(`No app found matching "${appIdOrName}"`);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Interactive selection
|
|
120
|
+
const { Separator } = await import("@inquirer/prompts");
|
|
121
|
+
const { default: searchPrompt } = await import("@inquirer/search");
|
|
122
|
+
selectedApp = await searchPrompt({
|
|
123
|
+
message: "Select an app:",
|
|
124
|
+
source: (input) => {
|
|
125
|
+
const term = (input || "").toLowerCase();
|
|
126
|
+
const filtered = apps.filter((app) => app.name.toLowerCase().includes(term) ||
|
|
127
|
+
app.id.toLowerCase().includes(term));
|
|
128
|
+
return filtered.map((app) => ({
|
|
129
|
+
name: `${app.name} (${formatId(app.id)})`,
|
|
130
|
+
value: app,
|
|
131
|
+
}));
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (selectedApp) {
|
|
136
|
+
setCurrentApp(selectedApp.id, selectedApp.name);
|
|
137
|
+
success(`Now using app: ${selectedApp.name} (${selectedApp.id})`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
error(err.message || "Failed to list apps");
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
// Context command - show or clear current app context
|
|
146
|
+
program
|
|
147
|
+
.command("context")
|
|
148
|
+
.description("Show or manage current app context")
|
|
149
|
+
.argument("[action]", "Action: 'clear' to remove context")
|
|
150
|
+
.option("--json", "Output as JSON")
|
|
151
|
+
.action((action, options) => {
|
|
152
|
+
if (action === "clear") {
|
|
153
|
+
clearCurrentApp();
|
|
154
|
+
success("App context cleared.");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const credentials = loadCredentials();
|
|
158
|
+
if (!credentials) {
|
|
159
|
+
error("Not logged in. Run 'primitive login' first.");
|
|
160
|
+
process.exit(2);
|
|
161
|
+
}
|
|
162
|
+
if (options.json) {
|
|
163
|
+
json({
|
|
164
|
+
currentAppId: credentials.currentAppId || null,
|
|
165
|
+
currentAppName: credentials.currentAppName || null,
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (credentials.currentAppId) {
|
|
170
|
+
keyValue("Current App", credentials.currentAppName || "");
|
|
171
|
+
keyValue("App ID", credentials.currentAppId);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
info("No app context set. Use 'primitive use <app-id>' to set one.");
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|