@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 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: __accessProp.bind(mod, key),
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: __exportSetter.bind(all, name)
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 setState2(newValue) {
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 readdirSync2, renameSync, statSync as statSync2 } from "fs";
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 (!["company", "project", "both"].includes(m.scope))
7982
- errors2.push('scope: must be "company", "project", or "both"');
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 resolvePages(m, prefix) {
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
- let component = p.component;
8019
- if (!component) {
8020
- component = p.path === "" ? "pages/index.vue" : `pages/${p.path}.vue`;
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
- let varName = "IndexPage";
8023
- if (p.path) {
8024
- let cleanPath = p.path.replace(/:/g, "");
8025
- if (p.component) {
8026
- let base = basename(p.component);
8027
- base = base.replace(extname(base), "").replace(/[\[\]]/g, "");
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 = capitalize(cleanPath) + "Page";
7469
+ return { varName, importPath: prefix + legacyComponent, path: p.path };
8031
7470
  }
8032
- return { varName, importPath: prefix + component, path: p.path };
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 readdirSync(dir)) {
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 readdirSync(dir)) {
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) && statSync2(agentDir).isDirectory()) {
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 = readdirSync2(distDir).filter((f) => f.startsWith("space-") && f.endsWith(".iife.js"));
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 existsSync8, readFileSync as readFileSync6, cpSync, mkdirSync as mkdirSync3 } from "fs";
8264
- import { join as join10 } from "path";
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/esm/index.js
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 * as sysPath2 from "path";
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/esm/index.js
8274
- import { stat, lstat, readdir, realpath } from "fs/promises";
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 ?? defaultOptions.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/esm/handler.js
8494
- import { watchFile, unwatchFile, watch as fs_watch } from "fs";
8495
- import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
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(sysPath.extname(filePath).slice(1).toLowerCase());
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(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
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 = sysPath.dirname(path);
8949
- const basename4 = sysPath.basename(path);
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 = sysPath.resolve(path);
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 = sysPath.dirname(file);
8980
- const basename4 = sysPath.basename(file);
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 = sysPath.join(directory, "");
9064
- throttler = this.fsw._throttle("readdir", directory, 1000);
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 = sysPath.join(directory, item);
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 = sysPath.join(dir, sysPath.relative(dir, 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(sysPath.dirname(dir));
9119
- const tracked = parentDir.has(sysPath.basename(dir));
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(sysPath.basename(dir));
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 = sysPath.resolve(path);
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 = sysPath.dirname(wh.watchPath);
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(sysPath.resolve(path), targetPath);
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/esm/index.js
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 relative3 = sysPath2.relative(matcher.path, string);
9231
- if (!relative3) {
8686
+ const relative4 = sp2.relative(matcher.path, string);
8687
+ if (!relative4) {
9232
8688
  return false;
9233
8689
  }
9234
- return !relative3.startsWith("..") && !sysPath2.isAbsolute(relative3);
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 = sysPath2.normalize(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
- const DOUBLE_SLASH_RE2 = /\/\//;
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
- while (str.match(DOUBLE_SLASH_RE)) {
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(sysPath2.normalize(toUnix(path)));
8752
+ var normalizePathToUnix = (path) => toUnix(sp2.normalize(toUnix(path)));
9301
8753
  var normalizeIgnored = (cwd = "") => (path) => {
9302
8754
  if (typeof path === "string") {
9303
- return normalizePathToUnix(sysPath2.isAbsolute(path) ? path : sysPath2.join(cwd, path));
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 (sysPath2.isAbsolute(path)) {
8761
+ if (sp2.isAbsolute(path)) {
9310
8762
  return path;
9311
8763
  }
9312
- return sysPath2.join(cwd, path);
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(sysPath2.dirname(dir), sysPath2.basename(dir));
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 = sysPath2.resolve(watchPath);
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 sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
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(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
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 (!sysPath2.isAbsolute(path) && !this._closers.has(path)) {
8998
+ if (!sp2.isAbsolute(path) && !this._closers.has(path)) {
9519
8999
  if (cwd)
9520
- path = sysPath2.join(cwd, path);
9521
- path = sysPath2.resolve(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 ? sysPath2.relative(this.options.cwd, dir) : dir;
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 = sysPath2.normalize(path);
9061
+ path = sp2.normalize(path);
9582
9062
  if (opts.cwd)
9583
- path = sysPath2.relative(opts.cwd, 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 ? sysPath2.join(opts.cwd, path) : path;
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 && !sysPath2.isAbsolute(path)) {
9691
- fullPath = sysPath2.join(this.options.cwd, path);
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 = sysPath2.resolve(directory);
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 = sysPath2.join(directory, item);
9760
- const fullPath = sysPath2.resolve(path);
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 = sysPath2.relative(this.options.cwd, path);
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 = sysPath2.dirname(path);
9794
- this._getWatchedDir(dir).remove(sysPath2.basename(path));
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
- join10(root, MANIFEST_FILE),
9885
- join10(root, "src", "actions.ts")
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 = join10(root, "dist");
9925
- const bundleFile = join10(distDir, `space-${m.id}.iife.js`);
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 (!existsSync8(bundleFile))
9365
+ if (!existsSync7(bundleFile))
9930
9366
  return;
9931
- const bundleData = readFileSync6(bundleFile);
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
- try {
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 existsSync9, cpSync as cpSync2, mkdirSync as mkdirSync4 } from "fs";
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 (!existsSync9(distDir)) {
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 (existsSync9(agentDir)) {
9432
+ if (existsSync8(agentDir)) {
9975
9433
  bundleAgentDir(agentDir, distDir);
9976
9434
  }
9977
9435
  const installDir = spaceDir(m.id);
9978
- mkdirSync4(installDir, { recursive: true });
9979
- cpSync2(distDir, installDir, { recursive: true });
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 readFileSync8, writeFileSync as writeFileSync6, statSync as statSync4, unlinkSync as unlinkSync2 } from "fs";
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 readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, unlinkSync, existsSync as existsSync10 } from "fs";
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
- mkdirSync5(dirname4(path), { recursive: true });
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 (!existsSync10(path)) {
10042
- throw new Error("not logged in \u2014 run 'construct login' first (or sign in to the Construct app)");
9462
+ if (!existsSync9(path)) {
9463
+ throw new Error("not logged in \u2014 run 'construct login' first");
10043
9464
  }
10044
- const data = JSON.parse(readFileSync7(path, "utf-8"));
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 (existsSync10(path))
9481
+ if (existsSync9(path))
10061
9482
  unlinkSync(path);
10062
9483
  }
10063
9484
 
10064
9485
  // src/lib/pack.ts
10065
- import { readdirSync as readdirSync3, statSync as statSync3, existsSync as existsSync11 } from "fs";
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 (existsSync11(join13(root, name)))
9525
+ if (existsSync10(join13(root, name)))
10105
9526
  entries.push(name);
10106
9527
  }
10107
- for (const entry of readdirSync3(root)) {
10108
- if (statSync3(join13(root, entry)).isDirectory())
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 (existsSync11(join13(root, dir)))
9539
+ if (existsSync10(join13(root, dir)))
10119
9540
  entries.push(dir);
10120
9541
  }
10121
- const validEntries = entries.filter((e) => existsSync11(join13(root, 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 = statSync3(tarballPath).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 = readFileSync8(tarballPath);
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 = readFileSync8(path, "utf-8");
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 = statSync4(tarballPath).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 existsSync12, readFileSync as readFileSync9 } from "fs";
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 (!existsSync12(fullPath)) {
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 (!existsSync12(agentPath)) {
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 (existsSync12(pkgPath)) {
10359
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
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 existsSync13, readFileSync as readFileSync10 } from "fs";
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 (!existsSync13(join16(root, "src", component))) {
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 && !existsSync13(join16(root, 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 (existsSync13(pkgPath)) {
10405
- const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
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 existsSync14 } from "fs";
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 (existsSync14(path)) {
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 (existsSync14(path)) {
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, publishers } = await resp.json();
10540
- store({ token, portal: portalURL, user, publishers });
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
- if (wasCli) {
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 existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync6 } from "fs";
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
- mkdirSync6(modelsDir, { recursive: true });
10001
+ mkdirSync5(modelsDir, { recursive: true });
10678
10002
  const indexPath = join18(modelsDir, "index.ts");
10679
- if (!existsSync15(indexPath)) {
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(readFileSync11(pkgPath, "utf-8"));
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 existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "fs";
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
- mkdirSync7(modelsDir, { recursive: true });
10196
+ mkdirSync6(modelsDir, { recursive: true });
10873
10197
  const filePath = join19(modelsDir, `${name}.ts`);
10874
- if (existsSync16(filePath)) {
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 (existsSync16(indexPath)) {
10894
- const content = readFileSync12(indexPath, "utf-8");
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 existsSync17, readdirSync as readdirSync4, readFileSync as readFileSync13 } from "fs";
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 (!existsSync17(modelsDir)) {
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 = readdirSync4(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
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 = readFileSync13(join20(modelsDir, file), "utf-8");
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://graph.construct.space";
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 existsSync18, readdirSync as readdirSync5, readFileSync as readFileSync14 } from "fs";
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 (!existsSync18(modelsDir)) {
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://graph.construct.space";
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 = readdirSync5(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
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 = readFileSync14(join21(modelsDir, file), "utf-8");
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.1.12";
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());