emulate 0.5.0 → 0.6.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/README.md +141 -19
- package/dist/api.js +460 -24
- package/dist/api.js.map +1 -1
- package/dist/{dist-PWGOAQC6.js → dist-2ZZGNPJI.js} +1 -1
- package/dist/dist-2ZZGNPJI.js.map +1 -0
- package/dist/{dist-4X2KPMAJ.js → dist-CXRPM6BK.js} +1 -3
- package/dist/dist-CXRPM6BK.js.map +1 -0
- package/dist/{dist-LDUHEJAN.js → dist-DSJSF3GY.js} +1 -3
- package/dist/dist-DSJSF3GY.js.map +1 -0
- package/dist/{dist-ETHHYBGF.js → dist-IFULY5LE.js} +1 -2
- package/dist/dist-IFULY5LE.js.map +1 -0
- package/dist/{dist-J6LHUR52.js → dist-IRUBHCZU.js} +1 -2
- package/dist/dist-IRUBHCZU.js.map +1 -0
- package/dist/{dist-ENKE2S7V.js → dist-NJJLJT2N.js} +1 -3
- package/dist/dist-NJJLJT2N.js.map +1 -0
- package/dist/dist-OGSAVJ25.js +4874 -0
- package/dist/dist-OGSAVJ25.js.map +1 -0
- package/dist/{dist-REDHDZ3V.js → dist-PO4CL5SJ.js} +1 -3
- package/dist/dist-PO4CL5SJ.js.map +1 -0
- package/dist/{dist-IBXD3O6A.js → dist-R3TNKUIE.js} +1 -3
- package/dist/dist-R3TNKUIE.js.map +1 -0
- package/dist/{dist-CFST4X4K.js → dist-WACHAAVU.js} +1 -2
- package/dist/dist-WACHAAVU.js.map +1 -0
- package/dist/{dist-5JVGPOL3.js → dist-XWWZVLQQ.js} +1 -2
- package/dist/dist-XWWZVLQQ.js.map +1 -0
- package/dist/{dist-KKTYBE5S.js → dist-ZY5SZSJ2.js} +8 -3
- package/dist/dist-ZY5SZSJ2.js.map +1 -0
- package/dist/index.js +464 -26
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
- package/dist/chunk-AQ2CLRU3.js +0 -2146
- package/dist/chunk-AQ2CLRU3.js.map +0 -1
- package/dist/dist-4X2KPMAJ.js.map +0 -1
- package/dist/dist-5JVGPOL3.js.map +0 -1
- package/dist/dist-CE6BUCWQ.js +0 -1438
- package/dist/dist-CE6BUCWQ.js.map +0 -1
- package/dist/dist-CFST4X4K.js.map +0 -1
- package/dist/dist-ENKE2S7V.js.map +0 -1
- package/dist/dist-ETHHYBGF.js.map +0 -1
- package/dist/dist-IBXD3O6A.js.map +0 -1
- package/dist/dist-J6LHUR52.js.map +0 -1
- package/dist/dist-KKTYBE5S.js.map +0 -1
- package/dist/dist-LDUHEJAN.js.map +0 -1
- package/dist/dist-PWGOAQC6.js.map +0 -1
- package/dist/dist-REDHDZ3V.js.map +0 -1
package/README.md
CHANGED
|
@@ -22,25 +22,25 @@ All services start with sensible defaults. No config file needed:
|
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
24
|
# Start all services (zero-config)
|
|
25
|
-
emulate
|
|
25
|
+
npx emulate
|
|
26
26
|
|
|
27
27
|
# Start specific services
|
|
28
|
-
emulate --service vercel,github
|
|
28
|
+
npx emulate --service vercel,github
|
|
29
29
|
|
|
30
30
|
# Custom port
|
|
31
|
-
emulate --port 3000
|
|
31
|
+
npx emulate --port 3000
|
|
32
32
|
|
|
33
33
|
# Use a seed config file
|
|
34
|
-
emulate --seed config.yaml
|
|
34
|
+
npx emulate --seed config.yaml
|
|
35
35
|
|
|
36
36
|
# Generate a starter config
|
|
37
|
-
emulate init
|
|
37
|
+
npx emulate init
|
|
38
38
|
|
|
39
39
|
# Generate config for a specific service
|
|
40
|
-
emulate init --service vercel
|
|
40
|
+
npx emulate init --service vercel
|
|
41
41
|
|
|
42
42
|
# List available services
|
|
43
|
-
emulate list
|
|
43
|
+
npx emulate list
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
### Options
|
|
@@ -64,7 +64,7 @@ The port can also be set via `EMULATE_PORT` or `PORT` environment variables.
|
|
|
64
64
|
portless proxy start
|
|
65
65
|
|
|
66
66
|
# Start emulate with portless integration
|
|
67
|
-
emulate start --portless
|
|
67
|
+
npx emulate start --portless
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
Each service registers as a portless alias and gets a named HTTPS URL:
|
|
@@ -82,7 +82,7 @@ The `--portless` flag overwrites any existing portless aliases matching `*.emula
|
|
|
82
82
|
For a custom base URL without portless (any reverse proxy), use `--base-url` or the `EMULATE_BASE_URL` env var:
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
emulate start --base-url "https://{service}.myproxy.test"
|
|
85
|
+
npx emulate start --base-url "https://{service}.myproxy.test"
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
The `PORTLESS_URL` env var is automatically set by the `portless` CLI wrapper when running a command through it (e.g. `portless github.emulate emulate start`), typically to a value like `https://{service}.emulate.localhost`. It supports `{service}` interpolation, just like `--base-url` and `EMULATE_BASE_URL`. When no explicit `baseUrl` is provided, it is used as a fallback.
|
|
@@ -156,7 +156,7 @@ afterAll(() => Promise.all([github.close(), vercel.close()]))
|
|
|
156
156
|
|
|
157
157
|
## Configuration
|
|
158
158
|
|
|
159
|
-
Configuration is optional. The CLI auto-detects config files in this order: `emulate.config.yaml` / `.yml`, `emulate.config.json`, `service-emulator.config.yaml` / `.yml`, `service-emulator.config.json`. Or pass `--seed <file>` explicitly. Run `emulate init` to generate a starter file.
|
|
159
|
+
Configuration is optional. The CLI auto-detects config files in this order: `emulate.config.yaml` / `.yml`, `emulate.config.json`, `service-emulator.config.yaml` / `.yml`, `service-emulator.config.json`. Or pass `--seed <file>` explicitly. Run `npx emulate init` to generate a starter file.
|
|
160
160
|
|
|
161
161
|
```yaml
|
|
162
162
|
tokens:
|
|
@@ -246,6 +246,11 @@ slack:
|
|
|
246
246
|
- name: developer
|
|
247
247
|
real_name: Developer
|
|
248
248
|
email: dev@example.com
|
|
249
|
+
profile:
|
|
250
|
+
title: Local Developer
|
|
251
|
+
status_text: Testing locally
|
|
252
|
+
status_emoji: ":computer:"
|
|
253
|
+
presence: active
|
|
249
254
|
channels:
|
|
250
255
|
- name: general
|
|
251
256
|
topic: General discussion
|
|
@@ -256,9 +261,76 @@ slack:
|
|
|
256
261
|
oauth_apps:
|
|
257
262
|
- client_id: "12345.67890"
|
|
258
263
|
client_secret: example_client_secret
|
|
264
|
+
app_id: A000000001
|
|
259
265
|
name: My Slack App
|
|
260
266
|
redirect_uris:
|
|
261
267
|
- http://localhost:3000/api/auth/callback/slack
|
|
268
|
+
scopes:
|
|
269
|
+
- chat:write
|
|
270
|
+
- channels:read
|
|
271
|
+
- channels:history
|
|
272
|
+
- channels:join
|
|
273
|
+
- channels:manage
|
|
274
|
+
- channels:write
|
|
275
|
+
- groups:read
|
|
276
|
+
- groups:history
|
|
277
|
+
- groups:write
|
|
278
|
+
- im:read
|
|
279
|
+
- im:history
|
|
280
|
+
- im:write
|
|
281
|
+
- mpim:read
|
|
282
|
+
- mpim:history
|
|
283
|
+
- mpim:write
|
|
284
|
+
- users:read
|
|
285
|
+
- users:read.email
|
|
286
|
+
- users.profile:read
|
|
287
|
+
- users.profile:write
|
|
288
|
+
- users:write
|
|
289
|
+
- files:read
|
|
290
|
+
- files:write
|
|
291
|
+
- pins:read
|
|
292
|
+
- pins:write
|
|
293
|
+
- bookmarks:read
|
|
294
|
+
- bookmarks:write
|
|
295
|
+
- reactions:read
|
|
296
|
+
- reactions:write
|
|
297
|
+
- team:read
|
|
298
|
+
user_scopes: [users:read, users.profile:read]
|
|
299
|
+
bot_name: my-bot
|
|
300
|
+
tokens:
|
|
301
|
+
- token: xoxb-local-test
|
|
302
|
+
user: developer
|
|
303
|
+
scopes:
|
|
304
|
+
- chat:write
|
|
305
|
+
- channels:read
|
|
306
|
+
- channels:history
|
|
307
|
+
- channels:join
|
|
308
|
+
- channels:manage
|
|
309
|
+
- channels:write
|
|
310
|
+
- groups:read
|
|
311
|
+
- groups:history
|
|
312
|
+
- groups:write
|
|
313
|
+
- im:read
|
|
314
|
+
- im:history
|
|
315
|
+
- im:write
|
|
316
|
+
- mpim:read
|
|
317
|
+
- mpim:history
|
|
318
|
+
- mpim:write
|
|
319
|
+
- users:read
|
|
320
|
+
- users:read.email
|
|
321
|
+
- users.profile:read
|
|
322
|
+
- users.profile:write
|
|
323
|
+
- users:write
|
|
324
|
+
- files:read
|
|
325
|
+
- files:write
|
|
326
|
+
- pins:read
|
|
327
|
+
- pins:write
|
|
328
|
+
- bookmarks:read
|
|
329
|
+
- bookmarks:write
|
|
330
|
+
- reactions:read
|
|
331
|
+
- reactions:write
|
|
332
|
+
- team:read
|
|
333
|
+
strict_scopes: false
|
|
262
334
|
|
|
263
335
|
apple:
|
|
264
336
|
users:
|
|
@@ -598,39 +670,89 @@ OAuth 2.0, OpenID Connect, and mutable Google Workspace-style surfaces for local
|
|
|
598
670
|
|
|
599
671
|
## Slack API
|
|
600
672
|
|
|
601
|
-
Fully stateful Slack Web API emulation with channels, messages, threads, reactions, OAuth v2, and incoming webhooks.
|
|
673
|
+
Fully stateful Slack Web API emulation with channels, messages, threads, reactions, user profiles, presence, modern file uploads, pins, bookmarks, views, OAuth v2, and incoming webhooks. Chat writes preserve common rich message fields such as `blocks`, `attachments`, `metadata`, formatting flags, unfurl flags, and client message ids. Conversation writes update archive state, names, topics, purposes, membership, DMs, MPIMs, and read cursors. User writes update profile fields, status, custom fields, and deterministic active or away presence. File writes support the current external upload flow with local upload URLs, file share messages, reads, lists, downloads, and deletes. Pin and bookmark writes support channel message pins and link bookmarks. View writes support App Home publishing and modal stacks. Seeded OAuth apps and OAuth installs create bot users and installation records. OAuth exchanges and explicit token seeds create scoped token records. Supported write state changes dispatch Slack `event_callback` payloads to configured webhook URLs.
|
|
602
674
|
|
|
603
675
|
### Auth & Chat
|
|
604
676
|
- `POST /api/auth.test` - test authentication
|
|
605
|
-
- `POST /api/chat.postMessage` - post message (supports threads via `thread_ts`)
|
|
606
|
-
- `POST /api/chat.
|
|
677
|
+
- `POST /api/chat.postMessage` - post message with text or rich payload fields (supports threads via `thread_ts` and DM user IDs)
|
|
678
|
+
- `POST /api/chat.postEphemeral` - post ephemeral message outside channel history
|
|
679
|
+
- `POST /api/chat.update` - update message text and rich payload fields
|
|
607
680
|
- `POST /api/chat.delete` - delete message
|
|
681
|
+
- `GET /api/chat.getPermalink` / `POST /api/chat.getPermalink` - get message permalink
|
|
682
|
+
- `POST /api/chat.scheduleMessage` - schedule pending message
|
|
683
|
+
- `POST /api/chat.deleteScheduledMessage` - delete pending scheduled message
|
|
684
|
+
- `POST /api/chat.scheduledMessages.list` - list pending scheduled messages
|
|
608
685
|
- `POST /api/chat.meMessage` - /me message
|
|
609
686
|
|
|
610
687
|
### Conversations
|
|
611
|
-
- `POST /api/conversations.list` - list
|
|
688
|
+
- `POST /api/conversations.list` - list conversations (cursor pagination, `types`, `exclude_archived`)
|
|
612
689
|
- `POST /api/conversations.info` - get channel info
|
|
613
690
|
- `POST /api/conversations.create` - create channel
|
|
614
|
-
- `POST /api/conversations.
|
|
615
|
-
- `POST /api/conversations.
|
|
691
|
+
- `POST /api/conversations.archive` / `conversations.unarchive` - archive/restore channel
|
|
692
|
+
- `POST /api/conversations.rename` - rename channel
|
|
693
|
+
- `POST /api/conversations.setTopic` / `conversations.setPurpose` - update topic/purpose
|
|
694
|
+
- `POST /api/conversations.history` - channel history with rich message fields
|
|
695
|
+
- `POST /api/conversations.replies` - thread replies with rich message fields
|
|
616
696
|
- `POST /api/conversations.join` / `conversations.leave` - join/leave
|
|
697
|
+
- `POST /api/conversations.invite` / `conversations.kick` - manage membership
|
|
698
|
+
- `POST /api/conversations.open` / `conversations.close` - open/close DMs and MPIMs
|
|
699
|
+
- `POST /api/conversations.mark` - mark read cursor
|
|
617
700
|
- `POST /api/conversations.members` - list members
|
|
618
701
|
|
|
619
702
|
### Users & Reactions
|
|
620
703
|
- `POST /api/users.list` - list users (cursor pagination)
|
|
621
704
|
- `POST /api/users.info` - get user info
|
|
622
705
|
- `POST /api/users.lookupByEmail` - lookup by email
|
|
706
|
+
- `GET /api/users.profile.get` / `POST /api/users.profile.get` - get user profile fields
|
|
707
|
+
- `POST /api/users.profile.set` - update profile fields, status, and custom fields
|
|
708
|
+
- `GET /api/users.getPresence` / `POST /api/users.getPresence` - get active or away presence
|
|
709
|
+
- `POST /api/users.setPresence` - set the authed user to away or automatic presence
|
|
623
710
|
- `POST /api/reactions.add` / `reactions.remove` / `reactions.get` - manage reactions
|
|
624
711
|
|
|
712
|
+
### Files
|
|
713
|
+
- `POST /api/files.getUploadURLExternal` - create a local external upload session
|
|
714
|
+
- `POST /upload/v1/:fileId` - receive raw uploaded file bytes
|
|
715
|
+
- `POST /api/files.completeUploadExternal` - complete uploads and optionally share file messages
|
|
716
|
+
- `GET /api/files.info` / `POST /api/files.info` - get file metadata
|
|
717
|
+
- `GET /api/files.list` / `POST /api/files.list` - list completed files
|
|
718
|
+
- `GET /files-pri/:fileId/:filename` - download file bytes with a bearer token that can access the file
|
|
719
|
+
- `POST /api/files.delete` - delete a completed file
|
|
720
|
+
|
|
721
|
+
### Pins & Bookmarks
|
|
722
|
+
- `POST /api/pins.add` - pin a message to a channel
|
|
723
|
+
- `GET /api/pins.list` / `POST /api/pins.list` - list pinned message items for a channel
|
|
724
|
+
- `POST /api/pins.remove` - remove a message pin from a channel
|
|
725
|
+
- `POST /api/bookmarks.add` - add a link bookmark to a channel
|
|
726
|
+
- `POST /api/bookmarks.edit` - update a link bookmark
|
|
727
|
+
- `POST /api/bookmarks.list` - list channel bookmarks
|
|
728
|
+
- `POST /api/bookmarks.remove` - remove a bookmark from a channel
|
|
729
|
+
|
|
730
|
+
### Views
|
|
731
|
+
- `POST /api/views.publish` - publish or update an App Home view for a user
|
|
732
|
+
- `POST /api/views.open` - open a modal view
|
|
733
|
+
- `POST /api/views.update` - update a view by `view_id` or `external_id`
|
|
734
|
+
- `POST /api/views.push` - push a modal view onto the current modal stack
|
|
735
|
+
- `POST /api/views.generateTriggerId` - local helper for tests that need a modal trigger id
|
|
736
|
+
|
|
737
|
+
Modal opens and pushes require values from `/api/views.generateTriggerId`. Pass the returned value as `trigger_id` or `interactivity_pointer`; generate push values with an existing `view_id` and use them within 3 seconds.
|
|
738
|
+
|
|
625
739
|
### Team, Bots & Webhooks
|
|
626
740
|
- `POST /api/team.info` - workspace info
|
|
627
741
|
- `POST /api/bots.info` - bot info
|
|
628
|
-
- `POST /services/:teamId/:botId/:webhookId` - incoming webhook
|
|
742
|
+
- `POST /services/:teamId/:botId/:webhookId` - incoming webhook with text or rich payload fields
|
|
629
743
|
|
|
630
744
|
### OAuth
|
|
631
745
|
- `GET /oauth/v2/authorize` - authorization (shows user picker)
|
|
746
|
+
- `POST /oauth/v2/authorize/callback` - local user picker callback that creates the auth code
|
|
632
747
|
- `POST /api/oauth.v2.access` - token exchange
|
|
633
748
|
|
|
749
|
+
### Inspector
|
|
750
|
+
- `GET /` - tabbed local inspector for conversations, messages, files, views, auth records, incoming webhooks, event subscriptions, and event deliveries
|
|
751
|
+
|
|
752
|
+
Slack scope checks are relaxed by default so local tests can use simple bearer tokens. Set `slack.strict_scopes: true` in seed config to make supported Web API methods return Slack-style `missing_scope` errors with `needed` and `provided` fields. Strict mode checks `chat:write`, `channels:read`, `channels:history`, `channels:join`, `channels:manage`, `channels:write`, `groups:read`, `groups:history`, `groups:write`, `im:read`, `im:history`, `im:write`, `mpim:read`, `mpim:history`, `mpim:write`, `users:read`, `users:read.email`, `users.profile:read`, `users.profile:write`, `users:write`, `files:read`, `files:write`, `pins:read`, `pins:write`, `bookmarks:read`, `bookmarks:write`, `reactions:read`, `reactions:write`, and `team:read`. Slack lists no method-specific scopes for `views.publish`, `views.open`, `views.update`, or `views.push`, so the emulator requires auth but does not add strict-scope checks for those methods.
|
|
753
|
+
|
|
754
|
+
Current Slack limits: Slack Connect, Enterprise Grid admin APIs, Audit Logs API, SCIM, Legal Holds, Socket Mode, slash command and interaction simulation, user groups, reminders, stars, calls, canvases, lists, functions, workflows, chat streaming, legacy `files.upload`, exact rate limiting, and paid-plan behavior are not implemented.
|
|
755
|
+
|
|
634
756
|
## Apple Sign In
|
|
635
757
|
|
|
636
758
|
Sign in with Apple emulation with authorization code flow, PKCE support, RS256 ID tokens, and OIDC discovery.
|
|
@@ -821,7 +943,7 @@ apps/
|
|
|
821
943
|
web/ # Documentation site (Next.js)
|
|
822
944
|
```
|
|
823
945
|
|
|
824
|
-
The core provides a generic `Store` with typed `Collection<T>` instances supporting CRUD, indexing, filtering, and pagination. Each service plugin registers its routes
|
|
946
|
+
The core provides a generic `Store` with typed `Collection<T>` instances supporting CRUD, indexing, filtering, and pagination. Each service plugin registers its routes with the shared internal app and uses the store for state.
|
|
825
947
|
|
|
826
948
|
## Auth
|
|
827
949
|
|
|
@@ -833,7 +955,7 @@ Tokens are configured in the seed config and map to users. Pass them as `Authori
|
|
|
833
955
|
|
|
834
956
|
**Google**: Standard OAuth 2.0 authorization code flow. Configure clients in the seed config.
|
|
835
957
|
|
|
836
|
-
**Slack**: All Web API endpoints require `Authorization: Bearer <token>`. OAuth v2 flow with user picker UI.
|
|
958
|
+
**Slack**: All Web API endpoints require `Authorization: Bearer <token>`. Seeded OAuth apps create local installation records, and OAuth v2 flow with user picker UI creates scoped bot tokens. Optional strict scope mode returns `missing_scope` when a token lacks a required method scope.
|
|
837
959
|
|
|
838
960
|
**Apple**: OIDC authorization code flow with RS256 ID tokens. On first auth per user/client pair, a `user` JSON blob is included.
|
|
839
961
|
|