@yolk-sdk/emulators 0.1.0-canary.96
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/LICENSE +21 -0
- package/README.md +2135 -0
- package/dist/anthropic.d.mts +269 -0
- package/dist/anthropic.d.mts.map +1 -0
- package/dist/anthropic.mjs +177 -0
- package/dist/anthropic.mjs.map +1 -0
- package/dist/chat-completions.d.mts +288 -0
- package/dist/chat-completions.d.mts.map +1 -0
- package/dist/chat-completions.mjs +451 -0
- package/dist/chat-completions.mjs.map +1 -0
- package/dist/codex.d.mts +265 -0
- package/dist/codex.d.mts.map +1 -0
- package/dist/codex.mjs +199 -0
- package/dist/codex.mjs.map +1 -0
- package/dist/dropbox/api.d.mts +63 -0
- package/dist/dropbox/api.d.mts.map +1 -0
- package/dist/dropbox/api.mjs +565 -0
- package/dist/dropbox/api.mjs.map +1 -0
- package/dist/dropbox/state.d.mts +136 -0
- package/dist/dropbox/state.d.mts.map +1 -0
- package/dist/dropbox/state.mjs +209 -0
- package/dist/dropbox/state.mjs.map +1 -0
- package/dist/dropbox.d.mts +79 -0
- package/dist/dropbox.d.mts.map +1 -0
- package/dist/dropbox.mjs +124 -0
- package/dist/dropbox.mjs.map +1 -0
- package/dist/email-fixtures.d.mts +36 -0
- package/dist/email-fixtures.d.mts.map +1 -0
- package/dist/email-fixtures.mjs +1080 -0
- package/dist/email-fixtures.mjs.map +1 -0
- package/dist/email.d.mts +160 -0
- package/dist/email.d.mts.map +1 -0
- package/dist/email.mjs +608 -0
- package/dist/email.mjs.map +1 -0
- package/dist/emulator-compose.d.mts +40 -0
- package/dist/emulator-compose.d.mts.map +1 -0
- package/dist/emulator-compose.mjs +91 -0
- package/dist/emulator-compose.mjs.map +1 -0
- package/dist/emulator-http.d.mts +53 -0
- package/dist/emulator-http.d.mts.map +1 -0
- package/dist/emulator-http.mjs +117 -0
- package/dist/emulator-http.mjs.map +1 -0
- package/dist/emulator-kernel.d.mts +176 -0
- package/dist/emulator-kernel.d.mts.map +1 -0
- package/dist/emulator-kernel.mjs +413 -0
- package/dist/emulator-kernel.mjs.map +1 -0
- package/dist/fixture-route.d.mts +129 -0
- package/dist/fixture-route.d.mts.map +1 -0
- package/dist/fixture-route.mjs +257 -0
- package/dist/fixture-route.mjs.map +1 -0
- package/dist/fortnox/api.d.mts +92 -0
- package/dist/fortnox/api.d.mts.map +1 -0
- package/dist/fortnox/api.mjs +750 -0
- package/dist/fortnox/api.mjs.map +1 -0
- package/dist/fortnox/state.d.mts +533 -0
- package/dist/fortnox/state.d.mts.map +1 -0
- package/dist/fortnox/state.mjs +612 -0
- package/dist/fortnox/state.mjs.map +1 -0
- package/dist/fortnox.d.mts +128 -0
- package/dist/fortnox.d.mts.map +1 -0
- package/dist/fortnox.mjs +403 -0
- package/dist/fortnox.mjs.map +1 -0
- package/dist/gateway-evaluate-recordings.d.mts +12 -0
- package/dist/gateway-evaluate-recordings.d.mts.map +1 -0
- package/dist/gateway-evaluate-recordings.mjs +128 -0
- package/dist/gateway-evaluate-recordings.mjs.map +1 -0
- package/dist/gateway.d.mts +272 -0
- package/dist/gateway.d.mts.map +1 -0
- package/dist/gateway.mjs +400 -0
- package/dist/gateway.mjs.map +1 -0
- package/dist/github/api.d.mts +63 -0
- package/dist/github/api.d.mts.map +1 -0
- package/dist/github/api.mjs +527 -0
- package/dist/github/api.mjs.map +1 -0
- package/dist/github/state.d.mts +272 -0
- package/dist/github/state.d.mts.map +1 -0
- package/dist/github/state.mjs +303 -0
- package/dist/github/state.mjs.map +1 -0
- package/dist/github.d.mts +77 -0
- package/dist/github.d.mts.map +1 -0
- package/dist/github.mjs +180 -0
- package/dist/github.mjs.map +1 -0
- package/dist/google/calendar.d.mts +10 -0
- package/dist/google/calendar.d.mts.map +1 -0
- package/dist/google/calendar.mjs +252 -0
- package/dist/google/calendar.mjs.map +1 -0
- package/dist/google/drive.d.mts +8 -0
- package/dist/google/drive.d.mts.map +1 -0
- package/dist/google/drive.mjs +252 -0
- package/dist/google/drive.mjs.map +1 -0
- package/dist/google/gmail.d.mts +10 -0
- package/dist/google/gmail.d.mts.map +1 -0
- package/dist/google/gmail.mjs +591 -0
- package/dist/google/gmail.mjs.map +1 -0
- package/dist/google/shared.d.mts +107 -0
- package/dist/google/shared.d.mts.map +1 -0
- package/dist/google/shared.mjs +146 -0
- package/dist/google/shared.mjs.map +1 -0
- package/dist/google/state.d.mts +385 -0
- package/dist/google/state.d.mts.map +1 -0
- package/dist/google/state.mjs +496 -0
- package/dist/google/state.mjs.map +1 -0
- package/dist/google.d.mts +75 -0
- package/dist/google.d.mts.map +1 -0
- package/dist/google.mjs +210 -0
- package/dist/google.mjs.map +1 -0
- package/dist/linkedin-search/api.d.mts +45 -0
- package/dist/linkedin-search/api.d.mts.map +1 -0
- package/dist/linkedin-search/api.mjs +181 -0
- package/dist/linkedin-search/api.mjs.map +1 -0
- package/dist/linkedin-search/state.d.mts +123 -0
- package/dist/linkedin-search/state.d.mts.map +1 -0
- package/dist/linkedin-search/state.mjs +261 -0
- package/dist/linkedin-search/state.mjs.map +1 -0
- package/dist/linkedin-search.d.mts +69 -0
- package/dist/linkedin-search.d.mts.map +1 -0
- package/dist/linkedin-search.mjs +158 -0
- package/dist/linkedin-search.mjs.map +1 -0
- package/dist/mcp/api.d.mts +44 -0
- package/dist/mcp/api.d.mts.map +1 -0
- package/dist/mcp/api.mjs +557 -0
- package/dist/mcp/api.mjs.map +1 -0
- package/dist/mcp/recordings.d.mts +40 -0
- package/dist/mcp/recordings.d.mts.map +1 -0
- package/dist/mcp/recordings.mjs +2390 -0
- package/dist/mcp/recordings.mjs.map +1 -0
- package/dist/mcp/state.d.mts +71 -0
- package/dist/mcp/state.d.mts.map +1 -0
- package/dist/mcp/state.mjs +83 -0
- package/dist/mcp/state.mjs.map +1 -0
- package/dist/mcp.d.mts +84 -0
- package/dist/mcp.d.mts.map +1 -0
- package/dist/mcp.mjs +241 -0
- package/dist/mcp.mjs.map +1 -0
- package/dist/messages.d.mts +183 -0
- package/dist/messages.d.mts.map +1 -0
- package/dist/messages.mjs +532 -0
- package/dist/messages.mjs.map +1 -0
- package/dist/microsoft/api.d.mts +47 -0
- package/dist/microsoft/api.d.mts.map +1 -0
- package/dist/microsoft/api.mjs +178 -0
- package/dist/microsoft/api.mjs.map +1 -0
- package/dist/microsoft/calendar.d.mts +30 -0
- package/dist/microsoft/calendar.d.mts.map +1 -0
- package/dist/microsoft/calendar.mjs +271 -0
- package/dist/microsoft/calendar.mjs.map +1 -0
- package/dist/microsoft/drive.d.mts +36 -0
- package/dist/microsoft/drive.d.mts.map +1 -0
- package/dist/microsoft/drive.mjs +298 -0
- package/dist/microsoft/drive.mjs.map +1 -0
- package/dist/microsoft/graph.d.mts +198 -0
- package/dist/microsoft/graph.d.mts.map +1 -0
- package/dist/microsoft/graph.mjs +264 -0
- package/dist/microsoft/graph.mjs.map +1 -0
- package/dist/microsoft/mail.d.mts +48 -0
- package/dist/microsoft/mail.d.mts.map +1 -0
- package/dist/microsoft/mail.mjs +488 -0
- package/dist/microsoft/mail.mjs.map +1 -0
- package/dist/microsoft/state.d.mts +480 -0
- package/dist/microsoft/state.d.mts.map +1 -0
- package/dist/microsoft/state.mjs +625 -0
- package/dist/microsoft/state.mjs.map +1 -0
- package/dist/microsoft.d.mts +168 -0
- package/dist/microsoft.d.mts.map +1 -0
- package/dist/microsoft.mjs +483 -0
- package/dist/microsoft.mjs.map +1 -0
- package/dist/node.d.mts +47 -0
- package/dist/node.d.mts.map +1 -0
- package/dist/node.mjs +178 -0
- package/dist/node.mjs.map +1 -0
- package/dist/notion/api.d.mts +51 -0
- package/dist/notion/api.d.mts.map +1 -0
- package/dist/notion/api.mjs +507 -0
- package/dist/notion/api.mjs.map +1 -0
- package/dist/notion/state.d.mts +329 -0
- package/dist/notion/state.d.mts.map +1 -0
- package/dist/notion/state.mjs +432 -0
- package/dist/notion/state.mjs.map +1 -0
- package/dist/notion.d.mts +72 -0
- package/dist/notion.d.mts.map +1 -0
- package/dist/notion.mjs +127 -0
- package/dist/notion.mjs.map +1 -0
- package/dist/openai.d.mts +165 -0
- package/dist/openai.d.mts.map +1 -0
- package/dist/openai.mjs +141 -0
- package/dist/openai.mjs.map +1 -0
- package/dist/opencode-recordings.d.mts +7 -0
- package/dist/opencode-recordings.d.mts.map +1 -0
- package/dist/opencode-recordings.mjs +222 -0
- package/dist/opencode-recordings.mjs.map +1 -0
- package/dist/opencode.d.mts +70 -0
- package/dist/opencode.d.mts.map +1 -0
- package/dist/opencode.mjs +217 -0
- package/dist/opencode.mjs.map +1 -0
- package/dist/r2-fixtures.d.mts +36 -0
- package/dist/r2-fixtures.d.mts.map +1 -0
- package/dist/r2-fixtures.mjs +245 -0
- package/dist/r2-fixtures.mjs.map +1 -0
- package/dist/r2-guard.d.mts +43 -0
- package/dist/r2-guard.d.mts.map +1 -0
- package/dist/r2-guard.mjs +215 -0
- package/dist/r2-guard.mjs.map +1 -0
- package/dist/r2.d.mts +166 -0
- package/dist/r2.d.mts.map +1 -0
- package/dist/r2.mjs +517 -0
- package/dist/r2.mjs.map +1 -0
- package/dist/responses.d.mts +231 -0
- package/dist/responses.d.mts.map +1 -0
- package/dist/responses.mjs +556 -0
- package/dist/responses.mjs.map +1 -0
- package/dist/route-evidence.d.mts +45 -0
- package/dist/route-evidence.d.mts.map +1 -0
- package/dist/route-evidence.mjs +56 -0
- package/dist/route-evidence.mjs.map +1 -0
- package/dist/router.d.mts +93 -0
- package/dist/router.d.mts.map +1 -0
- package/dist/router.mjs +259 -0
- package/dist/router.mjs.map +1 -0
- package/dist/stateful-core.d.mts +17 -0
- package/dist/stateful-core.d.mts.map +1 -0
- package/dist/stateful-core.mjs +41 -0
- package/dist/stateful-core.mjs.map +1 -0
- package/dist/stateful-emulator.d.mts +565 -0
- package/dist/stateful-emulator.d.mts.map +1 -0
- package/dist/stateful-emulator.mjs +1228 -0
- package/dist/stateful-emulator.mjs.map +1 -0
- package/dist/stateful-secrets.d.mts +84 -0
- package/dist/stateful-secrets.d.mts.map +1 -0
- package/dist/stateful-secrets.mjs +216 -0
- package/dist/stateful-secrets.mjs.map +1 -0
- package/dist/subscription-usage-recordings.d.mts +9 -0
- package/dist/subscription-usage-recordings.d.mts.map +1 -0
- package/dist/subscription-usage-recordings.mjs +53 -0
- package/dist/subscription-usage-recordings.mjs.map +1 -0
- package/dist/subscription-usage.d.mts +53 -0
- package/dist/subscription-usage.d.mts.map +1 -0
- package/dist/subscription-usage.mjs +21 -0
- package/dist/subscription-usage.mjs.map +1 -0
- package/dist/telegram/api.d.mts +34 -0
- package/dist/telegram/api.d.mts.map +1 -0
- package/dist/telegram/api.mjs +257 -0
- package/dist/telegram/api.mjs.map +1 -0
- package/dist/telegram/state.d.mts +128 -0
- package/dist/telegram/state.d.mts.map +1 -0
- package/dist/telegram/state.mjs +154 -0
- package/dist/telegram/state.mjs.map +1 -0
- package/dist/telegram.d.mts +62 -0
- package/dist/telegram.d.mts.map +1 -0
- package/dist/telegram.mjs +127 -0
- package/dist/telegram.mjs.map +1 -0
- package/dist/todoist/api.d.mts +55 -0
- package/dist/todoist/api.d.mts.map +1 -0
- package/dist/todoist/api.mjs +415 -0
- package/dist/todoist/api.mjs.map +1 -0
- package/dist/todoist/state.d.mts +275 -0
- package/dist/todoist/state.d.mts.map +1 -0
- package/dist/todoist/state.mjs +345 -0
- package/dist/todoist/state.mjs.map +1 -0
- package/dist/todoist.d.mts +68 -0
- package/dist/todoist.d.mts.map +1 -0
- package/dist/todoist.mjs +181 -0
- package/dist/todoist.mjs.map +1 -0
- package/dist/xai.d.mts +267 -0
- package/dist/xai.d.mts.map +1 -0
- package/dist/xai.mjs +252 -0
- package/dist/xai.mjs.map +1 -0
- package/package.json +157 -0
- package/src/anthropic.ts +289 -0
- package/src/chat-completions.ts +924 -0
- package/src/codex.ts +296 -0
- package/src/dropbox/api.ts +1084 -0
- package/src/dropbox/state.ts +364 -0
- package/src/dropbox.ts +203 -0
- package/src/email-fixtures.ts +1297 -0
- package/src/email.ts +1108 -0
- package/src/emulator-compose.ts +147 -0
- package/src/emulator-http.ts +184 -0
- package/src/emulator-kernel.ts +844 -0
- package/src/fixture-route.ts +561 -0
- package/src/fortnox/api.ts +1352 -0
- package/src/fortnox/state.ts +798 -0
- package/src/fortnox.ts +801 -0
- package/src/gateway-evaluate-recordings.ts +153 -0
- package/src/gateway.ts +530 -0
- package/src/github/api.ts +986 -0
- package/src/github/state.ts +439 -0
- package/src/github.ts +271 -0
- package/src/google/calendar.ts +486 -0
- package/src/google/drive.ts +471 -0
- package/src/google/gmail.ts +1011 -0
- package/src/google/shared.ts +321 -0
- package/src/google/state.ts +686 -0
- package/src/google.ts +298 -0
- package/src/linkedin-search/api.ts +363 -0
- package/src/linkedin-search/state.ts +373 -0
- package/src/linkedin-search.ts +241 -0
- package/src/mcp/api.ts +995 -0
- package/src/mcp/recordings.ts +2665 -0
- package/src/mcp/state.ts +125 -0
- package/src/mcp.ts +319 -0
- package/src/messages.ts +844 -0
- package/src/microsoft/api.ts +426 -0
- package/src/microsoft/calendar.ts +491 -0
- package/src/microsoft/drive.ts +541 -0
- package/src/microsoft/graph.ts +550 -0
- package/src/microsoft/mail.ts +833 -0
- package/src/microsoft/state.ts +822 -0
- package/src/microsoft.ts +982 -0
- package/src/node.ts +293 -0
- package/src/notion/api.ts +976 -0
- package/src/notion/state.ts +512 -0
- package/src/notion.ts +210 -0
- package/src/openai.ts +198 -0
- package/src/opencode-recordings.ts +257 -0
- package/src/opencode.ts +271 -0
- package/src/r2-fixtures.ts +295 -0
- package/src/r2-guard.ts +323 -0
- package/src/r2.ts +890 -0
- package/src/responses.ts +901 -0
- package/src/route-evidence.ts +90 -0
- package/src/router.ts +490 -0
- package/src/stateful-core.ts +70 -0
- package/src/stateful-emulator.ts +2571 -0
- package/src/stateful-secrets.ts +299 -0
- package/src/subscription-usage-recordings.ts +77 -0
- package/src/subscription-usage.ts +68 -0
- package/src/telegram/api.ts +437 -0
- package/src/telegram/state.ts +229 -0
- package/src/telegram.ts +227 -0
- package/src/todoist/api.ts +736 -0
- package/src/todoist/state.ts +456 -0
- package/src/todoist.ts +316 -0
- package/src/xai.ts +341 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import * as Schema from "effect/Schema";
|
|
2
|
+
|
|
3
|
+
//#region src/github/state.d.ts
|
|
4
|
+
/** A GitHub owner login (the connector's owner pattern). */
|
|
5
|
+
declare const githubOwnerPattern: RegExp;
|
|
6
|
+
/** A repository name in plain characters (no `.`/`..`, no `.git` suffix; checked below). */
|
|
7
|
+
declare const githubRepoPattern: RegExp;
|
|
8
|
+
/** A label name in plain characters (the conformance seed pattern; never percent-encoded). */
|
|
9
|
+
declare const githubLabelNamePattern: RegExp;
|
|
10
|
+
/**
|
|
11
|
+
* The source of a relative file path whose segments never start with a dot (the conformance seed
|
|
12
|
+
* pattern), unanchored, so the route's raw pattern can add its length bound explicitly.
|
|
13
|
+
*/
|
|
14
|
+
declare const githubFilePathSource = "[A-Za-z0-9_-][A-Za-z0-9._-]*(?:/[A-Za-z0-9_-][A-Za-z0-9._-]*)*";
|
|
15
|
+
/** A relative file path whose segments never start with a dot (the conformance seed pattern). */
|
|
16
|
+
declare const githubFilePathPattern: RegExp;
|
|
17
|
+
/** A GitHub timestamp as the fixtures write it: whole seconds, UTC. */
|
|
18
|
+
declare const githubTimestampPattern: RegExp;
|
|
19
|
+
/** The largest issue number the emulator addresses (ten digits, the route pattern). */
|
|
20
|
+
declare const githubMaxIssueNumber = 9999999999;
|
|
21
|
+
/** The largest comment id the emulator addresses (fifteen digits, the delete route's pattern). */
|
|
22
|
+
declare const githubMaxCommentId = 999999999999999;
|
|
23
|
+
/** A user as the fixtures render it (`login`, `id`, `type`, `site_admin`). */
|
|
24
|
+
declare const GithubEmulatorUser: Schema.Struct<{
|
|
25
|
+
readonly login: Schema.String;
|
|
26
|
+
readonly id: Schema.Int;
|
|
27
|
+
readonly type: Schema.String;
|
|
28
|
+
readonly siteAdmin: Schema.Boolean;
|
|
29
|
+
}>;
|
|
30
|
+
type GithubEmulatorUser = typeof GithubEmulatorUser.Type;
|
|
31
|
+
/** The practice repository: its owner and name, its numeric id, and its default branch. */
|
|
32
|
+
declare const GithubEmulatorRepository: Schema.Struct<{
|
|
33
|
+
readonly owner: Schema.String;
|
|
34
|
+
readonly repo: Schema.String; /** The id the `Link` URLs name (`/repositories/<id>/labels`). */
|
|
35
|
+
readonly id: Schema.Int;
|
|
36
|
+
readonly defaultBranch: Schema.String;
|
|
37
|
+
}>;
|
|
38
|
+
type GithubEmulatorRepository = typeof GithubEmulatorRepository.Type;
|
|
39
|
+
/** A repository label. */
|
|
40
|
+
declare const GithubEmulatorLabel: Schema.Struct<{
|
|
41
|
+
readonly id: Schema.Int;
|
|
42
|
+
readonly nodeId: Schema.String;
|
|
43
|
+
readonly name: Schema.String; /** Six hex digits, as the fixtures write colors. */
|
|
44
|
+
readonly color: Schema.String;
|
|
45
|
+
readonly default: Schema.Boolean;
|
|
46
|
+
readonly description: Schema.NullOr<Schema.String>;
|
|
47
|
+
}>;
|
|
48
|
+
type GithubEmulatorLabel = typeof GithubEmulatorLabel.Type;
|
|
49
|
+
/** A seeded issue (its labels by name; never a pull request, never locked). */
|
|
50
|
+
declare const GithubEmulatorSeedIssue: Schema.Struct<{
|
|
51
|
+
readonly number: Schema.Int;
|
|
52
|
+
readonly id: Schema.Int;
|
|
53
|
+
readonly nodeId: Schema.String;
|
|
54
|
+
readonly title: Schema.String;
|
|
55
|
+
readonly body: Schema.NullOr<Schema.String>;
|
|
56
|
+
readonly state: Schema.Literals<readonly ["open", "closed"]>;
|
|
57
|
+
readonly stateReason: Schema.NullOr<Schema.String>;
|
|
58
|
+
readonly labels: Schema.$Array<Schema.String>;
|
|
59
|
+
readonly user: Schema.Struct<{
|
|
60
|
+
readonly login: Schema.String;
|
|
61
|
+
readonly id: Schema.Int;
|
|
62
|
+
readonly type: Schema.String;
|
|
63
|
+
readonly siteAdmin: Schema.Boolean;
|
|
64
|
+
}>;
|
|
65
|
+
readonly authorAssociation: Schema.String;
|
|
66
|
+
readonly createdAt: Schema.String;
|
|
67
|
+
readonly updatedAt: Schema.String;
|
|
68
|
+
readonly closedAt: Schema.NullOr<Schema.String>;
|
|
69
|
+
}>;
|
|
70
|
+
type GithubEmulatorSeedIssue = typeof GithubEmulatorSeedIssue.Type;
|
|
71
|
+
/** A stored issue: a seeded one, or one created through the recorded create flow. */
|
|
72
|
+
declare const GithubEmulatorIssue: Schema.Struct<{
|
|
73
|
+
/** Created here (only such issues are renamed or closed). */readonly createdHere: Schema.Boolean;
|
|
74
|
+
readonly number: Schema.Int;
|
|
75
|
+
readonly id: Schema.Int;
|
|
76
|
+
readonly nodeId: Schema.String;
|
|
77
|
+
readonly title: Schema.String;
|
|
78
|
+
readonly body: Schema.NullOr<Schema.String>;
|
|
79
|
+
readonly state: Schema.Literals<readonly ["open", "closed"]>;
|
|
80
|
+
readonly stateReason: Schema.NullOr<Schema.String>;
|
|
81
|
+
readonly labels: Schema.$Array<Schema.String>;
|
|
82
|
+
readonly user: Schema.Struct<{
|
|
83
|
+
readonly login: Schema.String;
|
|
84
|
+
readonly id: Schema.Int;
|
|
85
|
+
readonly type: Schema.String;
|
|
86
|
+
readonly siteAdmin: Schema.Boolean;
|
|
87
|
+
}>;
|
|
88
|
+
readonly authorAssociation: Schema.String;
|
|
89
|
+
readonly createdAt: Schema.String;
|
|
90
|
+
readonly updatedAt: Schema.String;
|
|
91
|
+
readonly closedAt: Schema.NullOr<Schema.String>;
|
|
92
|
+
}>;
|
|
93
|
+
type GithubEmulatorIssue = typeof GithubEmulatorIssue.Type;
|
|
94
|
+
/** A comment created here on an issue. */
|
|
95
|
+
declare const GithubEmulatorComment: Schema.Struct<{
|
|
96
|
+
readonly id: Schema.Int;
|
|
97
|
+
readonly issueNumber: Schema.Int;
|
|
98
|
+
readonly body: Schema.String;
|
|
99
|
+
readonly user: Schema.Struct<{
|
|
100
|
+
readonly login: Schema.String;
|
|
101
|
+
readonly id: Schema.Int;
|
|
102
|
+
readonly type: Schema.String;
|
|
103
|
+
readonly siteAdmin: Schema.Boolean;
|
|
104
|
+
}>;
|
|
105
|
+
readonly authorAssociation: Schema.String;
|
|
106
|
+
readonly createdAt: Schema.String;
|
|
107
|
+
readonly updatedAt: Schema.String;
|
|
108
|
+
}>;
|
|
109
|
+
type GithubEmulatorComment = typeof GithubEmulatorComment.Type;
|
|
110
|
+
/** A UTF-8 text file in the default branch. */
|
|
111
|
+
declare const GithubEmulatorFile: Schema.Struct<{
|
|
112
|
+
readonly path: Schema.String; /** The blob sha (40 lower-case hex digits). */
|
|
113
|
+
readonly sha: Schema.String;
|
|
114
|
+
readonly text: Schema.String;
|
|
115
|
+
}>;
|
|
116
|
+
type GithubEmulatorFile = typeof GithubEmulatorFile.Type;
|
|
117
|
+
declare const Counters: Schema.Struct<{
|
|
118
|
+
/** The number the next created issue takes (one past the maximum when exhausted). */readonly nextIssueNumber: Schema.Int; /** The id the next created comment takes (one past the maximum when exhausted). */
|
|
119
|
+
readonly nextCommentId: Schema.Int;
|
|
120
|
+
}>;
|
|
121
|
+
/** The whole emulator state (JSON-compatible; what `snapshot()` returns). */
|
|
122
|
+
declare const GithubEmulatorStateSchema: Schema.Struct<{
|
|
123
|
+
/** The authenticated user: the author of everything created here. */readonly viewer: Schema.Struct<{
|
|
124
|
+
readonly login: Schema.String;
|
|
125
|
+
readonly id: Schema.Int;
|
|
126
|
+
readonly type: Schema.String;
|
|
127
|
+
readonly siteAdmin: Schema.Boolean;
|
|
128
|
+
}>;
|
|
129
|
+
readonly repository: Schema.Struct<{
|
|
130
|
+
readonly owner: Schema.String;
|
|
131
|
+
readonly repo: Schema.String; /** The id the `Link` URLs name (`/repositories/<id>/labels`). */
|
|
132
|
+
readonly id: Schema.Int;
|
|
133
|
+
readonly defaultBranch: Schema.String;
|
|
134
|
+
}>;
|
|
135
|
+
readonly labels: Schema.$Array<Schema.Struct<{
|
|
136
|
+
readonly id: Schema.Int;
|
|
137
|
+
readonly nodeId: Schema.String;
|
|
138
|
+
readonly name: Schema.String; /** Six hex digits, as the fixtures write colors. */
|
|
139
|
+
readonly color: Schema.String;
|
|
140
|
+
readonly default: Schema.Boolean;
|
|
141
|
+
readonly description: Schema.NullOr<Schema.String>;
|
|
142
|
+
}>>;
|
|
143
|
+
readonly issues: Schema.$Array<Schema.Struct<{
|
|
144
|
+
/** Created here (only such issues are renamed or closed). */readonly createdHere: Schema.Boolean;
|
|
145
|
+
readonly number: Schema.Int;
|
|
146
|
+
readonly id: Schema.Int;
|
|
147
|
+
readonly nodeId: Schema.String;
|
|
148
|
+
readonly title: Schema.String;
|
|
149
|
+
readonly body: Schema.NullOr<Schema.String>;
|
|
150
|
+
readonly state: Schema.Literals<readonly ["open", "closed"]>;
|
|
151
|
+
readonly stateReason: Schema.NullOr<Schema.String>;
|
|
152
|
+
readonly labels: Schema.$Array<Schema.String>;
|
|
153
|
+
readonly user: Schema.Struct<{
|
|
154
|
+
readonly login: Schema.String;
|
|
155
|
+
readonly id: Schema.Int;
|
|
156
|
+
readonly type: Schema.String;
|
|
157
|
+
readonly siteAdmin: Schema.Boolean;
|
|
158
|
+
}>;
|
|
159
|
+
readonly authorAssociation: Schema.String;
|
|
160
|
+
readonly createdAt: Schema.String;
|
|
161
|
+
readonly updatedAt: Schema.String;
|
|
162
|
+
readonly closedAt: Schema.NullOr<Schema.String>;
|
|
163
|
+
}>>;
|
|
164
|
+
readonly comments: Schema.$Array<Schema.Struct<{
|
|
165
|
+
readonly id: Schema.Int;
|
|
166
|
+
readonly issueNumber: Schema.Int;
|
|
167
|
+
readonly body: Schema.String;
|
|
168
|
+
readonly user: Schema.Struct<{
|
|
169
|
+
readonly login: Schema.String;
|
|
170
|
+
readonly id: Schema.Int;
|
|
171
|
+
readonly type: Schema.String;
|
|
172
|
+
readonly siteAdmin: Schema.Boolean;
|
|
173
|
+
}>;
|
|
174
|
+
readonly authorAssociation: Schema.String;
|
|
175
|
+
readonly createdAt: Schema.String;
|
|
176
|
+
readonly updatedAt: Schema.String;
|
|
177
|
+
}>>; /** Ids of comments deleted here (a second delete answers the recorded 404). */
|
|
178
|
+
readonly deletedComments: Schema.$Array<Schema.Int>;
|
|
179
|
+
readonly files: Schema.$Array<Schema.Struct<{
|
|
180
|
+
readonly path: Schema.String; /** The blob sha (40 lower-case hex digits). */
|
|
181
|
+
readonly sha: Schema.String;
|
|
182
|
+
readonly text: Schema.String;
|
|
183
|
+
}>>;
|
|
184
|
+
readonly counters: Schema.Struct<{
|
|
185
|
+
/** The number the next created issue takes (one past the maximum when exhausted). */readonly nextIssueNumber: Schema.Int; /** The id the next created comment takes (one past the maximum when exhausted). */
|
|
186
|
+
readonly nextCommentId: Schema.Int;
|
|
187
|
+
}>;
|
|
188
|
+
}>;
|
|
189
|
+
/**
|
|
190
|
+
* The emulator state. The container is mutable (routes replace whole lists); every entity is
|
|
191
|
+
* replaced, never edited in place.
|
|
192
|
+
*/
|
|
193
|
+
type GithubEmulatorState = {
|
|
194
|
+
viewer: GithubEmulatorUser;
|
|
195
|
+
repository: GithubEmulatorRepository;
|
|
196
|
+
labels: ReadonlyArray<GithubEmulatorLabel>;
|
|
197
|
+
issues: ReadonlyArray<GithubEmulatorIssue>;
|
|
198
|
+
comments: ReadonlyArray<GithubEmulatorComment>;
|
|
199
|
+
deletedComments: ReadonlyArray<number>;
|
|
200
|
+
files: ReadonlyArray<GithubEmulatorFile>;
|
|
201
|
+
counters: typeof Counters.Type;
|
|
202
|
+
};
|
|
203
|
+
/** Account-variance profiles for the default seed. */
|
|
204
|
+
declare const GithubEmulatorProfile: Schema.Literals<readonly ["default", "empty"]>;
|
|
205
|
+
type GithubEmulatorProfile = typeof GithubEmulatorProfile.Type;
|
|
206
|
+
/**
|
|
207
|
+
* A typed seed. Start from `profile` (default `'default'`, the fixture entities); every other key,
|
|
208
|
+
* when given, replaces that part of the profile. Counters default to the profile's, raised above
|
|
209
|
+
* the highest seeded issue number; a counter given at or below a seeded value is invalid.
|
|
210
|
+
*/
|
|
211
|
+
declare const GithubEmulatorSeed: Schema.Struct<{
|
|
212
|
+
readonly profile: Schema.optionalKey<Schema.Literals<readonly ["default", "empty"]>>;
|
|
213
|
+
readonly viewer: Schema.optionalKey<Schema.Struct<{
|
|
214
|
+
readonly login: Schema.String;
|
|
215
|
+
readonly id: Schema.Int;
|
|
216
|
+
readonly type: Schema.String;
|
|
217
|
+
readonly siteAdmin: Schema.Boolean;
|
|
218
|
+
}>>;
|
|
219
|
+
readonly repository: Schema.optionalKey<Schema.Struct<{
|
|
220
|
+
readonly owner: Schema.String;
|
|
221
|
+
readonly repo: Schema.String; /** The id the `Link` URLs name (`/repositories/<id>/labels`). */
|
|
222
|
+
readonly id: Schema.Int;
|
|
223
|
+
readonly defaultBranch: Schema.String;
|
|
224
|
+
}>>;
|
|
225
|
+
readonly labels: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
226
|
+
readonly id: Schema.Int;
|
|
227
|
+
readonly nodeId: Schema.String;
|
|
228
|
+
readonly name: Schema.String; /** Six hex digits, as the fixtures write colors. */
|
|
229
|
+
readonly color: Schema.String;
|
|
230
|
+
readonly default: Schema.Boolean;
|
|
231
|
+
readonly description: Schema.NullOr<Schema.String>;
|
|
232
|
+
}>>>;
|
|
233
|
+
readonly issues: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
234
|
+
readonly number: Schema.Int;
|
|
235
|
+
readonly id: Schema.Int;
|
|
236
|
+
readonly nodeId: Schema.String;
|
|
237
|
+
readonly title: Schema.String;
|
|
238
|
+
readonly body: Schema.NullOr<Schema.String>;
|
|
239
|
+
readonly state: Schema.Literals<readonly ["open", "closed"]>;
|
|
240
|
+
readonly stateReason: Schema.NullOr<Schema.String>;
|
|
241
|
+
readonly labels: Schema.$Array<Schema.String>;
|
|
242
|
+
readonly user: Schema.Struct<{
|
|
243
|
+
readonly login: Schema.String;
|
|
244
|
+
readonly id: Schema.Int;
|
|
245
|
+
readonly type: Schema.String;
|
|
246
|
+
readonly siteAdmin: Schema.Boolean;
|
|
247
|
+
}>;
|
|
248
|
+
readonly authorAssociation: Schema.String;
|
|
249
|
+
readonly createdAt: Schema.String;
|
|
250
|
+
readonly updatedAt: Schema.String;
|
|
251
|
+
readonly closedAt: Schema.NullOr<Schema.String>;
|
|
252
|
+
}>>>;
|
|
253
|
+
readonly files: Schema.optionalKey<Schema.$Array<Schema.Struct<{
|
|
254
|
+
readonly path: Schema.String; /** The blob sha (40 lower-case hex digits). */
|
|
255
|
+
readonly sha: Schema.String;
|
|
256
|
+
readonly text: Schema.String;
|
|
257
|
+
}>>>;
|
|
258
|
+
readonly nextIssueNumber: Schema.optionalKey<Schema.Int>;
|
|
259
|
+
readonly nextCommentId: Schema.optionalKey<Schema.Int>;
|
|
260
|
+
}>;
|
|
261
|
+
type GithubEmulatorSeed = typeof GithubEmulatorSeed.Type;
|
|
262
|
+
/** Minted issue `id` values: `3000000000 + number`, as the fixtures write them. */
|
|
263
|
+
declare const mintedIssueIdBase = 3000000000;
|
|
264
|
+
declare const mintedIssueNodeId: (number: number) => string;
|
|
265
|
+
declare const mintedCommentNodeId: (id: number) => string;
|
|
266
|
+
/** Decode and build a seed; a string is the reason it is invalid. */
|
|
267
|
+
declare const buildSeedState: (input: unknown) => GithubEmulatorState | string;
|
|
268
|
+
/** Decode a full state (a restored snapshot); a string is the reason it is invalid. */
|
|
269
|
+
declare const decodeState: (input: unknown) => GithubEmulatorState | string;
|
|
270
|
+
//#endregion
|
|
271
|
+
export { GithubEmulatorComment, GithubEmulatorFile, GithubEmulatorIssue, GithubEmulatorLabel, GithubEmulatorProfile, GithubEmulatorRepository, GithubEmulatorSeed, GithubEmulatorSeedIssue, GithubEmulatorState, GithubEmulatorStateSchema, GithubEmulatorUser, buildSeedState, decodeState, githubFilePathPattern, githubFilePathSource, githubLabelNamePattern, githubMaxCommentId, githubMaxIssueNumber, githubOwnerPattern, githubRepoPattern, githubTimestampPattern, mintedCommentNodeId, mintedIssueIdBase, mintedIssueNodeId };
|
|
272
|
+
//# sourceMappingURL=state.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.mts","names":[],"sources":["../../src/github/state.ts"],"mappings":";;;;cA8Ba,kBAAA,EAAkB,MAAwD;AAAvF;AAAA,cAGa,iBAAA,EAAiB,MAA4B;;cAG7C,sBAAA,EAAsB,MAAsC;AANc;AAGvF;;;AAHuF,cAY1E,oBAAA;AAT6C;AAAA,cAY7C,qBAAA,EAAqB,MAA0C;;cAG/D,sBAAA,EAAsB,MAA2C;;cAOjE,oBAAA;AAbb;AAAA,cAkBa,kBAAA;;cAOA,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;;;KAOnB,kBAAA,UAA4B,kBAAA,CAAmB,IAAI;AA1B/D;AAAA,cA6Ba,wBAAA,EAAwB,MAAA,CAAA,MAAA;EAAA;gCA7ByC;EAAA;;;KA4ClE,wBAAA,UAAkC,wBAAA,CAAyB,IAAI;AArC1C;AAAA,cAwCpB,mBAAA,EAAmB,MAAA,CAAA,MAAA;EAAA;;gCAnCD;EAAA;;;;KA6CnB,mBAAA,UAA6B,mBAAA,CAAoB,IAAI;;cAGpD,uBAAA,EAAuB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;;;;KAgBxB,uBAAA,UAAiC,uBAAA,CAAwB,IAAI;;cAG5D,mBAAA,EAAmB,MAAA,CAAA,MAAA;EArDQ;;;;;;;;;;;;;;;;;;;;KA2D5B,mBAAA,UAA6B,mBAAA,CAAoB,IAAI;;cAGpD,qBAAA,EAAqB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;KAUtB,qBAAA,UAA+B,qBAAA,CAAsB,IAAI;;cAGxD,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;;KAOnB,kBAAA,UAA4B,kBAAA,CAAmB,IAAI;AAAA,cAEzD,QAAA,EAAQ,MAAA,CAAA,MAAA;EA/DkB;;;;cAuEnB,yBAAA,EAAyB,MAAA,CAAA,MAAA;;;;;;;;;;;;;;;;kCA7DG;IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA8E7B,mBAAA;EACV,MAAA,EAAQ,kBAAA;EACR,UAAA,EAAY,wBAAA;EACZ,MAAA,EAAQ,aAAA,CAAc,mBAAA;EACtB,MAAA,EAAQ,aAAA,CAAc,mBAAA;EACtB,QAAA,EAAU,aAAA,CAAc,qBAAA;EACxB,eAAA,EAAiB,aAAA;EACjB,KAAA,EAAO,aAAA,CAAc,kBAAA;EACrB,QAAA,SAAiB,QAAA,CAAS,IAAA;AAAA;;cAIf,qBAAA,EAAqB,MAAA,CAAA,QAAA;AAAA,KAEtB,qBAAA,UAA+B,qBAAA,CAAsB,IAAI;;;;;;cAOxD,kBAAA,EAAkB,MAAA,CAAA,MAAA;EAAA;;;;;;;;;;;;;;;;kCAhF0C;IAAA;;;;;;;;;;;;;;;;;;;;;;;;;kCAGzC;IAAA;;;;;;KAwFpB,kBAAA,UAA4B,kBAAA,CAAmB,IAAI;;cAYlD,iBAAA;AAAA,cAEA,iBAAA,GAAqB,MAAc;AAAA,cAEnC,mBAAA,GAAuB,EAAU;;cAkMjC,cAAA,GAAkB,KAAA,cAAiB,mBAAmB;;cAStD,WAAA,GAAe,KAAA,cAAiB,mBAAmB"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { Result } from "effect";
|
|
2
|
+
import * as Schema from "effect/Schema";
|
|
3
|
+
//#region src/github/state.ts
|
|
4
|
+
/**
|
|
5
|
+
* GitHub emulator state: the authenticated user, the practice repository, its labels, issues,
|
|
6
|
+
* comments, and files, the record of deleted comments, the counters, the seed input, the default
|
|
7
|
+
* seed, and the profiles (internal; re-exported by `src/github.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Entity shapes and the default entities follow the synthetic GitHub conformance fixtures, copied
|
|
10
|
+
* as data (the same owner, repository, labels, work issue, file, user, and ids as the fixtures and
|
|
11
|
+
* `githubConformanceFixtureSeeds`), never imported from SDK code. The repository id is the one the
|
|
12
|
+
* paging fixture's `Link` URLs name, and the default branch is the one the contents fixture's URLs
|
|
13
|
+
* name.
|
|
14
|
+
*
|
|
15
|
+
* Issue numbers below `nextIssueNumber` that the state does not hold are implied (the repository
|
|
16
|
+
* reached them, but no fixture shows them): an answer that would render one is not emulated.
|
|
17
|
+
* Numbers at or above it are not reached yet and answer the not-found fixture's 404. Created issue
|
|
18
|
+
* numbers and comment ids come from counters that only advance; the default seed starts them at the
|
|
19
|
+
* fixtures' created values (issue 42, comment 9000000001), and a seed's counters must lie above
|
|
20
|
+
* every seeded number. Created issue `id` and `node_id` values derive from the minted number in the
|
|
21
|
+
* fixtures' form (`3000000000 + number`, `I_kwSynthetic<number>`), and created comment `node_id`
|
|
22
|
+
* values from the minted id (`IC_kwSynthetic<id>`); a seed may not use those minted forms at or
|
|
23
|
+
* above its counters.
|
|
24
|
+
*
|
|
25
|
+
* Comments exist only as created here (no fixture shows a seeded comment). A deleted comment is
|
|
26
|
+
* kept as a record (`deletedComments`): deleting it again answers the comment fixture's 404.
|
|
27
|
+
*
|
|
28
|
+
* @experimental
|
|
29
|
+
*/
|
|
30
|
+
/** A GitHub owner login (the connector's owner pattern). */
|
|
31
|
+
const githubOwnerPattern = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/;
|
|
32
|
+
/** A repository name in plain characters (no `.`/`..`, no `.git` suffix; checked below). */
|
|
33
|
+
const githubRepoPattern = /^[A-Za-z0-9._-]{1,100}$/;
|
|
34
|
+
/** A label name in plain characters (the conformance seed pattern; never percent-encoded). */
|
|
35
|
+
const githubLabelNamePattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,49}$/;
|
|
36
|
+
/**
|
|
37
|
+
* The source of a relative file path whose segments never start with a dot (the conformance seed
|
|
38
|
+
* pattern), unanchored, so the route's raw pattern can add its length bound explicitly.
|
|
39
|
+
*/
|
|
40
|
+
const githubFilePathSource = "[A-Za-z0-9_-][A-Za-z0-9._-]*(?:/[A-Za-z0-9_-][A-Za-z0-9._-]*)*";
|
|
41
|
+
/** A relative file path whose segments never start with a dot (the conformance seed pattern). */
|
|
42
|
+
const githubFilePathPattern = new RegExp(`^${githubFilePathSource}$`);
|
|
43
|
+
/** A GitHub timestamp as the fixtures write it: whole seconds, UTC. */
|
|
44
|
+
const githubTimestampPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
|
|
45
|
+
const Timestamp = Schema.String.check(Schema.isPattern(githubTimestampPattern));
|
|
46
|
+
const PositiveInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1));
|
|
47
|
+
/** The largest issue number the emulator addresses (ten digits, the route pattern). */
|
|
48
|
+
const githubMaxIssueNumber = 9999999999;
|
|
49
|
+
const IssueNumber = PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxIssueNumber));
|
|
50
|
+
/** The largest comment id the emulator addresses (fifteen digits, the delete route's pattern). */
|
|
51
|
+
const githubMaxCommentId = 999999999999999;
|
|
52
|
+
const CommentId = PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxCommentId));
|
|
53
|
+
const LabelName = Schema.String.check(Schema.isPattern(githubLabelNamePattern));
|
|
54
|
+
/** A user as the fixtures render it (`login`, `id`, `type`, `site_admin`). */
|
|
55
|
+
const GithubEmulatorUser = Schema.Struct({
|
|
56
|
+
login: Schema.String.check(Schema.isPattern(githubOwnerPattern)),
|
|
57
|
+
id: PositiveInt,
|
|
58
|
+
type: Schema.String,
|
|
59
|
+
siteAdmin: Schema.Boolean
|
|
60
|
+
});
|
|
61
|
+
/** The practice repository: its owner and name, its numeric id, and its default branch. */
|
|
62
|
+
const GithubEmulatorRepository = Schema.Struct({
|
|
63
|
+
owner: Schema.String.check(Schema.isPattern(githubOwnerPattern)),
|
|
64
|
+
repo: Schema.String.check(Schema.isPattern(githubRepoPattern), Schema.makeFilter((repo) => repo !== "." && repo !== ".." && !repo.endsWith(".git") || "a repository name is not . or .. and does not end in .git")),
|
|
65
|
+
/** The id the `Link` URLs name (`/repositories/<id>/labels`). */
|
|
66
|
+
id: PositiveInt,
|
|
67
|
+
defaultBranch: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9._-]{1,100}$/))
|
|
68
|
+
});
|
|
69
|
+
/** A repository label. */
|
|
70
|
+
const GithubEmulatorLabel = Schema.Struct({
|
|
71
|
+
id: PositiveInt,
|
|
72
|
+
nodeId: Schema.String,
|
|
73
|
+
name: LabelName,
|
|
74
|
+
/** Six hex digits, as the fixtures write colors. */
|
|
75
|
+
color: Schema.String.check(Schema.isPattern(/^[0-9a-f]{6}$/)),
|
|
76
|
+
default: Schema.Boolean,
|
|
77
|
+
description: Schema.NullOr(Schema.String)
|
|
78
|
+
});
|
|
79
|
+
/** A seeded issue (its labels by name; never a pull request, never locked). */
|
|
80
|
+
const GithubEmulatorSeedIssue = Schema.Struct({
|
|
81
|
+
number: IssueNumber,
|
|
82
|
+
id: PositiveInt,
|
|
83
|
+
nodeId: Schema.String,
|
|
84
|
+
title: Schema.String.check(Schema.isMinLength(1)),
|
|
85
|
+
body: Schema.NullOr(Schema.String),
|
|
86
|
+
state: Schema.Literals(["open", "closed"]),
|
|
87
|
+
stateReason: Schema.NullOr(Schema.String),
|
|
88
|
+
labels: Schema.Array(LabelName),
|
|
89
|
+
user: GithubEmulatorUser,
|
|
90
|
+
authorAssociation: Schema.String,
|
|
91
|
+
createdAt: Timestamp,
|
|
92
|
+
updatedAt: Timestamp,
|
|
93
|
+
closedAt: Schema.NullOr(Timestamp)
|
|
94
|
+
});
|
|
95
|
+
/** A stored issue: a seeded one, or one created through the recorded create flow. */
|
|
96
|
+
const GithubEmulatorIssue = Schema.Struct({
|
|
97
|
+
...GithubEmulatorSeedIssue.fields,
|
|
98
|
+
/** Created here (only such issues are renamed or closed). */
|
|
99
|
+
createdHere: Schema.Boolean
|
|
100
|
+
});
|
|
101
|
+
/** A comment created here on an issue. */
|
|
102
|
+
const GithubEmulatorComment = Schema.Struct({
|
|
103
|
+
id: CommentId,
|
|
104
|
+
issueNumber: IssueNumber,
|
|
105
|
+
body: Schema.String,
|
|
106
|
+
user: GithubEmulatorUser,
|
|
107
|
+
authorAssociation: Schema.String,
|
|
108
|
+
createdAt: Timestamp,
|
|
109
|
+
updatedAt: Timestamp
|
|
110
|
+
});
|
|
111
|
+
/** A UTF-8 text file in the default branch. */
|
|
112
|
+
const GithubEmulatorFile = Schema.Struct({
|
|
113
|
+
path: Schema.String.check(Schema.isPattern(githubFilePathPattern), Schema.isMaxLength(200)),
|
|
114
|
+
/** The blob sha (40 lower-case hex digits). */
|
|
115
|
+
sha: Schema.String.check(Schema.isPattern(/^[0-9a-f]{40}$/)),
|
|
116
|
+
text: Schema.String
|
|
117
|
+
});
|
|
118
|
+
const Counters = Schema.Struct({
|
|
119
|
+
/** The number the next created issue takes (one past the maximum when exhausted). */
|
|
120
|
+
nextIssueNumber: PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxIssueNumber + 1)),
|
|
121
|
+
/** The id the next created comment takes (one past the maximum when exhausted). */
|
|
122
|
+
nextCommentId: PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxCommentId + 1))
|
|
123
|
+
});
|
|
124
|
+
/** The whole emulator state (JSON-compatible; what `snapshot()` returns). */
|
|
125
|
+
const GithubEmulatorStateSchema = Schema.Struct({
|
|
126
|
+
/** The authenticated user: the author of everything created here. */
|
|
127
|
+
viewer: GithubEmulatorUser,
|
|
128
|
+
repository: GithubEmulatorRepository,
|
|
129
|
+
labels: Schema.Array(GithubEmulatorLabel),
|
|
130
|
+
issues: Schema.Array(GithubEmulatorIssue),
|
|
131
|
+
comments: Schema.Array(GithubEmulatorComment),
|
|
132
|
+
/** Ids of comments deleted here (a second delete answers the recorded 404). */
|
|
133
|
+
deletedComments: Schema.Array(CommentId),
|
|
134
|
+
files: Schema.Array(GithubEmulatorFile),
|
|
135
|
+
counters: Counters
|
|
136
|
+
});
|
|
137
|
+
/** Account-variance profiles for the default seed. */
|
|
138
|
+
const GithubEmulatorProfile = Schema.Literals(["default", "empty"]);
|
|
139
|
+
/**
|
|
140
|
+
* A typed seed. Start from `profile` (default `'default'`, the fixture entities); every other key,
|
|
141
|
+
* when given, replaces that part of the profile. Counters default to the profile's, raised above
|
|
142
|
+
* the highest seeded issue number; a counter given at or below a seeded value is invalid.
|
|
143
|
+
*/
|
|
144
|
+
const GithubEmulatorSeed = Schema.Struct({
|
|
145
|
+
profile: Schema.optionalKey(GithubEmulatorProfile),
|
|
146
|
+
viewer: Schema.optionalKey(GithubEmulatorUser),
|
|
147
|
+
repository: Schema.optionalKey(GithubEmulatorRepository),
|
|
148
|
+
labels: Schema.optionalKey(Schema.Array(GithubEmulatorLabel)),
|
|
149
|
+
issues: Schema.optionalKey(Schema.Array(GithubEmulatorSeedIssue)),
|
|
150
|
+
files: Schema.optionalKey(Schema.Array(GithubEmulatorFile)),
|
|
151
|
+
nextIssueNumber: Schema.optionalKey(IssueNumber),
|
|
152
|
+
nextCommentId: Schema.optionalKey(CommentId)
|
|
153
|
+
});
|
|
154
|
+
const strict = { onExcessProperty: "error" };
|
|
155
|
+
const decodeSeedInput = Schema.decodeUnknownResult(GithubEmulatorSeed, strict);
|
|
156
|
+
const decodeStateInput = Schema.decodeUnknownResult(GithubEmulatorStateSchema, strict);
|
|
157
|
+
const issueMessage = (issue) => new Schema.SchemaError(issue).message;
|
|
158
|
+
/** Minted issue `id` values: `3000000000 + number`, as the fixtures write them. */
|
|
159
|
+
const mintedIssueIdBase = 3e9;
|
|
160
|
+
const mintedIssueNodeId = (number) => `I_kwSynthetic${number}`;
|
|
161
|
+
const mintedCommentNodeId = (id) => `IC_kwSynthetic${id}`;
|
|
162
|
+
const seededAt = "2026-09-30T12:00:00Z";
|
|
163
|
+
const defaultViewer = {
|
|
164
|
+
login: "yolk-synthetic-bot",
|
|
165
|
+
id: 1000001,
|
|
166
|
+
type: "User",
|
|
167
|
+
siteAdmin: false
|
|
168
|
+
};
|
|
169
|
+
const defaultRepository = {
|
|
170
|
+
owner: "yolk-synthetic",
|
|
171
|
+
repo: "conformance-practice",
|
|
172
|
+
id: 100000001,
|
|
173
|
+
defaultBranch: "main"
|
|
174
|
+
};
|
|
175
|
+
const label = (id, name, color) => ({
|
|
176
|
+
id,
|
|
177
|
+
nodeId: `LA_kwSynthetic${id}`,
|
|
178
|
+
name,
|
|
179
|
+
color,
|
|
180
|
+
default: false,
|
|
181
|
+
description: `Synthetic ${name} label`
|
|
182
|
+
});
|
|
183
|
+
const defaultLabels = [
|
|
184
|
+
label(700000001, "bug", "d73a4a"),
|
|
185
|
+
label(700000002, "documentation", "0075ca"),
|
|
186
|
+
label(700000003, "enhancement", "a2eeef"),
|
|
187
|
+
label(700000004, "question", "d876e3"),
|
|
188
|
+
label(700000005, "synthetic-conformance", "ededed")
|
|
189
|
+
];
|
|
190
|
+
const workIssue = {
|
|
191
|
+
number: 1,
|
|
192
|
+
id: mintedIssueIdBase + 1,
|
|
193
|
+
nodeId: mintedIssueNodeId(1),
|
|
194
|
+
title: "Synthetic work issue for conformance runs",
|
|
195
|
+
body: "Synthetic work issue: conformance cases add and remove a label and a comment here.",
|
|
196
|
+
state: "open",
|
|
197
|
+
stateReason: null,
|
|
198
|
+
labels: ["bug"],
|
|
199
|
+
user: defaultViewer,
|
|
200
|
+
authorAssociation: "OWNER",
|
|
201
|
+
createdAt: seededAt,
|
|
202
|
+
updatedAt: seededAt,
|
|
203
|
+
closedAt: null
|
|
204
|
+
};
|
|
205
|
+
const notesFile = {
|
|
206
|
+
path: "docs/synthetic-notes.txt",
|
|
207
|
+
sha: "5f1c0ffee5f1c0ffee5f1c0ffee5f1c0ffee0001",
|
|
208
|
+
text: "Synthetic conformance notes for the practice repository: café, naïve, façade.\nSecond synthetic line.\n"
|
|
209
|
+
};
|
|
210
|
+
const profileParts = (profile) => profile === "default" ? {
|
|
211
|
+
viewer: defaultViewer,
|
|
212
|
+
repository: defaultRepository,
|
|
213
|
+
labels: defaultLabels,
|
|
214
|
+
issues: [workIssue],
|
|
215
|
+
files: [notesFile],
|
|
216
|
+
counters: {
|
|
217
|
+
nextIssueNumber: 42,
|
|
218
|
+
nextCommentId: 9000000001
|
|
219
|
+
}
|
|
220
|
+
} : {
|
|
221
|
+
viewer: defaultViewer,
|
|
222
|
+
repository: defaultRepository,
|
|
223
|
+
labels: [],
|
|
224
|
+
issues: [],
|
|
225
|
+
files: [],
|
|
226
|
+
counters: {
|
|
227
|
+
nextIssueNumber: 1,
|
|
228
|
+
nextCommentId: 1
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const duplicate = (values) => values.find((value, index) => values.indexOf(value) !== index);
|
|
232
|
+
/** Integrity problems a decoded seed can still have (duplicates, dangling or minted values). */
|
|
233
|
+
const seedProblem = (parts) => {
|
|
234
|
+
const duplicates = [
|
|
235
|
+
["label name", duplicate(parts.labels.map((entry) => entry.name))],
|
|
236
|
+
["label id", duplicate(parts.labels.map((entry) => entry.id))],
|
|
237
|
+
["issue number", duplicate(parts.issues.map((issue) => issue.number))],
|
|
238
|
+
["issue id", duplicate(parts.issues.map((issue) => issue.id))],
|
|
239
|
+
["node id", duplicate([...parts.labels.map((entry) => entry.nodeId), ...parts.issues.map((i) => i.nodeId)])],
|
|
240
|
+
["file path", duplicate(parts.files.map((file) => file.path))]
|
|
241
|
+
];
|
|
242
|
+
for (const [kind, value] of duplicates) if (value !== void 0) return `duplicate ${kind} ${String(value)}`;
|
|
243
|
+
const labelNames = new Set(parts.labels.map((entry) => entry.name));
|
|
244
|
+
for (const issue of parts.issues) {
|
|
245
|
+
const missing = issue.labels.find((name) => !labelNames.has(name));
|
|
246
|
+
if (missing !== void 0) return `issue ${issue.number} names missing label ${missing}`;
|
|
247
|
+
if (duplicate(issue.labels) !== void 0) return `issue ${issue.number} repeats a label`;
|
|
248
|
+
if (issue.number >= parts.counters.nextIssueNumber) return `nextIssueNumber must lie above seeded issue ${issue.number}`;
|
|
249
|
+
if (issue.id >= 3e9 + parts.counters.nextIssueNumber) return `issue ${issue.number} uses an id in the minted form at or above nextIssueNumber`;
|
|
250
|
+
}
|
|
251
|
+
const reserved = [...parts.labels.map((entry) => entry.nodeId), ...parts.issues.map((i) => i.nodeId)].map((nodeId) => {
|
|
252
|
+
const issueNumber = /^I_kwSynthetic(\d+)$/.exec(nodeId)?.[1];
|
|
253
|
+
const commentId = /^IC_kwSynthetic(\d+)$/.exec(nodeId)?.[1];
|
|
254
|
+
return issueNumber !== void 0 && Number(issueNumber) >= parts.counters.nextIssueNumber || commentId !== void 0 && Number(commentId) >= parts.counters.nextCommentId ? nodeId : void 0;
|
|
255
|
+
}).find((nodeId) => nodeId !== void 0);
|
|
256
|
+
if (reserved !== void 0) return `node id ${reserved} uses a minted form at or above its counter`;
|
|
257
|
+
const prefix = parts.files.find((file) => parts.files.some((other) => other.path.startsWith(`${file.path}/`)));
|
|
258
|
+
return prefix === void 0 ? void 0 : `file ${prefix.path} is also a folder`;
|
|
259
|
+
};
|
|
260
|
+
/** Build the emulator state for a decoded seed; a string is an integrity problem. */
|
|
261
|
+
const stateFromSeed = (seed) => {
|
|
262
|
+
const profile = profileParts(seed.profile ?? "default");
|
|
263
|
+
const issues = seed.issues ?? profile.issues;
|
|
264
|
+
const highest = Math.max(0, ...issues.map((issue) => issue.number));
|
|
265
|
+
const parts = {
|
|
266
|
+
viewer: seed.viewer ?? profile.viewer,
|
|
267
|
+
repository: seed.repository ?? profile.repository,
|
|
268
|
+
labels: seed.labels ?? profile.labels,
|
|
269
|
+
issues,
|
|
270
|
+
files: seed.files ?? profile.files,
|
|
271
|
+
counters: {
|
|
272
|
+
nextIssueNumber: seed.nextIssueNumber ?? Math.max(profile.counters.nextIssueNumber, highest + 1),
|
|
273
|
+
nextCommentId: seed.nextCommentId ?? profile.counters.nextCommentId
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
return seedProblem(parts) ?? {
|
|
277
|
+
viewer: parts.viewer,
|
|
278
|
+
repository: parts.repository,
|
|
279
|
+
labels: parts.labels,
|
|
280
|
+
issues: parts.issues.map((issue) => ({
|
|
281
|
+
...issue,
|
|
282
|
+
createdHere: false
|
|
283
|
+
})),
|
|
284
|
+
comments: [],
|
|
285
|
+
deletedComments: [],
|
|
286
|
+
files: parts.files,
|
|
287
|
+
counters: parts.counters
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
/** Decode and build a seed; a string is the reason it is invalid. */
|
|
291
|
+
const buildSeedState = (input) => {
|
|
292
|
+
const decoded = decodeSeedInput(input);
|
|
293
|
+
return Result.isFailure(decoded) ? issueMessage(decoded.failure.issue) : stateFromSeed(decoded.success);
|
|
294
|
+
};
|
|
295
|
+
/** Decode a full state (a restored snapshot); a string is the reason it is invalid. */
|
|
296
|
+
const decodeState = (input) => {
|
|
297
|
+
const decoded = decodeStateInput(input);
|
|
298
|
+
return Result.isFailure(decoded) ? issueMessage(decoded.failure.issue) : { ...decoded.success };
|
|
299
|
+
};
|
|
300
|
+
//#endregion
|
|
301
|
+
export { GithubEmulatorComment, GithubEmulatorFile, GithubEmulatorIssue, GithubEmulatorLabel, GithubEmulatorProfile, GithubEmulatorRepository, GithubEmulatorSeed, GithubEmulatorSeedIssue, GithubEmulatorStateSchema, GithubEmulatorUser, buildSeedState, decodeState, githubFilePathPattern, githubFilePathSource, githubLabelNamePattern, githubMaxCommentId, githubMaxIssueNumber, githubOwnerPattern, githubRepoPattern, githubTimestampPattern, mintedCommentNodeId, mintedIssueIdBase, mintedIssueNodeId };
|
|
302
|
+
|
|
303
|
+
//# sourceMappingURL=state.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.mjs","names":[],"sources":["../../src/github/state.ts"],"sourcesContent":["/**\n * GitHub emulator state: the authenticated user, the practice repository, its labels, issues,\n * comments, and files, the record of deleted comments, the counters, the seed input, the default\n * seed, and the profiles (internal; re-exported by `src/github.ts`).\n *\n * Entity shapes and the default entities follow the synthetic GitHub conformance fixtures, copied\n * as data (the same owner, repository, labels, work issue, file, user, and ids as the fixtures and\n * `githubConformanceFixtureSeeds`), never imported from SDK code. The repository id is the one the\n * paging fixture's `Link` URLs name, and the default branch is the one the contents fixture's URLs\n * name.\n *\n * Issue numbers below `nextIssueNumber` that the state does not hold are implied (the repository\n * reached them, but no fixture shows them): an answer that would render one is not emulated.\n * Numbers at or above it are not reached yet and answer the not-found fixture's 404. Created issue\n * numbers and comment ids come from counters that only advance; the default seed starts them at the\n * fixtures' created values (issue 42, comment 9000000001), and a seed's counters must lie above\n * every seeded number. Created issue `id` and `node_id` values derive from the minted number in the\n * fixtures' form (`3000000000 + number`, `I_kwSynthetic<number>`), and created comment `node_id`\n * values from the minted id (`IC_kwSynthetic<id>`); a seed may not use those minted forms at or\n * above its counters.\n *\n * Comments exist only as created here (no fixture shows a seeded comment). A deleted comment is\n * kept as a record (`deletedComments`): deleting it again answers the comment fixture's 404.\n *\n * @experimental\n */\nimport { Result } from 'effect'\nimport * as Schema from 'effect/Schema'\n\n/** A GitHub owner login (the connector's owner pattern). */\nexport const githubOwnerPattern = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/\n\n/** A repository name in plain characters (no `.`/`..`, no `.git` suffix; checked below). */\nexport const githubRepoPattern = /^[A-Za-z0-9._-]{1,100}$/\n\n/** A label name in plain characters (the conformance seed pattern; never percent-encoded). */\nexport const githubLabelNamePattern = /^[A-Za-z0-9][A-Za-z0-9._-]{0,49}$/\n\n/**\n * The source of a relative file path whose segments never start with a dot (the conformance seed\n * pattern), unanchored, so the route's raw pattern can add its length bound explicitly.\n */\nexport const githubFilePathSource = '[A-Za-z0-9_-][A-Za-z0-9._-]*(?:/[A-Za-z0-9_-][A-Za-z0-9._-]*)*'\n\n/** A relative file path whose segments never start with a dot (the conformance seed pattern). */\nexport const githubFilePathPattern = new RegExp(`^${githubFilePathSource}$`)\n\n/** A GitHub timestamp as the fixtures write it: whole seconds, UTC. */\nexport const githubTimestampPattern = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/\n\nconst Timestamp = Schema.String.check(Schema.isPattern(githubTimestampPattern))\n\nconst PositiveInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(1))\n\n/** The largest issue number the emulator addresses (ten digits, the route pattern). */\nexport const githubMaxIssueNumber = 9_999_999_999\n\nconst IssueNumber = PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxIssueNumber))\n\n/** The largest comment id the emulator addresses (fifteen digits, the delete route's pattern). */\nexport const githubMaxCommentId = 999_999_999_999_999\n\nconst CommentId = PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxCommentId))\n\nconst LabelName = Schema.String.check(Schema.isPattern(githubLabelNamePattern))\n\n/** A user as the fixtures render it (`login`, `id`, `type`, `site_admin`). */\nexport const GithubEmulatorUser = Schema.Struct({\n login: Schema.String.check(Schema.isPattern(githubOwnerPattern)),\n id: PositiveInt,\n type: Schema.String,\n siteAdmin: Schema.Boolean\n})\n\nexport type GithubEmulatorUser = typeof GithubEmulatorUser.Type\n\n/** The practice repository: its owner and name, its numeric id, and its default branch. */\nexport const GithubEmulatorRepository = Schema.Struct({\n owner: Schema.String.check(Schema.isPattern(githubOwnerPattern)),\n repo: Schema.String.check(\n Schema.isPattern(githubRepoPattern),\n Schema.makeFilter(\n (repo: string) =>\n (repo !== '.' && repo !== '..' && !repo.endsWith('.git')) ||\n 'a repository name is not . or .. and does not end in .git'\n )\n ),\n /** The id the `Link` URLs name (`/repositories/<id>/labels`). */\n id: PositiveInt,\n defaultBranch: Schema.String.check(Schema.isPattern(/^[A-Za-z0-9._-]{1,100}$/))\n})\n\nexport type GithubEmulatorRepository = typeof GithubEmulatorRepository.Type\n\n/** A repository label. */\nexport const GithubEmulatorLabel = Schema.Struct({\n id: PositiveInt,\n nodeId: Schema.String,\n name: LabelName,\n /** Six hex digits, as the fixtures write colors. */\n color: Schema.String.check(Schema.isPattern(/^[0-9a-f]{6}$/)),\n default: Schema.Boolean,\n description: Schema.NullOr(Schema.String)\n})\n\nexport type GithubEmulatorLabel = typeof GithubEmulatorLabel.Type\n\n/** A seeded issue (its labels by name; never a pull request, never locked). */\nexport const GithubEmulatorSeedIssue = Schema.Struct({\n number: IssueNumber,\n id: PositiveInt,\n nodeId: Schema.String,\n title: Schema.String.check(Schema.isMinLength(1)),\n body: Schema.NullOr(Schema.String),\n state: Schema.Literals(['open', 'closed']),\n stateReason: Schema.NullOr(Schema.String),\n labels: Schema.Array(LabelName),\n user: GithubEmulatorUser,\n authorAssociation: Schema.String,\n createdAt: Timestamp,\n updatedAt: Timestamp,\n closedAt: Schema.NullOr(Timestamp)\n})\n\nexport type GithubEmulatorSeedIssue = typeof GithubEmulatorSeedIssue.Type\n\n/** A stored issue: a seeded one, or one created through the recorded create flow. */\nexport const GithubEmulatorIssue = Schema.Struct({\n ...GithubEmulatorSeedIssue.fields,\n /** Created here (only such issues are renamed or closed). */\n createdHere: Schema.Boolean\n})\n\nexport type GithubEmulatorIssue = typeof GithubEmulatorIssue.Type\n\n/** A comment created here on an issue. */\nexport const GithubEmulatorComment = Schema.Struct({\n id: CommentId,\n issueNumber: IssueNumber,\n body: Schema.String,\n user: GithubEmulatorUser,\n authorAssociation: Schema.String,\n createdAt: Timestamp,\n updatedAt: Timestamp\n})\n\nexport type GithubEmulatorComment = typeof GithubEmulatorComment.Type\n\n/** A UTF-8 text file in the default branch. */\nexport const GithubEmulatorFile = Schema.Struct({\n path: Schema.String.check(Schema.isPattern(githubFilePathPattern), Schema.isMaxLength(200)),\n /** The blob sha (40 lower-case hex digits). */\n sha: Schema.String.check(Schema.isPattern(/^[0-9a-f]{40}$/)),\n text: Schema.String\n})\n\nexport type GithubEmulatorFile = typeof GithubEmulatorFile.Type\n\nconst Counters = Schema.Struct({\n /** The number the next created issue takes (one past the maximum when exhausted). */\n nextIssueNumber: PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxIssueNumber + 1)),\n /** The id the next created comment takes (one past the maximum when exhausted). */\n nextCommentId: PositiveInt.check(Schema.isLessThanOrEqualTo(githubMaxCommentId + 1))\n})\n\n/** The whole emulator state (JSON-compatible; what `snapshot()` returns). */\nexport const GithubEmulatorStateSchema = Schema.Struct({\n /** The authenticated user: the author of everything created here. */\n viewer: GithubEmulatorUser,\n repository: GithubEmulatorRepository,\n labels: Schema.Array(GithubEmulatorLabel),\n issues: Schema.Array(GithubEmulatorIssue),\n comments: Schema.Array(GithubEmulatorComment),\n /** Ids of comments deleted here (a second delete answers the recorded 404). */\n deletedComments: Schema.Array(CommentId),\n files: Schema.Array(GithubEmulatorFile),\n counters: Counters\n})\n\n/**\n * The emulator state. The container is mutable (routes replace whole lists); every entity is\n * replaced, never edited in place.\n */\nexport type GithubEmulatorState = {\n viewer: GithubEmulatorUser\n repository: GithubEmulatorRepository\n labels: ReadonlyArray<GithubEmulatorLabel>\n issues: ReadonlyArray<GithubEmulatorIssue>\n comments: ReadonlyArray<GithubEmulatorComment>\n deletedComments: ReadonlyArray<number>\n files: ReadonlyArray<GithubEmulatorFile>\n counters: typeof Counters.Type\n}\n\n/** Account-variance profiles for the default seed. */\nexport const GithubEmulatorProfile = Schema.Literals(['default', 'empty'])\n\nexport type GithubEmulatorProfile = typeof GithubEmulatorProfile.Type\n\n/**\n * A typed seed. Start from `profile` (default `'default'`, the fixture entities); every other key,\n * when given, replaces that part of the profile. Counters default to the profile's, raised above\n * the highest seeded issue number; a counter given at or below a seeded value is invalid.\n */\nexport const GithubEmulatorSeed = Schema.Struct({\n profile: Schema.optionalKey(GithubEmulatorProfile),\n viewer: Schema.optionalKey(GithubEmulatorUser),\n repository: Schema.optionalKey(GithubEmulatorRepository),\n labels: Schema.optionalKey(Schema.Array(GithubEmulatorLabel)),\n issues: Schema.optionalKey(Schema.Array(GithubEmulatorSeedIssue)),\n files: Schema.optionalKey(Schema.Array(GithubEmulatorFile)),\n nextIssueNumber: Schema.optionalKey(IssueNumber),\n nextCommentId: Schema.optionalKey(CommentId)\n})\n\nexport type GithubEmulatorSeed = typeof GithubEmulatorSeed.Type\n\nconst strict = { onExcessProperty: 'error' } as const\n\nconst decodeSeedInput = Schema.decodeUnknownResult(GithubEmulatorSeed, strict)\n\nconst decodeStateInput = Schema.decodeUnknownResult(GithubEmulatorStateSchema, strict)\n\nconst issueMessage = (issue: Schema.SchemaError['issue']): string =>\n new Schema.SchemaError(issue).message\n\n/** Minted issue `id` values: `3000000000 + number`, as the fixtures write them. */\nexport const mintedIssueIdBase = 3_000_000_000\n\nexport const mintedIssueNodeId = (number: number): string => `I_kwSynthetic${number}`\n\nexport const mintedCommentNodeId = (id: number): string => `IC_kwSynthetic${id}`\n\n// Default entities, copied from the fixtures: the user, the practice repository (the paging\n// fixture's repository id, the contents fixture's branch), the five labels of the paging fixture,\n// the work issue of the label fixture, and the text file of the contents fixture.\n\nconst seededAt = '2026-09-30T12:00:00Z'\n\nconst defaultViewer: GithubEmulatorUser = {\n login: 'yolk-synthetic-bot',\n id: 1000001,\n type: 'User',\n siteAdmin: false\n}\n\nconst defaultRepository: GithubEmulatorRepository = {\n owner: 'yolk-synthetic',\n repo: 'conformance-practice',\n id: 100000001,\n defaultBranch: 'main'\n}\n\nconst label = (id: number, name: string, color: string): GithubEmulatorLabel => ({\n id,\n nodeId: `LA_kwSynthetic${id}`,\n name,\n color,\n default: false,\n description: `Synthetic ${name} label`\n})\n\nconst defaultLabels: ReadonlyArray<GithubEmulatorLabel> = [\n label(700000001, 'bug', 'd73a4a'),\n label(700000002, 'documentation', '0075ca'),\n label(700000003, 'enhancement', 'a2eeef'),\n label(700000004, 'question', 'd876e3'),\n label(700000005, 'synthetic-conformance', 'ededed')\n]\n\nconst workIssue: GithubEmulatorSeedIssue = {\n number: 1,\n id: mintedIssueIdBase + 1,\n nodeId: mintedIssueNodeId(1),\n title: 'Synthetic work issue for conformance runs',\n body: 'Synthetic work issue: conformance cases add and remove a label and a comment here.',\n state: 'open',\n stateReason: null,\n labels: ['bug'],\n user: defaultViewer,\n authorAssociation: 'OWNER',\n createdAt: seededAt,\n updatedAt: seededAt,\n closedAt: null\n}\n\nconst notesFile: GithubEmulatorFile = {\n path: 'docs/synthetic-notes.txt',\n sha: '5f1c0ffee5f1c0ffee5f1c0ffee5f1c0ffee0001',\n text:\n 'Synthetic conformance notes for the practice repository: café, naïve, façade.\\n' +\n 'Second synthetic line.\\n'\n}\n\ntype ProfileParts = {\n readonly viewer: GithubEmulatorUser\n readonly repository: GithubEmulatorRepository\n readonly labels: ReadonlyArray<GithubEmulatorLabel>\n readonly issues: ReadonlyArray<GithubEmulatorSeedIssue>\n readonly files: ReadonlyArray<GithubEmulatorFile>\n readonly counters: typeof Counters.Type\n}\n\nconst profileParts = (profile: GithubEmulatorProfile): ProfileParts =>\n profile === 'default'\n ? {\n viewer: defaultViewer,\n repository: defaultRepository,\n labels: defaultLabels,\n issues: [workIssue],\n files: [notesFile],\n // The lifecycle fixture's created issue and the comment fixture's created comment.\n counters: { nextIssueNumber: 42, nextCommentId: 9000000001 }\n }\n : {\n viewer: defaultViewer,\n repository: defaultRepository,\n labels: [],\n issues: [],\n files: [],\n counters: { nextIssueNumber: 1, nextCommentId: 1 }\n }\n\nconst duplicate = <A>(values: ReadonlyArray<A>): A | undefined =>\n values.find((value, index) => values.indexOf(value) !== index)\n\n/** Integrity problems a decoded seed can still have (duplicates, dangling or minted values). */\nconst seedProblem = (parts: ProfileParts): string | undefined => {\n const duplicates: ReadonlyArray<readonly [string, unknown]> = [\n ['label name', duplicate(parts.labels.map(entry => entry.name))],\n ['label id', duplicate(parts.labels.map(entry => entry.id))],\n ['issue number', duplicate(parts.issues.map(issue => issue.number))],\n ['issue id', duplicate(parts.issues.map(issue => issue.id))],\n // Node ids are global across types (labels and issues alike).\n [\n 'node id',\n duplicate([...parts.labels.map(entry => entry.nodeId), ...parts.issues.map(i => i.nodeId)])\n ],\n ['file path', duplicate(parts.files.map(file => file.path))]\n ]\n\n for (const [kind, value] of duplicates) {\n if (value !== undefined) return `duplicate ${kind} ${String(value)}`\n }\n\n const labelNames = new Set(parts.labels.map(entry => entry.name))\n\n for (const issue of parts.issues) {\n const missing = issue.labels.find(name => !labelNames.has(name))\n\n if (missing !== undefined) return `issue ${issue.number} names missing label ${missing}`\n\n if (duplicate(issue.labels) !== undefined) return `issue ${issue.number} repeats a label`\n\n if (issue.number >= parts.counters.nextIssueNumber) {\n return `nextIssueNumber must lie above seeded issue ${issue.number}`\n }\n\n // Minted ids never collide with seeded ones.\n if (issue.id >= mintedIssueIdBase + parts.counters.nextIssueNumber) {\n return `issue ${issue.number} uses an id in the minted form at or above nextIssueNumber`\n }\n }\n\n // Every minted node id form is reserved across all seeded node ids, of issues and labels alike.\n const reserved = [...parts.labels.map(entry => entry.nodeId), ...parts.issues.map(i => i.nodeId)]\n .map(nodeId => {\n const issueNumber = /^I_kwSynthetic(\\d+)$/.exec(nodeId)?.[1]\n const commentId = /^IC_kwSynthetic(\\d+)$/.exec(nodeId)?.[1]\n\n return (issueNumber !== undefined && Number(issueNumber) >= parts.counters.nextIssueNumber) ||\n (commentId !== undefined && Number(commentId) >= parts.counters.nextCommentId)\n ? nodeId\n : undefined\n })\n .find(nodeId => nodeId !== undefined)\n\n if (reserved !== undefined) {\n return `node id ${reserved} uses a minted form at or above its counter`\n }\n\n const prefix = parts.files.find(file =>\n parts.files.some(other => other.path.startsWith(`${file.path}/`))\n )\n\n return prefix === undefined ? undefined : `file ${prefix.path} is also a folder`\n}\n\n/** Build the emulator state for a decoded seed; a string is an integrity problem. */\nconst stateFromSeed = (seed: GithubEmulatorSeed): GithubEmulatorState | string => {\n const profile = profileParts(seed.profile ?? 'default')\n const issues = seed.issues ?? profile.issues\n const highest = Math.max(0, ...issues.map(issue => issue.number))\n\n const parts: ProfileParts = {\n viewer: seed.viewer ?? profile.viewer,\n repository: seed.repository ?? profile.repository,\n labels: seed.labels ?? profile.labels,\n issues,\n files: seed.files ?? profile.files,\n counters: {\n // Raised above the seeded numbers unless the seed names the counter itself (then checked).\n nextIssueNumber:\n seed.nextIssueNumber ?? Math.max(profile.counters.nextIssueNumber, highest + 1),\n nextCommentId: seed.nextCommentId ?? profile.counters.nextCommentId\n }\n }\n\n const problem = seedProblem(parts)\n\n return (\n problem ?? {\n viewer: parts.viewer,\n repository: parts.repository,\n labels: parts.labels,\n issues: parts.issues.map(issue => ({ ...issue, createdHere: false })),\n comments: [],\n deletedComments: [],\n files: parts.files,\n counters: parts.counters\n }\n )\n}\n\n/** Decode and build a seed; a string is the reason it is invalid. */\nexport const buildSeedState = (input: unknown): GithubEmulatorState | string => {\n const decoded = decodeSeedInput(input)\n\n return Result.isFailure(decoded)\n ? issueMessage(decoded.failure.issue)\n : stateFromSeed(decoded.success)\n}\n\n/** Decode a full state (a restored snapshot); a string is the reason it is invalid. */\nexport const decodeState = (input: unknown): GithubEmulatorState | string => {\n const decoded = decodeStateInput(input)\n\n return Result.isFailure(decoded) ? issueMessage(decoded.failure.issue) : { ...decoded.success }\n}\n"],"mappings":"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"}
|