@jskit-ai/jskit-cli 0.2.128 → 0.2.129
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/jskit-cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.129",
|
|
4
4
|
"description": "Bundle and package orchestration CLI for JSKIT apps.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"test": "node --test"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@jskit-ai/jskit-catalog": "0.1.
|
|
24
|
-
"@jskit-ai/kernel": "0.1.
|
|
25
|
-
"@jskit-ai/shell-web": "0.1.
|
|
23
|
+
"@jskit-ai/jskit-catalog": "0.1.124",
|
|
24
|
+
"@jskit-ai/kernel": "0.1.117",
|
|
25
|
+
"@jskit-ai/shell-web": "0.1.116",
|
|
26
26
|
"@vue/compiler-sfc": "^3.5.29",
|
|
27
27
|
"ts-morph": "^28.0.0"
|
|
28
28
|
},
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
import { runAppAdoptManagedScriptsCommand } from "./appCommands/adoptManagedScripts.js";
|
|
12
12
|
import { runAppLinkLocalPackagesCommand } from "./appCommands/linkLocalPackages.js";
|
|
13
13
|
import { runAppMigrateSourceMutationsCommand } from "./appCommands/migrateSourceMutations.js";
|
|
14
|
-
import { runAppPreparePreviewUserCommand } from "./appCommands/preparePreviewUser.js";
|
|
15
14
|
import { runAppReleaseCommand } from "./appCommands/release.js";
|
|
16
15
|
import { runAppUpdatePackagesCommand } from "./appCommands/updatePackages.js";
|
|
17
16
|
import { runAppVerifyCommand } from "./appCommands/verify.js";
|
|
@@ -156,10 +155,6 @@ function createAppCommands(ctx = {}) {
|
|
|
156
155
|
if (definition.name === "migrate-source-mutations") {
|
|
157
156
|
return runAppMigrateSourceMutationsCommand(ctx, { appRoot, options, stdout, stderr });
|
|
158
157
|
}
|
|
159
|
-
if (definition.name === "prepare-preview-user") {
|
|
160
|
-
return runAppPreparePreviewUserCommand(ctx, { appRoot, options, stdout, stderr });
|
|
161
|
-
}
|
|
162
|
-
|
|
163
158
|
throw createCliError(`Unhandled app subcommand: ${definition.name}.`, {
|
|
164
159
|
renderUsage: () => renderAppHelp(stderr, definition)
|
|
165
160
|
});
|
|
@@ -109,46 +109,6 @@ const APP_COMMAND_DEFINITIONS = Object.freeze({
|
|
|
109
109
|
"Clears node_modules/.vite so Vite does not keep stale prebundled paths."
|
|
110
110
|
])
|
|
111
111
|
}),
|
|
112
|
-
"prepare-preview-user": Object.freeze({
|
|
113
|
-
name: "prepare-preview-user",
|
|
114
|
-
summary: "Prepare the JSKIT preview auth user and optional first workspace.",
|
|
115
|
-
usage: "jskit app prepare-preview-user [--profile-file <path>] [--email <email>] [--username <username>] [--display-name <name>] [--auth-provider <provider>] [--auth-provider-user-sid <sid>] [--ensure-workspace]",
|
|
116
|
-
options: Object.freeze([
|
|
117
|
-
Object.freeze({
|
|
118
|
-
label: "--profile-file <path>",
|
|
119
|
-
description: "JSON profile path to write for the preview auth bridge. Defaults to VIBE64_PREVIEW_AUTH_PROFILE_FILE."
|
|
120
|
-
}),
|
|
121
|
-
Object.freeze({
|
|
122
|
-
label: "--email <email>",
|
|
123
|
-
description: "Email address for the preview user."
|
|
124
|
-
}),
|
|
125
|
-
Object.freeze({
|
|
126
|
-
label: "--username <username>",
|
|
127
|
-
description: "Preferred username for the preview user."
|
|
128
|
-
}),
|
|
129
|
-
Object.freeze({
|
|
130
|
-
label: "--display-name <name>",
|
|
131
|
-
description: "Display name for the preview user."
|
|
132
|
-
}),
|
|
133
|
-
Object.freeze({
|
|
134
|
-
label: "--auth-provider <provider>",
|
|
135
|
-
description: "Auth provider id stored on the preview user."
|
|
136
|
-
}),
|
|
137
|
-
Object.freeze({
|
|
138
|
-
label: "--auth-provider-user-sid <sid>",
|
|
139
|
-
description: "Provider user id stored on the preview user."
|
|
140
|
-
}),
|
|
141
|
-
Object.freeze({
|
|
142
|
-
label: "--ensure-workspace",
|
|
143
|
-
description: "When workspace tables and tenancy config exist, ensure the preview user owns a first workspace."
|
|
144
|
-
})
|
|
145
|
-
]),
|
|
146
|
-
defaults: Object.freeze([
|
|
147
|
-
"Runs after migrations and before the app server starts.",
|
|
148
|
-
"Exits successfully without changes when the app has no knexfile.js or users table.",
|
|
149
|
-
"Uses the app knexfile and app-local JSKIT package provisioning contracts instead of booting the HTTP server."
|
|
150
|
-
])
|
|
151
|
-
}),
|
|
152
112
|
release: Object.freeze({
|
|
153
113
|
name: "release",
|
|
154
114
|
summary: "Run the JSKIT release helper for an app repository.",
|
|
@@ -255,16 +215,6 @@ function buildAppCommandOptionMeta(subcommandName = "") {
|
|
|
255
215
|
if (definition.name === "link-local-packages") {
|
|
256
216
|
optionMeta["repo-root"] = { inputType: "text" };
|
|
257
217
|
}
|
|
258
|
-
if (definition.name === "prepare-preview-user") {
|
|
259
|
-
optionMeta["profile-file"] = { inputType: "text" };
|
|
260
|
-
optionMeta.email = { inputType: "text" };
|
|
261
|
-
optionMeta.username = { inputType: "text" };
|
|
262
|
-
optionMeta["display-name"] = { inputType: "text" };
|
|
263
|
-
optionMeta["auth-provider"] = { inputType: "text" };
|
|
264
|
-
optionMeta["auth-provider-user-sid"] = { inputType: "text" };
|
|
265
|
-
optionMeta["ensure-workspace"] = { inputType: "flag" };
|
|
266
|
-
}
|
|
267
|
-
|
|
268
218
|
return optionMeta;
|
|
269
219
|
}
|
|
270
220
|
|
|
@@ -137,11 +137,6 @@ function parseArgs(argv, { createCliError } = {}) {
|
|
|
137
137
|
options.inlineOptions["skip-main-sync"] = "true";
|
|
138
138
|
continue;
|
|
139
139
|
}
|
|
140
|
-
if (token === "--ensure-workspace") {
|
|
141
|
-
options.inlineOptions["ensure-workspace"] = "true";
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
140
|
if (token.startsWith("--")) {
|
|
146
141
|
const withoutPrefix = token.slice(2);
|
|
147
142
|
const hasInlineValue = withoutPrefix.includes("=");
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import { access, mkdir, writeFile } from "node:fs/promises";
|
|
2
|
-
import { createRequire } from "node:module";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { pathToFileURL } from "node:url";
|
|
5
|
-
import { loadAppConfigFromAppRoot } from "@jskit-ai/kernel/server/support";
|
|
6
|
-
|
|
7
|
-
const TENANCY_MODE_NONE = "none";
|
|
8
|
-
|
|
9
|
-
function normalizeText(value = "") {
|
|
10
|
-
return String(value || "").trim();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function normalizeLowerText(value = "") {
|
|
14
|
-
return normalizeText(value).toLowerCase();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function profileFromOptions(options = {}) {
|
|
18
|
-
const inlineOptions = options?.inlineOptions && typeof options.inlineOptions === "object" ? options.inlineOptions : {};
|
|
19
|
-
const profile = {};
|
|
20
|
-
|
|
21
|
-
const email = normalizeLowerText(inlineOptions.email || process.env.JSKIT_PREVIEW_USER_EMAIL);
|
|
22
|
-
const authProvider = normalizeLowerText(inlineOptions["auth-provider"] || process.env.JSKIT_PREVIEW_AUTH_PROVIDER);
|
|
23
|
-
const username = normalizeLowerText(inlineOptions.username || process.env.JSKIT_PREVIEW_USER_USERNAME);
|
|
24
|
-
const displayName = normalizeText(inlineOptions["display-name"] || process.env.JSKIT_PREVIEW_USER_DISPLAY_NAME);
|
|
25
|
-
const authProviderUserSid = normalizeText(
|
|
26
|
-
inlineOptions["auth-provider-user-sid"] || process.env.JSKIT_PREVIEW_AUTH_PROVIDER_USER_SID
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
if (authProvider) {
|
|
30
|
-
profile.authProvider = authProvider;
|
|
31
|
-
}
|
|
32
|
-
if (authProviderUserSid) {
|
|
33
|
-
profile.authProviderUserSid = authProviderUserSid;
|
|
34
|
-
}
|
|
35
|
-
if (displayName) {
|
|
36
|
-
profile.displayName = displayName;
|
|
37
|
-
}
|
|
38
|
-
if (email) {
|
|
39
|
-
profile.email = email;
|
|
40
|
-
}
|
|
41
|
-
if (username) {
|
|
42
|
-
profile.username = username;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return profile;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function fileExists(filePath = "") {
|
|
49
|
-
try {
|
|
50
|
-
await access(filePath);
|
|
51
|
-
return true;
|
|
52
|
-
} catch {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function createAppRequire(appRoot = "") {
|
|
58
|
-
return createRequire(path.join(appRoot, "package.json"));
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function importFreshModule(filePath = "") {
|
|
62
|
-
return import(`${pathToFileURL(filePath).href}?mtime=${Date.now()}`);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function loadKnexConfig(appRoot = "") {
|
|
66
|
-
const knexfilePath = path.join(appRoot, "knexfile.js");
|
|
67
|
-
if (!(await fileExists(knexfilePath))) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const requireFromApp = createAppRequire(appRoot);
|
|
72
|
-
const moduleValue = requireFromApp("knex");
|
|
73
|
-
const createKnex =
|
|
74
|
-
typeof moduleValue === "function"
|
|
75
|
-
? moduleValue
|
|
76
|
-
: typeof moduleValue?.default === "function"
|
|
77
|
-
? moduleValue.default
|
|
78
|
-
: null;
|
|
79
|
-
if (!createKnex) {
|
|
80
|
-
throw new Error("App-local knex package resolved but did not expose a callable factory.");
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const knexfileModule = await importFreshModule(knexfilePath);
|
|
84
|
-
const exported = knexfileModule.default || knexfileModule.config || knexfileModule;
|
|
85
|
-
const knexfile = typeof exported === "function" ? await exported() : exported;
|
|
86
|
-
const environment = normalizeText(process.env.NODE_ENV) || "development";
|
|
87
|
-
|
|
88
|
-
return {
|
|
89
|
-
createKnex,
|
|
90
|
-
knexConfig: knexfile?.[environment] || knexfile
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
async function importAppPackageExport(appRoot = "", specifier = "", { required = true } = {}) {
|
|
95
|
-
const requireFromApp = createAppRequire(appRoot);
|
|
96
|
-
let resolvedPath = "";
|
|
97
|
-
try {
|
|
98
|
-
resolvedPath = requireFromApp.resolve(specifier);
|
|
99
|
-
} catch {
|
|
100
|
-
if (!required) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
throw new Error(
|
|
104
|
-
`Unable to load app-local ${specifier}. Upgrade the installed JSKIT package that owns this preview provisioning contract.`
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
return importFreshModule(resolvedPath);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function writeProfile(profileFile = "", authProfile = {}) {
|
|
111
|
-
if (!profileFile) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
await mkdir(path.dirname(profileFile), { recursive: true });
|
|
115
|
-
await writeFile(profileFile, `${JSON.stringify(authProfile, null, 2)}\n`, "utf8");
|
|
116
|
-
return true;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function isTrueOption(value) {
|
|
120
|
-
const normalized = normalizeLowerText(value);
|
|
121
|
-
return value === true || normalized === "true" || normalized === "1" || normalized === "yes";
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function normalizeTenancyMode(value = "") {
|
|
125
|
-
const normalized = normalizeLowerText(value);
|
|
126
|
-
return normalized === "personal" || normalized === "workspaces" ? normalized : TENANCY_MODE_NONE;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async function hasWorkspaceTables(db) {
|
|
130
|
-
return (
|
|
131
|
-
(await db.schema.hasTable("workspaces")) &&
|
|
132
|
-
(await db.schema.hasTable("workspace_memberships")) &&
|
|
133
|
-
(await db.schema.hasTable("workspace_settings"))
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
async function runAppPreparePreviewUserCommand(_ctx = {}, { appRoot = "", options = {}, stdout = process.stdout }) {
|
|
138
|
-
const inlineOptions = options?.inlineOptions && typeof options.inlineOptions === "object" ? options.inlineOptions : {};
|
|
139
|
-
const profileFile = normalizeText(inlineOptions["profile-file"] || process.env.VIBE64_PREVIEW_AUTH_PROFILE_FILE);
|
|
140
|
-
const ensureWorkspace = isTrueOption(inlineOptions["ensure-workspace"]);
|
|
141
|
-
const loadedKnex = await loadKnexConfig(appRoot);
|
|
142
|
-
if (!loadedKnex) {
|
|
143
|
-
stdout.write("[jskit:preview] skipped: knexfile.js was not found.\n");
|
|
144
|
-
return 0;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const db = loadedKnex.createKnex(loadedKnex.knexConfig);
|
|
148
|
-
try {
|
|
149
|
-
if (!(await db.schema.hasTable("users"))) {
|
|
150
|
-
stdout.write("[jskit:preview] skipped: users table was not found.\n");
|
|
151
|
-
return 0;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const usersPreviewModule = await importAppPackageExport(
|
|
155
|
-
appRoot,
|
|
156
|
-
"@jskit-ai/users-core/server/previewUserProvisioning"
|
|
157
|
-
);
|
|
158
|
-
if (typeof usersPreviewModule?.ensurePreviewUser !== "function") {
|
|
159
|
-
throw new Error("@jskit-ai/users-core preview provisioning export is missing ensurePreviewUser().");
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const userResult = await usersPreviewModule.ensurePreviewUser(db, profileFromOptions(options));
|
|
163
|
-
if (userResult?.skipped) {
|
|
164
|
-
stdout.write(`[jskit:preview] skipped: ${userResult.skipped}.\n`);
|
|
165
|
-
return 0;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const authProfile = userResult.profile;
|
|
169
|
-
let workspace = null;
|
|
170
|
-
|
|
171
|
-
if (ensureWorkspace) {
|
|
172
|
-
const appConfig = await loadAppConfigFromAppRoot({ appRoot });
|
|
173
|
-
const tenancyMode = normalizeTenancyMode(appConfig?.tenancyMode);
|
|
174
|
-
if (tenancyMode === TENANCY_MODE_NONE) {
|
|
175
|
-
stdout.write("[jskit:preview] skipped workspace: workspace tenancy is disabled.\n");
|
|
176
|
-
} else if (!(await hasWorkspaceTables(db))) {
|
|
177
|
-
throw new Error(
|
|
178
|
-
`Workspace tenancy is "${tenancyMode}", but workspace tables were not found. Run migrations before prepare-preview-user.`
|
|
179
|
-
);
|
|
180
|
-
} else {
|
|
181
|
-
const workspacesPreviewModule = await importAppPackageExport(
|
|
182
|
-
appRoot,
|
|
183
|
-
"@jskit-ai/workspaces-core/server/previewWorkspaceProvisioning"
|
|
184
|
-
);
|
|
185
|
-
if (typeof workspacesPreviewModule?.ensurePreviewWorkspace !== "function") {
|
|
186
|
-
throw new Error("@jskit-ai/workspaces-core preview provisioning export is missing ensurePreviewWorkspace().");
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const workspaceResult = await workspacesPreviewModule.ensurePreviewWorkspace(db, userResult.user, authProfile, {
|
|
190
|
-
appConfig,
|
|
191
|
-
tenancyMode
|
|
192
|
-
});
|
|
193
|
-
workspace = workspaceResult?.workspace || null;
|
|
194
|
-
if (workspaceResult?.skipped) {
|
|
195
|
-
stdout.write(`[jskit:preview] skipped workspace: ${workspaceResult.skipped}.\n`);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const outputProfile = {
|
|
201
|
-
...authProfile,
|
|
202
|
-
...(workspace ? { workspace } : {})
|
|
203
|
-
};
|
|
204
|
-
await writeProfile(profileFile, outputProfile);
|
|
205
|
-
stdout.write(`[jskit:preview] user is ready: ${outputProfile.email} (${outputProfile.id}).\n`);
|
|
206
|
-
if (workspace) {
|
|
207
|
-
stdout.write(`[jskit:preview] workspace is ready: ${workspace.slug} (${workspace.id}).\n`);
|
|
208
|
-
}
|
|
209
|
-
return 0;
|
|
210
|
-
} finally {
|
|
211
|
-
await db.destroy();
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export { runAppPreparePreviewUserCommand };
|