@construct-space/cli 1.1.11 → 1.2.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/index.js +231 -272
- package/dist/templates/space/full/space.manifest.json.tmpl +1 -1
- package/dist/templates/space/space.manifest.json.tmpl +2 -2
- package/dist/templates/space/widgets/2x1.vue.tmpl +7 -0
- package/dist/templates/space/widgets/4x1.vue.tmpl +7 -0
- package/package.json +1 -1
- package/templates/space/full/space.manifest.json.tmpl +1 -1
- package/templates/space/space.manifest.json.tmpl +2 -2
- package/templates/space/widgets/2x1.vue.tmpl +7 -0
- package/templates/space/widgets/4x1.vue.tmpl +7 -0
package/dist/index.js
CHANGED
|
@@ -5,43 +5,25 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
function __accessProp(key) {
|
|
9
|
-
return this[key];
|
|
10
|
-
}
|
|
11
|
-
var __toESMCache_node;
|
|
12
|
-
var __toESMCache_esm;
|
|
13
8
|
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
-
var canCache = mod != null && typeof mod === "object";
|
|
15
|
-
if (canCache) {
|
|
16
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
-
var cached = cache.get(mod);
|
|
18
|
-
if (cached)
|
|
19
|
-
return cached;
|
|
20
|
-
}
|
|
21
9
|
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
22
10
|
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
23
11
|
for (let key of __getOwnPropNames(mod))
|
|
24
12
|
if (!__hasOwnProp.call(to, key))
|
|
25
13
|
__defProp(to, key, {
|
|
26
|
-
get:
|
|
14
|
+
get: () => mod[key],
|
|
27
15
|
enumerable: true
|
|
28
16
|
});
|
|
29
|
-
if (canCache)
|
|
30
|
-
cache.set(mod, to);
|
|
31
17
|
return to;
|
|
32
18
|
};
|
|
33
19
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
34
|
-
var __returnValue = (v) => v;
|
|
35
|
-
function __exportSetter(name, newValue) {
|
|
36
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
37
|
-
}
|
|
38
20
|
var __export = (target, all) => {
|
|
39
21
|
for (var name in all)
|
|
40
22
|
__defProp(target, name, {
|
|
41
23
|
get: all[name],
|
|
42
24
|
enumerable: true,
|
|
43
25
|
configurable: true,
|
|
44
|
-
set:
|
|
26
|
+
set: (newValue) => all[name] = () => newValue
|
|
45
27
|
});
|
|
46
28
|
};
|
|
47
29
|
var __require = import.meta.require;
|
|
@@ -2807,6 +2789,7 @@ Object.defineProperties(createChalk.prototype, styles2);
|
|
|
2807
2789
|
var chalk = createChalk();
|
|
2808
2790
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
2809
2791
|
var source_default = chalk;
|
|
2792
|
+
|
|
2810
2793
|
// node_modules/@inquirer/core/dist/lib/key.js
|
|
2811
2794
|
var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
|
|
2812
2795
|
var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
|
|
@@ -2951,7 +2934,7 @@ var effectScheduler = {
|
|
|
2951
2934
|
// node_modules/@inquirer/core/dist/lib/use-state.js
|
|
2952
2935
|
function useState(defaultValue) {
|
|
2953
2936
|
return withPointer((pointer) => {
|
|
2954
|
-
const setState = AsyncResource2.bind(function
|
|
2937
|
+
const setState = AsyncResource2.bind(function setState(newValue) {
|
|
2955
2938
|
if (pointer.get() !== newValue) {
|
|
2956
2939
|
pointer.set(newValue);
|
|
2957
2940
|
handleChange();
|
|
@@ -4727,7 +4710,7 @@ async function scaffold(nameArg, options) {
|
|
|
4727
4710
|
}
|
|
4728
4711
|
|
|
4729
4712
|
// src/commands/build.ts
|
|
4730
|
-
import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as
|
|
4713
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync3, renameSync, statSync as statSync3 } from "fs";
|
|
4731
4714
|
import { join as join6 } from "path";
|
|
4732
4715
|
import { createHash } from "crypto";
|
|
4733
4716
|
|
|
@@ -7380,8 +7363,8 @@ function validate2(m) {
|
|
|
7380
7363
|
errors2.push("author: must be an object with a name");
|
|
7381
7364
|
if (!m.icon)
|
|
7382
7365
|
errors2.push("icon: must be a string");
|
|
7383
|
-
if (!["
|
|
7384
|
-
errors2.push('scope: must be "
|
|
7366
|
+
if (!["app", "project", "org", "any"].includes(m.scope))
|
|
7367
|
+
errors2.push('scope: must be "app", "project", "org", or "any"');
|
|
7385
7368
|
if (!m.pages?.length)
|
|
7386
7369
|
errors2.push("pages: must be a non-empty array");
|
|
7387
7370
|
if (!m.navigation?.label)
|
|
@@ -7408,30 +7391,84 @@ function exists(dir) {
|
|
|
7408
7391
|
}
|
|
7409
7392
|
|
|
7410
7393
|
// src/lib/entry.ts
|
|
7411
|
-
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
7412
|
-
import { join as join4, basename, extname } from "path";
|
|
7394
|
+
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4, readdirSync, statSync } from "fs";
|
|
7395
|
+
import { join as join4, basename, extname, relative } from "path";
|
|
7413
7396
|
function capitalize(s) {
|
|
7414
7397
|
if (!s)
|
|
7415
7398
|
return s;
|
|
7416
7399
|
return s.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
7417
7400
|
}
|
|
7418
|
-
function
|
|
7401
|
+
function scanPagesDir(pagesDir) {
|
|
7402
|
+
const results = [];
|
|
7403
|
+
function walk(dir, routeSegments) {
|
|
7404
|
+
if (!existsSync4(dir))
|
|
7405
|
+
return;
|
|
7406
|
+
const entries = readdirSync(dir).sort();
|
|
7407
|
+
for (const entry of entries) {
|
|
7408
|
+
const fullPath = join4(dir, entry);
|
|
7409
|
+
const stat = statSync(fullPath);
|
|
7410
|
+
if (stat.isDirectory()) {
|
|
7411
|
+
const segment = entry.replace(/^\[(.+)\]$/, ":$1");
|
|
7412
|
+
walk(fullPath, [...routeSegments, segment]);
|
|
7413
|
+
} else if (stat.isFile() && entry.endsWith(".vue")) {
|
|
7414
|
+
const nameWithoutExt = entry.replace(/\.vue$/, "");
|
|
7415
|
+
const relFile = relative(join4(pagesDir, ".."), fullPath).replace(/\\/g, "/");
|
|
7416
|
+
let routePath;
|
|
7417
|
+
if (nameWithoutExt === "index") {
|
|
7418
|
+
routePath = routeSegments.join("/");
|
|
7419
|
+
} else {
|
|
7420
|
+
const segment = nameWithoutExt.replace(/^\[(.+)\]$/, ":$1");
|
|
7421
|
+
routePath = [...routeSegments, segment].join("/");
|
|
7422
|
+
}
|
|
7423
|
+
results.push({ filePath: relFile, routePath });
|
|
7424
|
+
}
|
|
7425
|
+
}
|
|
7426
|
+
}
|
|
7427
|
+
walk(pagesDir, []);
|
|
7428
|
+
return results;
|
|
7429
|
+
}
|
|
7430
|
+
function varNameFromFile(filePath) {
|
|
7431
|
+
let cleaned = filePath.replace(/^pages\//, "").replace(/\.vue$/, "");
|
|
7432
|
+
cleaned = cleaned.replace(/\[([^\]]+)\]/g, "$1");
|
|
7433
|
+
const segments = cleaned.split(/[\/-]/).filter(Boolean);
|
|
7434
|
+
const name = segments.map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
7435
|
+
return (name || "Index") + "Page";
|
|
7436
|
+
}
|
|
7437
|
+
function resolvePages(m, root, prefix) {
|
|
7438
|
+
const pagesDir = join4(root, "src", "pages");
|
|
7439
|
+
const fsPages = scanPagesDir(pagesDir);
|
|
7440
|
+
const fsMap = new Map;
|
|
7441
|
+
for (const fp of fsPages) {
|
|
7442
|
+
fsMap.set(fp.routePath, fp);
|
|
7443
|
+
}
|
|
7419
7444
|
return m.pages.map((p) => {
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7445
|
+
if (p.component) {
|
|
7446
|
+
const base = basename(p.component);
|
|
7447
|
+
const nameWithoutExt = base.replace(extname(base), "").replace(/[\[\]]/g, "");
|
|
7448
|
+
const dir = p.component.replace(/^pages\//, "").replace(/\/[^/]+$/, "");
|
|
7449
|
+
let varName;
|
|
7450
|
+
if (dir && dir !== p.component.replace(/^pages\//, "")) {
|
|
7451
|
+
varName = capitalize(dir.split("/").map((s) => s.replace(/[\[\]]/g, "")).join("-")) + capitalize(nameWithoutExt) + "Page";
|
|
7452
|
+
} else {
|
|
7453
|
+
varName = capitalize(nameWithoutExt) + "Page";
|
|
7454
|
+
}
|
|
7455
|
+
return { varName, importPath: prefix + p.component, path: p.path };
|
|
7456
|
+
}
|
|
7457
|
+
const fsPage = fsMap.get(p.path);
|
|
7458
|
+
if (fsPage) {
|
|
7459
|
+
const varName = varNameFromFile(fsPage.filePath);
|
|
7460
|
+
return { varName, importPath: prefix + fsPage.filePath, path: p.path };
|
|
7423
7461
|
}
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
cleanPath = base;
|
|
7462
|
+
const legacyComponent = p.path === "" ? "pages/index.vue" : `pages/${p.path}.vue`;
|
|
7463
|
+
const legacyFullPath = join4(root, "src", legacyComponent);
|
|
7464
|
+
if (existsSync4(legacyFullPath)) {
|
|
7465
|
+
let varName = "IndexPage";
|
|
7466
|
+
if (p.path) {
|
|
7467
|
+
varName = capitalize(p.path.replace(/[\/:]/g, "-").replace(/-+/g, "-")) + "Page";
|
|
7431
7468
|
}
|
|
7432
|
-
varName
|
|
7469
|
+
return { varName, importPath: prefix + legacyComponent, path: p.path };
|
|
7433
7470
|
}
|
|
7434
|
-
|
|
7471
|
+
throw new Error(`[entry] Could not resolve component for page "${p.path}". ` + `Checked: manifest component field, filesystem scan of src/pages/, ` + `and legacy fallback at ${legacyComponent}. ` + `Ensure a .vue file exists for this route.`);
|
|
7435
7472
|
});
|
|
7436
7473
|
}
|
|
7437
7474
|
function resolveWidgets(m, prefix) {
|
|
@@ -7450,7 +7487,7 @@ function resolveWidgets(m, prefix) {
|
|
|
7450
7487
|
}
|
|
7451
7488
|
function generate(root, m) {
|
|
7452
7489
|
const pagePrefix = existsSync4(join4(root, "src", "pages")) ? "./" : "../";
|
|
7453
|
-
const pages = resolvePages(m, pagePrefix);
|
|
7490
|
+
const pages = resolvePages(m, root, pagePrefix);
|
|
7454
7491
|
const widgets = resolveWidgets(m, "../");
|
|
7455
7492
|
const actionsPath = join4(root, "src", "actions.ts");
|
|
7456
7493
|
const hasActions = existsSync4(actionsPath);
|
|
@@ -7506,7 +7543,7 @@ function writeEntry(root, m) {
|
|
|
7506
7543
|
}
|
|
7507
7544
|
|
|
7508
7545
|
// src/lib/agent.ts
|
|
7509
|
-
import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, readdirSync, existsSync as existsSync5 } from "fs";
|
|
7546
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync2, existsSync as existsSync5 } from "fs";
|
|
7510
7547
|
import { join as join5, extname as extname2, basename as basename2 } from "path";
|
|
7511
7548
|
var AGENT_KEY = "construct-agent-obfuscate-v1";
|
|
7512
7549
|
function encode(content) {
|
|
@@ -7522,7 +7559,7 @@ function readMdFiles(dir) {
|
|
|
7522
7559
|
const result = {};
|
|
7523
7560
|
if (!existsSync5(dir))
|
|
7524
7561
|
return result;
|
|
7525
|
-
for (const f of
|
|
7562
|
+
for (const f of readdirSync2(dir)) {
|
|
7526
7563
|
if (extname2(f) !== ".md")
|
|
7527
7564
|
continue;
|
|
7528
7565
|
result[basename2(f, ".md")] = readFileSync3(join5(dir, f), "utf-8");
|
|
@@ -7533,7 +7570,7 @@ function readJsonFiles(dir) {
|
|
|
7533
7570
|
const result = {};
|
|
7534
7571
|
if (!existsSync5(dir))
|
|
7535
7572
|
return result;
|
|
7536
|
-
for (const f of
|
|
7573
|
+
for (const f of readdirSync2(dir)) {
|
|
7537
7574
|
if (extname2(f) !== ".json")
|
|
7538
7575
|
continue;
|
|
7539
7576
|
result[basename2(f, ".json")] = readFileSync3(join5(dir, f), "utf-8");
|
|
@@ -7623,7 +7660,7 @@ async function build(options) {
|
|
|
7623
7660
|
}
|
|
7624
7661
|
runHook(m.hooks, "postBuild", root);
|
|
7625
7662
|
const agentDir = join6(root, "agent");
|
|
7626
|
-
if (existsSync6(agentDir) &&
|
|
7663
|
+
if (existsSync6(agentDir) && statSync3(agentDir).isDirectory()) {
|
|
7627
7664
|
const distDir2 = join6(root, "dist");
|
|
7628
7665
|
bundleAgentDir(agentDir, distDir2);
|
|
7629
7666
|
bundleAgentDir(agentDir, root);
|
|
@@ -7632,7 +7669,7 @@ async function build(options) {
|
|
|
7632
7669
|
const expectedBundle = `space-${m.id}.iife.js`;
|
|
7633
7670
|
let bundlePath = join6(distDir, expectedBundle);
|
|
7634
7671
|
if (!existsSync6(bundlePath)) {
|
|
7635
|
-
const matches =
|
|
7672
|
+
const matches = readdirSync3(distDir).filter((f) => f.startsWith("space-") && f.endsWith(".iife.js"));
|
|
7636
7673
|
if (matches.length === 1) {
|
|
7637
7674
|
renameSync(join6(distDir, matches[0]), bundlePath);
|
|
7638
7675
|
const oldCSS = join6(distDir, matches[0].replace(".iife.js", ".css"));
|
|
@@ -7666,16 +7703,16 @@ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
|
7666
7703
|
import { join as join9 } from "path";
|
|
7667
7704
|
import { createHash as createHash2 } from "crypto";
|
|
7668
7705
|
|
|
7669
|
-
// node_modules/chokidar/
|
|
7670
|
-
import { stat as statcb } from "fs";
|
|
7671
|
-
import { stat as stat3, readdir as readdir2 } from "fs/promises";
|
|
7706
|
+
// node_modules/chokidar/index.js
|
|
7672
7707
|
import { EventEmitter } from "events";
|
|
7673
|
-
import
|
|
7708
|
+
import { stat as statcb, Stats } from "fs";
|
|
7709
|
+
import { readdir as readdir2, stat as stat3 } from "fs/promises";
|
|
7710
|
+
import * as sp2 from "path";
|
|
7674
7711
|
|
|
7675
|
-
// node_modules/readdirp/
|
|
7676
|
-
import {
|
|
7712
|
+
// node_modules/readdirp/index.js
|
|
7713
|
+
import { lstat, readdir, realpath, stat } from "fs/promises";
|
|
7714
|
+
import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "path";
|
|
7677
7715
|
import { Readable } from "stream";
|
|
7678
|
-
import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "path";
|
|
7679
7716
|
var EntryTypes = {
|
|
7680
7717
|
FILE_TYPE: "files",
|
|
7681
7718
|
DIR_TYPE: "directories",
|
|
@@ -7731,6 +7768,20 @@ var normalizeFilter = (filter) => {
|
|
|
7731
7768
|
};
|
|
7732
7769
|
|
|
7733
7770
|
class ReaddirpStream extends Readable {
|
|
7771
|
+
parents;
|
|
7772
|
+
reading;
|
|
7773
|
+
parent;
|
|
7774
|
+
_stat;
|
|
7775
|
+
_maxDepth;
|
|
7776
|
+
_wantsDir;
|
|
7777
|
+
_wantsFile;
|
|
7778
|
+
_wantsEverything;
|
|
7779
|
+
_root;
|
|
7780
|
+
_isDirent;
|
|
7781
|
+
_statsProp;
|
|
7782
|
+
_rdOptions;
|
|
7783
|
+
_fileFilter;
|
|
7784
|
+
_directoryFilter;
|
|
7734
7785
|
constructor(options = {}) {
|
|
7735
7786
|
super({
|
|
7736
7787
|
objectMode: true,
|
|
@@ -7747,7 +7798,7 @@ class ReaddirpStream extends Readable {
|
|
|
7747
7798
|
} else {
|
|
7748
7799
|
this._stat = statMethod;
|
|
7749
7800
|
}
|
|
7750
|
-
this._maxDepth = opts.depth
|
|
7801
|
+
this._maxDepth = opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;
|
|
7751
7802
|
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
7752
7803
|
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
7753
7804
|
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
@@ -7892,11 +7943,11 @@ function readdirp(root, options = {}) {
|
|
|
7892
7943
|
return new ReaddirpStream(options);
|
|
7893
7944
|
}
|
|
7894
7945
|
|
|
7895
|
-
// node_modules/chokidar/
|
|
7896
|
-
import {
|
|
7897
|
-
import {
|
|
7898
|
-
import * as sysPath from "path";
|
|
7946
|
+
// node_modules/chokidar/handler.js
|
|
7947
|
+
import { watch as fs_watch, unwatchFile, watchFile } from "fs";
|
|
7948
|
+
import { realpath as fsrealpath, lstat as lstat2, open, stat as stat2 } from "fs/promises";
|
|
7899
7949
|
import { type as osType } from "os";
|
|
7950
|
+
import * as sp from "path";
|
|
7900
7951
|
var STR_DATA = "data";
|
|
7901
7952
|
var STR_END = "end";
|
|
7902
7953
|
var STR_CLOSE = "close";
|
|
@@ -8188,7 +8239,7 @@ var binaryExtensions = new Set([
|
|
|
8188
8239
|
"zip",
|
|
8189
8240
|
"zipx"
|
|
8190
8241
|
]);
|
|
8191
|
-
var isBinaryPath = (filePath) => binaryExtensions.has(
|
|
8242
|
+
var isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());
|
|
8192
8243
|
var foreach = (val, fn) => {
|
|
8193
8244
|
if (val instanceof Set) {
|
|
8194
8245
|
val.forEach(fn);
|
|
@@ -8226,7 +8277,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
|
|
|
8226
8277
|
listener(path);
|
|
8227
8278
|
emitRaw(rawEvent, evPath, { watchedPath: path });
|
|
8228
8279
|
if (evPath && path !== evPath) {
|
|
8229
|
-
fsWatchBroadcast(
|
|
8280
|
+
fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));
|
|
8230
8281
|
}
|
|
8231
8282
|
};
|
|
8232
8283
|
try {
|
|
@@ -8341,17 +8392,19 @@ var setFsWatchFileListener = (path, fullPath, options, handlers) => {
|
|
|
8341
8392
|
};
|
|
8342
8393
|
|
|
8343
8394
|
class NodeFsHandler {
|
|
8395
|
+
fsw;
|
|
8396
|
+
_boundHandleError;
|
|
8344
8397
|
constructor(fsW) {
|
|
8345
8398
|
this.fsw = fsW;
|
|
8346
8399
|
this._boundHandleError = (error2) => fsW._handleError(error2);
|
|
8347
8400
|
}
|
|
8348
8401
|
_watchWithNodeFs(path, listener) {
|
|
8349
8402
|
const opts = this.fsw.options;
|
|
8350
|
-
const directory =
|
|
8351
|
-
const basename4 =
|
|
8403
|
+
const directory = sp.dirname(path);
|
|
8404
|
+
const basename4 = sp.basename(path);
|
|
8352
8405
|
const parent = this.fsw._getWatchedDir(directory);
|
|
8353
8406
|
parent.add(basename4);
|
|
8354
|
-
const absolutePath =
|
|
8407
|
+
const absolutePath = sp.resolve(path);
|
|
8355
8408
|
const options = {
|
|
8356
8409
|
persistent: opts.persistent
|
|
8357
8410
|
};
|
|
@@ -8378,8 +8431,8 @@ class NodeFsHandler {
|
|
|
8378
8431
|
if (this.fsw.closed) {
|
|
8379
8432
|
return;
|
|
8380
8433
|
}
|
|
8381
|
-
const dirname3 =
|
|
8382
|
-
const basename4 =
|
|
8434
|
+
const dirname3 = sp.dirname(file);
|
|
8435
|
+
const basename4 = sp.basename(file);
|
|
8383
8436
|
const parent = this.fsw._getWatchedDir(dirname3);
|
|
8384
8437
|
let prevStats = stats;
|
|
8385
8438
|
if (parent.has(basename4))
|
|
@@ -8462,8 +8515,9 @@ class NodeFsHandler {
|
|
|
8462
8515
|
this.fsw._symlinkPaths.set(full, true);
|
|
8463
8516
|
}
|
|
8464
8517
|
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
|
|
8465
|
-
directory =
|
|
8466
|
-
|
|
8518
|
+
directory = sp.join(directory, "");
|
|
8519
|
+
const throttleKey = target ? `${directory}:${target}` : directory;
|
|
8520
|
+
throttler = this.fsw._throttle("readdir", throttleKey, 1000);
|
|
8467
8521
|
if (!throttler)
|
|
8468
8522
|
return;
|
|
8469
8523
|
const previous = this.fsw._getWatchedDir(wh.path);
|
|
@@ -8480,7 +8534,7 @@ class NodeFsHandler {
|
|
|
8480
8534
|
return;
|
|
8481
8535
|
}
|
|
8482
8536
|
const item = entry.path;
|
|
8483
|
-
let path =
|
|
8537
|
+
let path = sp.join(directory, item);
|
|
8484
8538
|
current.add(item);
|
|
8485
8539
|
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
|
|
8486
8540
|
return;
|
|
@@ -8491,7 +8545,7 @@ class NodeFsHandler {
|
|
|
8491
8545
|
}
|
|
8492
8546
|
if (item === target || !target && !previous.has(item)) {
|
|
8493
8547
|
this.fsw._incrReadyCount();
|
|
8494
|
-
path =
|
|
8548
|
+
path = sp.join(dir, sp.relative(dir, path));
|
|
8495
8549
|
this._addToNodeFs(path, initialAdd, wh, depth + 1);
|
|
8496
8550
|
}
|
|
8497
8551
|
}).on(EV.ERROR, this._boundHandleError);
|
|
@@ -8517,12 +8571,12 @@ class NodeFsHandler {
|
|
|
8517
8571
|
});
|
|
8518
8572
|
}
|
|
8519
8573
|
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
|
|
8520
|
-
const parentDir = this.fsw._getWatchedDir(
|
|
8521
|
-
const tracked = parentDir.has(
|
|
8574
|
+
const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));
|
|
8575
|
+
const tracked = parentDir.has(sp.basename(dir));
|
|
8522
8576
|
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
|
8523
8577
|
this.fsw._emit(EV.ADD_DIR, dir, stats);
|
|
8524
8578
|
}
|
|
8525
|
-
parentDir.add(
|
|
8579
|
+
parentDir.add(sp.basename(dir));
|
|
8526
8580
|
this.fsw._getWatchedDir(dir);
|
|
8527
8581
|
let throttler;
|
|
8528
8582
|
let closer;
|
|
@@ -8563,7 +8617,7 @@ class NodeFsHandler {
|
|
|
8563
8617
|
const follow = this.fsw.options.followSymlinks;
|
|
8564
8618
|
let closer;
|
|
8565
8619
|
if (stats.isDirectory()) {
|
|
8566
|
-
const absPath =
|
|
8620
|
+
const absPath = sp.resolve(path);
|
|
8567
8621
|
const targetPath = follow ? await fsrealpath(path) : path;
|
|
8568
8622
|
if (this.fsw.closed)
|
|
8569
8623
|
return;
|
|
@@ -8577,14 +8631,14 @@ class NodeFsHandler {
|
|
|
8577
8631
|
const targetPath = follow ? await fsrealpath(path) : path;
|
|
8578
8632
|
if (this.fsw.closed)
|
|
8579
8633
|
return;
|
|
8580
|
-
const parent =
|
|
8634
|
+
const parent = sp.dirname(wh.watchPath);
|
|
8581
8635
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
8582
8636
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
8583
8637
|
closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
|
|
8584
8638
|
if (this.fsw.closed)
|
|
8585
8639
|
return;
|
|
8586
8640
|
if (targetPath !== undefined) {
|
|
8587
|
-
this.fsw._symlinkPaths.set(
|
|
8641
|
+
this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);
|
|
8588
8642
|
}
|
|
8589
8643
|
} else {
|
|
8590
8644
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
@@ -8602,7 +8656,7 @@ class NodeFsHandler {
|
|
|
8602
8656
|
}
|
|
8603
8657
|
}
|
|
8604
8658
|
|
|
8605
|
-
// node_modules/chokidar/
|
|
8659
|
+
// node_modules/chokidar/index.js
|
|
8606
8660
|
/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
|
|
8607
8661
|
var SLASH = "/";
|
|
8608
8662
|
var SLASH_SLASH = "//";
|
|
@@ -8610,7 +8664,7 @@ var ONE_DOT = ".";
|
|
|
8610
8664
|
var TWO_DOTS = "..";
|
|
8611
8665
|
var STRING_TYPE = "string";
|
|
8612
8666
|
var BACK_SLASH_RE = /\\/g;
|
|
8613
|
-
var DOUBLE_SLASH_RE =
|
|
8667
|
+
var DOUBLE_SLASH_RE = /\/\//g;
|
|
8614
8668
|
var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
|
|
8615
8669
|
var REPLACER_RE = /^\.[/\\]/;
|
|
8616
8670
|
function arrify(item) {
|
|
@@ -8629,11 +8683,11 @@ function createPattern(matcher) {
|
|
|
8629
8683
|
if (matcher.path === string)
|
|
8630
8684
|
return true;
|
|
8631
8685
|
if (matcher.recursive) {
|
|
8632
|
-
const
|
|
8633
|
-
if (!
|
|
8686
|
+
const relative4 = sp2.relative(matcher.path, string);
|
|
8687
|
+
if (!relative4) {
|
|
8634
8688
|
return false;
|
|
8635
8689
|
}
|
|
8636
|
-
return !
|
|
8690
|
+
return !relative4.startsWith("..") && !sp2.isAbsolute(relative4);
|
|
8637
8691
|
}
|
|
8638
8692
|
return false;
|
|
8639
8693
|
};
|
|
@@ -8643,14 +8697,12 @@ function createPattern(matcher) {
|
|
|
8643
8697
|
function normalizePath(path) {
|
|
8644
8698
|
if (typeof path !== "string")
|
|
8645
8699
|
throw new Error("string expected");
|
|
8646
|
-
path =
|
|
8700
|
+
path = sp2.normalize(path);
|
|
8647
8701
|
path = path.replace(/\\/g, "/");
|
|
8648
8702
|
let prepend = false;
|
|
8649
8703
|
if (path.startsWith("//"))
|
|
8650
8704
|
prepend = true;
|
|
8651
|
-
|
|
8652
|
-
while (path.match(DOUBLE_SLASH_RE2))
|
|
8653
|
-
path = path.replace(DOUBLE_SLASH_RE2, "/");
|
|
8705
|
+
path = path.replace(DOUBLE_SLASH_RE, "/");
|
|
8654
8706
|
if (prepend)
|
|
8655
8707
|
path = "/" + path;
|
|
8656
8708
|
return path;
|
|
@@ -8691,31 +8743,32 @@ var toUnix = (string) => {
|
|
|
8691
8743
|
if (str.startsWith(SLASH_SLASH)) {
|
|
8692
8744
|
prepend = true;
|
|
8693
8745
|
}
|
|
8694
|
-
|
|
8695
|
-
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
8696
|
-
}
|
|
8746
|
+
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
8697
8747
|
if (prepend) {
|
|
8698
8748
|
str = SLASH + str;
|
|
8699
8749
|
}
|
|
8700
8750
|
return str;
|
|
8701
8751
|
};
|
|
8702
|
-
var normalizePathToUnix = (path) => toUnix(
|
|
8752
|
+
var normalizePathToUnix = (path) => toUnix(sp2.normalize(toUnix(path)));
|
|
8703
8753
|
var normalizeIgnored = (cwd = "") => (path) => {
|
|
8704
8754
|
if (typeof path === "string") {
|
|
8705
|
-
return normalizePathToUnix(
|
|
8755
|
+
return normalizePathToUnix(sp2.isAbsolute(path) ? path : sp2.join(cwd, path));
|
|
8706
8756
|
} else {
|
|
8707
8757
|
return path;
|
|
8708
8758
|
}
|
|
8709
8759
|
};
|
|
8710
8760
|
var getAbsolutePath = (path, cwd) => {
|
|
8711
|
-
if (
|
|
8761
|
+
if (sp2.isAbsolute(path)) {
|
|
8712
8762
|
return path;
|
|
8713
8763
|
}
|
|
8714
|
-
return
|
|
8764
|
+
return sp2.join(cwd, path);
|
|
8715
8765
|
};
|
|
8716
8766
|
var EMPTY_SET = Object.freeze(new Set);
|
|
8717
8767
|
|
|
8718
8768
|
class DirEntry {
|
|
8769
|
+
path;
|
|
8770
|
+
_removeWatcher;
|
|
8771
|
+
items;
|
|
8719
8772
|
constructor(dir, removeWatcher) {
|
|
8720
8773
|
this.path = dir;
|
|
8721
8774
|
this._removeWatcher = removeWatcher;
|
|
@@ -8740,7 +8793,7 @@ class DirEntry {
|
|
|
8740
8793
|
await readdir2(dir);
|
|
8741
8794
|
} catch (err) {
|
|
8742
8795
|
if (this._removeWatcher) {
|
|
8743
|
-
this._removeWatcher(
|
|
8796
|
+
this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
|
|
8744
8797
|
}
|
|
8745
8798
|
}
|
|
8746
8799
|
}
|
|
@@ -8768,12 +8821,19 @@ var STAT_METHOD_F = "stat";
|
|
|
8768
8821
|
var STAT_METHOD_L = "lstat";
|
|
8769
8822
|
|
|
8770
8823
|
class WatchHelper {
|
|
8824
|
+
fsw;
|
|
8825
|
+
path;
|
|
8826
|
+
watchPath;
|
|
8827
|
+
fullWatchPath;
|
|
8828
|
+
dirParts;
|
|
8829
|
+
followSymlinks;
|
|
8830
|
+
statMethod;
|
|
8771
8831
|
constructor(path, follow, fsw) {
|
|
8772
8832
|
this.fsw = fsw;
|
|
8773
8833
|
const watchPath = path;
|
|
8774
8834
|
this.path = path = path.replace(REPLACER_RE, "");
|
|
8775
8835
|
this.watchPath = watchPath;
|
|
8776
|
-
this.fullWatchPath =
|
|
8836
|
+
this.fullWatchPath = sp2.resolve(watchPath);
|
|
8777
8837
|
this.dirParts = [];
|
|
8778
8838
|
this.dirParts.forEach((parts) => {
|
|
8779
8839
|
if (parts.length > 1)
|
|
@@ -8783,7 +8843,7 @@ class WatchHelper {
|
|
|
8783
8843
|
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
|
|
8784
8844
|
}
|
|
8785
8845
|
entryPath(entry) {
|
|
8786
|
-
return
|
|
8846
|
+
return sp2.join(this.watchPath, sp2.relative(this.watchPath, entry.fullPath));
|
|
8787
8847
|
}
|
|
8788
8848
|
filterPath(entry) {
|
|
8789
8849
|
const { stats } = entry;
|
|
@@ -8798,6 +8858,24 @@ class WatchHelper {
|
|
|
8798
8858
|
}
|
|
8799
8859
|
|
|
8800
8860
|
class FSWatcher extends EventEmitter {
|
|
8861
|
+
closed;
|
|
8862
|
+
options;
|
|
8863
|
+
_closers;
|
|
8864
|
+
_ignoredPaths;
|
|
8865
|
+
_throttled;
|
|
8866
|
+
_streams;
|
|
8867
|
+
_symlinkPaths;
|
|
8868
|
+
_watched;
|
|
8869
|
+
_pendingWrites;
|
|
8870
|
+
_pendingUnlinks;
|
|
8871
|
+
_readyCount;
|
|
8872
|
+
_emitReady;
|
|
8873
|
+
_closePromise;
|
|
8874
|
+
_userIgnored;
|
|
8875
|
+
_readyEmitted;
|
|
8876
|
+
_emitRaw;
|
|
8877
|
+
_boundRemove;
|
|
8878
|
+
_nodeFsHandler;
|
|
8801
8879
|
constructor(_opts = {}) {
|
|
8802
8880
|
super();
|
|
8803
8881
|
this.closed = false;
|
|
@@ -8906,7 +8984,7 @@ class FSWatcher extends EventEmitter {
|
|
|
8906
8984
|
return;
|
|
8907
8985
|
results.forEach((item) => {
|
|
8908
8986
|
if (item)
|
|
8909
|
-
this.add(
|
|
8987
|
+
this.add(sp2.dirname(item), sp2.basename(_origAdd || item));
|
|
8910
8988
|
});
|
|
8911
8989
|
});
|
|
8912
8990
|
return this;
|
|
@@ -8917,10 +8995,10 @@ class FSWatcher extends EventEmitter {
|
|
|
8917
8995
|
const paths = unifyPaths(paths_);
|
|
8918
8996
|
const { cwd } = this.options;
|
|
8919
8997
|
paths.forEach((path) => {
|
|
8920
|
-
if (!
|
|
8998
|
+
if (!sp2.isAbsolute(path) && !this._closers.has(path)) {
|
|
8921
8999
|
if (cwd)
|
|
8922
|
-
path =
|
|
8923
|
-
path =
|
|
9000
|
+
path = sp2.join(cwd, path);
|
|
9001
|
+
path = sp2.resolve(path);
|
|
8924
9002
|
}
|
|
8925
9003
|
this._closePath(path);
|
|
8926
9004
|
this._addIgnoredPath(path);
|
|
@@ -8964,7 +9042,7 @@ class FSWatcher extends EventEmitter {
|
|
|
8964
9042
|
getWatched() {
|
|
8965
9043
|
const watchList = {};
|
|
8966
9044
|
this._watched.forEach((entry, dir) => {
|
|
8967
|
-
const key = this.options.cwd ?
|
|
9045
|
+
const key = this.options.cwd ? sp2.relative(this.options.cwd, dir) : dir;
|
|
8968
9046
|
const index = key || ONE_DOT;
|
|
8969
9047
|
watchList[index] = entry.getChildren().sort();
|
|
8970
9048
|
});
|
|
@@ -8980,9 +9058,9 @@ class FSWatcher extends EventEmitter {
|
|
|
8980
9058
|
return;
|
|
8981
9059
|
const opts = this.options;
|
|
8982
9060
|
if (isWindows)
|
|
8983
|
-
path =
|
|
9061
|
+
path = sp2.normalize(path);
|
|
8984
9062
|
if (opts.cwd)
|
|
8985
|
-
path =
|
|
9063
|
+
path = sp2.relative(opts.cwd, path);
|
|
8986
9064
|
const args = [path];
|
|
8987
9065
|
if (stats != null)
|
|
8988
9066
|
args.push(stats);
|
|
@@ -9033,7 +9111,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9033
9111
|
return this;
|
|
9034
9112
|
}
|
|
9035
9113
|
if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
9036
|
-
const fullPath = opts.cwd ?
|
|
9114
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path) : path;
|
|
9037
9115
|
let stats2;
|
|
9038
9116
|
try {
|
|
9039
9117
|
stats2 = await stat3(fullPath);
|
|
@@ -9089,8 +9167,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9089
9167
|
const pollInterval = awf.pollInterval;
|
|
9090
9168
|
let timeoutHandler;
|
|
9091
9169
|
let fullPath = path;
|
|
9092
|
-
if (this.options.cwd && !
|
|
9093
|
-
fullPath =
|
|
9170
|
+
if (this.options.cwd && !sp2.isAbsolute(path)) {
|
|
9171
|
+
fullPath = sp2.join(this.options.cwd, path);
|
|
9094
9172
|
}
|
|
9095
9173
|
const now = new Date;
|
|
9096
9174
|
const writes = this._pendingWrites;
|
|
@@ -9147,7 +9225,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9147
9225
|
return new WatchHelper(path, this.options.followSymlinks, this);
|
|
9148
9226
|
}
|
|
9149
9227
|
_getWatchedDir(directory) {
|
|
9150
|
-
const dir =
|
|
9228
|
+
const dir = sp2.resolve(directory);
|
|
9151
9229
|
if (!this._watched.has(dir))
|
|
9152
9230
|
this._watched.set(dir, new DirEntry(dir, this._boundRemove));
|
|
9153
9231
|
return this._watched.get(dir);
|
|
@@ -9158,8 +9236,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9158
9236
|
return Boolean(Number(stats.mode) & 256);
|
|
9159
9237
|
}
|
|
9160
9238
|
_remove(directory, item, isDirectory) {
|
|
9161
|
-
const path =
|
|
9162
|
-
const fullPath =
|
|
9239
|
+
const path = sp2.join(directory, item);
|
|
9240
|
+
const fullPath = sp2.resolve(path);
|
|
9163
9241
|
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
|
|
9164
9242
|
if (!this._throttle("remove", path, 100))
|
|
9165
9243
|
return;
|
|
@@ -9177,7 +9255,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9177
9255
|
}
|
|
9178
9256
|
let relPath = path;
|
|
9179
9257
|
if (this.options.cwd)
|
|
9180
|
-
relPath =
|
|
9258
|
+
relPath = sp2.relative(this.options.cwd, path);
|
|
9181
9259
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
9182
9260
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
9183
9261
|
if (event === EVENTS.ADD)
|
|
@@ -9192,8 +9270,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9192
9270
|
}
|
|
9193
9271
|
_closePath(path) {
|
|
9194
9272
|
this._closeFile(path);
|
|
9195
|
-
const dir =
|
|
9196
|
-
this._getWatchedDir(dir).remove(
|
|
9273
|
+
const dir = sp2.dirname(path);
|
|
9274
|
+
this._getWatchedDir(dir).remove(sp2.basename(path));
|
|
9197
9275
|
}
|
|
9198
9276
|
_closeFile(path) {
|
|
9199
9277
|
const closers = this._closers.get(path);
|
|
@@ -9362,51 +9440,17 @@ function install() {
|
|
|
9362
9440
|
}
|
|
9363
9441
|
|
|
9364
9442
|
// src/commands/publish.ts
|
|
9365
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, statSync as
|
|
9443
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, statSync as statSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
9366
9444
|
import { join as join14, basename as basename6 } from "path";
|
|
9367
9445
|
|
|
9368
9446
|
// src/lib/auth.ts
|
|
9369
9447
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, unlinkSync, existsSync as existsSync9 } from "fs";
|
|
9370
9448
|
import { join as join12, dirname as dirname4 } from "path";
|
|
9371
9449
|
var CREDENTIALS_FILE = "credentials.json";
|
|
9372
|
-
var APP_PROFILES_FILE = "profiles.json";
|
|
9373
9450
|
var DEFAULT_PORTAL = "https://developer.construct.space";
|
|
9374
9451
|
function credentialsPath() {
|
|
9375
9452
|
return join12(dataDir(), CREDENTIALS_FILE);
|
|
9376
9453
|
}
|
|
9377
|
-
function appProfilesPath() {
|
|
9378
|
-
return join12(dataDir(), APP_PROFILES_FILE);
|
|
9379
|
-
}
|
|
9380
|
-
function appProfileAuthPath(profileId) {
|
|
9381
|
-
return join12(dataDir(), "profiles", profileId, "auth.json");
|
|
9382
|
-
}
|
|
9383
|
-
function loadFromApp() {
|
|
9384
|
-
try {
|
|
9385
|
-
const profilesPath = appProfilesPath();
|
|
9386
|
-
if (!existsSync9(profilesPath))
|
|
9387
|
-
return null;
|
|
9388
|
-
const profiles = JSON.parse(readFileSync6(profilesPath, "utf-8"));
|
|
9389
|
-
if (!profiles?.active_profile)
|
|
9390
|
-
return null;
|
|
9391
|
-
const authPath = appProfileAuthPath(profiles.active_profile);
|
|
9392
|
-
if (!existsSync9(authPath))
|
|
9393
|
-
return null;
|
|
9394
|
-
const auth = JSON.parse(readFileSync6(authPath, "utf-8"));
|
|
9395
|
-
if (!auth?.authenticated || !auth?.token)
|
|
9396
|
-
return null;
|
|
9397
|
-
return {
|
|
9398
|
-
token: auth.token,
|
|
9399
|
-
portal: DEFAULT_PORTAL,
|
|
9400
|
-
user: {
|
|
9401
|
-
id: auth.user.id,
|
|
9402
|
-
name: auth.user.name || [auth.user.first_name, auth.user.last_name].filter(Boolean).join(" ") || auth.user.email,
|
|
9403
|
-
email: auth.user.email
|
|
9404
|
-
}
|
|
9405
|
-
};
|
|
9406
|
-
} catch {
|
|
9407
|
-
return null;
|
|
9408
|
-
}
|
|
9409
|
-
}
|
|
9410
9454
|
function store(creds) {
|
|
9411
9455
|
const path = credentialsPath();
|
|
9412
9456
|
mkdirSync4(dirname4(path), { recursive: true });
|
|
@@ -9414,12 +9458,9 @@ function store(creds) {
|
|
|
9414
9458
|
`, { mode: 384 });
|
|
9415
9459
|
}
|
|
9416
9460
|
function load2() {
|
|
9417
|
-
const fromApp = loadFromApp();
|
|
9418
|
-
if (fromApp)
|
|
9419
|
-
return fromApp;
|
|
9420
9461
|
const path = credentialsPath();
|
|
9421
9462
|
if (!existsSync9(path)) {
|
|
9422
|
-
throw new Error("not logged in \u2014 run 'construct login' first
|
|
9463
|
+
throw new Error("not logged in \u2014 run 'construct login' first");
|
|
9423
9464
|
}
|
|
9424
9465
|
const data = JSON.parse(readFileSync6(path, "utf-8"));
|
|
9425
9466
|
if (!data.token) {
|
|
@@ -9442,7 +9483,7 @@ function clear() {
|
|
|
9442
9483
|
}
|
|
9443
9484
|
|
|
9444
9485
|
// src/lib/pack.ts
|
|
9445
|
-
import { readdirSync as
|
|
9486
|
+
import { readdirSync as readdirSync4, statSync as statSync4, existsSync as existsSync10 } from "fs";
|
|
9446
9487
|
import { join as join13 } from "path";
|
|
9447
9488
|
import { tmpdir } from "os";
|
|
9448
9489
|
import { execSync as execSync3 } from "child_process";
|
|
@@ -9484,8 +9525,8 @@ async function packSource(root) {
|
|
|
9484
9525
|
if (existsSync10(join13(root, name)))
|
|
9485
9526
|
entries.push(name);
|
|
9486
9527
|
}
|
|
9487
|
-
for (const entry of
|
|
9488
|
-
if (
|
|
9528
|
+
for (const entry of readdirSync4(root)) {
|
|
9529
|
+
if (statSync4(join13(root, entry)).isDirectory())
|
|
9489
9530
|
continue;
|
|
9490
9531
|
if (allowedRootFiles.includes(entry))
|
|
9491
9532
|
continue;
|
|
@@ -9505,7 +9546,7 @@ async function packSource(root) {
|
|
|
9505
9546
|
const excludes = "--exclude=node_modules --exclude=dist --exclude=.git --exclude=*.env --exclude=*.log --exclude=*.lock --exclude=*.lockb";
|
|
9506
9547
|
const cmd = `tar czf "${tarballPath}" ${excludes} ${validEntries.join(" ")}`;
|
|
9507
9548
|
execSync3(cmd, { cwd: root });
|
|
9508
|
-
const size =
|
|
9549
|
+
const size = statSync4(tarballPath).size;
|
|
9509
9550
|
if (size > MAX_SIZE) {
|
|
9510
9551
|
throw new Error(`Source exceeds maximum size of ${MAX_SIZE / 1024 / 1024}MB`);
|
|
9511
9552
|
}
|
|
@@ -9528,6 +9569,16 @@ async function uploadSource(portalURL, token, tarballPath, m) {
|
|
|
9528
9569
|
if (resp.status === 401) {
|
|
9529
9570
|
throw new Error("authentication failed \u2014 run 'construct login' to re-authenticate");
|
|
9530
9571
|
}
|
|
9572
|
+
if (resp.status === 403) {
|
|
9573
|
+
let msg = result.error || "You are not the owner of this space";
|
|
9574
|
+
if (result.owner_user_id) {
|
|
9575
|
+
msg += `
|
|
9576
|
+
Current owner: ${result.owner_user_id}`;
|
|
9577
|
+
}
|
|
9578
|
+
msg += `
|
|
9579
|
+
Fork to a new space_id to publish your own version.`;
|
|
9580
|
+
throw new Error(msg);
|
|
9581
|
+
}
|
|
9531
9582
|
if (resp.status >= 400) {
|
|
9532
9583
|
const msg = result.error || result.errors?.join("; ") || `server returned ${resp.status}`;
|
|
9533
9584
|
throw new Error(msg);
|
|
@@ -9562,24 +9613,6 @@ async function publish(options) {
|
|
|
9562
9613
|
console.log(source_default.dim(" Run 'construct login' to authenticate."));
|
|
9563
9614
|
process.exit(1);
|
|
9564
9615
|
}
|
|
9565
|
-
const publishers = creds.publishers || [];
|
|
9566
|
-
if (publishers.length === 0) {
|
|
9567
|
-
console.log(source_default.yellow(" No publisher linked to this session. The upload will likely be rejected."));
|
|
9568
|
-
console.log(source_default.dim(" Run 'construct login' after enrolling at developer.construct.space."));
|
|
9569
|
-
} else {
|
|
9570
|
-
const primary = publishers[0];
|
|
9571
|
-
const kindLabel = primary.kind === "org" ? source_default.cyan("org") : primary.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
9572
|
-
console.log(source_default.dim(` Publishing as ${primary.name} (${kindLabel})`));
|
|
9573
|
-
if (publishers.length > 1 && !yes) {
|
|
9574
|
-
const proceed = await dist_default4({
|
|
9575
|
-
message: `You have ${publishers.length} publisher identities. Publish under ${primary.name}?`
|
|
9576
|
-
});
|
|
9577
|
-
if (!proceed) {
|
|
9578
|
-
console.log("Cancelled.");
|
|
9579
|
-
return;
|
|
9580
|
-
}
|
|
9581
|
-
}
|
|
9582
|
-
}
|
|
9583
9616
|
const status = gitSafe(root, "status", "--porcelain");
|
|
9584
9617
|
if (status) {
|
|
9585
9618
|
console.log(source_default.yellow("You have uncommitted changes."));
|
|
@@ -9663,7 +9696,7 @@ async function publish(options) {
|
|
|
9663
9696
|
let tarballPath;
|
|
9664
9697
|
try {
|
|
9665
9698
|
tarballPath = await packSource(root);
|
|
9666
|
-
const size =
|
|
9699
|
+
const size = statSync5(tarballPath).size;
|
|
9667
9700
|
spinner.succeed(`Source packed (${formatBytes(size)})`);
|
|
9668
9701
|
} catch (err) {
|
|
9669
9702
|
spinner.fail("Pack failed");
|
|
@@ -9845,12 +9878,6 @@ function clean(options) {
|
|
|
9845
9878
|
import { createServer } from "http";
|
|
9846
9879
|
async function login(options) {
|
|
9847
9880
|
const portalURL = options?.portal || DEFAULT_PORTAL;
|
|
9848
|
-
const fromApp = loadFromApp();
|
|
9849
|
-
if (fromApp) {
|
|
9850
|
-
console.log(source_default.green(`Using Construct app profile: ${fromApp.user?.name || fromApp.user?.email}`));
|
|
9851
|
-
console.log(source_default.dim(" To use a different identity, sign out of the app or run `construct logout` after login."));
|
|
9852
|
-
return;
|
|
9853
|
-
}
|
|
9854
9881
|
if (isAuthenticated()) {
|
|
9855
9882
|
const creds = load2();
|
|
9856
9883
|
const name = creds.user?.name || "unknown";
|
|
@@ -9916,101 +9943,18 @@ async function login(options) {
|
|
|
9916
9943
|
const resp = await fetch(`${portalURL}/api/auth/cli-verify`, {
|
|
9917
9944
|
headers: { Authorization: `Bearer ${token}` }
|
|
9918
9945
|
});
|
|
9919
|
-
const { user
|
|
9920
|
-
store({ token, portal: portalURL, user
|
|
9946
|
+
const { user } = await resp.json();
|
|
9947
|
+
store({ token, portal: portalURL, user });
|
|
9921
9948
|
console.log();
|
|
9922
9949
|
console.log(source_default.green(`Logged in as ${user?.name || "there"}`));
|
|
9923
|
-
const list = publishers || [];
|
|
9924
|
-
if (list.length === 0) {
|
|
9925
|
-
console.log(source_default.yellow(" No publisher yet. Run developer enrollment to publish spaces."));
|
|
9926
|
-
} else {
|
|
9927
|
-
for (const p of list) {
|
|
9928
|
-
const label = p.kind === "org" ? source_default.cyan("org") : p.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
9929
|
-
console.log(source_default.dim(` Publisher: ${p.name} (${label})`));
|
|
9930
|
-
}
|
|
9931
|
-
}
|
|
9932
9950
|
} catch (err) {
|
|
9933
9951
|
console.error(source_default.red(`Login failed: ${err.message}`));
|
|
9934
9952
|
process.exit(1);
|
|
9935
9953
|
}
|
|
9936
9954
|
}
|
|
9937
9955
|
function logout() {
|
|
9938
|
-
const wasCli = isAuthenticated();
|
|
9939
9956
|
clear();
|
|
9940
|
-
|
|
9941
|
-
console.log(source_default.green("Logged out of CLI credentials."));
|
|
9942
|
-
} else {
|
|
9943
|
-
console.log(source_default.dim("No CLI credentials to clear."));
|
|
9944
|
-
}
|
|
9945
|
-
const appStill = loadFromApp();
|
|
9946
|
-
if (appStill) {
|
|
9947
|
-
console.log();
|
|
9948
|
-
console.log(source_default.yellow("Note: the Construct app is still signed in as ") + source_default.white(appStill.user?.name || appStill.user?.email || ""));
|
|
9949
|
-
console.log(source_default.dim(" The CLI will continue to use the app profile. Sign out of the app to fully disconnect."));
|
|
9950
|
-
}
|
|
9951
|
-
}
|
|
9952
|
-
|
|
9953
|
-
// src/commands/whoami.ts
|
|
9954
|
-
async function whoami() {
|
|
9955
|
-
const fromApp = loadFromApp();
|
|
9956
|
-
let creds = null;
|
|
9957
|
-
let source = "none";
|
|
9958
|
-
if (fromApp) {
|
|
9959
|
-
creds = fromApp;
|
|
9960
|
-
source = "app";
|
|
9961
|
-
} else {
|
|
9962
|
-
try {
|
|
9963
|
-
creds = load2();
|
|
9964
|
-
source = "cli";
|
|
9965
|
-
} catch {
|
|
9966
|
-
source = "none";
|
|
9967
|
-
}
|
|
9968
|
-
}
|
|
9969
|
-
if (source === "none" || !creds) {
|
|
9970
|
-
console.log(source_default.yellow("Not signed in."));
|
|
9971
|
-
console.log(source_default.dim(" Run ") + source_default.white("construct login") + source_default.dim(" or sign in to the Construct app."));
|
|
9972
|
-
return;
|
|
9973
|
-
}
|
|
9974
|
-
const user = creds.user;
|
|
9975
|
-
const sourceLabel = source === "app" ? source_default.cyan("Construct app profile") : source_default.blue("CLI login");
|
|
9976
|
-
console.log();
|
|
9977
|
-
console.log(source_default.bold(user?.name || "Signed in"));
|
|
9978
|
-
console.log(source_default.dim(" " + (user?.email || "")));
|
|
9979
|
-
console.log(source_default.dim(" id: ") + source_default.dim(user?.id || "\u2014"));
|
|
9980
|
-
console.log(source_default.dim(" source: ") + sourceLabel);
|
|
9981
|
-
console.log(source_default.dim(" portal: ") + (creds.portal || DEFAULT_PORTAL));
|
|
9982
|
-
try {
|
|
9983
|
-
const resp = await fetch(`${creds.portal || DEFAULT_PORTAL}/api/auth/cli-verify`, {
|
|
9984
|
-
headers: { Authorization: `Bearer ${creds.token}` }
|
|
9985
|
-
});
|
|
9986
|
-
if (!resp.ok) {
|
|
9987
|
-
console.log(source_default.dim(" publishers: ") + source_default.red(`error (${resp.status})`));
|
|
9988
|
-
return;
|
|
9989
|
-
}
|
|
9990
|
-
const body = await resp.json();
|
|
9991
|
-
const list = body.publishers || [];
|
|
9992
|
-
if (list.length === 0) {
|
|
9993
|
-
console.log(source_default.dim(" publishers: ") + source_default.yellow("none yet \u2014 enroll at developer.construct.space"));
|
|
9994
|
-
return;
|
|
9995
|
-
}
|
|
9996
|
-
console.log();
|
|
9997
|
-
console.log(source_default.bold("Publishers"));
|
|
9998
|
-
for (const p of list) {
|
|
9999
|
-
const kindLabel = p.kind === "org" ? source_default.cyan("org") : p.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
10000
|
-
const verified = p.verified ? source_default.green(" \u2713") : "";
|
|
10001
|
-
console.log(` ${source_default.white(p.name)} (${kindLabel})${verified}`);
|
|
10002
|
-
if (p.orgId)
|
|
10003
|
-
console.log(source_default.dim(` org: ${p.orgId}`));
|
|
10004
|
-
}
|
|
10005
|
-
} catch (err) {
|
|
10006
|
-
console.log(source_default.dim(" publishers: ") + source_default.red("could not reach portal"));
|
|
10007
|
-
}
|
|
10008
|
-
console.log();
|
|
10009
|
-
if (source === "app") {
|
|
10010
|
-
console.log(source_default.dim("To switch identities, change the active profile in the Construct app."));
|
|
10011
|
-
} else {
|
|
10012
|
-
console.log(source_default.dim("To switch identities, run 'construct logout' then 'construct login'."));
|
|
10013
|
-
}
|
|
9957
|
+
console.log(source_default.green("Logged out."));
|
|
10014
9958
|
}
|
|
10015
9959
|
|
|
10016
9960
|
// src/commands/update.ts
|
|
@@ -10285,7 +10229,7 @@ function updateBarrel(modelsDir, modelName) {
|
|
|
10285
10229
|
}
|
|
10286
10230
|
|
|
10287
10231
|
// src/commands/graph/push.ts
|
|
10288
|
-
import { existsSync as existsSync16, readdirSync as
|
|
10232
|
+
import { existsSync as existsSync16, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "fs";
|
|
10289
10233
|
import { join as join20, basename as basename7 } from "path";
|
|
10290
10234
|
async function graphPush() {
|
|
10291
10235
|
const root = process.cwd();
|
|
@@ -10299,7 +10243,7 @@ async function graphPush() {
|
|
|
10299
10243
|
console.error(source_default.red("No src/models/ directory found. Run 'construct graph init' first."));
|
|
10300
10244
|
process.exit(1);
|
|
10301
10245
|
}
|
|
10302
|
-
const modelFiles =
|
|
10246
|
+
const modelFiles = readdirSync5(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
|
|
10303
10247
|
if (modelFiles.length === 0) {
|
|
10304
10248
|
console.error(source_default.red("No model files found in src/models/"));
|
|
10305
10249
|
console.log(source_default.dim(" Generate one: construct graph g User name:string email:string"));
|
|
@@ -10324,15 +10268,17 @@ async function graphPush() {
|
|
|
10324
10268
|
console.error(source_default.red(err.message));
|
|
10325
10269
|
process.exit(1);
|
|
10326
10270
|
}
|
|
10327
|
-
const graphURL = process.env.GRAPH_URL || "https://
|
|
10271
|
+
const graphURL = process.env.GRAPH_URL || "https://my.construct.space/api/graph";
|
|
10328
10272
|
const spinner = ora("Registering models...").start();
|
|
10329
10273
|
try {
|
|
10274
|
+
const userID = creds.user?.id || "";
|
|
10330
10275
|
const resp = await fetch(`${graphURL}/api/schemas/register`, {
|
|
10331
10276
|
method: "POST",
|
|
10332
10277
|
headers: {
|
|
10333
10278
|
"Content-Type": "application/json",
|
|
10334
10279
|
Authorization: `Bearer ${creds.token}`,
|
|
10335
|
-
"X-Space-ID": m.id
|
|
10280
|
+
"X-Space-ID": m.id,
|
|
10281
|
+
"X-Auth-User-ID": userID
|
|
10336
10282
|
},
|
|
10337
10283
|
body: JSON.stringify({
|
|
10338
10284
|
space_id: m.id,
|
|
@@ -10342,6 +10288,20 @@ async function graphPush() {
|
|
|
10342
10288
|
manifest: { version: 1, models }
|
|
10343
10289
|
})
|
|
10344
10290
|
});
|
|
10291
|
+
if (resp.status === 403) {
|
|
10292
|
+
spinner.fail("Ownership check failed");
|
|
10293
|
+
try {
|
|
10294
|
+
const errBody = await resp.json();
|
|
10295
|
+
console.error(source_default.red(` ${errBody.error || "You are not the owner of this space"}`));
|
|
10296
|
+
if (errBody.owner_user_id) {
|
|
10297
|
+
console.error(source_default.dim(` Current owner: ${errBody.owner_user_id}`));
|
|
10298
|
+
}
|
|
10299
|
+
console.error(source_default.dim(" Fork to a new space_id to publish your own version."));
|
|
10300
|
+
} catch {
|
|
10301
|
+
console.error(source_default.red(` 403: Forbidden \u2014 ownership check failed`));
|
|
10302
|
+
}
|
|
10303
|
+
process.exit(1);
|
|
10304
|
+
}
|
|
10345
10305
|
if (!resp.ok) {
|
|
10346
10306
|
const body = await resp.text();
|
|
10347
10307
|
spinner.fail("Registration failed");
|
|
@@ -10424,7 +10384,7 @@ function parseModelFile(content, fileName) {
|
|
|
10424
10384
|
}
|
|
10425
10385
|
|
|
10426
10386
|
// src/commands/graph/migrate.ts
|
|
10427
|
-
import { existsSync as existsSync17, readdirSync as
|
|
10387
|
+
import { existsSync as existsSync17, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
10428
10388
|
import { join as join21, basename as basename8 } from "path";
|
|
10429
10389
|
async function graphMigrate(options) {
|
|
10430
10390
|
const root = process.cwd();
|
|
@@ -10445,7 +10405,7 @@ async function graphMigrate(options) {
|
|
|
10445
10405
|
console.error(source_default.red(err.message));
|
|
10446
10406
|
process.exit(1);
|
|
10447
10407
|
}
|
|
10448
|
-
const graphURL = process.env.GRAPH_URL || "https://
|
|
10408
|
+
const graphURL = process.env.GRAPH_URL || "https://my.construct.space/api/graph";
|
|
10449
10409
|
const spinner = ora("Fetching current schema...").start();
|
|
10450
10410
|
let serverModels = [];
|
|
10451
10411
|
try {
|
|
@@ -10461,7 +10421,7 @@ async function graphMigrate(options) {
|
|
|
10461
10421
|
spinner.fail("Could not fetch schema");
|
|
10462
10422
|
process.exit(1);
|
|
10463
10423
|
}
|
|
10464
|
-
const modelFiles =
|
|
10424
|
+
const modelFiles = readdirSync6(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
|
|
10465
10425
|
const localModels = [];
|
|
10466
10426
|
for (const file of modelFiles) {
|
|
10467
10427
|
const content = readFileSync13(join21(modelsDir, file), "utf-8");
|
|
@@ -10568,7 +10528,7 @@ function parseModelFields(content, fileName) {
|
|
|
10568
10528
|
}
|
|
10569
10529
|
|
|
10570
10530
|
// src/index.ts
|
|
10571
|
-
var VERSION = "1.
|
|
10531
|
+
var VERSION = "1.2.0";
|
|
10572
10532
|
var program2 = new Command;
|
|
10573
10533
|
program2.name("construct").description("Construct CLI \u2014 scaffold, build, develop, and publish spaces").version(VERSION);
|
|
10574
10534
|
program2.command("scaffold [name]").alias("new").alias("create").description("Create a new Construct space project").option("--with-tests", "Include E2E testing boilerplate").option("--full", "Full preset: multiple pages, extra skills, widget templates").action(async (name, opts) => scaffold(name, opts));
|
|
@@ -10581,7 +10541,6 @@ program2.command("check").description("Run type-check (vue-tsc) and linter (esli
|
|
|
10581
10541
|
program2.command("clean").description("Remove build artifacts").option("--all", "Also remove node_modules and lockfiles").action((opts) => clean(opts));
|
|
10582
10542
|
program2.command("login").description("Authenticate with Construct").option("--portal <url>", "Portal URL").action(async (opts) => login(opts));
|
|
10583
10543
|
program2.command("logout").description("Sign out").action(() => logout());
|
|
10584
|
-
program2.command("whoami").alias("status").description("Show the active profile, its source (app or CLI), and linked publishers").action(() => whoami());
|
|
10585
10544
|
program2.command("update").description("Update the CLI to the latest version").action(() => update());
|
|
10586
10545
|
var graph = program2.command("graph").description("Construct Graph \u2014 data models and GraphQL");
|
|
10587
10546
|
graph.command("init").description("Initialize Graph in a space project").action(() => graphInit());
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"name": "Your Name"
|
|
8
8
|
},
|
|
9
9
|
"icon": "i-lucide-box",
|
|
10
|
-
"scope": "
|
|
10
|
+
"scope": "app",
|
|
11
11
|
"minConstructVersion": "0.7.0",
|
|
12
12
|
"navigation": {
|
|
13
13
|
"label": "{{.DisplayName}}",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"keywords": ["{{.ID}}"],
|
|
35
35
|
"agent": "agent/config.md",
|
|
36
36
|
"skills": ["agent/skills/default.md"],
|
|
37
|
-
"actions":
|
|
37
|
+
"actions": "src/actions.ts",
|
|
38
38
|
"widgets": [
|
|
39
39
|
{
|
|
40
40
|
"id": "summary",
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* {{.DisplayName}} Summary Widget — 2×1 compact view
|
|
4
|
+
*
|
|
5
|
+
* Widgets run inside a closed Shadow DOM sandbox.
|
|
6
|
+
* Use the injected widgetApi for theme and actions — do not access
|
|
7
|
+
* window, document, or global stores directly.
|
|
4
8
|
*/
|
|
9
|
+
import { inject } from 'vue'
|
|
10
|
+
|
|
11
|
+
const api = inject<{ theme: { mode: string; vars: Record<string, string> }; space: { id: string; name: string } }>('widgetApi')
|
|
5
12
|
</script>
|
|
6
13
|
|
|
7
14
|
<template>
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* {{.DisplayName}} Summary Widget — 4×1 wide view
|
|
4
|
+
*
|
|
5
|
+
* Widgets run inside a closed Shadow DOM sandbox.
|
|
6
|
+
* Use the injected widgetApi for theme and actions — do not access
|
|
7
|
+
* window, document, or global stores directly.
|
|
4
8
|
*/
|
|
9
|
+
import { inject } from 'vue'
|
|
10
|
+
|
|
11
|
+
const api = inject<{ theme: { mode: string; vars: Record<string, string> }; space: { id: string; name: string } }>('widgetApi')
|
|
5
12
|
</script>
|
|
6
13
|
|
|
7
14
|
<template>
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"name": "Your Name"
|
|
8
8
|
},
|
|
9
9
|
"icon": "i-lucide-box",
|
|
10
|
-
"scope": "
|
|
10
|
+
"scope": "app",
|
|
11
11
|
"minConstructVersion": "0.7.0",
|
|
12
12
|
"navigation": {
|
|
13
13
|
"label": "{{.DisplayName}}",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"keywords": ["{{.ID}}"],
|
|
35
35
|
"agent": "agent/config.md",
|
|
36
36
|
"skills": ["agent/skills/default.md"],
|
|
37
|
-
"actions":
|
|
37
|
+
"actions": "src/actions.ts",
|
|
38
38
|
"widgets": [
|
|
39
39
|
{
|
|
40
40
|
"id": "summary",
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* {{.DisplayName}} Summary Widget — 2×1 compact view
|
|
4
|
+
*
|
|
5
|
+
* Widgets run inside a closed Shadow DOM sandbox.
|
|
6
|
+
* Use the injected widgetApi for theme and actions — do not access
|
|
7
|
+
* window, document, or global stores directly.
|
|
4
8
|
*/
|
|
9
|
+
import { inject } from 'vue'
|
|
10
|
+
|
|
11
|
+
const api = inject<{ theme: { mode: string; vars: Record<string, string> }; space: { id: string; name: string } }>('widgetApi')
|
|
5
12
|
</script>
|
|
6
13
|
|
|
7
14
|
<template>
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
3
|
* {{.DisplayName}} Summary Widget — 4×1 wide view
|
|
4
|
+
*
|
|
5
|
+
* Widgets run inside a closed Shadow DOM sandbox.
|
|
6
|
+
* Use the injected widgetApi for theme and actions — do not access
|
|
7
|
+
* window, document, or global stores directly.
|
|
4
8
|
*/
|
|
9
|
+
import { inject } from 'vue'
|
|
10
|
+
|
|
11
|
+
const api = inject<{ theme: { mode: string; vars: Record<string, string> }; space: { id: string; name: string } }>('widgetApi')
|
|
5
12
|
</script>
|
|
6
13
|
|
|
7
14
|
<template>
|