sim-setup 1.0.2 → 1.0.3-preview.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -6
- package/dist/index.js +463 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,17 +1,288 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Sim Setup
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`sim-setup` is the installer and management tool for a self-hosted
|
|
4
|
+
[Sim](https://sim.ai) deployment. Sim is a workspace for building, deploying,
|
|
5
|
+
and managing AI agents and workflows.
|
|
6
|
+
|
|
7
|
+
For an npm user, `sim-setup` creates a Docker Compose installation from published
|
|
8
|
+
Sim images. It generates the required secrets, writes the deployment files,
|
|
9
|
+
starts the containers, runs database migrations, and checks that the application
|
|
10
|
+
is healthy. It does not clone the Sim repository.
|
|
11
|
+
|
|
12
|
+
This package installs the Sim server. To manage workflows, tables, files, and
|
|
13
|
+
other resources in a running Sim workspace, use the separate
|
|
14
|
+
[`sim` CLI](https://www.npmjs.com/package/sim).
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- Node.js 20 or newer
|
|
19
|
+
- Docker with the Compose plugin
|
|
20
|
+
- Ports `3000`, `3002`, and, by default, `5432` available
|
|
21
|
+
- At least 12 GB of system memory and 20 GB of free disk for a small installation
|
|
22
|
+
|
|
23
|
+
Allocate at least 8 GB of memory to Docker for reliable workflow execution.
|
|
24
|
+
Docker Desktop, OrbStack, Colima, and Docker Engine are supported as long as the
|
|
25
|
+
`docker` command can reach the daemon.
|
|
26
|
+
|
|
27
|
+
## Install and run
|
|
28
|
+
|
|
29
|
+
You normally do not need to install the package globally:
|
|
4
30
|
|
|
5
31
|
```bash
|
|
6
32
|
npx sim-setup
|
|
7
33
|
```
|
|
8
34
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
35
|
+
To install it globally instead:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm install --global sim-setup
|
|
39
|
+
sim-setup
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The examples below use `npx`; omit it if you installed the package globally.
|
|
43
|
+
|
|
44
|
+
The default standalone setup creates a `sim` directory under the current
|
|
45
|
+
directory:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
sim/
|
|
49
|
+
├── .env
|
|
50
|
+
├── .sim-setup.json
|
|
51
|
+
└── docker-compose.prod.yml
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Use `--dir` to choose an explicit location:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx sim-setup --dir /srv/sim
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
When setup finishes, open [http://localhost:3000](http://localhost:3000) and
|
|
61
|
+
create the first account.
|
|
62
|
+
|
|
63
|
+
## What the setup wizard does
|
|
64
|
+
|
|
65
|
+
The wizard:
|
|
66
|
+
|
|
67
|
+
1. checks Docker, available ports, memory, and disk space
|
|
68
|
+
2. creates or reuses the installation directory
|
|
69
|
+
3. generates authentication, encryption, internal API, and scheduler secrets
|
|
70
|
+
4. optionally connects Sim Chat and model providers
|
|
71
|
+
5. writes `.env` and the managed production Compose file
|
|
72
|
+
6. starts PostgreSQL, Redis, the Sim application, realtime, and scheduled jobs
|
|
73
|
+
7. runs migrations and waits for the health checks to pass
|
|
74
|
+
|
|
75
|
+
Choose **Quick** for sensible defaults and the fewest questions. Choose
|
|
76
|
+
**Custom** to configure additional options such as object storage, email,
|
|
77
|
+
sign-in providers, security settings, and self-hosted feature flags. Skip the
|
|
78
|
+
prompt with:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx sim-setup --quick
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The wizard detects an existing installation. Re-running it lets you keep and
|
|
85
|
+
check the current configuration, review and update it, or archive the current
|
|
86
|
+
`.env` and build a new configuration. If setup fails partway through, fix the
|
|
87
|
+
reported problem and run the same command again; completed configuration is
|
|
88
|
+
preserved.
|
|
89
|
+
|
|
90
|
+
## Chat and model access
|
|
91
|
+
|
|
92
|
+
Sim can run without the optional Chat API key. If you skip Chat setup, the
|
|
93
|
+
wizard hides the Chat module instead of leaving it enabled but unusable. Connect
|
|
94
|
+
or replace the key later with:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx sim-setup add chat
|
|
98
|
+
npx sim-setup start
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Agent blocks also need access to a model provider. Configure provider keys in a
|
|
102
|
+
workspace in the Sim UI, pass supported keys such as `OPENAI_API_KEY` or
|
|
103
|
+
`ANTHROPIC_API_KEY` into the setup environment, or add deployment-wide model
|
|
104
|
+
configuration later:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx sim-setup add llm
|
|
108
|
+
npx sim-setup start
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For Docker Compose installations, `add` updates `.env` but does not recreate the
|
|
112
|
+
application container. Run `npx sim-setup start` afterward to apply the changed
|
|
113
|
+
environment. `restart` only restarts containers with their current configuration.
|
|
114
|
+
|
|
115
|
+
## Manage the installation
|
|
116
|
+
|
|
117
|
+
Run commands from the installation directory or pass `--dir <path>` to target a
|
|
118
|
+
specific installation.
|
|
119
|
+
|
|
120
|
+
| Command | What it does |
|
|
121
|
+
| --- | --- |
|
|
122
|
+
| `npx sim-setup status` | Show detected installations, container state, and app health |
|
|
123
|
+
| `npx sim-setup logs` | Follow the last 100 lines of Docker Compose logs |
|
|
124
|
+
| `npx sim-setup start` | Start or reconcile the containers; data is kept |
|
|
125
|
+
| `npx sim-setup stop` | Stop containers without removing them |
|
|
126
|
+
| `npx sim-setup restart` | Restart the current containers |
|
|
127
|
+
| `npx sim-setup update` | Refresh the managed Compose file, pull images, recreate services, and run migrations |
|
|
128
|
+
| `npx sim-setup down` | Remove containers but keep data volumes |
|
|
129
|
+
| `npx sim-setup reset` | Archive `.env`, remove containers, and delete managed data volumes |
|
|
130
|
+
|
|
131
|
+
`down` and `reset` are deliberately different. Use `down` when you want to
|
|
132
|
+
remove containers and bring the same installation back later. `reset` is a
|
|
133
|
+
destructive fresh start and asks for confirmation before deleting data.
|
|
134
|
+
|
|
135
|
+
### Check configuration
|
|
136
|
+
|
|
137
|
+
`config` reports which effective configuration sources, capabilities, and OAuth
|
|
138
|
+
integrations were detected. It does not print secret values:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npx sim-setup config
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`doctor` validates environment files, required values, cross-service
|
|
145
|
+
consistency, and live dependencies:
|
|
12
146
|
|
|
13
|
-
|
|
147
|
+
```bash
|
|
148
|
+
npx sim-setup doctor
|
|
149
|
+
npx sim-setup doctor --fix
|
|
150
|
+
npx sim-setup doctor --json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Use `config` to answer “what is configured?” and `status` to answer “what is
|
|
154
|
+
running and healthy?”
|
|
155
|
+
|
|
156
|
+
### Install the desktop app
|
|
157
|
+
|
|
158
|
+
`desktop` resolves the macOS installer from your own deployment and prints the
|
|
159
|
+
server URL to enter in the app:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npx sim-setup desktop
|
|
163
|
+
npx sim-setup desktop --url https://sim.example.com
|
|
164
|
+
npx sim-setup desktop --no-open
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The desktop app is not tied to sim.ai — it bakes in only a default server, and
|
|
168
|
+
every Sim deployment already serves `/api/desktop/update/download` and the
|
|
169
|
+
update feed installed apps poll. Install the signed build, then point it at your
|
|
170
|
+
deployment with **Sim → Server…**. Nothing has to be built or signed by you.
|
|
171
|
+
|
|
172
|
+
### Add or change capabilities
|
|
173
|
+
|
|
174
|
+
Configure one capability without walking through the complete wizard:
|
|
14
175
|
|
|
15
176
|
```bash
|
|
177
|
+
npx sim-setup add email
|
|
178
|
+
npx sim-setup add storage
|
|
179
|
+
npx sim-setup add sandbox
|
|
180
|
+
npx sim-setup add jobs
|
|
181
|
+
npx sim-setup add cache
|
|
182
|
+
npx sim-setup add knowledge
|
|
183
|
+
npx sim-setup add knowledge-embeddings
|
|
16
184
|
npx sim-setup add chat
|
|
185
|
+
npx sim-setup add llm
|
|
186
|
+
npx sim-setup add integration slack
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Run `npx sim-setup start` after changing a Docker Compose capability so the app
|
|
190
|
+
container receives the new environment.
|
|
191
|
+
|
|
192
|
+
## Updating
|
|
193
|
+
|
|
194
|
+
Update a Docker Compose installation with:
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx sim-setup update
|
|
198
|
+
npx sim-setup status
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The update command keeps Docker volumes, applies the current managed Compose
|
|
202
|
+
file, pulls the version selected by `SIM_VERSION`, and runs migrations. If
|
|
203
|
+
`SIM_VERSION` is unset, the deployment tracks `latest`.
|
|
204
|
+
|
|
205
|
+
For production, pin an explicit version, back up the database first, and read
|
|
206
|
+
the [upgrade guide](https://docs.sim.ai/platform/self-hosting/upgrades). Docker
|
|
207
|
+
Compose updates briefly interrupt the application because Compose does not
|
|
208
|
+
provide rolling deployments.
|
|
209
|
+
|
|
210
|
+
## Files, secrets, and data
|
|
211
|
+
|
|
212
|
+
The generated `.env` contains credentials and encryption keys. It is written
|
|
213
|
+
with owner-only permissions and must not be committed to source control.
|
|
214
|
+
|
|
215
|
+
Back up `.env` securely outside the server before using the deployment for real
|
|
216
|
+
data. In particular, `ENCRYPTION_KEY` and `API_ENCRYPTION_KEY` protect stored
|
|
217
|
+
credentials and API keys. A database backup restored without the matching keys
|
|
218
|
+
contains data that Sim cannot decrypt.
|
|
219
|
+
|
|
220
|
+
PostgreSQL data lives in a Docker volume. These commands preserve it:
|
|
221
|
+
|
|
222
|
+
- `start`
|
|
223
|
+
- `stop`
|
|
224
|
+
- `restart`
|
|
225
|
+
- `update`
|
|
226
|
+
- `down`
|
|
227
|
+
|
|
228
|
+
`reset` deletes managed volumes. It archives `.env` beside the installation
|
|
229
|
+
before doing so, but that local archive is not a substitute for an off-machine
|
|
230
|
+
backup.
|
|
231
|
+
|
|
232
|
+
The default local file-storage fallback is different: uploaded files live inside
|
|
233
|
+
the application container, not in a managed volume. They can be lost when the
|
|
234
|
+
container is removed or recreated, including during `down` or `update`.
|
|
235
|
+
Configure object storage before keeping files you care about.
|
|
236
|
+
|
|
237
|
+
## Production deployments
|
|
238
|
+
|
|
239
|
+
The generated Compose installation is suitable for local evaluation and a
|
|
240
|
+
single-node deployment. Before exposing it publicly, configure at least:
|
|
241
|
+
|
|
242
|
+
- a public application URL and TLS reverse proxy
|
|
243
|
+
- database and `.env` backups
|
|
244
|
+
- durable object storage for uploaded files
|
|
245
|
+
- email delivery for invitations and email-based authentication
|
|
246
|
+
- OAuth applications for integrations you plan to use
|
|
247
|
+
- a pinned Sim version and an upgrade procedure
|
|
248
|
+
|
|
249
|
+
See the [Docker deployment guide](https://docs.sim.ai/platform/self-hosting/docker)
|
|
250
|
+
and the complete [self-hosting documentation](https://docs.sim.ai/platform/self-hosting).
|
|
251
|
+
|
|
252
|
+
## Working from the Sim source repository
|
|
253
|
+
|
|
254
|
+
Inside a cloned Sim repository, use:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
bun run sim-setup
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The source checkout adds local development and Kubernetes modes:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
bun run sim-setup --mode dev
|
|
264
|
+
bun run sim-setup --mode k8s
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Standalone npm use supports Docker Compose mode only. Development and Kubernetes
|
|
268
|
+
modes need source-only files and are rejected outside a complete checkout.
|
|
269
|
+
|
|
270
|
+
## Help
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
npx sim-setup --help
|
|
274
|
+
npx sim-setup --version
|
|
17
275
|
```
|
|
276
|
+
|
|
277
|
+
Further documentation:
|
|
278
|
+
|
|
279
|
+
- [Self-hosting overview](https://docs.sim.ai/platform/self-hosting)
|
|
280
|
+
- [Docker Compose](https://docs.sim.ai/platform/self-hosting/docker)
|
|
281
|
+
- [Environment variables](https://docs.sim.ai/platform/self-hosting/environment-variables)
|
|
282
|
+
- [Upgrades](https://docs.sim.ai/platform/self-hosting/upgrades)
|
|
283
|
+
- [Troubleshooting](https://docs.sim.ai/platform/self-hosting/troubleshooting)
|
|
284
|
+
- [Verification checklist](https://docs.sim.ai/platform/self-hosting/verify)
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
Apache-2.0
|
package/dist/index.js
CHANGED
|
@@ -1561,7 +1561,8 @@ var init_env_capabilities = __esm(() => {
|
|
|
1561
1561
|
"microsoft-dataverse",
|
|
1562
1562
|
"microsoft-excel",
|
|
1563
1563
|
"microsoft-teams",
|
|
1564
|
-
"microsoft-planner"
|
|
1564
|
+
"microsoft-planner",
|
|
1565
|
+
"microsoft-word"
|
|
1565
1566
|
]);
|
|
1566
1567
|
});
|
|
1567
1568
|
|
|
@@ -1569,7 +1570,7 @@ var init_env_capabilities = __esm(() => {
|
|
|
1569
1570
|
var integrations_default;
|
|
1570
1571
|
var init_integrations = __esm(() => {
|
|
1571
1572
|
integrations_default = {
|
|
1572
|
-
updatedAt: "2026-08-
|
|
1573
|
+
updatedAt: "2026-08-26",
|
|
1573
1574
|
integrations: [
|
|
1574
1575
|
{
|
|
1575
1576
|
type: "onepassword",
|
|
@@ -8988,11 +8989,11 @@ var init_integrations = __esm(() => {
|
|
|
8988
8989
|
operations: [
|
|
8989
8990
|
{
|
|
8990
8991
|
name: "Find Email",
|
|
8991
|
-
description: "Find a verified B2B email address from a full name and company domain or name. Uses the Enrow async finder — submits a search and polls until the result is ready. Costs 1 credit per valid email found. (https://enrow.
|
|
8992
|
+
description: "Find a verified B2B email address from a full name and company domain or name. Uses the Enrow async finder — submits a search and polls until the result is ready. Costs 1 credit per valid email found. (https://docs.enrow.io/api-reference/email-finder/find-single)"
|
|
8992
8993
|
},
|
|
8993
8994
|
{
|
|
8994
8995
|
name: "Verify Email",
|
|
8995
|
-
description: "Verify the deliverability of an email address using the Enrow async verifier. Submits a verification request and polls until the result is ready. Costs 0.25 credits per verification. (https://enrow.
|
|
8996
|
+
description: "Verify the deliverability of an email address using the Enrow async verifier. Submits a verification request and polls until the result is ready. Costs 0.25 credits per verification. (https://docs.enrow.io/api-reference/email-verifier/verify-single)"
|
|
8996
8997
|
}
|
|
8997
8998
|
],
|
|
8998
8999
|
operationCount: 2,
|
|
@@ -16126,6 +16127,58 @@ var init_integrations = __esm(() => {
|
|
|
16126
16127
|
integrationType: "communication",
|
|
16127
16128
|
tags: ["messaging", "microsoft-365"]
|
|
16128
16129
|
},
|
|
16130
|
+
{
|
|
16131
|
+
type: "microsoft_word",
|
|
16132
|
+
slug: "microsoft-word",
|
|
16133
|
+
name: "Microsoft Word",
|
|
16134
|
+
description: "Create, fill, read, edit, and export Word documents",
|
|
16135
|
+
longDescription: "Integrate Microsoft Word into the workflow. Create .docx documents from text, fill a formatted template by substituting its placeholders, read a document back as text, replace or append content, find and replace text across the body plus headers and footers, list and search documents in OneDrive or SharePoint, and export a document as PDF.",
|
|
16136
|
+
bgColor: "#FFFFFF",
|
|
16137
|
+
iconName: "MicrosoftWordIcon",
|
|
16138
|
+
docsUrl: "https://docs.sim.ai/integrations/microsoft_word",
|
|
16139
|
+
operations: [
|
|
16140
|
+
{
|
|
16141
|
+
name: "Read Document",
|
|
16142
|
+
description: "Read the text content of a Microsoft Word (.docx) document stored in OneDrive or SharePoint."
|
|
16143
|
+
},
|
|
16144
|
+
{
|
|
16145
|
+
name: "Create Document",
|
|
16146
|
+
description: "Create a new Microsoft Word (.docx) document in OneDrive or SharePoint from text content. Supports Markdown headings (# ## ###), bullets (-), and inline **bold** / *italic*. An existing document with the same name is never overwritten — the new one is given a unique name instead."
|
|
16147
|
+
},
|
|
16148
|
+
{
|
|
16149
|
+
name: "Create from Template",
|
|
16150
|
+
description: "Copy an existing Microsoft Word (.docx) template to a new document and fill its placeholders. The template keeps all of its formatting, styles, headers, and footers, and is never modified. An existing document with the same name is never overwritten — the new one is given a unique name instead."
|
|
16151
|
+
},
|
|
16152
|
+
{
|
|
16153
|
+
name: "Replace Content",
|
|
16154
|
+
description: "Replace the entire contents of an existing Microsoft Word (.docx) document with new text. The previous content and its formatting are discarded — use Append to add to a document instead."
|
|
16155
|
+
},
|
|
16156
|
+
{
|
|
16157
|
+
name: "Append Content",
|
|
16158
|
+
description: "Append plain-text paragraphs to the end of an existing Microsoft Word (.docx) document, leaving the existing content and formatting intact. Fails rather than overwriting if someone else changed the document while the edit was in flight."
|
|
16159
|
+
},
|
|
16160
|
+
{
|
|
16161
|
+
name: "Find and Replace Text",
|
|
16162
|
+
description: "Find and replace text throughout a Microsoft Word (.docx) document, including its headers and footers. Use this to fill placeholders in a template document. Fails rather than overwriting if someone else changed the document while the edit was in flight."
|
|
16163
|
+
},
|
|
16164
|
+
{
|
|
16165
|
+
name: "List Documents",
|
|
16166
|
+
description: "List or search Microsoft Word (.docx) documents in OneDrive or SharePoint. Non-Word items are filtered out of the results."
|
|
16167
|
+
},
|
|
16168
|
+
{
|
|
16169
|
+
name: "Export as PDF",
|
|
16170
|
+
description: "Convert a Microsoft Word (.docx) document to PDF using Microsoft Graph and return it as a file."
|
|
16171
|
+
}
|
|
16172
|
+
],
|
|
16173
|
+
operationCount: 8,
|
|
16174
|
+
triggers: [],
|
|
16175
|
+
triggerCount: 0,
|
|
16176
|
+
authType: "oauth",
|
|
16177
|
+
oauthServiceId: "microsoft-word",
|
|
16178
|
+
category: "tools",
|
|
16179
|
+
integrationType: "documents",
|
|
16180
|
+
tags: ["microsoft-365", "document-processing", "cloud"]
|
|
16181
|
+
},
|
|
16129
16182
|
{
|
|
16130
16183
|
type: "millionverifier",
|
|
16131
16184
|
slug: "millionverifier",
|
|
@@ -21246,6 +21299,201 @@ var init_integrations = __esm(() => {
|
|
|
21246
21299
|
integrationType: "hr",
|
|
21247
21300
|
tags: ["automation"]
|
|
21248
21301
|
},
|
|
21302
|
+
{
|
|
21303
|
+
type: "semrush",
|
|
21304
|
+
slug: "semrush",
|
|
21305
|
+
name: "Semrush",
|
|
21306
|
+
description: "Research SEO and paid search data with Semrush",
|
|
21307
|
+
longDescription: "Query the Semrush SEO API for domain, subdomain, and URL traffic overviews, organic and paid keywords, ad and product listing creatives, competitor sets, keyword research, and backlink profiles. Requires a Semrush subscription with API units.",
|
|
21308
|
+
bgColor: "#FFFFFF",
|
|
21309
|
+
iconName: "SemrushIcon",
|
|
21310
|
+
docsUrl: "https://docs.sim.ai/integrations/semrush",
|
|
21311
|
+
operations: [
|
|
21312
|
+
{
|
|
21313
|
+
name: "Domain Overview",
|
|
21314
|
+
description: "Get the Semrush rank plus organic and paid search totals for a domain in one regional database."
|
|
21315
|
+
},
|
|
21316
|
+
{
|
|
21317
|
+
name: "Domain Overview (All Databases)",
|
|
21318
|
+
description: "Get organic and paid search totals for a domain across every regional Semrush database."
|
|
21319
|
+
},
|
|
21320
|
+
{
|
|
21321
|
+
name: "Domain Overview History",
|
|
21322
|
+
description: "Get the historical trend of a domain rank plus its organic and paid search totals."
|
|
21323
|
+
},
|
|
21324
|
+
{
|
|
21325
|
+
name: "Domain Organic Keywords",
|
|
21326
|
+
description: "List the keywords a domain ranks for in Google organic search, with position, volume, and traffic share."
|
|
21327
|
+
},
|
|
21328
|
+
{
|
|
21329
|
+
name: "Domain Paid Keywords",
|
|
21330
|
+
description: "List the keywords a domain buys in Google Ads, with ad position, copy, and traffic share."
|
|
21331
|
+
},
|
|
21332
|
+
{
|
|
21333
|
+
name: "Domain Ad Copies",
|
|
21334
|
+
description: "List the unique Google Ads creatives a domain runs, with title, description, and keyword count."
|
|
21335
|
+
},
|
|
21336
|
+
{
|
|
21337
|
+
name: "Domain Ad History",
|
|
21338
|
+
description: "List a domain past Google Ads placements month by month, with the copy used each time."
|
|
21339
|
+
},
|
|
21340
|
+
{
|
|
21341
|
+
name: "Organic Competitors",
|
|
21342
|
+
description: "List the domains competing with a target domain in Google organic search results."
|
|
21343
|
+
},
|
|
21344
|
+
{
|
|
21345
|
+
name: "Paid Competitors",
|
|
21346
|
+
description: "List the domains competing with a target domain in Google paid search results."
|
|
21347
|
+
},
|
|
21348
|
+
{
|
|
21349
|
+
name: "Domain PLA Keywords",
|
|
21350
|
+
description: "List the keywords that trigger a domain product listing ads, with the promoted product and price."
|
|
21351
|
+
},
|
|
21352
|
+
{
|
|
21353
|
+
name: "Domain PLA Copies",
|
|
21354
|
+
description: "List the unique product listing ads a domain runs, with product title, price, and shop name."
|
|
21355
|
+
},
|
|
21356
|
+
{
|
|
21357
|
+
name: "Domain vs. Domain",
|
|
21358
|
+
description: "Compare up to five domains on the keywords they rank for, returning each domain position side by side."
|
|
21359
|
+
},
|
|
21360
|
+
{
|
|
21361
|
+
name: "Subdomain Overview",
|
|
21362
|
+
description: "Get the organic and paid search totals for a subdomain in one regional database."
|
|
21363
|
+
},
|
|
21364
|
+
{
|
|
21365
|
+
name: "Subdomain Overview (All Databases)",
|
|
21366
|
+
description: "Get organic and paid search totals for a subdomain across every regional Semrush database."
|
|
21367
|
+
},
|
|
21368
|
+
{
|
|
21369
|
+
name: "Subdomain Overview History",
|
|
21370
|
+
description: "Get the historical trend of a subdomain organic and paid search totals."
|
|
21371
|
+
},
|
|
21372
|
+
{
|
|
21373
|
+
name: "Subdomain Organic Keywords",
|
|
21374
|
+
description: "List the keywords a subdomain ranks for in Google organic search."
|
|
21375
|
+
},
|
|
21376
|
+
{
|
|
21377
|
+
name: "Subdomain Paid Keywords",
|
|
21378
|
+
description: "List the keywords a subdomain buys in Google Ads."
|
|
21379
|
+
},
|
|
21380
|
+
{
|
|
21381
|
+
name: "Subdomain Ad Copies",
|
|
21382
|
+
description: "List the unique Google Ads creatives a subdomain runs."
|
|
21383
|
+
},
|
|
21384
|
+
{
|
|
21385
|
+
name: "URL Overview",
|
|
21386
|
+
description: "Get the organic and paid search totals for a single URL in one regional database."
|
|
21387
|
+
},
|
|
21388
|
+
{
|
|
21389
|
+
name: "URL Overview (All Databases)",
|
|
21390
|
+
description: "Get organic and paid search totals for a single URL across every regional Semrush database."
|
|
21391
|
+
},
|
|
21392
|
+
{
|
|
21393
|
+
name: "URL Overview History",
|
|
21394
|
+
description: "Get the historical trend of a URL organic and paid search totals."
|
|
21395
|
+
},
|
|
21396
|
+
{
|
|
21397
|
+
name: "URL Organic Keywords",
|
|
21398
|
+
description: "List the keywords a single URL ranks for in Google organic search."
|
|
21399
|
+
},
|
|
21400
|
+
{
|
|
21401
|
+
name: "URL Paid Keywords",
|
|
21402
|
+
description: "List the keywords a single URL is advertised on in Google Ads, with the ad copy used."
|
|
21403
|
+
},
|
|
21404
|
+
{
|
|
21405
|
+
name: "Keyword Overview",
|
|
21406
|
+
description: "Get search volume, CPC, competition, difficulty, and intent for a single keyword."
|
|
21407
|
+
},
|
|
21408
|
+
{
|
|
21409
|
+
name: "Keyword Overview (All Databases)",
|
|
21410
|
+
description: "Get search volume, CPC, and competition for a keyword across every regional Semrush database."
|
|
21411
|
+
},
|
|
21412
|
+
{
|
|
21413
|
+
name: "Batch Keyword Overview",
|
|
21414
|
+
description: "Get search volume, CPC, competition, difficulty, and intent for up to 100 keywords at once."
|
|
21415
|
+
},
|
|
21416
|
+
{
|
|
21417
|
+
name: "Keyword Difficulty",
|
|
21418
|
+
description: "Get the Keyword Difficulty Index for up to 100 keywords at once."
|
|
21419
|
+
},
|
|
21420
|
+
{
|
|
21421
|
+
name: "Related Keywords",
|
|
21422
|
+
description: "Find keywords semantically related to a seed keyword, with volume, difficulty, and relevance."
|
|
21423
|
+
},
|
|
21424
|
+
{
|
|
21425
|
+
name: "Broad Match Keywords",
|
|
21426
|
+
description: "Find broad-match and phrase-match variations of a seed keyword, with volume and difficulty."
|
|
21427
|
+
},
|
|
21428
|
+
{
|
|
21429
|
+
name: "Keyword Questions",
|
|
21430
|
+
description: "Find question-form keywords containing a seed keyword, with volume and difficulty."
|
|
21431
|
+
},
|
|
21432
|
+
{
|
|
21433
|
+
name: "Organic Results",
|
|
21434
|
+
description: "List the domains and URLs ranking in Google organic search results for a keyword."
|
|
21435
|
+
},
|
|
21436
|
+
{
|
|
21437
|
+
name: "Paid Results",
|
|
21438
|
+
description: "List the domains and URLs advertising on a keyword in Google paid search results."
|
|
21439
|
+
},
|
|
21440
|
+
{
|
|
21441
|
+
name: "Keyword Ad History",
|
|
21442
|
+
description: "List which domains advertised on a keyword month by month, with the copy each one used."
|
|
21443
|
+
},
|
|
21444
|
+
{
|
|
21445
|
+
name: "Winners and Losers",
|
|
21446
|
+
description: "List the domains that gained or lost the most organic and paid search visibility in a database."
|
|
21447
|
+
},
|
|
21448
|
+
{
|
|
21449
|
+
name: "Top Domains",
|
|
21450
|
+
description: "List the highest-ranked domains in a regional database by Semrush rank."
|
|
21451
|
+
},
|
|
21452
|
+
{
|
|
21453
|
+
name: "Backlinks Overview",
|
|
21454
|
+
description: "Get the Authority Score and backlink profile totals for a domain, subdomain, or URL."
|
|
21455
|
+
},
|
|
21456
|
+
{
|
|
21457
|
+
name: "Backlinks",
|
|
21458
|
+
description: "List the backlinks pointing at a domain, subdomain, or URL, with source page, anchor, and authority."
|
|
21459
|
+
},
|
|
21460
|
+
{
|
|
21461
|
+
name: "Referring Domains",
|
|
21462
|
+
description: "List the domains linking to a target, with Authority Score, backlink count, and country."
|
|
21463
|
+
},
|
|
21464
|
+
{
|
|
21465
|
+
name: "Referring IPs",
|
|
21466
|
+
description: "List the IP addresses linking to a target, with the domain and backlink counts behind each one."
|
|
21467
|
+
},
|
|
21468
|
+
{
|
|
21469
|
+
name: "Backlink TLD Distribution",
|
|
21470
|
+
description: "Break a target backlink profile down by the top-level domain of its referring domains."
|
|
21471
|
+
},
|
|
21472
|
+
{
|
|
21473
|
+
name: "Backlink Country Distribution",
|
|
21474
|
+
description: "Break a target backlink profile down by the country of its referring domains."
|
|
21475
|
+
},
|
|
21476
|
+
{
|
|
21477
|
+
name: "Backlink Anchors",
|
|
21478
|
+
description: "List the anchor texts used in backlinks to a target, with domain and backlink counts."
|
|
21479
|
+
},
|
|
21480
|
+
{
|
|
21481
|
+
name: "Indexed Pages",
|
|
21482
|
+
description: "List the pages of a target that attract backlinks, with response code and link counts."
|
|
21483
|
+
},
|
|
21484
|
+
{
|
|
21485
|
+
name: "Backlink Competitors",
|
|
21486
|
+
description: "List domains with a backlink profile similar to the target, ranked by shared referring domains."
|
|
21487
|
+
}
|
|
21488
|
+
],
|
|
21489
|
+
operationCount: 44,
|
|
21490
|
+
triggers: [],
|
|
21491
|
+
triggerCount: 0,
|
|
21492
|
+
authType: "api-key",
|
|
21493
|
+
category: "tools",
|
|
21494
|
+
integrationType: "analytics",
|
|
21495
|
+
tags: ["seo", "marketing", "data-analytics"]
|
|
21496
|
+
},
|
|
21249
21497
|
{
|
|
21250
21498
|
type: "sendblue",
|
|
21251
21499
|
slug: "sendblue",
|
|
@@ -21989,7 +22237,7 @@ var init_integrations = __esm(() => {
|
|
|
21989
22237
|
tags: ["enrichment", "sales-engagement"]
|
|
21990
22238
|
},
|
|
21991
22239
|
{
|
|
21992
|
-
type: "
|
|
22240
|
+
type: "slack_v2",
|
|
21993
22241
|
slug: "slack",
|
|
21994
22242
|
name: "Slack",
|
|
21995
22243
|
description: "Send, update, delete messages, manage views and modals, add or remove reactions, manage canvases, get channel info and user presence in Slack",
|
|
@@ -22170,9 +22418,9 @@ var init_integrations = __esm(() => {
|
|
|
22170
22418
|
operationCount: 42,
|
|
22171
22419
|
triggers: [
|
|
22172
22420
|
{
|
|
22173
|
-
id: "
|
|
22174
|
-
name: "Slack
|
|
22175
|
-
description: "Trigger
|
|
22421
|
+
id: "slack_oauth",
|
|
22422
|
+
name: "Slack",
|
|
22423
|
+
description: "Trigger from Slack events (mentions, messages, reactions)"
|
|
22176
22424
|
}
|
|
22177
22425
|
],
|
|
22178
22426
|
triggerCount: 1,
|
|
@@ -27115,7 +27363,6 @@ var DEPLOYMENT_REQUIREMENT_BY_OAUTH_SERVICE_ID, SERVICE_ACCOUNT_METADATA_BY_OAUT
|
|
|
27115
27363
|
var init_service_account_metadata = __esm(() => {
|
|
27116
27364
|
init_service_account_providers_generated();
|
|
27117
27365
|
DEPLOYMENT_REQUIREMENT_BY_OAUTH_SERVICE_ID = {
|
|
27118
|
-
slack: "preview-gated",
|
|
27119
27366
|
trello: "oauth-client"
|
|
27120
27367
|
};
|
|
27121
27368
|
SERVICE_ACCOUNT_METADATA_BY_OAUTH_SERVICE_ID = buildServiceAccountMetadata();
|
|
@@ -30843,6 +31090,7 @@ var init_twins = __esm(() => {
|
|
|
30843
31090
|
{ server: "ORGANIZATIONS_ENABLED", client: "NEXT_PUBLIC_ORGANIZATIONS_ENABLED" },
|
|
30844
31091
|
{ server: "WHITELABELING_ENABLED", client: "NEXT_PUBLIC_WHITELABELING_ENABLED" },
|
|
30845
31092
|
{ server: "AUDIT_LOGS_ENABLED", client: "NEXT_PUBLIC_AUDIT_LOGS_ENABLED" },
|
|
31093
|
+
{ server: "CUSTOM_BLOCKS_ENABLED", client: "NEXT_PUBLIC_CUSTOM_BLOCKS_ENABLED" },
|
|
30846
31094
|
{ server: "DATA_RETENTION_ENABLED", client: "NEXT_PUBLIC_DATA_RETENTION_ENABLED" },
|
|
30847
31095
|
{ server: "SESSION_POLICIES_ENABLED", client: "NEXT_PUBLIC_SESSION_POLICIES_ENABLED" },
|
|
30848
31096
|
{ server: "DATA_DRAINS_ENABLED", client: "NEXT_PUBLIC_DATA_DRAINS_ENABLED" },
|
|
@@ -30853,7 +31101,7 @@ var init_twins = __esm(() => {
|
|
|
30853
31101
|
{ server: "SSO_ENABLED", client: "NEXT_PUBLIC_SSO_ENABLED" },
|
|
30854
31102
|
{ server: "EMAIL_PASSWORD_SIGNUP_ENABLED", client: "NEXT_PUBLIC_EMAIL_PASSWORD_SIGNUP_ENABLED" },
|
|
30855
31103
|
{ server: "E2B_ENABLED", client: "NEXT_PUBLIC_E2B_ENABLED" },
|
|
30856
|
-
{ server: "
|
|
31104
|
+
{ server: "SLACK_EXTENDED_SCOPES", client: "NEXT_PUBLIC_SLACK_EXTENDED_SCOPES" }
|
|
30857
31105
|
];
|
|
30858
31106
|
SELF_HOST_UNLOCKS = [
|
|
30859
31107
|
{
|
|
@@ -30868,17 +31116,13 @@ var init_twins = __esm(() => {
|
|
|
30868
31116
|
},
|
|
30869
31117
|
{ server: "ORGANIZATIONS_ENABLED", label: "Organizations", hint: "multi-workspace orgs" },
|
|
30870
31118
|
{ server: "AUDIT_LOGS_ENABLED", label: "Audit logs", hint: "" },
|
|
31119
|
+
{ server: "CUSTOM_BLOCKS_ENABLED", label: "Custom blocks", hint: "reusable org-wide blocks" },
|
|
30871
31120
|
{ server: "DATA_RETENTION_ENABLED", label: "Data retention", hint: "deletes expired data" },
|
|
30872
31121
|
{ server: "SESSION_POLICIES_ENABLED", label: "Session policies", hint: "session lifetime caps" },
|
|
30873
31122
|
{ server: "DATA_DRAINS_ENABLED", label: "Data drains", hint: "export streams" },
|
|
30874
31123
|
{ server: "FORKING_ENABLED", label: "Workflow forking", hint: "" },
|
|
30875
31124
|
{ server: "INBOX_ENABLED", label: "Inbox", hint: "" },
|
|
30876
|
-
{ server: "WHITELABELING_ENABLED", label: "Whitelabeling", hint: "custom branding" }
|
|
30877
|
-
{
|
|
30878
|
-
server: "DEPLOY_AS_BLOCK",
|
|
30879
|
-
label: "Deploy as block",
|
|
30880
|
-
hint: "publish workflows as reusable blocks"
|
|
30881
|
-
}
|
|
31125
|
+
{ server: "WHITELABELING_ENABLED", label: "Whitelabeling", hint: "custom branding" }
|
|
30882
31126
|
];
|
|
30883
31127
|
LOGIN_PROVIDERS = [
|
|
30884
31128
|
{ id: "google", label: "Google", idKey: "GOOGLE_CLIENT_ID", secretKey: "GOOGLE_CLIENT_SECRET" },
|
|
@@ -31249,14 +31493,6 @@ function checkCoherence(ctx) {
|
|
|
31249
31493
|
});
|
|
31250
31494
|
}
|
|
31251
31495
|
}
|
|
31252
|
-
if (isTruthy(sim.vars.get("PII_GRANULAR_REDACTION")) && !isTruthy(sim.vars.get("PII_REDACTION"))) {
|
|
31253
|
-
findings.push({
|
|
31254
|
-
group: "coherence",
|
|
31255
|
-
status: "warn",
|
|
31256
|
-
message: "PII_GRANULAR_REDACTION is on but PII_REDACTION is off — the granular flag is inert without it",
|
|
31257
|
-
fix: "set PII_REDACTION=true or remove PII_GRANULAR_REDACTION"
|
|
31258
|
-
});
|
|
31259
|
-
}
|
|
31260
31496
|
if (Boolean(sim.vars.get("TURNSTILE_SECRET_KEY")) !== Boolean(sim.vars.get("NEXT_PUBLIC_TURNSTILE_SITE_KEY"))) {
|
|
31261
31497
|
findings.push({
|
|
31262
31498
|
group: "coherence",
|
|
@@ -35870,6 +36106,178 @@ var init_feature_setup = __esm(() => {
|
|
|
35870
36106
|
init_theme();
|
|
35871
36107
|
});
|
|
35872
36108
|
|
|
36109
|
+
// src/urls.ts
|
|
36110
|
+
var APP_URL = "http://localhost:3000", APP_SIGNUP_URL;
|
|
36111
|
+
var init_urls = __esm(() => {
|
|
36112
|
+
APP_SIGNUP_URL = `${APP_URL}/signup`;
|
|
36113
|
+
});
|
|
36114
|
+
|
|
36115
|
+
// src/desktop.ts
|
|
36116
|
+
var exports_desktop = {};
|
|
36117
|
+
__export(exports_desktop, {
|
|
36118
|
+
sanitizeForTerminal: () => sanitizeForTerminal,
|
|
36119
|
+
runDesktop: () => runDesktop,
|
|
36120
|
+
resolveDeploymentUrl: () => resolveDeploymentUrl,
|
|
36121
|
+
probeDownload: () => probeDownload,
|
|
36122
|
+
describeProbe: () => describeProbe
|
|
36123
|
+
});
|
|
36124
|
+
function deploymentKey(value) {
|
|
36125
|
+
try {
|
|
36126
|
+
return new URL(value).origin.toLowerCase();
|
|
36127
|
+
} catch {
|
|
36128
|
+
return value;
|
|
36129
|
+
}
|
|
36130
|
+
}
|
|
36131
|
+
function sanitizeForTerminal(value) {
|
|
36132
|
+
const printable = value.replace(/\p{C}/gu, "").replace(/\p{Z}/gu, " ").replace(/ {2,}/g, " ").trim();
|
|
36133
|
+
return truncate(printable, MAX_INSTALLER_NAME);
|
|
36134
|
+
}
|
|
36135
|
+
function resolveDeploymentUrl(sources, override) {
|
|
36136
|
+
const discovered = sources.flatMap((source) => {
|
|
36137
|
+
const value = source.values?.get(APP_URL_KEY)?.trim();
|
|
36138
|
+
return value ? [{ label: source.label ?? "configuration", value }] : [];
|
|
36139
|
+
});
|
|
36140
|
+
const byDeployment = new Map;
|
|
36141
|
+
for (const { value } of discovered) {
|
|
36142
|
+
byDeployment.set(deploymentKey(value), value);
|
|
36143
|
+
}
|
|
36144
|
+
if (!override && byDeployment.size > 1) {
|
|
36145
|
+
throw new SetupError(`Found ${byDeployment.size} configurations naming different ${APP_URL_KEY} values.`, [
|
|
36146
|
+
...discovered.map(({ label, value }) => `${label}: ${value}`),
|
|
36147
|
+
"Re-run with --url <deployment url> to say which one the desktop app should use."
|
|
36148
|
+
]);
|
|
36149
|
+
}
|
|
36150
|
+
const raw = override ?? byDeployment.values().next().value;
|
|
36151
|
+
if (!raw) {
|
|
36152
|
+
return APP_URL;
|
|
36153
|
+
}
|
|
36154
|
+
let url;
|
|
36155
|
+
try {
|
|
36156
|
+
url = new URL(raw.trim());
|
|
36157
|
+
} catch {
|
|
36158
|
+
throw new SetupError(`${APP_URL_KEY} is not a valid URL: ${raw}`, [
|
|
36159
|
+
"Set it to the origin browsers use to reach Sim, e.g. https://sim.example.com"
|
|
36160
|
+
]);
|
|
36161
|
+
}
|
|
36162
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
36163
|
+
throw new SetupError(`${APP_URL_KEY} must be an http(s) URL: ${raw}`);
|
|
36164
|
+
}
|
|
36165
|
+
return url.origin;
|
|
36166
|
+
}
|
|
36167
|
+
async function probeDownload(downloadUrl, fetchImpl = fetch) {
|
|
36168
|
+
let response;
|
|
36169
|
+
try {
|
|
36170
|
+
response = await fetchImpl(downloadUrl, {
|
|
36171
|
+
redirect: "manual",
|
|
36172
|
+
signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
|
|
36173
|
+
});
|
|
36174
|
+
} catch (error) {
|
|
36175
|
+
return { status: "unreachable", error: getErrorMessage(error, "request failed") };
|
|
36176
|
+
}
|
|
36177
|
+
if (REDIRECT_STATUSES.has(response.status)) {
|
|
36178
|
+
const location = response.headers.get("location");
|
|
36179
|
+
if (!location)
|
|
36180
|
+
return { status: "unexpected", code: response.status };
|
|
36181
|
+
let name = location;
|
|
36182
|
+
try {
|
|
36183
|
+
name = decodeURIComponent(new URL(location).pathname.split("/").pop() ?? location);
|
|
36184
|
+
} catch {}
|
|
36185
|
+
return { status: "ok", installerUrl: location, installerName: sanitizeForTerminal(name) };
|
|
36186
|
+
}
|
|
36187
|
+
if (response.status === 404)
|
|
36188
|
+
return { status: "no-release" };
|
|
36189
|
+
if (response.status === 502)
|
|
36190
|
+
return { status: "feed-unavailable" };
|
|
36191
|
+
return { status: "unexpected", code: response.status };
|
|
36192
|
+
}
|
|
36193
|
+
function describeProbe(probe, appUrl) {
|
|
36194
|
+
switch (probe.status) {
|
|
36195
|
+
case "ok":
|
|
36196
|
+
return { headline: `${glyph.pass} Installer resolved: ${probe.installerName}`, hints: [] };
|
|
36197
|
+
case "no-release":
|
|
36198
|
+
return {
|
|
36199
|
+
headline: `${glyph.fail} This deployment reports no desktop release for its channel.`,
|
|
36200
|
+
hints: [
|
|
36201
|
+
"Stable desktop builds are published on GitHub releases of simstudioai/sim.",
|
|
36202
|
+
"A brand-new fork with no releases of its own will report this."
|
|
36203
|
+
]
|
|
36204
|
+
};
|
|
36205
|
+
case "feed-unavailable":
|
|
36206
|
+
return {
|
|
36207
|
+
headline: `${glyph.fail} The deployment could not reach the GitHub release feed.`,
|
|
36208
|
+
hints: [
|
|
36209
|
+
"The Sim server needs outbound access to api.github.com and github.com.",
|
|
36210
|
+
"Unauthenticated GitHub API calls are capped at 60/hour per IP — set GITHUB_TOKEN on the Sim server to raise it to 5000/hour."
|
|
36211
|
+
]
|
|
36212
|
+
};
|
|
36213
|
+
case "unreachable":
|
|
36214
|
+
return {
|
|
36215
|
+
headline: `${glyph.fail} Could not reach ${appUrl} — ${probe.error}`,
|
|
36216
|
+
hints: [
|
|
36217
|
+
`Check that Sim is running and reachable at ${appUrl} (npx sim-setup status).`,
|
|
36218
|
+
"Pass --url if this machine reaches Sim at a different address."
|
|
36219
|
+
]
|
|
36220
|
+
};
|
|
36221
|
+
case "unexpected":
|
|
36222
|
+
return { headline: `${glyph.fail} The download endpoint answered ${probe.code}.`, hints: [] };
|
|
36223
|
+
}
|
|
36224
|
+
}
|
|
36225
|
+
async function runDesktop(flags) {
|
|
36226
|
+
const appUrl = resolveDeploymentUrl(flags.url ? [] : discoverConfigurationSources(), flags.url);
|
|
36227
|
+
const downloadUrl = `${appUrl}${DOWNLOAD_PATH}`;
|
|
36228
|
+
log2.step(`Deployment: ${theme.accent(appUrl)}`);
|
|
36229
|
+
const spin = spinner2();
|
|
36230
|
+
spin.start("Resolving the desktop installer…");
|
|
36231
|
+
const [probe, feedOk] = await Promise.all([
|
|
36232
|
+
probeDownload(downloadUrl),
|
|
36233
|
+
httpHealth(`${appUrl}${FEED_PATH}`, PROBE_TIMEOUT_MS)
|
|
36234
|
+
]);
|
|
36235
|
+
const { headline, hints } = describeProbe(probe, appUrl);
|
|
36236
|
+
spin.stop(headline);
|
|
36237
|
+
if (probe.status !== "ok") {
|
|
36238
|
+
for (const hint of hints) {
|
|
36239
|
+
log2.info(hint);
|
|
36240
|
+
}
|
|
36241
|
+
outro2(theme.error("The desktop installer could not be resolved."));
|
|
36242
|
+
return 1;
|
|
36243
|
+
}
|
|
36244
|
+
if (!feedOk) {
|
|
36245
|
+
log2.warn(`${FEED_PATH} did not resolve — the app will install but will not auto-update from this deployment.`);
|
|
36246
|
+
}
|
|
36247
|
+
note2([
|
|
36248
|
+
`1. Download and install Sim:`,
|
|
36249
|
+
` ${theme.accent(downloadUrl)}`,
|
|
36250
|
+
"",
|
|
36251
|
+
`2. Open Sim, then choose ${theme.command("Sim → Server…")} in the menu bar.`,
|
|
36252
|
+
"",
|
|
36253
|
+
`3. Enter your server URL and press Connect:`,
|
|
36254
|
+
` ${theme.accent(appUrl)}`,
|
|
36255
|
+
"",
|
|
36256
|
+
theme.muted("Sim relaunches against your deployment and updates from it from then on."),
|
|
36257
|
+
theme.muted("The desktop app is macOS-only today; the web app works everywhere.")
|
|
36258
|
+
].join(`
|
|
36259
|
+
`), "Connect the desktop app");
|
|
36260
|
+
if (!flags.noOpen) {
|
|
36261
|
+
if (await confirm2({ message: "Download it now?", initialValue: true })) {
|
|
36262
|
+
openBrowser(downloadUrl);
|
|
36263
|
+
}
|
|
36264
|
+
}
|
|
36265
|
+
outro2(theme.accent("Ready."));
|
|
36266
|
+
return 0;
|
|
36267
|
+
}
|
|
36268
|
+
var DOWNLOAD_PATH = "/api/desktop/update/download", FEED_PATH = "/api/desktop/update/latest-mac.yml", PROBE_TIMEOUT_MS = 15000, REDIRECT_STATUSES, APP_URL_KEY = "NEXT_PUBLIC_APP_URL", MAX_INSTALLER_NAME = 120;
|
|
36269
|
+
var init_desktop = __esm(() => {
|
|
36270
|
+
init_string();
|
|
36271
|
+
init_cli_auth();
|
|
36272
|
+
init_configuration_sources();
|
|
36273
|
+
init_errors();
|
|
36274
|
+
init_probes();
|
|
36275
|
+
init_prompter();
|
|
36276
|
+
init_theme();
|
|
36277
|
+
init_urls();
|
|
36278
|
+
REDIRECT_STATUSES = new Set([301, 302, 307, 308]);
|
|
36279
|
+
});
|
|
36280
|
+
|
|
35873
36281
|
// src/doctor.ts
|
|
35874
36282
|
var exports_doctor = {};
|
|
35875
36283
|
__export(exports_doctor, {
|
|
@@ -36131,12 +36539,6 @@ var init_docker = __esm(() => {
|
|
|
36131
36539
|
APP_DIRS = ["/Applications", join(homedir(), "Applications")];
|
|
36132
36540
|
});
|
|
36133
36541
|
|
|
36134
|
-
// src/urls.ts
|
|
36135
|
-
var APP_URL = "http://localhost:3000", APP_SIGNUP_URL;
|
|
36136
|
-
var init_urls = __esm(() => {
|
|
36137
|
-
APP_SIGNUP_URL = `${APP_URL}/signup`;
|
|
36138
|
-
});
|
|
36139
|
-
|
|
36140
36542
|
// src/modes/k8s.ts
|
|
36141
36543
|
import { spawn, spawnSync as spawnSync6 } from "node:child_process";
|
|
36142
36544
|
function run(command, args, failMessage, input) {
|
|
@@ -38024,24 +38426,31 @@ function oneFlag(args, flag) {
|
|
|
38024
38426
|
fail(`${flag} may only be provided once`);
|
|
38025
38427
|
return count === 1;
|
|
38026
38428
|
}
|
|
38027
|
-
function
|
|
38028
|
-
let
|
|
38429
|
+
function parseValueOption(args, flag, requirement) {
|
|
38430
|
+
let value;
|
|
38029
38431
|
const remaining = [];
|
|
38432
|
+
const prefix = `${flag}=`;
|
|
38030
38433
|
for (let index = 0;index < args.length; index += 1) {
|
|
38031
38434
|
const arg = args[index];
|
|
38032
|
-
if (arg !==
|
|
38435
|
+
if (arg !== flag && !arg.startsWith(prefix)) {
|
|
38033
38436
|
remaining.push(arg);
|
|
38034
38437
|
continue;
|
|
38035
38438
|
}
|
|
38036
|
-
if (
|
|
38037
|
-
fail(
|
|
38038
|
-
const
|
|
38039
|
-
if (
|
|
38040
|
-
fail(
|
|
38041
|
-
|
|
38042
|
-
mode = value;
|
|
38439
|
+
if (value !== undefined)
|
|
38440
|
+
fail(`${flag} may only be provided once`);
|
|
38441
|
+
const candidate = arg === flag ? args[++index] : arg.slice(prefix.length);
|
|
38442
|
+
if (!candidate || candidate.startsWith("-"))
|
|
38443
|
+
fail(requirement);
|
|
38444
|
+
value = candidate;
|
|
38043
38445
|
}
|
|
38044
|
-
return {
|
|
38446
|
+
return { value, remaining };
|
|
38447
|
+
}
|
|
38448
|
+
function parseMode(args) {
|
|
38449
|
+
const { value, remaining } = parseValueOption(args, "--mode", "--mode requires a value");
|
|
38450
|
+
if (value !== undefined && value !== "compose" && value !== "dev" && value !== "k8s") {
|
|
38451
|
+
fail(`invalid --mode "${value}" — expected compose, dev, or k8s`);
|
|
38452
|
+
}
|
|
38453
|
+
return { mode: value, remaining };
|
|
38045
38454
|
}
|
|
38046
38455
|
function expectNoArguments(command, args) {
|
|
38047
38456
|
if (args.length > 0)
|
|
@@ -38084,6 +38493,13 @@ function parseCore(args, helpRequested) {
|
|
|
38084
38493
|
}
|
|
38085
38494
|
return { kind: "add", feature, args: featureArgs };
|
|
38086
38495
|
}
|
|
38496
|
+
if (command === "desktop") {
|
|
38497
|
+
const noOpen = oneFlag(commandArgs, "--no-open");
|
|
38498
|
+
const { value: url, remaining } = parseValueOption(commandArgs.filter((arg) => arg !== "--no-open"), "--url", "--url requires a deployment URL");
|
|
38499
|
+
if (remaining.length > 0)
|
|
38500
|
+
fail(`Unknown desktop option: ${remaining[0]}`);
|
|
38501
|
+
return { kind: "desktop", noOpen, ...url ? { url } : {} };
|
|
38502
|
+
}
|
|
38087
38503
|
if (command === "doctor") {
|
|
38088
38504
|
const fix = oneFlag(commandArgs, "--fix");
|
|
38089
38505
|
const json = oneFlag(commandArgs, "--json");
|
|
@@ -38128,6 +38544,7 @@ var USAGE = `Usage:
|
|
|
38128
38544
|
sim-setup [--quick] [--dir <path>] [--mode compose|dev|k8s]
|
|
38129
38545
|
sim-setup config show configured capabilities and integrations
|
|
38130
38546
|
sim-setup add <feature> configure ${SETUP_FEATURES2}
|
|
38547
|
+
sim-setup desktop [--url <url>] install the macOS desktop app against this deployment
|
|
38131
38548
|
sim-setup doctor [--fix] [--json] check your setup
|
|
38132
38549
|
sim-setup start | stop | restart bring your install up / down / cycle
|
|
38133
38550
|
sim-setup update pull/rebuild and apply Compose images
|
|
@@ -38158,6 +38575,11 @@ async function main() {
|
|
|
38158
38575
|
await runFeatureSetup2(invocation.feature, invocation.args);
|
|
38159
38576
|
return;
|
|
38160
38577
|
}
|
|
38578
|
+
if (invocation.kind === "desktop") {
|
|
38579
|
+
const { runDesktop: runDesktop2 } = await Promise.resolve().then(() => (init_desktop(), exports_desktop));
|
|
38580
|
+
process.exitCode = await runDesktop2({ url: invocation.url, noOpen: invocation.noOpen });
|
|
38581
|
+
return;
|
|
38582
|
+
}
|
|
38161
38583
|
if (invocation.kind === "doctor") {
|
|
38162
38584
|
const { runDoctor: runDoctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
|
|
38163
38585
|
process.exitCode = await runDoctor2({ fix: invocation.fix, json: invocation.json });
|