@construct-space/cli 1.1.12 → 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 +313 -974
- 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 +2 -2
- 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();
|
|
@@ -4613,616 +4596,18 @@ function runHook(hooks, hookName, root) {
|
|
|
4613
4596
|
execSync2(cmd, { cwd: root, stdio: "inherit" });
|
|
4614
4597
|
}
|
|
4615
4598
|
|
|
4616
|
-
// src/lib/embedded-templates.ts
|
|
4617
|
-
var EMBEDDED_TEMPLATES = {
|
|
4618
|
-
"package.json.tmpl": `{
|
|
4619
|
-
"name": "@construct-spaces/{{.Name}}",
|
|
4620
|
-
"version": "0.1.0",
|
|
4621
|
-
"private": true,
|
|
4622
|
-
"type": "module",
|
|
4623
|
-
"scripts": {
|
|
4624
|
-
"generate-entry": "construct build --entry-only",
|
|
4625
|
-
"build": "construct build",
|
|
4626
|
-
"dev": "construct dev",
|
|
4627
|
-
"check": "construct check",
|
|
4628
|
-
"validate": "construct validate"
|
|
4629
|
-
},
|
|
4630
|
-
"peerDependencies": {
|
|
4631
|
-
"vue": "^3.5.0",
|
|
4632
|
-
"pinia": "^3.0.0",
|
|
4633
|
-
"@vueuse/core": "^14.0.0"
|
|
4634
|
-
},
|
|
4635
|
-
"devDependencies": {
|
|
4636
|
-
"@construct-space/cli": "latest",
|
|
4637
|
-
"@construct-space/sdk": "latest",
|
|
4638
|
-
"@vitejs/plugin-vue": "^5.2.3",
|
|
4639
|
-
"lucide-vue-next": "^1.0.0",
|
|
4640
|
-
"typescript": "^5.9.3",
|
|
4641
|
-
"vite": "^6.3.5",
|
|
4642
|
-
"vue-tsc": "^3.2.5"
|
|
4643
|
-
}
|
|
4644
|
-
}
|
|
4645
|
-
`,
|
|
4646
|
-
"config.md.tmpl": `---
|
|
4647
|
-
id: {{.ID}}
|
|
4648
|
-
name: {{.DisplayName}}
|
|
4649
|
-
category: space
|
|
4650
|
-
description: AI agent for the {{.DisplayName}} space
|
|
4651
|
-
maxIterations: 15
|
|
4652
|
-
tools: []
|
|
4653
|
-
canInvokeAgents: []
|
|
4654
|
-
---
|
|
4655
|
-
|
|
4656
|
-
You are Construct's {{.DisplayName}} agent. You help users work within the {{.DisplayName}} space.
|
|
4657
|
-
|
|
4658
|
-
## Context
|
|
4659
|
-
|
|
4660
|
-
Use space_list_actions to discover available actions for this space.
|
|
4661
|
-
Use space_run_action to execute actions.
|
|
4662
|
-
Do NOT call get_project_context \u2014 you work with space content, not project files.
|
|
4663
|
-
|
|
4664
|
-
## Behavior
|
|
4665
|
-
|
|
4666
|
-
- Start by listing available actions to understand what you can do
|
|
4667
|
-
- Be concise and action-oriented
|
|
4668
|
-
- Focus on tasks relevant to this space
|
|
4669
|
-
`,
|
|
4670
|
-
"full/skill-data.md.tmpl": `---
|
|
4671
|
-
id: {{.ID}}-data
|
|
4672
|
-
name: {{.DisplayName}} Data Management
|
|
4673
|
-
description: Skill for managing {{.DisplayName}} data and content
|
|
4674
|
-
trigger: {{.ID}} data|content|manage
|
|
4675
|
-
category: space
|
|
4676
|
-
tools: [read_file, list_dir, glob, grep, write_file]
|
|
4677
|
-
---
|
|
4678
|
-
|
|
4679
|
-
# {{.DisplayName}} Data Management Skill
|
|
4680
|
-
|
|
4681
|
-
This skill handles data operations for the {{.DisplayName}} space.
|
|
4682
|
-
|
|
4683
|
-
## Instructions
|
|
4684
|
-
- Help users create, read, update, and delete content
|
|
4685
|
-
- Validate data before writing
|
|
4686
|
-
- Use the space actions API when available
|
|
4687
|
-
- Prefer batch operations for bulk changes
|
|
4688
|
-
`,
|
|
4689
|
-
"full/entry.ts.tmpl": `// Space entry \u2014 exports pages, widgets, and actions for the host loader.
|
|
4690
|
-
// \`construct dev\` regenerates this from space.manifest.json on changes.
|
|
4691
|
-
import IndexPage from './pages/index.vue'
|
|
4692
|
-
import SettingsPage from './pages/settings.vue'
|
|
4693
|
-
import { actions } from './actions'
|
|
4694
|
-
|
|
4695
|
-
const spaceExport = {
|
|
4696
|
-
pages: {
|
|
4697
|
-
'': IndexPage,
|
|
4698
|
-
'settings': SettingsPage,
|
|
4699
|
-
},
|
|
4700
|
-
widgets: {},
|
|
4701
|
-
actions,
|
|
4702
|
-
}
|
|
4703
|
-
|
|
4704
|
-
export default spaceExport
|
|
4705
|
-
`,
|
|
4706
|
-
"full/skill-ui.md.tmpl": `---
|
|
4707
|
-
id: {{.ID}}-ui
|
|
4708
|
-
name: {{.DisplayName}} UI Customization
|
|
4709
|
-
description: Skill for customizing the {{.DisplayName}} user interface
|
|
4710
|
-
trigger: {{.ID}} ui|layout|design|style
|
|
4711
|
-
category: space
|
|
4712
|
-
tools: [read_file, write_file, glob]
|
|
4713
|
-
---
|
|
4714
|
-
|
|
4715
|
-
# {{.DisplayName}} UI Customization Skill
|
|
4716
|
-
|
|
4717
|
-
This skill helps customize the {{.DisplayName}} space interface.
|
|
4718
|
-
|
|
4719
|
-
## Instructions
|
|
4720
|
-
- Help users adjust layout and styling
|
|
4721
|
-
- Use Construct CSS variables (--app-foreground, --app-background, --app-accent, etc.)
|
|
4722
|
-
- Follow the host design system conventions
|
|
4723
|
-
- Suggest accessible color combinations
|
|
4724
|
-
`,
|
|
4725
|
-
"full/space.manifest.json.tmpl": `{
|
|
4726
|
-
"id": "{{.ID}}",
|
|
4727
|
-
"name": "{{.DisplayName}}",
|
|
4728
|
-
"version": "0.1.0",
|
|
4729
|
-
"description": "{{.DisplayName}} space for Construct",
|
|
4730
|
-
"author": {
|
|
4731
|
-
"name": "Your Name"
|
|
4732
|
-
},
|
|
4733
|
-
"icon": "i-lucide-box",
|
|
4734
|
-
"scope": "both",
|
|
4735
|
-
"minConstructVersion": "0.7.0",
|
|
4736
|
-
"navigation": {
|
|
4737
|
-
"label": "{{.DisplayName}}",
|
|
4738
|
-
"icon": "i-lucide-box",
|
|
4739
|
-
"to": "{{.ID}}",
|
|
4740
|
-
"order": 100
|
|
4741
|
-
},
|
|
4742
|
-
"pages": [
|
|
4743
|
-
{
|
|
4744
|
-
"path": "",
|
|
4745
|
-
"label": "Home",
|
|
4746
|
-
"icon": "i-lucide-home",
|
|
4747
|
-
"default": true
|
|
4748
|
-
},
|
|
4749
|
-
{
|
|
4750
|
-
"path": "settings",
|
|
4751
|
-
"label": "Settings",
|
|
4752
|
-
"icon": "i-lucide-settings"
|
|
4753
|
-
}
|
|
4754
|
-
],
|
|
4755
|
-
"toolbar": [
|
|
4756
|
-
{
|
|
4757
|
-
"id": "{{.ID}}-new",
|
|
4758
|
-
"icon": "i-lucide-plus",
|
|
4759
|
-
"label": "New {{.DisplayName}}",
|
|
4760
|
-
"action": "create{{.DisplayNameNoSpace}}"
|
|
4761
|
-
}
|
|
4762
|
-
],
|
|
4763
|
-
"keywords": ["{{.ID}}"],
|
|
4764
|
-
"agent": "agent/config.md",
|
|
4765
|
-
"skills": [
|
|
4766
|
-
"agent/skills/default.md",
|
|
4767
|
-
"agent/skills/data.md",
|
|
4768
|
-
"agent/skills/ui.md"
|
|
4769
|
-
],
|
|
4770
|
-
"actions": "src/actions.ts",
|
|
4771
|
-
"widgets": [
|
|
4772
|
-
{
|
|
4773
|
-
"id": "summary",
|
|
4774
|
-
"name": "{{.DisplayName}} Summary",
|
|
4775
|
-
"description": "Quick summary widget for {{.DisplayName}}",
|
|
4776
|
-
"icon": "i-lucide-box",
|
|
4777
|
-
"defaultSize": "4x1",
|
|
4778
|
-
"sizes": {
|
|
4779
|
-
"2x1": "widgets/summary/2x1.vue",
|
|
4780
|
-
"4x1": "widgets/summary/4x1.vue"
|
|
4781
|
-
}
|
|
4782
|
-
}
|
|
4783
|
-
]
|
|
4784
|
-
}
|
|
4785
|
-
`,
|
|
4786
|
-
"full/settings.vue.tmpl": `<script setup lang="ts">
|
|
4787
|
-
/**
|
|
4788
|
-
* {{.DisplayName}} \u2014 Settings page
|
|
4789
|
-
*/
|
|
4790
|
-
import { ref } from 'vue'
|
|
4791
|
-
|
|
4792
|
-
const autoSave = ref(true)
|
|
4793
|
-
const theme = ref<'system' | 'light' | 'dark'>('system')
|
|
4794
|
-
</script>
|
|
4795
|
-
|
|
4796
|
-
<template>
|
|
4797
|
-
<div class="h-full overflow-auto p-6">
|
|
4798
|
-
<h1 class="text-xl font-bold text-[var(--app-foreground)] mb-6">Settings</h1>
|
|
4799
|
-
|
|
4800
|
-
<div class="space-y-4 max-w-md">
|
|
4801
|
-
<label class="flex items-center justify-between">
|
|
4802
|
-
<span class="text-sm text-[var(--app-foreground)]">Auto-save</span>
|
|
4803
|
-
<input v-model="autoSave" type="checkbox" class="rounded" />
|
|
4804
|
-
</label>
|
|
4805
|
-
|
|
4806
|
-
<label class="block">
|
|
4807
|
-
<span class="text-sm text-[var(--app-foreground)] block mb-1">Theme</span>
|
|
4808
|
-
<select v-model="theme" class="w-full rounded border border-[var(--app-border)] bg-[var(--app-background)] px-3 py-1.5 text-sm">
|
|
4809
|
-
<option value="system">System</option>
|
|
4810
|
-
<option value="light">Light</option>
|
|
4811
|
-
<option value="dark">Dark</option>
|
|
4812
|
-
</select>
|
|
4813
|
-
</label>
|
|
4814
|
-
</div>
|
|
4815
|
-
</div>
|
|
4816
|
-
</template>
|
|
4817
|
-
`,
|
|
4818
|
-
"vite.config.ts.tmpl": `import { defineConfig } from 'vite'
|
|
4819
|
-
import vue from '@vitejs/plugin-vue'
|
|
4820
|
-
import { resolve } from 'path'
|
|
4821
|
-
|
|
4822
|
-
/**
|
|
4823
|
-
* Host-provided externals \u2014 these are supplied by Construct at runtime
|
|
4824
|
-
* via window.__CONSTRUCT__. Do NOT bundle them; they must stay external.
|
|
4825
|
-
*
|
|
4826
|
-
* Full list lives in: construct-app/frontend/lib/spaceHost.ts
|
|
4827
|
-
*/
|
|
4828
|
-
const hostExternals = [
|
|
4829
|
-
'vue',
|
|
4830
|
-
'vue-router',
|
|
4831
|
-
'pinia',
|
|
4832
|
-
'@vueuse/core',
|
|
4833
|
-
'@vueuse/integrations',
|
|
4834
|
-
'@tauri-apps/api',
|
|
4835
|
-
'@tauri-apps/api/core',
|
|
4836
|
-
'@tauri-apps/api/path',
|
|
4837
|
-
'@tauri-apps/api/event',
|
|
4838
|
-
'@tauri-apps/api/webview',
|
|
4839
|
-
'@tauri-apps/plugin-fs',
|
|
4840
|
-
'@tauri-apps/plugin-shell',
|
|
4841
|
-
'@tauri-apps/plugin-dialog',
|
|
4842
|
-
'@tauri-apps/plugin-process',
|
|
4843
|
-
'lucide-vue-next',
|
|
4844
|
-
'date-fns',
|
|
4845
|
-
'dexie',
|
|
4846
|
-
'zod',
|
|
4847
|
-
'@construct-space/ui',
|
|
4848
|
-
'@construct/sdk',
|
|
4849
|
-
'@construct-space/sdk',
|
|
4850
|
-
]
|
|
4851
|
-
|
|
4852
|
-
function makeGlobals(externals: string[]): Record<string, string> {
|
|
4853
|
-
const globals: Record<string, string> = {}
|
|
4854
|
-
for (const ext of externals) {
|
|
4855
|
-
// Simple ids use dot access, scoped/slashed ids use bracket access
|
|
4856
|
-
if (/^[a-z]+$/.test(ext)) {
|
|
4857
|
-
globals[ext] = \`window.__CONSTRUCT__.\${ext}\`
|
|
4858
|
-
} else {
|
|
4859
|
-
globals[ext] = \`window.__CONSTRUCT__["\${ext}"]\`
|
|
4860
|
-
}
|
|
4861
|
-
}
|
|
4862
|
-
return globals
|
|
4863
|
-
}
|
|
4864
|
-
|
|
4865
|
-
export default defineConfig({
|
|
4866
|
-
plugins: [vue()],
|
|
4867
|
-
build: {
|
|
4868
|
-
lib: {
|
|
4869
|
-
entry: resolve(__dirname, 'src/entry.ts'),
|
|
4870
|
-
name: '__CONSTRUCT_SPACE_{{.IDUpper}}',
|
|
4871
|
-
fileName: 'space-{{.ID}}',
|
|
4872
|
-
formats: ['iife'],
|
|
4873
|
-
},
|
|
4874
|
-
rollupOptions: {
|
|
4875
|
-
external: hostExternals,
|
|
4876
|
-
output: {
|
|
4877
|
-
globals: makeGlobals(hostExternals),
|
|
4878
|
-
},
|
|
4879
|
-
},
|
|
4880
|
-
},
|
|
4881
|
-
resolve: {
|
|
4882
|
-
alias: {
|
|
4883
|
-
'~': resolve(__dirname),
|
|
4884
|
-
'@': resolve(__dirname, 'src'),
|
|
4885
|
-
},
|
|
4886
|
-
},
|
|
4887
|
-
})
|
|
4888
|
-
`,
|
|
4889
|
-
"index.vue.tmpl": `<script setup lang="ts">
|
|
4890
|
-
/**
|
|
4891
|
-
* {{.DisplayName}} \u2014 Home page
|
|
4892
|
-
*
|
|
4893
|
-
* Host-provided packages (vue, pinia, @vueuse/core, @construct/sdk, etc.)
|
|
4894
|
-
* are available as imports \u2014 they resolve to the host at runtime.
|
|
4895
|
-
*/
|
|
4896
|
-
import { ref } from 'vue'
|
|
4897
|
-
|
|
4898
|
-
const greeting = ref('Your space is ready. Start building!')
|
|
4899
|
-
</script>
|
|
4900
|
-
|
|
4901
|
-
<template>
|
|
4902
|
-
<div class="h-full flex items-center justify-center">
|
|
4903
|
-
<div class="text-center">
|
|
4904
|
-
<h1 class="text-2xl font-bold text-[var(--app-foreground)] mb-2">{{.DisplayName}}</h1>
|
|
4905
|
-
<p class="text-sm text-[var(--app-muted)]">{{ greeting }}</p>
|
|
4906
|
-
</div>
|
|
4907
|
-
</div>
|
|
4908
|
-
</template>
|
|
4909
|
-
`,
|
|
4910
|
-
"entry.ts.tmpl": `// Space entry \u2014 exports pages, widgets, and actions for the host loader.
|
|
4911
|
-
// \`construct dev\` regenerates this from space.manifest.json on changes.
|
|
4912
|
-
import IndexPage from './pages/index.vue'
|
|
4913
|
-
import { actions } from './actions'
|
|
4914
|
-
|
|
4915
|
-
const spaceExport = {
|
|
4916
|
-
pages: {
|
|
4917
|
-
'': IndexPage,
|
|
4918
|
-
},
|
|
4919
|
-
widgets: {},
|
|
4920
|
-
actions,
|
|
4921
|
-
}
|
|
4922
|
-
|
|
4923
|
-
export default spaceExport
|
|
4924
|
-
`,
|
|
4925
|
-
"space.manifest.json.tmpl": `{
|
|
4926
|
-
"id": "{{.ID}}",
|
|
4927
|
-
"name": "{{.DisplayName}}",
|
|
4928
|
-
"version": "0.1.0",
|
|
4929
|
-
"description": "{{.DisplayName}} space for Construct",
|
|
4930
|
-
"author": {
|
|
4931
|
-
"name": "Your Name"
|
|
4932
|
-
},
|
|
4933
|
-
"icon": "i-lucide-box",
|
|
4934
|
-
"scope": "both",
|
|
4935
|
-
"minConstructVersion": "0.7.0",
|
|
4936
|
-
"navigation": {
|
|
4937
|
-
"label": "{{.DisplayName}}",
|
|
4938
|
-
"icon": "i-lucide-box",
|
|
4939
|
-
"to": "{{.ID}}",
|
|
4940
|
-
"order": 100
|
|
4941
|
-
},
|
|
4942
|
-
"pages": [
|
|
4943
|
-
{
|
|
4944
|
-
"path": "",
|
|
4945
|
-
"label": "Home",
|
|
4946
|
-
"icon": "i-lucide-home",
|
|
4947
|
-
"default": true
|
|
4948
|
-
}
|
|
4949
|
-
],
|
|
4950
|
-
"toolbar": [
|
|
4951
|
-
{
|
|
4952
|
-
"id": "{{.ID}}-new",
|
|
4953
|
-
"icon": "i-lucide-plus",
|
|
4954
|
-
"label": "New {{.DisplayName}}",
|
|
4955
|
-
"action": "create{{.DisplayNameNoSpace}}"
|
|
4956
|
-
}
|
|
4957
|
-
],
|
|
4958
|
-
"keywords": ["{{.ID}}"],
|
|
4959
|
-
"agent": "agent/config.md",
|
|
4960
|
-
"skills": ["agent/skills/default.md"],
|
|
4961
|
-
"actions": {},
|
|
4962
|
-
"widgets": [
|
|
4963
|
-
{
|
|
4964
|
-
"id": "summary",
|
|
4965
|
-
"name": "{{.DisplayName}} Summary",
|
|
4966
|
-
"description": "Quick summary widget for {{.DisplayName}}",
|
|
4967
|
-
"icon": "i-lucide-box",
|
|
4968
|
-
"defaultSize": "4x1",
|
|
4969
|
-
"sizes": {
|
|
4970
|
-
"2x1": "widgets/summary/2x1.vue",
|
|
4971
|
-
"4x1": "widgets/summary/4x1.vue"
|
|
4972
|
-
}
|
|
4973
|
-
}
|
|
4974
|
-
]
|
|
4975
|
-
}
|
|
4976
|
-
`,
|
|
4977
|
-
"skill.md.tmpl": `---
|
|
4978
|
-
id: {{.ID}}-default
|
|
4979
|
-
name: {{.DisplayName}} Basics
|
|
4980
|
-
description: Default skill for {{.DisplayName}} space
|
|
4981
|
-
trigger: {{.ID}}|help
|
|
4982
|
-
category: space
|
|
4983
|
-
tools: [read_file, list_dir, glob, grep]
|
|
4984
|
-
---
|
|
4985
|
-
|
|
4986
|
-
# {{.DisplayName}} Space Skill
|
|
4987
|
-
|
|
4988
|
-
This skill provides default behavior for the {{.DisplayName}} space.
|
|
4989
|
-
|
|
4990
|
-
## Instructions
|
|
4991
|
-
- Assist with {{.DisplayName}}-related tasks
|
|
4992
|
-
- Follow project conventions
|
|
4993
|
-
- Read relevant files before making suggestions
|
|
4994
|
-
`,
|
|
4995
|
-
"gitignore.tmpl": `node_modules/
|
|
4996
|
-
dist/
|
|
4997
|
-
src/entry.ts
|
|
4998
|
-
*.local
|
|
4999
|
-
.DS_Store
|
|
5000
|
-
`,
|
|
5001
|
-
"actions.ts.tmpl": `/**
|
|
5002
|
-
* Space Actions \u2014 exposed to the AI agent via space_run_action
|
|
5003
|
-
*
|
|
5004
|
-
* Define actions here and they'll be automatically available as agent tools.
|
|
5005
|
-
* The agent calls: space_run_action(action: "action_id", payload: {...})
|
|
5006
|
-
*/
|
|
5007
|
-
|
|
5008
|
-
// --- Graph SDK (data layer) ---
|
|
5009
|
-
// Uncomment after running \`construct graph init\` and defining models:
|
|
5010
|
-
//
|
|
5011
|
-
// import { useGraph } from '@construct-space/graph'
|
|
5012
|
-
// const graph = useGraph()
|
|
5013
|
-
//
|
|
5014
|
-
// Example action using Graph:
|
|
5015
|
-
// fetchItems: {
|
|
5016
|
-
// description: 'Fetch items from the graph',
|
|
5017
|
-
// params: {
|
|
5018
|
-
// limit: { type: 'number', description: 'Max items to return', required: false },
|
|
5019
|
-
// },
|
|
5020
|
-
// run: async (p: any) => {
|
|
5021
|
-
// const items = await graph.query('Item').limit(p.limit ?? 10).exec()
|
|
5022
|
-
// return { items }
|
|
5023
|
-
// },
|
|
5024
|
-
// },
|
|
5025
|
-
|
|
5026
|
-
export const actions = {
|
|
5027
|
-
// Example action:
|
|
5028
|
-
// hello: {
|
|
5029
|
-
// description: 'Say hello',
|
|
5030
|
-
// params: {
|
|
5031
|
-
// name: { type: 'string', description: 'Name to greet', required: true },
|
|
5032
|
-
// },
|
|
5033
|
-
// run: (p: any) => ({ message: \`Hello \${p.name}!\` }),
|
|
5034
|
-
// },
|
|
5035
|
-
}
|
|
5036
|
-
`,
|
|
5037
|
-
"readme.md.tmpl": `# {{.DisplayName}}
|
|
5038
|
-
|
|
5039
|
-
A Construct space.
|
|
5040
|
-
|
|
5041
|
-
## Development
|
|
5042
|
-
|
|
5043
|
-
\`\`\`bash
|
|
5044
|
-
bun install
|
|
5045
|
-
construct space dev
|
|
5046
|
-
\`\`\`
|
|
5047
|
-
|
|
5048
|
-
## Build
|
|
5049
|
-
|
|
5050
|
-
\`\`\`bash
|
|
5051
|
-
construct space build
|
|
5052
|
-
\`\`\`
|
|
5053
|
-
|
|
5054
|
-
Output goes to \`dist/\`.
|
|
5055
|
-
`,
|
|
5056
|
-
"safety.json.tmpl": `{
|
|
5057
|
-
"hooks": [
|
|
5058
|
-
{
|
|
5059
|
-
"id": "{{.ID}}-no-rm-rf",
|
|
5060
|
-
"type": "pre_tool",
|
|
5061
|
-
"tools": ["bash"],
|
|
5062
|
-
"command": "if echo \\"$TOOL_INPUT\\" | grep -qE 'rm\\\\s+-rf\\\\s+/'; then\\n echo '{\\"block\\":true,\\"message\\":\\"Blocked: rm -rf with absolute root path\\"}'\\nfi",
|
|
5063
|
-
"source": "space:{{.ID}}"
|
|
5064
|
-
}
|
|
5065
|
-
]
|
|
5066
|
-
}
|
|
5067
|
-
`,
|
|
5068
|
-
"e2e/playwright.config.ts.tmpl": `import { defineConfig } from '@playwright/test'
|
|
5069
|
-
|
|
5070
|
-
export default defineConfig({
|
|
5071
|
-
testDir: './e2e',
|
|
5072
|
-
timeout: 30_000,
|
|
5073
|
-
retries: 0,
|
|
5074
|
-
use: {
|
|
5075
|
-
baseURL: 'http://localhost:5173',
|
|
5076
|
-
trace: 'on-first-retry',
|
|
5077
|
-
},
|
|
5078
|
-
webServer: {
|
|
5079
|
-
command: 'construct dev',
|
|
5080
|
-
port: 5173,
|
|
5081
|
-
reuseExistingServer: true,
|
|
5082
|
-
},
|
|
5083
|
-
})
|
|
5084
|
-
`,
|
|
5085
|
-
"e2e/space.spec.ts.tmpl": `import { test, expect } from '@playwright/test'
|
|
5086
|
-
|
|
5087
|
-
test.describe('{{.DisplayName}} space', () => {
|
|
5088
|
-
test('renders the default page', async ({ page }) => {
|
|
5089
|
-
await page.goto('/')
|
|
5090
|
-
await expect(page.locator('[data-testid="space-root"]')).toBeVisible()
|
|
5091
|
-
})
|
|
5092
|
-
|
|
5093
|
-
test('displays the space title', async ({ page }) => {
|
|
5094
|
-
await page.goto('/')
|
|
5095
|
-
await expect(page.locator('text={{.DisplayName}}')).toBeVisible()
|
|
5096
|
-
})
|
|
5097
|
-
})
|
|
5098
|
-
`,
|
|
5099
|
-
"build.yml.tmpl": `name: Build Space
|
|
5100
|
-
|
|
5101
|
-
on:
|
|
5102
|
-
push:
|
|
5103
|
-
tags:
|
|
5104
|
-
- 'v*'
|
|
5105
|
-
pull_request:
|
|
5106
|
-
branches: [main]
|
|
5107
|
-
|
|
5108
|
-
jobs:
|
|
5109
|
-
build:
|
|
5110
|
-
runs-on: ubuntu-latest
|
|
5111
|
-
steps:
|
|
5112
|
-
- uses: actions/checkout@v4
|
|
5113
|
-
- uses: oven-sh/setup-bun@v2
|
|
5114
|
-
with:
|
|
5115
|
-
bun-version: latest
|
|
5116
|
-
- run: bun install
|
|
5117
|
-
- run: bun run build
|
|
5118
|
-
- name: Upload artifacts
|
|
5119
|
-
if: startsWith(github.ref, 'refs/tags/v')
|
|
5120
|
-
uses: actions/upload-artifact@v4
|
|
5121
|
-
with:
|
|
5122
|
-
name: space-dist
|
|
5123
|
-
path: dist/
|
|
5124
|
-
|
|
5125
|
-
release:
|
|
5126
|
-
needs: build
|
|
5127
|
-
if: startsWith(github.ref, 'refs/tags/v')
|
|
5128
|
-
runs-on: ubuntu-latest
|
|
5129
|
-
permissions:
|
|
5130
|
-
contents: write
|
|
5131
|
-
steps:
|
|
5132
|
-
- uses: actions/download-artifact@v4
|
|
5133
|
-
with:
|
|
5134
|
-
name: space-dist
|
|
5135
|
-
path: dist/
|
|
5136
|
-
- run: tar -czf space-dist.tar.gz -C dist .
|
|
5137
|
-
- uses: softprops/action-gh-release@v2
|
|
5138
|
-
with:
|
|
5139
|
-
files: |
|
|
5140
|
-
space-dist.tar.gz
|
|
5141
|
-
dist/manifest.json
|
|
5142
|
-
generate_release_notes: true
|
|
5143
|
-
`,
|
|
5144
|
-
"widgets/2x1.vue.tmpl": `<script setup lang="ts">
|
|
5145
|
-
/**
|
|
5146
|
-
* {{.DisplayName}} Summary Widget \u2014 2\xD71 compact view
|
|
5147
|
-
*/
|
|
5148
|
-
</script>
|
|
5149
|
-
|
|
5150
|
-
<template>
|
|
5151
|
-
<div class="h-full flex items-center gap-3 px-3">
|
|
5152
|
-
<div class="size-8 rounded-lg bg-[var(--app-accent)]/10 flex items-center justify-center">
|
|
5153
|
-
<Icon name="i-lucide-box" class="size-4 text-[var(--app-accent)]" />
|
|
5154
|
-
</div>
|
|
5155
|
-
<div class="min-w-0">
|
|
5156
|
-
<p class="text-sm font-medium text-[var(--app-foreground)] truncate">{{.DisplayName}}</p>
|
|
5157
|
-
<p class="text-xs text-[var(--app-muted)]">Ready</p>
|
|
5158
|
-
</div>
|
|
5159
|
-
</div>
|
|
5160
|
-
</template>
|
|
5161
|
-
`,
|
|
5162
|
-
"widgets/4x1.vue.tmpl": `<script setup lang="ts">
|
|
5163
|
-
/**
|
|
5164
|
-
* {{.DisplayName}} Summary Widget \u2014 4\xD71 wide view
|
|
5165
|
-
*/
|
|
5166
|
-
</script>
|
|
5167
|
-
|
|
5168
|
-
<template>
|
|
5169
|
-
<div class="h-full flex items-center justify-between px-4">
|
|
5170
|
-
<div class="flex items-center gap-3">
|
|
5171
|
-
<div class="size-8 rounded-lg bg-[var(--app-accent)]/10 flex items-center justify-center">
|
|
5172
|
-
<Icon name="i-lucide-box" class="size-4 text-[var(--app-accent)]" />
|
|
5173
|
-
</div>
|
|
5174
|
-
<div>
|
|
5175
|
-
<p class="text-sm font-medium text-[var(--app-foreground)]">{{.DisplayName}}</p>
|
|
5176
|
-
<p class="text-xs text-[var(--app-muted)]">Your space is ready</p>
|
|
5177
|
-
</div>
|
|
5178
|
-
</div>
|
|
5179
|
-
<div class="text-right">
|
|
5180
|
-
<p class="text-lg font-bold text-[var(--app-foreground)]">0</p>
|
|
5181
|
-
<p class="text-[10px] text-[var(--app-muted)] uppercase">Items</p>
|
|
5182
|
-
</div>
|
|
5183
|
-
</div>
|
|
5184
|
-
</template>
|
|
5185
|
-
`,
|
|
5186
|
-
"tsconfig.json.tmpl": `{
|
|
5187
|
-
"compilerOptions": {
|
|
5188
|
-
"target": "ESNext",
|
|
5189
|
-
"module": "ESNext",
|
|
5190
|
-
"moduleResolution": "bundler",
|
|
5191
|
-
"strict": true,
|
|
5192
|
-
"jsx": "preserve",
|
|
5193
|
-
"noEmit": true,
|
|
5194
|
-
"esModuleInterop": true,
|
|
5195
|
-
"skipLibCheck": true,
|
|
5196
|
-
"paths": {
|
|
5197
|
-
"@/*": ["./src/*"],
|
|
5198
|
-
"@construct/sdk": ["./node_modules/@construct-space/sdk/src/index.ts"]
|
|
5199
|
-
}
|
|
5200
|
-
},
|
|
5201
|
-
"include": [
|
|
5202
|
-
"src/**/*.ts",
|
|
5203
|
-
"src/**/*.vue",
|
|
5204
|
-
"widgets/**/*.vue"
|
|
5205
|
-
]
|
|
5206
|
-
}
|
|
5207
|
-
`
|
|
5208
|
-
};
|
|
5209
|
-
|
|
5210
4599
|
// src/commands/scaffold.ts
|
|
5211
4600
|
var nameRegex = /^[a-z][a-z0-9-]*$/;
|
|
5212
4601
|
function render(template, data) {
|
|
5213
4602
|
return template.replace(/\{\{\.Name\}\}/g, data.name).replace(/\{\{\.ID\}\}/g, data.id).replace(/\{\{\.IDUpper\}\}/g, data.idUpper).replace(/\{\{\.DisplayName\}\}/g, data.displayName).replace(/\{\{\.DisplayNameNoSpace\}\}/g, data.displayNameNoSpace);
|
|
5214
4603
|
}
|
|
5215
4604
|
function writeTemplate(templateDir, tmplName, outPath, data) {
|
|
5216
|
-
let content;
|
|
5217
4605
|
const tmplPath = join2(templateDir, tmplName);
|
|
5218
|
-
if (existsSync2(tmplPath)) {
|
|
5219
|
-
content = readFileSync(tmplPath, "utf-8");
|
|
5220
|
-
} else if (EMBEDDED_TEMPLATES[tmplName] !== undefined) {
|
|
5221
|
-
content = EMBEDDED_TEMPLATES[tmplName];
|
|
5222
|
-
} else {
|
|
4606
|
+
if (!existsSync2(tmplPath)) {
|
|
5223
4607
|
console.warn(source_default.yellow(`Template not found: ${tmplName}`));
|
|
5224
4608
|
return;
|
|
5225
4609
|
}
|
|
4610
|
+
const content = readFileSync(tmplPath, "utf-8");
|
|
5226
4611
|
mkdirSync(dirname(outPath), { recursive: true });
|
|
5227
4612
|
writeFileSync(outPath, render(content, data));
|
|
5228
4613
|
}
|
|
@@ -5325,7 +4710,7 @@ async function scaffold(nameArg, options) {
|
|
|
5325
4710
|
}
|
|
5326
4711
|
|
|
5327
4712
|
// src/commands/build.ts
|
|
5328
|
-
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";
|
|
5329
4714
|
import { join as join6 } from "path";
|
|
5330
4715
|
import { createHash } from "crypto";
|
|
5331
4716
|
|
|
@@ -7978,8 +7363,8 @@ function validate2(m) {
|
|
|
7978
7363
|
errors2.push("author: must be an object with a name");
|
|
7979
7364
|
if (!m.icon)
|
|
7980
7365
|
errors2.push("icon: must be a string");
|
|
7981
|
-
if (!["
|
|
7982
|
-
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"');
|
|
7983
7368
|
if (!m.pages?.length)
|
|
7984
7369
|
errors2.push("pages: must be a non-empty array");
|
|
7985
7370
|
if (!m.navigation?.label)
|
|
@@ -8006,30 +7391,84 @@ function exists(dir) {
|
|
|
8006
7391
|
}
|
|
8007
7392
|
|
|
8008
7393
|
// src/lib/entry.ts
|
|
8009
|
-
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
8010
|
-
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";
|
|
8011
7396
|
function capitalize(s) {
|
|
8012
7397
|
if (!s)
|
|
8013
7398
|
return s;
|
|
8014
7399
|
return s.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
|
|
8015
7400
|
}
|
|
8016
|
-
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
|
+
}
|
|
8017
7444
|
return m.pages.map((p) => {
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
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 };
|
|
8021
7461
|
}
|
|
8022
|
-
|
|
8023
|
-
|
|
8024
|
-
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
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";
|
|
8029
7468
|
}
|
|
8030
|
-
varName
|
|
7469
|
+
return { varName, importPath: prefix + legacyComponent, path: p.path };
|
|
8031
7470
|
}
|
|
8032
|
-
|
|
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.`);
|
|
8033
7472
|
});
|
|
8034
7473
|
}
|
|
8035
7474
|
function resolveWidgets(m, prefix) {
|
|
@@ -8048,7 +7487,7 @@ function resolveWidgets(m, prefix) {
|
|
|
8048
7487
|
}
|
|
8049
7488
|
function generate(root, m) {
|
|
8050
7489
|
const pagePrefix = existsSync4(join4(root, "src", "pages")) ? "./" : "../";
|
|
8051
|
-
const pages = resolvePages(m, pagePrefix);
|
|
7490
|
+
const pages = resolvePages(m, root, pagePrefix);
|
|
8052
7491
|
const widgets = resolveWidgets(m, "../");
|
|
8053
7492
|
const actionsPath = join4(root, "src", "actions.ts");
|
|
8054
7493
|
const hasActions = existsSync4(actionsPath);
|
|
@@ -8104,7 +7543,7 @@ function writeEntry(root, m) {
|
|
|
8104
7543
|
}
|
|
8105
7544
|
|
|
8106
7545
|
// src/lib/agent.ts
|
|
8107
|
-
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";
|
|
8108
7547
|
import { join as join5, extname as extname2, basename as basename2 } from "path";
|
|
8109
7548
|
var AGENT_KEY = "construct-agent-obfuscate-v1";
|
|
8110
7549
|
function encode(content) {
|
|
@@ -8120,7 +7559,7 @@ function readMdFiles(dir) {
|
|
|
8120
7559
|
const result = {};
|
|
8121
7560
|
if (!existsSync5(dir))
|
|
8122
7561
|
return result;
|
|
8123
|
-
for (const f of
|
|
7562
|
+
for (const f of readdirSync2(dir)) {
|
|
8124
7563
|
if (extname2(f) !== ".md")
|
|
8125
7564
|
continue;
|
|
8126
7565
|
result[basename2(f, ".md")] = readFileSync3(join5(dir, f), "utf-8");
|
|
@@ -8131,7 +7570,7 @@ function readJsonFiles(dir) {
|
|
|
8131
7570
|
const result = {};
|
|
8132
7571
|
if (!existsSync5(dir))
|
|
8133
7572
|
return result;
|
|
8134
|
-
for (const f of
|
|
7573
|
+
for (const f of readdirSync2(dir)) {
|
|
8135
7574
|
if (extname2(f) !== ".json")
|
|
8136
7575
|
continue;
|
|
8137
7576
|
result[basename2(f, ".json")] = readFileSync3(join5(dir, f), "utf-8");
|
|
@@ -8221,7 +7660,7 @@ async function build(options) {
|
|
|
8221
7660
|
}
|
|
8222
7661
|
runHook(m.hooks, "postBuild", root);
|
|
8223
7662
|
const agentDir = join6(root, "agent");
|
|
8224
|
-
if (existsSync6(agentDir) &&
|
|
7663
|
+
if (existsSync6(agentDir) && statSync3(agentDir).isDirectory()) {
|
|
8225
7664
|
const distDir2 = join6(root, "dist");
|
|
8226
7665
|
bundleAgentDir(agentDir, distDir2);
|
|
8227
7666
|
bundleAgentDir(agentDir, root);
|
|
@@ -8230,7 +7669,7 @@ async function build(options) {
|
|
|
8230
7669
|
const expectedBundle = `space-${m.id}.iife.js`;
|
|
8231
7670
|
let bundlePath = join6(distDir, expectedBundle);
|
|
8232
7671
|
if (!existsSync6(bundlePath)) {
|
|
8233
|
-
const matches =
|
|
7672
|
+
const matches = readdirSync3(distDir).filter((f) => f.startsWith("space-") && f.endsWith(".iife.js"));
|
|
8234
7673
|
if (matches.length === 1) {
|
|
8235
7674
|
renameSync(join6(distDir, matches[0]), bundlePath);
|
|
8236
7675
|
const oldCSS = join6(distDir, matches[0].replace(".iife.js", ".css"));
|
|
@@ -8260,20 +7699,20 @@ async function build(options) {
|
|
|
8260
7699
|
}
|
|
8261
7700
|
|
|
8262
7701
|
// src/commands/dev.ts
|
|
8263
|
-
import { existsSync as
|
|
8264
|
-
import { join as
|
|
7702
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
7703
|
+
import { join as join9 } from "path";
|
|
8265
7704
|
import { createHash as createHash2 } from "crypto";
|
|
8266
7705
|
|
|
8267
|
-
// node_modules/chokidar/
|
|
8268
|
-
import { stat as statcb } from "fs";
|
|
8269
|
-
import { stat as stat3, readdir as readdir2 } from "fs/promises";
|
|
7706
|
+
// node_modules/chokidar/index.js
|
|
8270
7707
|
import { EventEmitter } from "events";
|
|
8271
|
-
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";
|
|
8272
7711
|
|
|
8273
|
-
// node_modules/readdirp/
|
|
8274
|
-
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";
|
|
8275
7715
|
import { Readable } from "stream";
|
|
8276
|
-
import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "path";
|
|
8277
7716
|
var EntryTypes = {
|
|
8278
7717
|
FILE_TYPE: "files",
|
|
8279
7718
|
DIR_TYPE: "directories",
|
|
@@ -8329,6 +7768,20 @@ var normalizeFilter = (filter) => {
|
|
|
8329
7768
|
};
|
|
8330
7769
|
|
|
8331
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;
|
|
8332
7785
|
constructor(options = {}) {
|
|
8333
7786
|
super({
|
|
8334
7787
|
objectMode: true,
|
|
@@ -8345,7 +7798,7 @@ class ReaddirpStream extends Readable {
|
|
|
8345
7798
|
} else {
|
|
8346
7799
|
this._stat = statMethod;
|
|
8347
7800
|
}
|
|
8348
|
-
this._maxDepth = opts.depth
|
|
7801
|
+
this._maxDepth = opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;
|
|
8349
7802
|
this._wantsDir = type ? DIR_TYPES.has(type) : false;
|
|
8350
7803
|
this._wantsFile = type ? FILE_TYPES.has(type) : false;
|
|
8351
7804
|
this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
|
|
@@ -8490,11 +7943,11 @@ function readdirp(root, options = {}) {
|
|
|
8490
7943
|
return new ReaddirpStream(options);
|
|
8491
7944
|
}
|
|
8492
7945
|
|
|
8493
|
-
// node_modules/chokidar/
|
|
8494
|
-
import {
|
|
8495
|
-
import {
|
|
8496
|
-
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";
|
|
8497
7949
|
import { type as osType } from "os";
|
|
7950
|
+
import * as sp from "path";
|
|
8498
7951
|
var STR_DATA = "data";
|
|
8499
7952
|
var STR_END = "end";
|
|
8500
7953
|
var STR_CLOSE = "close";
|
|
@@ -8786,7 +8239,7 @@ var binaryExtensions = new Set([
|
|
|
8786
8239
|
"zip",
|
|
8787
8240
|
"zipx"
|
|
8788
8241
|
]);
|
|
8789
|
-
var isBinaryPath = (filePath) => binaryExtensions.has(
|
|
8242
|
+
var isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());
|
|
8790
8243
|
var foreach = (val, fn) => {
|
|
8791
8244
|
if (val instanceof Set) {
|
|
8792
8245
|
val.forEach(fn);
|
|
@@ -8824,7 +8277,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
|
|
|
8824
8277
|
listener(path);
|
|
8825
8278
|
emitRaw(rawEvent, evPath, { watchedPath: path });
|
|
8826
8279
|
if (evPath && path !== evPath) {
|
|
8827
|
-
fsWatchBroadcast(
|
|
8280
|
+
fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));
|
|
8828
8281
|
}
|
|
8829
8282
|
};
|
|
8830
8283
|
try {
|
|
@@ -8939,17 +8392,19 @@ var setFsWatchFileListener = (path, fullPath, options, handlers) => {
|
|
|
8939
8392
|
};
|
|
8940
8393
|
|
|
8941
8394
|
class NodeFsHandler {
|
|
8395
|
+
fsw;
|
|
8396
|
+
_boundHandleError;
|
|
8942
8397
|
constructor(fsW) {
|
|
8943
8398
|
this.fsw = fsW;
|
|
8944
8399
|
this._boundHandleError = (error2) => fsW._handleError(error2);
|
|
8945
8400
|
}
|
|
8946
8401
|
_watchWithNodeFs(path, listener) {
|
|
8947
8402
|
const opts = this.fsw.options;
|
|
8948
|
-
const directory =
|
|
8949
|
-
const basename4 =
|
|
8403
|
+
const directory = sp.dirname(path);
|
|
8404
|
+
const basename4 = sp.basename(path);
|
|
8950
8405
|
const parent = this.fsw._getWatchedDir(directory);
|
|
8951
8406
|
parent.add(basename4);
|
|
8952
|
-
const absolutePath =
|
|
8407
|
+
const absolutePath = sp.resolve(path);
|
|
8953
8408
|
const options = {
|
|
8954
8409
|
persistent: opts.persistent
|
|
8955
8410
|
};
|
|
@@ -8976,8 +8431,8 @@ class NodeFsHandler {
|
|
|
8976
8431
|
if (this.fsw.closed) {
|
|
8977
8432
|
return;
|
|
8978
8433
|
}
|
|
8979
|
-
const dirname3 =
|
|
8980
|
-
const basename4 =
|
|
8434
|
+
const dirname3 = sp.dirname(file);
|
|
8435
|
+
const basename4 = sp.basename(file);
|
|
8981
8436
|
const parent = this.fsw._getWatchedDir(dirname3);
|
|
8982
8437
|
let prevStats = stats;
|
|
8983
8438
|
if (parent.has(basename4))
|
|
@@ -9060,8 +8515,9 @@ class NodeFsHandler {
|
|
|
9060
8515
|
this.fsw._symlinkPaths.set(full, true);
|
|
9061
8516
|
}
|
|
9062
8517
|
_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
|
|
9063
|
-
directory =
|
|
9064
|
-
|
|
8518
|
+
directory = sp.join(directory, "");
|
|
8519
|
+
const throttleKey = target ? `${directory}:${target}` : directory;
|
|
8520
|
+
throttler = this.fsw._throttle("readdir", throttleKey, 1000);
|
|
9065
8521
|
if (!throttler)
|
|
9066
8522
|
return;
|
|
9067
8523
|
const previous = this.fsw._getWatchedDir(wh.path);
|
|
@@ -9078,7 +8534,7 @@ class NodeFsHandler {
|
|
|
9078
8534
|
return;
|
|
9079
8535
|
}
|
|
9080
8536
|
const item = entry.path;
|
|
9081
|
-
let path =
|
|
8537
|
+
let path = sp.join(directory, item);
|
|
9082
8538
|
current.add(item);
|
|
9083
8539
|
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
|
|
9084
8540
|
return;
|
|
@@ -9089,7 +8545,7 @@ class NodeFsHandler {
|
|
|
9089
8545
|
}
|
|
9090
8546
|
if (item === target || !target && !previous.has(item)) {
|
|
9091
8547
|
this.fsw._incrReadyCount();
|
|
9092
|
-
path =
|
|
8548
|
+
path = sp.join(dir, sp.relative(dir, path));
|
|
9093
8549
|
this._addToNodeFs(path, initialAdd, wh, depth + 1);
|
|
9094
8550
|
}
|
|
9095
8551
|
}).on(EV.ERROR, this._boundHandleError);
|
|
@@ -9115,12 +8571,12 @@ class NodeFsHandler {
|
|
|
9115
8571
|
});
|
|
9116
8572
|
}
|
|
9117
8573
|
async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
|
|
9118
|
-
const parentDir = this.fsw._getWatchedDir(
|
|
9119
|
-
const tracked = parentDir.has(
|
|
8574
|
+
const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));
|
|
8575
|
+
const tracked = parentDir.has(sp.basename(dir));
|
|
9120
8576
|
if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
|
|
9121
8577
|
this.fsw._emit(EV.ADD_DIR, dir, stats);
|
|
9122
8578
|
}
|
|
9123
|
-
parentDir.add(
|
|
8579
|
+
parentDir.add(sp.basename(dir));
|
|
9124
8580
|
this.fsw._getWatchedDir(dir);
|
|
9125
8581
|
let throttler;
|
|
9126
8582
|
let closer;
|
|
@@ -9161,7 +8617,7 @@ class NodeFsHandler {
|
|
|
9161
8617
|
const follow = this.fsw.options.followSymlinks;
|
|
9162
8618
|
let closer;
|
|
9163
8619
|
if (stats.isDirectory()) {
|
|
9164
|
-
const absPath =
|
|
8620
|
+
const absPath = sp.resolve(path);
|
|
9165
8621
|
const targetPath = follow ? await fsrealpath(path) : path;
|
|
9166
8622
|
if (this.fsw.closed)
|
|
9167
8623
|
return;
|
|
@@ -9175,14 +8631,14 @@ class NodeFsHandler {
|
|
|
9175
8631
|
const targetPath = follow ? await fsrealpath(path) : path;
|
|
9176
8632
|
if (this.fsw.closed)
|
|
9177
8633
|
return;
|
|
9178
|
-
const parent =
|
|
8634
|
+
const parent = sp.dirname(wh.watchPath);
|
|
9179
8635
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
9180
8636
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
9181
8637
|
closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
|
|
9182
8638
|
if (this.fsw.closed)
|
|
9183
8639
|
return;
|
|
9184
8640
|
if (targetPath !== undefined) {
|
|
9185
|
-
this.fsw._symlinkPaths.set(
|
|
8641
|
+
this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);
|
|
9186
8642
|
}
|
|
9187
8643
|
} else {
|
|
9188
8644
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
@@ -9200,7 +8656,7 @@ class NodeFsHandler {
|
|
|
9200
8656
|
}
|
|
9201
8657
|
}
|
|
9202
8658
|
|
|
9203
|
-
// node_modules/chokidar/
|
|
8659
|
+
// node_modules/chokidar/index.js
|
|
9204
8660
|
/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
|
|
9205
8661
|
var SLASH = "/";
|
|
9206
8662
|
var SLASH_SLASH = "//";
|
|
@@ -9208,7 +8664,7 @@ var ONE_DOT = ".";
|
|
|
9208
8664
|
var TWO_DOTS = "..";
|
|
9209
8665
|
var STRING_TYPE = "string";
|
|
9210
8666
|
var BACK_SLASH_RE = /\\/g;
|
|
9211
|
-
var DOUBLE_SLASH_RE =
|
|
8667
|
+
var DOUBLE_SLASH_RE = /\/\//g;
|
|
9212
8668
|
var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
|
|
9213
8669
|
var REPLACER_RE = /^\.[/\\]/;
|
|
9214
8670
|
function arrify(item) {
|
|
@@ -9227,11 +8683,11 @@ function createPattern(matcher) {
|
|
|
9227
8683
|
if (matcher.path === string)
|
|
9228
8684
|
return true;
|
|
9229
8685
|
if (matcher.recursive) {
|
|
9230
|
-
const
|
|
9231
|
-
if (!
|
|
8686
|
+
const relative4 = sp2.relative(matcher.path, string);
|
|
8687
|
+
if (!relative4) {
|
|
9232
8688
|
return false;
|
|
9233
8689
|
}
|
|
9234
|
-
return !
|
|
8690
|
+
return !relative4.startsWith("..") && !sp2.isAbsolute(relative4);
|
|
9235
8691
|
}
|
|
9236
8692
|
return false;
|
|
9237
8693
|
};
|
|
@@ -9241,14 +8697,12 @@ function createPattern(matcher) {
|
|
|
9241
8697
|
function normalizePath(path) {
|
|
9242
8698
|
if (typeof path !== "string")
|
|
9243
8699
|
throw new Error("string expected");
|
|
9244
|
-
path =
|
|
8700
|
+
path = sp2.normalize(path);
|
|
9245
8701
|
path = path.replace(/\\/g, "/");
|
|
9246
8702
|
let prepend = false;
|
|
9247
8703
|
if (path.startsWith("//"))
|
|
9248
8704
|
prepend = true;
|
|
9249
|
-
|
|
9250
|
-
while (path.match(DOUBLE_SLASH_RE2))
|
|
9251
|
-
path = path.replace(DOUBLE_SLASH_RE2, "/");
|
|
8705
|
+
path = path.replace(DOUBLE_SLASH_RE, "/");
|
|
9252
8706
|
if (prepend)
|
|
9253
8707
|
path = "/" + path;
|
|
9254
8708
|
return path;
|
|
@@ -9289,31 +8743,32 @@ var toUnix = (string) => {
|
|
|
9289
8743
|
if (str.startsWith(SLASH_SLASH)) {
|
|
9290
8744
|
prepend = true;
|
|
9291
8745
|
}
|
|
9292
|
-
|
|
9293
|
-
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
9294
|
-
}
|
|
8746
|
+
str = str.replace(DOUBLE_SLASH_RE, SLASH);
|
|
9295
8747
|
if (prepend) {
|
|
9296
8748
|
str = SLASH + str;
|
|
9297
8749
|
}
|
|
9298
8750
|
return str;
|
|
9299
8751
|
};
|
|
9300
|
-
var normalizePathToUnix = (path) => toUnix(
|
|
8752
|
+
var normalizePathToUnix = (path) => toUnix(sp2.normalize(toUnix(path)));
|
|
9301
8753
|
var normalizeIgnored = (cwd = "") => (path) => {
|
|
9302
8754
|
if (typeof path === "string") {
|
|
9303
|
-
return normalizePathToUnix(
|
|
8755
|
+
return normalizePathToUnix(sp2.isAbsolute(path) ? path : sp2.join(cwd, path));
|
|
9304
8756
|
} else {
|
|
9305
8757
|
return path;
|
|
9306
8758
|
}
|
|
9307
8759
|
};
|
|
9308
8760
|
var getAbsolutePath = (path, cwd) => {
|
|
9309
|
-
if (
|
|
8761
|
+
if (sp2.isAbsolute(path)) {
|
|
9310
8762
|
return path;
|
|
9311
8763
|
}
|
|
9312
|
-
return
|
|
8764
|
+
return sp2.join(cwd, path);
|
|
9313
8765
|
};
|
|
9314
8766
|
var EMPTY_SET = Object.freeze(new Set);
|
|
9315
8767
|
|
|
9316
8768
|
class DirEntry {
|
|
8769
|
+
path;
|
|
8770
|
+
_removeWatcher;
|
|
8771
|
+
items;
|
|
9317
8772
|
constructor(dir, removeWatcher) {
|
|
9318
8773
|
this.path = dir;
|
|
9319
8774
|
this._removeWatcher = removeWatcher;
|
|
@@ -9338,7 +8793,7 @@ class DirEntry {
|
|
|
9338
8793
|
await readdir2(dir);
|
|
9339
8794
|
} catch (err) {
|
|
9340
8795
|
if (this._removeWatcher) {
|
|
9341
|
-
this._removeWatcher(
|
|
8796
|
+
this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
|
|
9342
8797
|
}
|
|
9343
8798
|
}
|
|
9344
8799
|
}
|
|
@@ -9366,12 +8821,19 @@ var STAT_METHOD_F = "stat";
|
|
|
9366
8821
|
var STAT_METHOD_L = "lstat";
|
|
9367
8822
|
|
|
9368
8823
|
class WatchHelper {
|
|
8824
|
+
fsw;
|
|
8825
|
+
path;
|
|
8826
|
+
watchPath;
|
|
8827
|
+
fullWatchPath;
|
|
8828
|
+
dirParts;
|
|
8829
|
+
followSymlinks;
|
|
8830
|
+
statMethod;
|
|
9369
8831
|
constructor(path, follow, fsw) {
|
|
9370
8832
|
this.fsw = fsw;
|
|
9371
8833
|
const watchPath = path;
|
|
9372
8834
|
this.path = path = path.replace(REPLACER_RE, "");
|
|
9373
8835
|
this.watchPath = watchPath;
|
|
9374
|
-
this.fullWatchPath =
|
|
8836
|
+
this.fullWatchPath = sp2.resolve(watchPath);
|
|
9375
8837
|
this.dirParts = [];
|
|
9376
8838
|
this.dirParts.forEach((parts) => {
|
|
9377
8839
|
if (parts.length > 1)
|
|
@@ -9381,7 +8843,7 @@ class WatchHelper {
|
|
|
9381
8843
|
this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
|
|
9382
8844
|
}
|
|
9383
8845
|
entryPath(entry) {
|
|
9384
|
-
return
|
|
8846
|
+
return sp2.join(this.watchPath, sp2.relative(this.watchPath, entry.fullPath));
|
|
9385
8847
|
}
|
|
9386
8848
|
filterPath(entry) {
|
|
9387
8849
|
const { stats } = entry;
|
|
@@ -9396,6 +8858,24 @@ class WatchHelper {
|
|
|
9396
8858
|
}
|
|
9397
8859
|
|
|
9398
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;
|
|
9399
8879
|
constructor(_opts = {}) {
|
|
9400
8880
|
super();
|
|
9401
8881
|
this.closed = false;
|
|
@@ -9504,7 +8984,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9504
8984
|
return;
|
|
9505
8985
|
results.forEach((item) => {
|
|
9506
8986
|
if (item)
|
|
9507
|
-
this.add(
|
|
8987
|
+
this.add(sp2.dirname(item), sp2.basename(_origAdd || item));
|
|
9508
8988
|
});
|
|
9509
8989
|
});
|
|
9510
8990
|
return this;
|
|
@@ -9515,10 +8995,10 @@ class FSWatcher extends EventEmitter {
|
|
|
9515
8995
|
const paths = unifyPaths(paths_);
|
|
9516
8996
|
const { cwd } = this.options;
|
|
9517
8997
|
paths.forEach((path) => {
|
|
9518
|
-
if (!
|
|
8998
|
+
if (!sp2.isAbsolute(path) && !this._closers.has(path)) {
|
|
9519
8999
|
if (cwd)
|
|
9520
|
-
path =
|
|
9521
|
-
path =
|
|
9000
|
+
path = sp2.join(cwd, path);
|
|
9001
|
+
path = sp2.resolve(path);
|
|
9522
9002
|
}
|
|
9523
9003
|
this._closePath(path);
|
|
9524
9004
|
this._addIgnoredPath(path);
|
|
@@ -9562,7 +9042,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9562
9042
|
getWatched() {
|
|
9563
9043
|
const watchList = {};
|
|
9564
9044
|
this._watched.forEach((entry, dir) => {
|
|
9565
|
-
const key = this.options.cwd ?
|
|
9045
|
+
const key = this.options.cwd ? sp2.relative(this.options.cwd, dir) : dir;
|
|
9566
9046
|
const index = key || ONE_DOT;
|
|
9567
9047
|
watchList[index] = entry.getChildren().sort();
|
|
9568
9048
|
});
|
|
@@ -9578,9 +9058,9 @@ class FSWatcher extends EventEmitter {
|
|
|
9578
9058
|
return;
|
|
9579
9059
|
const opts = this.options;
|
|
9580
9060
|
if (isWindows)
|
|
9581
|
-
path =
|
|
9061
|
+
path = sp2.normalize(path);
|
|
9582
9062
|
if (opts.cwd)
|
|
9583
|
-
path =
|
|
9063
|
+
path = sp2.relative(opts.cwd, path);
|
|
9584
9064
|
const args = [path];
|
|
9585
9065
|
if (stats != null)
|
|
9586
9066
|
args.push(stats);
|
|
@@ -9631,7 +9111,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9631
9111
|
return this;
|
|
9632
9112
|
}
|
|
9633
9113
|
if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
9634
|
-
const fullPath = opts.cwd ?
|
|
9114
|
+
const fullPath = opts.cwd ? sp2.join(opts.cwd, path) : path;
|
|
9635
9115
|
let stats2;
|
|
9636
9116
|
try {
|
|
9637
9117
|
stats2 = await stat3(fullPath);
|
|
@@ -9687,8 +9167,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9687
9167
|
const pollInterval = awf.pollInterval;
|
|
9688
9168
|
let timeoutHandler;
|
|
9689
9169
|
let fullPath = path;
|
|
9690
|
-
if (this.options.cwd && !
|
|
9691
|
-
fullPath =
|
|
9170
|
+
if (this.options.cwd && !sp2.isAbsolute(path)) {
|
|
9171
|
+
fullPath = sp2.join(this.options.cwd, path);
|
|
9692
9172
|
}
|
|
9693
9173
|
const now = new Date;
|
|
9694
9174
|
const writes = this._pendingWrites;
|
|
@@ -9745,7 +9225,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9745
9225
|
return new WatchHelper(path, this.options.followSymlinks, this);
|
|
9746
9226
|
}
|
|
9747
9227
|
_getWatchedDir(directory) {
|
|
9748
|
-
const dir =
|
|
9228
|
+
const dir = sp2.resolve(directory);
|
|
9749
9229
|
if (!this._watched.has(dir))
|
|
9750
9230
|
this._watched.set(dir, new DirEntry(dir, this._boundRemove));
|
|
9751
9231
|
return this._watched.get(dir);
|
|
@@ -9756,8 +9236,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9756
9236
|
return Boolean(Number(stats.mode) & 256);
|
|
9757
9237
|
}
|
|
9758
9238
|
_remove(directory, item, isDirectory) {
|
|
9759
|
-
const path =
|
|
9760
|
-
const fullPath =
|
|
9239
|
+
const path = sp2.join(directory, item);
|
|
9240
|
+
const fullPath = sp2.resolve(path);
|
|
9761
9241
|
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
|
|
9762
9242
|
if (!this._throttle("remove", path, 100))
|
|
9763
9243
|
return;
|
|
@@ -9775,7 +9255,7 @@ class FSWatcher extends EventEmitter {
|
|
|
9775
9255
|
}
|
|
9776
9256
|
let relPath = path;
|
|
9777
9257
|
if (this.options.cwd)
|
|
9778
|
-
relPath =
|
|
9258
|
+
relPath = sp2.relative(this.options.cwd, path);
|
|
9779
9259
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
9780
9260
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
9781
9261
|
if (event === EVENTS.ADD)
|
|
@@ -9790,8 +9270,8 @@ class FSWatcher extends EventEmitter {
|
|
|
9790
9270
|
}
|
|
9791
9271
|
_closePath(path) {
|
|
9792
9272
|
this._closeFile(path);
|
|
9793
|
-
const dir =
|
|
9794
|
-
this._getWatchedDir(dir).remove(
|
|
9273
|
+
const dir = sp2.dirname(path);
|
|
9274
|
+
this._getWatchedDir(dir).remove(sp2.basename(path));
|
|
9795
9275
|
}
|
|
9796
9276
|
_closeFile(path) {
|
|
9797
9277
|
const closers = this._closers.get(path);
|
|
@@ -9834,55 +9314,11 @@ function watch(paths, options = {}) {
|
|
|
9834
9314
|
return watcher;
|
|
9835
9315
|
}
|
|
9836
9316
|
|
|
9837
|
-
// src/lib/appdir.ts
|
|
9838
|
-
import { join as join9 } from "path";
|
|
9839
|
-
import { homedir } from "os";
|
|
9840
|
-
import { platform as platform2 } from "process";
|
|
9841
|
-
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
9842
|
-
function dataDir() {
|
|
9843
|
-
if (process.env.CONSTRUCT_DATA_DIR)
|
|
9844
|
-
return process.env.CONSTRUCT_DATA_DIR;
|
|
9845
|
-
const home = homedir();
|
|
9846
|
-
switch (platform2) {
|
|
9847
|
-
case "darwin":
|
|
9848
|
-
return join9(home, "Library", "Application Support", "Construct");
|
|
9849
|
-
case "win32": {
|
|
9850
|
-
const appData = process.env.APPDATA || join9(home, "AppData", "Roaming");
|
|
9851
|
-
return join9(appData, "Construct");
|
|
9852
|
-
}
|
|
9853
|
-
default: {
|
|
9854
|
-
const xdg = process.env.XDG_DATA_HOME || join9(home, ".local", "share");
|
|
9855
|
-
return join9(xdg, "construct");
|
|
9856
|
-
}
|
|
9857
|
-
}
|
|
9858
|
-
}
|
|
9859
|
-
function activeProfileId() {
|
|
9860
|
-
try {
|
|
9861
|
-
const profilesPath = join9(dataDir(), "profiles.json");
|
|
9862
|
-
if (!existsSync7(profilesPath))
|
|
9863
|
-
return null;
|
|
9864
|
-
const data = JSON.parse(readFileSync5(profilesPath, "utf-8"));
|
|
9865
|
-
return data?.active_profile || null;
|
|
9866
|
-
} catch {
|
|
9867
|
-
return null;
|
|
9868
|
-
}
|
|
9869
|
-
}
|
|
9870
|
-
function spacesDir() {
|
|
9871
|
-
const profileId = activeProfileId();
|
|
9872
|
-
if (profileId) {
|
|
9873
|
-
return join9(dataDir(), "profiles", profileId, "spaces");
|
|
9874
|
-
}
|
|
9875
|
-
return join9(dataDir(), "spaces");
|
|
9876
|
-
}
|
|
9877
|
-
function spaceDir(spaceId) {
|
|
9878
|
-
return join9(spacesDir(), spaceId);
|
|
9879
|
-
}
|
|
9880
|
-
|
|
9881
9317
|
// src/commands/dev.ts
|
|
9882
9318
|
function getEntryWatchPaths(root) {
|
|
9883
9319
|
return [
|
|
9884
|
-
|
|
9885
|
-
|
|
9320
|
+
join9(root, MANIFEST_FILE),
|
|
9321
|
+
join9(root, "src", "actions.ts")
|
|
9886
9322
|
];
|
|
9887
9323
|
}
|
|
9888
9324
|
async function dev() {
|
|
@@ -9921,14 +9357,14 @@ async function dev() {
|
|
|
9921
9357
|
}
|
|
9922
9358
|
console.log(source_default.blue("Actions changed \u2014 entry regenerated"));
|
|
9923
9359
|
});
|
|
9924
|
-
const distDir =
|
|
9925
|
-
const bundleFile =
|
|
9360
|
+
const distDir = join9(root, "dist");
|
|
9361
|
+
const bundleFile = join9(distDir, `space-${m.id}.iife.js`);
|
|
9926
9362
|
let lastChecksum = "";
|
|
9927
9363
|
const distWatcher = watch(bundleFile, { ignoreInitial: false });
|
|
9928
9364
|
distWatcher.on("all", () => {
|
|
9929
|
-
if (!
|
|
9365
|
+
if (!existsSync7(bundleFile))
|
|
9930
9366
|
return;
|
|
9931
|
-
const bundleData =
|
|
9367
|
+
const bundleData = readFileSync5(bundleFile);
|
|
9932
9368
|
const checksum = createHash2("sha256").update(bundleData).digest("hex");
|
|
9933
9369
|
if (checksum === lastChecksum)
|
|
9934
9370
|
return;
|
|
@@ -9940,15 +9376,7 @@ async function dev() {
|
|
|
9940
9376
|
hostApiVersion: "0.2.0",
|
|
9941
9377
|
builtAt: new Date().toISOString()
|
|
9942
9378
|
});
|
|
9943
|
-
|
|
9944
|
-
const installDir = spaceDir(m.id);
|
|
9945
|
-
mkdirSync3(installDir, { recursive: true });
|
|
9946
|
-
cpSync(distDir, installDir, { recursive: true });
|
|
9947
|
-
console.log(source_default.green(`Built + installed \u2192 ${installDir} (${(bundleData.length / 1024).toFixed(1)} KB)`));
|
|
9948
|
-
} catch (err) {
|
|
9949
|
-
console.log(source_default.green(`Built \u2192 dist/ (${(bundleData.length / 1024).toFixed(1)} KB)`));
|
|
9950
|
-
console.log(source_default.yellow(` Install failed: ${err.message}`));
|
|
9951
|
-
}
|
|
9379
|
+
console.log(source_default.green(`Built \u2192 dist/ (${(bundleData.length / 1024).toFixed(1)} KB)`));
|
|
9952
9380
|
});
|
|
9953
9381
|
console.log(source_default.green("Watching for changes... (Ctrl+C to stop)"));
|
|
9954
9382
|
console.log(source_default.dim("Use the Preview button in Construct to open the Space Runner"));
|
|
@@ -9956,8 +9384,38 @@ async function dev() {
|
|
|
9956
9384
|
}
|
|
9957
9385
|
|
|
9958
9386
|
// src/commands/run.ts
|
|
9959
|
-
import { existsSync as
|
|
9387
|
+
import { existsSync as existsSync8, cpSync, mkdirSync as mkdirSync3 } from "fs";
|
|
9960
9388
|
import { join as join11 } from "path";
|
|
9389
|
+
|
|
9390
|
+
// src/lib/appdir.ts
|
|
9391
|
+
import { join as join10 } from "path";
|
|
9392
|
+
import { homedir } from "os";
|
|
9393
|
+
import { platform as platform2 } from "process";
|
|
9394
|
+
function dataDir() {
|
|
9395
|
+
if (process.env.CONSTRUCT_DATA_DIR)
|
|
9396
|
+
return process.env.CONSTRUCT_DATA_DIR;
|
|
9397
|
+
const home = homedir();
|
|
9398
|
+
switch (platform2) {
|
|
9399
|
+
case "darwin":
|
|
9400
|
+
return join10(home, "Library", "Application Support", "Construct");
|
|
9401
|
+
case "win32": {
|
|
9402
|
+
const appData = process.env.APPDATA || join10(home, "AppData", "Roaming");
|
|
9403
|
+
return join10(appData, "Construct");
|
|
9404
|
+
}
|
|
9405
|
+
default: {
|
|
9406
|
+
const xdg = process.env.XDG_DATA_HOME || join10(home, ".local", "share");
|
|
9407
|
+
return join10(xdg, "construct");
|
|
9408
|
+
}
|
|
9409
|
+
}
|
|
9410
|
+
}
|
|
9411
|
+
function spacesDir() {
|
|
9412
|
+
return join10(dataDir(), "spaces");
|
|
9413
|
+
}
|
|
9414
|
+
function spaceDir(spaceId) {
|
|
9415
|
+
return join10(spacesDir(), spaceId);
|
|
9416
|
+
}
|
|
9417
|
+
|
|
9418
|
+
// src/commands/run.ts
|
|
9961
9419
|
function install() {
|
|
9962
9420
|
const root = process.cwd();
|
|
9963
9421
|
if (!exists(root)) {
|
|
@@ -9965,83 +9423,46 @@ function install() {
|
|
|
9965
9423
|
process.exit(1);
|
|
9966
9424
|
}
|
|
9967
9425
|
const distDir = join11(root, "dist");
|
|
9968
|
-
if (!
|
|
9426
|
+
if (!existsSync8(distDir)) {
|
|
9969
9427
|
console.error(source_default.red("No dist/ directory found. Run 'construct build' first."));
|
|
9970
9428
|
process.exit(1);
|
|
9971
9429
|
}
|
|
9972
9430
|
const m = read(root);
|
|
9973
9431
|
const agentDir = join11(root, "agent");
|
|
9974
|
-
if (
|
|
9432
|
+
if (existsSync8(agentDir)) {
|
|
9975
9433
|
bundleAgentDir(agentDir, distDir);
|
|
9976
9434
|
}
|
|
9977
9435
|
const installDir = spaceDir(m.id);
|
|
9978
|
-
|
|
9979
|
-
|
|
9436
|
+
mkdirSync3(installDir, { recursive: true });
|
|
9437
|
+
cpSync(distDir, installDir, { recursive: true });
|
|
9980
9438
|
console.log(source_default.green(`Installed ${m.name} \u2192 ${installDir}`));
|
|
9981
9439
|
console.log(source_default.dim(" Restart Construct to load the updated space."));
|
|
9982
9440
|
}
|
|
9983
9441
|
|
|
9984
9442
|
// src/commands/publish.ts
|
|
9985
|
-
import { readFileSync as
|
|
9443
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, statSync as statSync5, unlinkSync as unlinkSync2 } from "fs";
|
|
9986
9444
|
import { join as join14, basename as basename6 } from "path";
|
|
9987
9445
|
|
|
9988
9446
|
// src/lib/auth.ts
|
|
9989
|
-
import { readFileSync as
|
|
9447
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, unlinkSync, existsSync as existsSync9 } from "fs";
|
|
9990
9448
|
import { join as join12, dirname as dirname4 } from "path";
|
|
9991
9449
|
var CREDENTIALS_FILE = "credentials.json";
|
|
9992
|
-
var APP_PROFILES_FILE = "profiles.json";
|
|
9993
9450
|
var DEFAULT_PORTAL = "https://developer.construct.space";
|
|
9994
9451
|
function credentialsPath() {
|
|
9995
9452
|
return join12(dataDir(), CREDENTIALS_FILE);
|
|
9996
9453
|
}
|
|
9997
|
-
function appProfilesPath() {
|
|
9998
|
-
return join12(dataDir(), APP_PROFILES_FILE);
|
|
9999
|
-
}
|
|
10000
|
-
function appProfileAuthPath(profileId) {
|
|
10001
|
-
return join12(dataDir(), "profiles", profileId, "auth.json");
|
|
10002
|
-
}
|
|
10003
|
-
function loadFromApp() {
|
|
10004
|
-
try {
|
|
10005
|
-
const profilesPath = appProfilesPath();
|
|
10006
|
-
if (!existsSync10(profilesPath))
|
|
10007
|
-
return null;
|
|
10008
|
-
const profiles = JSON.parse(readFileSync7(profilesPath, "utf-8"));
|
|
10009
|
-
if (!profiles?.active_profile)
|
|
10010
|
-
return null;
|
|
10011
|
-
const authPath = appProfileAuthPath(profiles.active_profile);
|
|
10012
|
-
if (!existsSync10(authPath))
|
|
10013
|
-
return null;
|
|
10014
|
-
const auth = JSON.parse(readFileSync7(authPath, "utf-8"));
|
|
10015
|
-
if (!auth?.authenticated || !auth?.token)
|
|
10016
|
-
return null;
|
|
10017
|
-
return {
|
|
10018
|
-
token: auth.token,
|
|
10019
|
-
portal: DEFAULT_PORTAL,
|
|
10020
|
-
user: {
|
|
10021
|
-
id: auth.user.id,
|
|
10022
|
-
name: auth.user.name || [auth.user.first_name, auth.user.last_name].filter(Boolean).join(" ") || auth.user.email,
|
|
10023
|
-
email: auth.user.email
|
|
10024
|
-
}
|
|
10025
|
-
};
|
|
10026
|
-
} catch {
|
|
10027
|
-
return null;
|
|
10028
|
-
}
|
|
10029
|
-
}
|
|
10030
9454
|
function store(creds) {
|
|
10031
9455
|
const path = credentialsPath();
|
|
10032
|
-
|
|
9456
|
+
mkdirSync4(dirname4(path), { recursive: true });
|
|
10033
9457
|
writeFileSync5(path, JSON.stringify(creds, null, 2) + `
|
|
10034
9458
|
`, { mode: 384 });
|
|
10035
9459
|
}
|
|
10036
9460
|
function load2() {
|
|
10037
|
-
const fromApp = loadFromApp();
|
|
10038
|
-
if (fromApp)
|
|
10039
|
-
return fromApp;
|
|
10040
9461
|
const path = credentialsPath();
|
|
10041
|
-
if (!
|
|
10042
|
-
throw new Error("not logged in \u2014 run 'construct login' first
|
|
9462
|
+
if (!existsSync9(path)) {
|
|
9463
|
+
throw new Error("not logged in \u2014 run 'construct login' first");
|
|
10043
9464
|
}
|
|
10044
|
-
const data = JSON.parse(
|
|
9465
|
+
const data = JSON.parse(readFileSync6(path, "utf-8"));
|
|
10045
9466
|
if (!data.token) {
|
|
10046
9467
|
throw new Error("not logged in \u2014 run 'construct login' first");
|
|
10047
9468
|
}
|
|
@@ -10057,12 +9478,12 @@ function isAuthenticated() {
|
|
|
10057
9478
|
}
|
|
10058
9479
|
function clear() {
|
|
10059
9480
|
const path = credentialsPath();
|
|
10060
|
-
if (
|
|
9481
|
+
if (existsSync9(path))
|
|
10061
9482
|
unlinkSync(path);
|
|
10062
9483
|
}
|
|
10063
9484
|
|
|
10064
9485
|
// src/lib/pack.ts
|
|
10065
|
-
import { readdirSync as
|
|
9486
|
+
import { readdirSync as readdirSync4, statSync as statSync4, existsSync as existsSync10 } from "fs";
|
|
10066
9487
|
import { join as join13 } from "path";
|
|
10067
9488
|
import { tmpdir } from "os";
|
|
10068
9489
|
import { execSync as execSync3 } from "child_process";
|
|
@@ -10101,11 +9522,11 @@ async function packSource(root) {
|
|
|
10101
9522
|
const tarballPath = join13(tmpdir(), `space-source-${Date.now()}.tar.gz`);
|
|
10102
9523
|
const entries = [];
|
|
10103
9524
|
for (const name of allowedRootFiles) {
|
|
10104
|
-
if (
|
|
9525
|
+
if (existsSync10(join13(root, name)))
|
|
10105
9526
|
entries.push(name);
|
|
10106
9527
|
}
|
|
10107
|
-
for (const entry of
|
|
10108
|
-
if (
|
|
9528
|
+
for (const entry of readdirSync4(root)) {
|
|
9529
|
+
if (statSync4(join13(root, entry)).isDirectory())
|
|
10109
9530
|
continue;
|
|
10110
9531
|
if (allowedRootFiles.includes(entry))
|
|
10111
9532
|
continue;
|
|
@@ -10115,17 +9536,17 @@ async function packSource(root) {
|
|
|
10115
9536
|
entries.push(entry);
|
|
10116
9537
|
}
|
|
10117
9538
|
for (const dir of allowedDirs) {
|
|
10118
|
-
if (
|
|
9539
|
+
if (existsSync10(join13(root, dir)))
|
|
10119
9540
|
entries.push(dir);
|
|
10120
9541
|
}
|
|
10121
|
-
const validEntries = entries.filter((e) =>
|
|
9542
|
+
const validEntries = entries.filter((e) => existsSync10(join13(root, e)));
|
|
10122
9543
|
if (validEntries.length === 0) {
|
|
10123
9544
|
throw new Error("No files to pack");
|
|
10124
9545
|
}
|
|
10125
9546
|
const excludes = "--exclude=node_modules --exclude=dist --exclude=.git --exclude=*.env --exclude=*.log --exclude=*.lock --exclude=*.lockb";
|
|
10126
9547
|
const cmd = `tar czf "${tarballPath}" ${excludes} ${validEntries.join(" ")}`;
|
|
10127
9548
|
execSync3(cmd, { cwd: root });
|
|
10128
|
-
const size =
|
|
9549
|
+
const size = statSync4(tarballPath).size;
|
|
10129
9550
|
if (size > MAX_SIZE) {
|
|
10130
9551
|
throw new Error(`Source exceeds maximum size of ${MAX_SIZE / 1024 / 1024}MB`);
|
|
10131
9552
|
}
|
|
@@ -10136,7 +9557,7 @@ async function packSource(root) {
|
|
|
10136
9557
|
async function uploadSource(portalURL, token, tarballPath, m) {
|
|
10137
9558
|
const formData = new FormData;
|
|
10138
9559
|
formData.append("manifest", JSON.stringify(m));
|
|
10139
|
-
const fileData =
|
|
9560
|
+
const fileData = readFileSync7(tarballPath);
|
|
10140
9561
|
const blob = new Blob([fileData]);
|
|
10141
9562
|
formData.append("source", blob, basename6(tarballPath));
|
|
10142
9563
|
const resp = await fetch(`${portalURL}/api/publish`, {
|
|
@@ -10148,6 +9569,16 @@ async function uploadSource(portalURL, token, tarballPath, m) {
|
|
|
10148
9569
|
if (resp.status === 401) {
|
|
10149
9570
|
throw new Error("authentication failed \u2014 run 'construct login' to re-authenticate");
|
|
10150
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
|
+
}
|
|
10151
9582
|
if (resp.status >= 400) {
|
|
10152
9583
|
const msg = result.error || result.errors?.join("; ") || `server returned ${resp.status}`;
|
|
10153
9584
|
throw new Error(msg);
|
|
@@ -10160,7 +9591,7 @@ function setVersionInFiles(root, oldVer, newVer) {
|
|
|
10160
9591
|
for (const file of ["package.json", "space.manifest.json"]) {
|
|
10161
9592
|
const path = join14(root, file);
|
|
10162
9593
|
try {
|
|
10163
|
-
const data =
|
|
9594
|
+
const data = readFileSync7(path, "utf-8");
|
|
10164
9595
|
writeFileSync6(path, data.replace(oldStr, newStr));
|
|
10165
9596
|
} catch {}
|
|
10166
9597
|
}
|
|
@@ -10182,24 +9613,6 @@ async function publish(options) {
|
|
|
10182
9613
|
console.log(source_default.dim(" Run 'construct login' to authenticate."));
|
|
10183
9614
|
process.exit(1);
|
|
10184
9615
|
}
|
|
10185
|
-
const publishers = creds.publishers || [];
|
|
10186
|
-
if (publishers.length === 0) {
|
|
10187
|
-
console.log(source_default.yellow(" No publisher linked to this session. The upload will likely be rejected."));
|
|
10188
|
-
console.log(source_default.dim(" Run 'construct login' after enrolling at developer.construct.space."));
|
|
10189
|
-
} else {
|
|
10190
|
-
const primary = publishers[0];
|
|
10191
|
-
const kindLabel = primary.kind === "org" ? source_default.cyan("org") : primary.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
10192
|
-
console.log(source_default.dim(` Publishing as ${primary.name} (${kindLabel})`));
|
|
10193
|
-
if (publishers.length > 1 && !yes) {
|
|
10194
|
-
const proceed = await dist_default4({
|
|
10195
|
-
message: `You have ${publishers.length} publisher identities. Publish under ${primary.name}?`
|
|
10196
|
-
});
|
|
10197
|
-
if (!proceed) {
|
|
10198
|
-
console.log("Cancelled.");
|
|
10199
|
-
return;
|
|
10200
|
-
}
|
|
10201
|
-
}
|
|
10202
|
-
}
|
|
10203
9616
|
const status = gitSafe(root, "status", "--porcelain");
|
|
10204
9617
|
if (status) {
|
|
10205
9618
|
console.log(source_default.yellow("You have uncommitted changes."));
|
|
@@ -10283,7 +9696,7 @@ async function publish(options) {
|
|
|
10283
9696
|
let tarballPath;
|
|
10284
9697
|
try {
|
|
10285
9698
|
tarballPath = await packSource(root);
|
|
10286
|
-
const size =
|
|
9699
|
+
const size = statSync5(tarballPath).size;
|
|
10287
9700
|
spinner.succeed(`Source packed (${formatBytes(size)})`);
|
|
10288
9701
|
} catch (err) {
|
|
10289
9702
|
spinner.fail("Pack failed");
|
|
@@ -10322,7 +9735,7 @@ async function publish(options) {
|
|
|
10322
9735
|
}
|
|
10323
9736
|
|
|
10324
9737
|
// src/commands/validate.ts
|
|
10325
|
-
import { existsSync as
|
|
9738
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
|
|
10326
9739
|
import { join as join15 } from "path";
|
|
10327
9740
|
function validate3() {
|
|
10328
9741
|
const root = process.cwd();
|
|
@@ -10342,21 +9755,21 @@ function validate3() {
|
|
|
10342
9755
|
for (const page of m.pages) {
|
|
10343
9756
|
const component = page.component || (page.path === "" ? "pages/index.vue" : `pages/${page.path}.vue`);
|
|
10344
9757
|
const fullPath = join15(root, "src", component);
|
|
10345
|
-
if (!
|
|
9758
|
+
if (!existsSync11(fullPath)) {
|
|
10346
9759
|
console.log(source_default.yellow(` \u26A0 Page component not found: src/${component}`));
|
|
10347
9760
|
warnings++;
|
|
10348
9761
|
}
|
|
10349
9762
|
}
|
|
10350
9763
|
if (m.agent) {
|
|
10351
9764
|
const agentPath = join15(root, m.agent);
|
|
10352
|
-
if (!
|
|
9765
|
+
if (!existsSync11(agentPath)) {
|
|
10353
9766
|
console.log(source_default.yellow(` \u26A0 Agent config not found: ${m.agent}`));
|
|
10354
9767
|
warnings++;
|
|
10355
9768
|
}
|
|
10356
9769
|
}
|
|
10357
9770
|
const pkgPath = join15(root, "package.json");
|
|
10358
|
-
if (
|
|
10359
|
-
const pkg = JSON.parse(
|
|
9771
|
+
if (existsSync11(pkgPath)) {
|
|
9772
|
+
const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
|
|
10360
9773
|
if (pkg.version && pkg.version !== m.version) {
|
|
10361
9774
|
console.log(source_default.yellow(` \u26A0 Version mismatch: manifest=${m.version} package.json=${pkg.version}`));
|
|
10362
9775
|
warnings++;
|
|
@@ -10371,7 +9784,7 @@ function validate3() {
|
|
|
10371
9784
|
|
|
10372
9785
|
// src/commands/check.ts
|
|
10373
9786
|
import { execSync as execSync4 } from "child_process";
|
|
10374
|
-
import { existsSync as
|
|
9787
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
10375
9788
|
import { join as join16 } from "path";
|
|
10376
9789
|
function check() {
|
|
10377
9790
|
const root = process.cwd();
|
|
@@ -10391,18 +9804,18 @@ function check() {
|
|
|
10391
9804
|
let warnings = 0;
|
|
10392
9805
|
for (const page of m.pages) {
|
|
10393
9806
|
const component = page.component || (page.path === "" ? "pages/index.vue" : `pages/${page.path}.vue`);
|
|
10394
|
-
if (!
|
|
9807
|
+
if (!existsSync12(join16(root, "src", component))) {
|
|
10395
9808
|
console.log(source_default.yellow(` \u26A0 Page not found: src/${component}`));
|
|
10396
9809
|
warnings++;
|
|
10397
9810
|
}
|
|
10398
9811
|
}
|
|
10399
|
-
if (m.agent && !
|
|
9812
|
+
if (m.agent && !existsSync12(join16(root, m.agent))) {
|
|
10400
9813
|
console.log(source_default.yellow(` \u26A0 Agent config not found: ${m.agent}`));
|
|
10401
9814
|
warnings++;
|
|
10402
9815
|
}
|
|
10403
9816
|
const pkgPath = join16(root, "package.json");
|
|
10404
|
-
if (
|
|
10405
|
-
const pkg = JSON.parse(
|
|
9817
|
+
if (existsSync12(pkgPath)) {
|
|
9818
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
|
|
10406
9819
|
if (pkg.version && pkg.version !== m.version) {
|
|
10407
9820
|
console.log(source_default.yellow(` \u26A0 Version mismatch: manifest=${m.version} package.json=${pkg.version}`));
|
|
10408
9821
|
warnings++;
|
|
@@ -10433,7 +9846,7 @@ function check() {
|
|
|
10433
9846
|
}
|
|
10434
9847
|
|
|
10435
9848
|
// src/commands/clean.ts
|
|
10436
|
-
import { rmSync, existsSync as
|
|
9849
|
+
import { rmSync, existsSync as existsSync13 } from "fs";
|
|
10437
9850
|
import { join as join17 } from "path";
|
|
10438
9851
|
function clean(options) {
|
|
10439
9852
|
const root = process.cwd();
|
|
@@ -10444,7 +9857,7 @@ function clean(options) {
|
|
|
10444
9857
|
const lockfiles = ["bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
|
|
10445
9858
|
for (const dir of dirs) {
|
|
10446
9859
|
const path = join17(root, dir);
|
|
10447
|
-
if (
|
|
9860
|
+
if (existsSync13(path)) {
|
|
10448
9861
|
rmSync(path, { recursive: true });
|
|
10449
9862
|
console.log(source_default.dim(` Removed ${dir}/`));
|
|
10450
9863
|
}
|
|
@@ -10452,7 +9865,7 @@ function clean(options) {
|
|
|
10452
9865
|
if (options?.all) {
|
|
10453
9866
|
for (const file of lockfiles) {
|
|
10454
9867
|
const path = join17(root, file);
|
|
10455
|
-
if (
|
|
9868
|
+
if (existsSync13(path)) {
|
|
10456
9869
|
rmSync(path);
|
|
10457
9870
|
console.log(source_default.dim(` Removed ${file}`));
|
|
10458
9871
|
}
|
|
@@ -10465,12 +9878,6 @@ function clean(options) {
|
|
|
10465
9878
|
import { createServer } from "http";
|
|
10466
9879
|
async function login(options) {
|
|
10467
9880
|
const portalURL = options?.portal || DEFAULT_PORTAL;
|
|
10468
|
-
const fromApp = loadFromApp();
|
|
10469
|
-
if (fromApp) {
|
|
10470
|
-
console.log(source_default.green(`Using Construct app profile: ${fromApp.user?.name || fromApp.user?.email}`));
|
|
10471
|
-
console.log(source_default.dim(" To use a different identity, sign out of the app or run `construct logout` after login."));
|
|
10472
|
-
return;
|
|
10473
|
-
}
|
|
10474
9881
|
if (isAuthenticated()) {
|
|
10475
9882
|
const creds = load2();
|
|
10476
9883
|
const name = creds.user?.name || "unknown";
|
|
@@ -10536,101 +9943,18 @@ async function login(options) {
|
|
|
10536
9943
|
const resp = await fetch(`${portalURL}/api/auth/cli-verify`, {
|
|
10537
9944
|
headers: { Authorization: `Bearer ${token}` }
|
|
10538
9945
|
});
|
|
10539
|
-
const { user
|
|
10540
|
-
store({ token, portal: portalURL, user
|
|
9946
|
+
const { user } = await resp.json();
|
|
9947
|
+
store({ token, portal: portalURL, user });
|
|
10541
9948
|
console.log();
|
|
10542
9949
|
console.log(source_default.green(`Logged in as ${user?.name || "there"}`));
|
|
10543
|
-
const list = publishers || [];
|
|
10544
|
-
if (list.length === 0) {
|
|
10545
|
-
console.log(source_default.yellow(" No publisher yet. Run developer enrollment to publish spaces."));
|
|
10546
|
-
} else {
|
|
10547
|
-
for (const p of list) {
|
|
10548
|
-
const label = p.kind === "org" ? source_default.cyan("org") : p.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
10549
|
-
console.log(source_default.dim(` Publisher: ${p.name} (${label})`));
|
|
10550
|
-
}
|
|
10551
|
-
}
|
|
10552
9950
|
} catch (err) {
|
|
10553
9951
|
console.error(source_default.red(`Login failed: ${err.message}`));
|
|
10554
9952
|
process.exit(1);
|
|
10555
9953
|
}
|
|
10556
9954
|
}
|
|
10557
9955
|
function logout() {
|
|
10558
|
-
const wasCli = isAuthenticated();
|
|
10559
9956
|
clear();
|
|
10560
|
-
|
|
10561
|
-
console.log(source_default.green("Logged out of CLI credentials."));
|
|
10562
|
-
} else {
|
|
10563
|
-
console.log(source_default.dim("No CLI credentials to clear."));
|
|
10564
|
-
}
|
|
10565
|
-
const appStill = loadFromApp();
|
|
10566
|
-
if (appStill) {
|
|
10567
|
-
console.log();
|
|
10568
|
-
console.log(source_default.yellow("Note: the Construct app is still signed in as ") + source_default.white(appStill.user?.name || appStill.user?.email || ""));
|
|
10569
|
-
console.log(source_default.dim(" The CLI will continue to use the app profile. Sign out of the app to fully disconnect."));
|
|
10570
|
-
}
|
|
10571
|
-
}
|
|
10572
|
-
|
|
10573
|
-
// src/commands/whoami.ts
|
|
10574
|
-
async function whoami() {
|
|
10575
|
-
const fromApp = loadFromApp();
|
|
10576
|
-
let creds = null;
|
|
10577
|
-
let source = "none";
|
|
10578
|
-
if (fromApp) {
|
|
10579
|
-
creds = fromApp;
|
|
10580
|
-
source = "app";
|
|
10581
|
-
} else {
|
|
10582
|
-
try {
|
|
10583
|
-
creds = load2();
|
|
10584
|
-
source = "cli";
|
|
10585
|
-
} catch {
|
|
10586
|
-
source = "none";
|
|
10587
|
-
}
|
|
10588
|
-
}
|
|
10589
|
-
if (source === "none" || !creds) {
|
|
10590
|
-
console.log(source_default.yellow("Not signed in."));
|
|
10591
|
-
console.log(source_default.dim(" Run ") + source_default.white("construct login") + source_default.dim(" or sign in to the Construct app."));
|
|
10592
|
-
return;
|
|
10593
|
-
}
|
|
10594
|
-
const user = creds.user;
|
|
10595
|
-
const sourceLabel = source === "app" ? source_default.cyan("Construct app profile") : source_default.blue("CLI login");
|
|
10596
|
-
console.log();
|
|
10597
|
-
console.log(source_default.bold(user?.name || "Signed in"));
|
|
10598
|
-
console.log(source_default.dim(" " + (user?.email || "")));
|
|
10599
|
-
console.log(source_default.dim(" id: ") + source_default.dim(user?.id || "\u2014"));
|
|
10600
|
-
console.log(source_default.dim(" source: ") + sourceLabel);
|
|
10601
|
-
console.log(source_default.dim(" portal: ") + (creds.portal || DEFAULT_PORTAL));
|
|
10602
|
-
try {
|
|
10603
|
-
const resp = await fetch(`${creds.portal || DEFAULT_PORTAL}/api/auth/cli-verify`, {
|
|
10604
|
-
headers: { Authorization: `Bearer ${creds.token}` }
|
|
10605
|
-
});
|
|
10606
|
-
if (!resp.ok) {
|
|
10607
|
-
console.log(source_default.dim(" publishers: ") + source_default.red(`error (${resp.status})`));
|
|
10608
|
-
return;
|
|
10609
|
-
}
|
|
10610
|
-
const body = await resp.json();
|
|
10611
|
-
const list = body.publishers || [];
|
|
10612
|
-
if (list.length === 0) {
|
|
10613
|
-
console.log(source_default.dim(" publishers: ") + source_default.yellow("none yet \u2014 enroll at developer.construct.space"));
|
|
10614
|
-
return;
|
|
10615
|
-
}
|
|
10616
|
-
console.log();
|
|
10617
|
-
console.log(source_default.bold("Publishers"));
|
|
10618
|
-
for (const p of list) {
|
|
10619
|
-
const kindLabel = p.kind === "org" ? source_default.cyan("org") : p.kind === "user" ? source_default.blue("personal") : source_default.dim("legacy");
|
|
10620
|
-
const verified = p.verified ? source_default.green(" \u2713") : "";
|
|
10621
|
-
console.log(` ${source_default.white(p.name)} (${kindLabel})${verified}`);
|
|
10622
|
-
if (p.orgId)
|
|
10623
|
-
console.log(source_default.dim(` org: ${p.orgId}`));
|
|
10624
|
-
}
|
|
10625
|
-
} catch (err) {
|
|
10626
|
-
console.log(source_default.dim(" publishers: ") + source_default.red("could not reach portal"));
|
|
10627
|
-
}
|
|
10628
|
-
console.log();
|
|
10629
|
-
if (source === "app") {
|
|
10630
|
-
console.log(source_default.dim("To switch identities, change the active profile in the Construct app."));
|
|
10631
|
-
} else {
|
|
10632
|
-
console.log(source_default.dim("To switch identities, run 'construct logout' then 'construct login'."));
|
|
10633
|
-
}
|
|
9957
|
+
console.log(source_default.green("Logged out."));
|
|
10634
9958
|
}
|
|
10635
9959
|
|
|
10636
9960
|
// src/commands/update.ts
|
|
@@ -10662,7 +9986,7 @@ function update() {
|
|
|
10662
9986
|
}
|
|
10663
9987
|
|
|
10664
9988
|
// src/commands/graph/init.ts
|
|
10665
|
-
import { existsSync as
|
|
9989
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
|
|
10666
9990
|
import { join as join18 } from "path";
|
|
10667
9991
|
import { execSync as execSync6 } from "child_process";
|
|
10668
9992
|
function graphInit() {
|
|
@@ -10674,9 +9998,9 @@ function graphInit() {
|
|
|
10674
9998
|
}
|
|
10675
9999
|
const m = read(root);
|
|
10676
10000
|
const modelsDir = join18(root, "src", "models");
|
|
10677
|
-
|
|
10001
|
+
mkdirSync5(modelsDir, { recursive: true });
|
|
10678
10002
|
const indexPath = join18(modelsDir, "index.ts");
|
|
10679
|
-
if (!
|
|
10003
|
+
if (!existsSync14(indexPath)) {
|
|
10680
10004
|
writeFileSync7(indexPath, `// Data models for ${m.name}
|
|
10681
10005
|
// Generated by construct graph init
|
|
10682
10006
|
|
|
@@ -10685,7 +10009,7 @@ function graphInit() {
|
|
|
10685
10009
|
`);
|
|
10686
10010
|
}
|
|
10687
10011
|
const pkgPath = join18(root, "package.json");
|
|
10688
|
-
const pkg = JSON.parse(
|
|
10012
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
10689
10013
|
if (!pkg.dependencies)
|
|
10690
10014
|
pkg.dependencies = {};
|
|
10691
10015
|
if (!pkg.dependencies["@construct-space/graph"]) {
|
|
@@ -10715,7 +10039,7 @@ function graphInit() {
|
|
|
10715
10039
|
}
|
|
10716
10040
|
|
|
10717
10041
|
// src/commands/graph/generate.ts
|
|
10718
|
-
import { existsSync as
|
|
10042
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6 } from "fs";
|
|
10719
10043
|
import { join as join19 } from "path";
|
|
10720
10044
|
var FIELD_TYPES = {
|
|
10721
10045
|
string: "field.string()",
|
|
@@ -10869,9 +10193,9 @@ function generate2(modelName, fieldSpecs, options) {
|
|
|
10869
10193
|
const content = lines.join(`
|
|
10870
10194
|
`);
|
|
10871
10195
|
const modelsDir = join19(root, "src", "models");
|
|
10872
|
-
|
|
10196
|
+
mkdirSync6(modelsDir, { recursive: true });
|
|
10873
10197
|
const filePath = join19(modelsDir, `${name}.ts`);
|
|
10874
|
-
if (
|
|
10198
|
+
if (existsSync15(filePath)) {
|
|
10875
10199
|
console.log(source_default.yellow(` Model file already exists: src/models/${name}.ts`));
|
|
10876
10200
|
console.log(source_default.dim(" Overwriting..."));
|
|
10877
10201
|
}
|
|
@@ -10890,8 +10214,8 @@ function generate2(modelName, fieldSpecs, options) {
|
|
|
10890
10214
|
function updateBarrel(modelsDir, modelName) {
|
|
10891
10215
|
const indexPath = join19(modelsDir, "index.ts");
|
|
10892
10216
|
const exportLine = `export { ${modelName} } from './${modelName}'`;
|
|
10893
|
-
if (
|
|
10894
|
-
const content =
|
|
10217
|
+
if (existsSync15(indexPath)) {
|
|
10218
|
+
const content = readFileSync11(indexPath, "utf-8");
|
|
10895
10219
|
if (content.includes(exportLine))
|
|
10896
10220
|
return;
|
|
10897
10221
|
writeFileSync8(indexPath, content.trimEnd() + `
|
|
@@ -10905,7 +10229,7 @@ function updateBarrel(modelsDir, modelName) {
|
|
|
10905
10229
|
}
|
|
10906
10230
|
|
|
10907
10231
|
// src/commands/graph/push.ts
|
|
10908
|
-
import { existsSync as
|
|
10232
|
+
import { existsSync as existsSync16, readdirSync as readdirSync5, readFileSync as readFileSync12 } from "fs";
|
|
10909
10233
|
import { join as join20, basename as basename7 } from "path";
|
|
10910
10234
|
async function graphPush() {
|
|
10911
10235
|
const root = process.cwd();
|
|
@@ -10915,11 +10239,11 @@ async function graphPush() {
|
|
|
10915
10239
|
}
|
|
10916
10240
|
const m = read(root);
|
|
10917
10241
|
const modelsDir = join20(root, "src", "models");
|
|
10918
|
-
if (!
|
|
10242
|
+
if (!existsSync16(modelsDir)) {
|
|
10919
10243
|
console.error(source_default.red("No src/models/ directory found. Run 'construct graph init' first."));
|
|
10920
10244
|
process.exit(1);
|
|
10921
10245
|
}
|
|
10922
|
-
const modelFiles =
|
|
10246
|
+
const modelFiles = readdirSync5(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
|
|
10923
10247
|
if (modelFiles.length === 0) {
|
|
10924
10248
|
console.error(source_default.red("No model files found in src/models/"));
|
|
10925
10249
|
console.log(source_default.dim(" Generate one: construct graph g User name:string email:string"));
|
|
@@ -10928,7 +10252,7 @@ async function graphPush() {
|
|
|
10928
10252
|
console.log(source_default.blue(`Pushing ${modelFiles.length} model(s) for space: ${m.id}`));
|
|
10929
10253
|
const models = [];
|
|
10930
10254
|
for (const file of modelFiles) {
|
|
10931
|
-
const content =
|
|
10255
|
+
const content = readFileSync12(join20(modelsDir, file), "utf-8");
|
|
10932
10256
|
const model = parseModelFile(content, basename7(file, ".ts"));
|
|
10933
10257
|
if (model)
|
|
10934
10258
|
models.push(model);
|
|
@@ -10944,15 +10268,17 @@ async function graphPush() {
|
|
|
10944
10268
|
console.error(source_default.red(err.message));
|
|
10945
10269
|
process.exit(1);
|
|
10946
10270
|
}
|
|
10947
|
-
const graphURL = process.env.GRAPH_URL || "https://
|
|
10271
|
+
const graphURL = process.env.GRAPH_URL || "https://my.construct.space/api/graph";
|
|
10948
10272
|
const spinner = ora("Registering models...").start();
|
|
10949
10273
|
try {
|
|
10274
|
+
const userID = creds.user?.id || "";
|
|
10950
10275
|
const resp = await fetch(`${graphURL}/api/schemas/register`, {
|
|
10951
10276
|
method: "POST",
|
|
10952
10277
|
headers: {
|
|
10953
10278
|
"Content-Type": "application/json",
|
|
10954
10279
|
Authorization: `Bearer ${creds.token}`,
|
|
10955
|
-
"X-Space-ID": m.id
|
|
10280
|
+
"X-Space-ID": m.id,
|
|
10281
|
+
"X-Auth-User-ID": userID
|
|
10956
10282
|
},
|
|
10957
10283
|
body: JSON.stringify({
|
|
10958
10284
|
space_id: m.id,
|
|
@@ -10962,6 +10288,20 @@ async function graphPush() {
|
|
|
10962
10288
|
manifest: { version: 1, models }
|
|
10963
10289
|
})
|
|
10964
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
|
+
}
|
|
10965
10305
|
if (!resp.ok) {
|
|
10966
10306
|
const body = await resp.text();
|
|
10967
10307
|
spinner.fail("Registration failed");
|
|
@@ -11044,7 +10384,7 @@ function parseModelFile(content, fileName) {
|
|
|
11044
10384
|
}
|
|
11045
10385
|
|
|
11046
10386
|
// src/commands/graph/migrate.ts
|
|
11047
|
-
import { existsSync as
|
|
10387
|
+
import { existsSync as existsSync17, readdirSync as readdirSync6, readFileSync as readFileSync13 } from "fs";
|
|
11048
10388
|
import { join as join21, basename as basename8 } from "path";
|
|
11049
10389
|
async function graphMigrate(options) {
|
|
11050
10390
|
const root = process.cwd();
|
|
@@ -11054,7 +10394,7 @@ async function graphMigrate(options) {
|
|
|
11054
10394
|
}
|
|
11055
10395
|
const m = read(root);
|
|
11056
10396
|
const modelsDir = join21(root, "src", "models");
|
|
11057
|
-
if (!
|
|
10397
|
+
if (!existsSync17(modelsDir)) {
|
|
11058
10398
|
console.error(source_default.red("No src/models/ directory. Run 'construct graph init' first."));
|
|
11059
10399
|
process.exit(1);
|
|
11060
10400
|
}
|
|
@@ -11065,7 +10405,7 @@ async function graphMigrate(options) {
|
|
|
11065
10405
|
console.error(source_default.red(err.message));
|
|
11066
10406
|
process.exit(1);
|
|
11067
10407
|
}
|
|
11068
|
-
const graphURL = process.env.GRAPH_URL || "https://
|
|
10408
|
+
const graphURL = process.env.GRAPH_URL || "https://my.construct.space/api/graph";
|
|
11069
10409
|
const spinner = ora("Fetching current schema...").start();
|
|
11070
10410
|
let serverModels = [];
|
|
11071
10411
|
try {
|
|
@@ -11081,10 +10421,10 @@ async function graphMigrate(options) {
|
|
|
11081
10421
|
spinner.fail("Could not fetch schema");
|
|
11082
10422
|
process.exit(1);
|
|
11083
10423
|
}
|
|
11084
|
-
const modelFiles =
|
|
10424
|
+
const modelFiles = readdirSync6(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
|
|
11085
10425
|
const localModels = [];
|
|
11086
10426
|
for (const file of modelFiles) {
|
|
11087
|
-
const content =
|
|
10427
|
+
const content = readFileSync13(join21(modelsDir, file), "utf-8");
|
|
11088
10428
|
const model = parseModelFields(content, basename8(file, ".ts"));
|
|
11089
10429
|
if (model)
|
|
11090
10430
|
localModels.push(model);
|
|
@@ -11188,7 +10528,7 @@ function parseModelFields(content, fileName) {
|
|
|
11188
10528
|
}
|
|
11189
10529
|
|
|
11190
10530
|
// src/index.ts
|
|
11191
|
-
var VERSION = "1.
|
|
10531
|
+
var VERSION = "1.2.0";
|
|
11192
10532
|
var program2 = new Command;
|
|
11193
10533
|
program2.name("construct").description("Construct CLI \u2014 scaffold, build, develop, and publish spaces").version(VERSION);
|
|
11194
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));
|
|
@@ -11201,7 +10541,6 @@ program2.command("check").description("Run type-check (vue-tsc) and linter (esli
|
|
|
11201
10541
|
program2.command("clean").description("Remove build artifacts").option("--all", "Also remove node_modules and lockfiles").action((opts) => clean(opts));
|
|
11202
10542
|
program2.command("login").description("Authenticate with Construct").option("--portal <url>", "Portal URL").action(async (opts) => login(opts));
|
|
11203
10543
|
program2.command("logout").description("Sign out").action(() => logout());
|
|
11204
|
-
program2.command("whoami").alias("status").description("Show the active profile, its source (app or CLI), and linked publishers").action(() => whoami());
|
|
11205
10544
|
program2.command("update").description("Update the CLI to the latest version").action(() => update());
|
|
11206
10545
|
var graph = program2.command("graph").description("Construct Graph \u2014 data models and GraphQL");
|
|
11207
10546
|
graph.command("init").description("Initialize Graph in a space project").action(() => graphInit());
|