@hitch42/applet 0.1.1-beta.14 → 0.1.1-beta.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/server.d.ts +10 -1
- package/dist/_internal/server.js +16 -2
- package/dist/applet.js +12 -12
- package/dist/auth-D3CrCtZq.js +21 -0
- package/dist/{build-CwOM9C0W.js → build-XHoa_sJL.js} +1 -1
- package/dist/build-ueR7XjZT.js +2 -0
- package/dist/{ci-BKw14X2h.js → ci-B5-mH-YW.js} +1 -1
- package/dist/client.d.ts +3 -3
- package/dist/contract-BbOj5EB7.js +23 -0
- package/dist/{contract-CZdT22tB.d.ts → contract-D9wEvxGI.d.ts} +1 -1
- package/dist/{deploy-CaGPhe2h.js → deploy-C5JDIn2Y.js} +4 -3
- package/dist/device-BgIfytaR.js +135 -0
- package/dist/email-protocol-B9u_dh2p.d.ts +202 -0
- package/dist/{generate-CORu1X2X.js → generate-BV_emZgy.js} +39 -13
- package/dist/generate-C9bWqdaB.js +2 -0
- package/dist/hitch-file-url-BPKj9zVG.js +25 -0
- package/dist/index.d.ts +15 -25
- package/dist/index.js +80 -192
- package/dist/{init-CD-xOYWV.js → init-BGQ_bP44.js} +5 -5
- package/dist/{manifest-CuY3ICpN.js → load-config-Dkr2VxZN.js} +37 -2
- package/dist/{login-CUx3TmFQ.js → login-CceGvlMi.js} +3 -1
- package/dist/{logs-BySh9fnH.js → logs-DOkT5ots.js} +3 -3
- package/dist/{manifest-ARAy2HP7.d.ts → manifest-BSUtHbu-.d.ts} +1 -4
- package/dist/markdown-CwlqzBtP.js +88 -0
- package/dist/markdown-DSHOQIOb.d.ts +14 -0
- package/dist/markdown-editor-BmEaBzd7.d.ts +27 -0
- package/dist/markdown-editor-C5mLHGqu.js +428 -0
- package/dist/{project-z7x0omdw.js → project-CCVqCCgU.js} +5 -4
- package/dist/react/markdown-editor.d.ts +2 -0
- package/dist/react/markdown-editor.js +2 -0
- package/dist/react/markdown.d.ts +2 -0
- package/dist/react/markdown.js +2 -0
- package/dist/react.d.ts +2 -37
- package/dist/react.js +2 -534
- package/dist/{schedules-B_p9U-vM.js → schedules-D6-3v-Az.js} +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/store-B8N_8JIN.js +196 -0
- package/dist/{upload-DKZzz5kW.d.ts → upload-D_kkmne_.d.ts} +5 -9
- package/dist/{variables-D9nEFyOK.js → variables-BSFZnLxY.js} +2 -2
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +165 -35
- package/dist/workspace-8yqXsvce.js +31 -0
- package/fonts/inter/LICENSE.txt +92 -0
- package/fonts/inter/inter-cyrillic-ext.woff2 +0 -0
- package/fonts/inter/inter-cyrillic.woff2 +0 -0
- package/fonts/inter/inter-greek-ext.woff2 +0 -0
- package/fonts/inter/inter-greek.woff2 +0 -0
- package/fonts/inter/inter-latin-ext.woff2 +0 -0
- package/fonts/inter/inter-latin.woff2 +0 -0
- package/fonts/inter/inter-vietnamese.woff2 +0 -0
- package/fonts/inter.css +81 -0
- package/package.json +15 -1
- package/scaffold/.agents/skills/hitch-applets/references/markdown.md +20 -2
- package/scaffold/applet/src/client/styles/globals.css +6 -1
- package/dist/build-CeRZYhM9.js +0 -2
- package/dist/email-WA4jnzZ0.js +0 -211
- package/dist/email-protocol-DqJ6YCiC.d.ts +0 -230
- package/dist/generate-CtbF9Zxd.js +0 -2
- package/dist/load-config-BeQZ2yOa.js +0 -27
- package/dist/me-BW7Paary.js +0 -32
- package/dist/workspace-D0dnnlxL.js +0 -385
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { ContractProcedure, Meta } from "@orpc/contract";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
//#region src/hitch/email.d.ts
|
|
4
|
-
type EmailTags = Record<string, string>;
|
|
5
|
-
type CreateEmailPixelInput = {
|
|
6
|
-
tags?: EmailTags;
|
|
7
|
-
};
|
|
8
|
-
type CreateEmailPixelOutput = {
|
|
9
|
-
id: string;
|
|
10
|
-
url: string;
|
|
11
|
-
};
|
|
12
|
-
type GetEmailTrackerInput = {
|
|
13
|
-
id: string;
|
|
14
|
-
};
|
|
15
|
-
type MarkEmailTrackerSentInput = {
|
|
16
|
-
id: string;
|
|
17
|
-
sentAt?: string;
|
|
18
|
-
};
|
|
19
|
-
type EmailTracker = {
|
|
20
|
-
id: string;
|
|
21
|
-
url: string;
|
|
22
|
-
tags: EmailTags;
|
|
23
|
-
createdAt: string;
|
|
24
|
-
sentAt: string | null;
|
|
25
|
-
firstHitAt: string | null;
|
|
26
|
-
lastHitAt: string | null;
|
|
27
|
-
};
|
|
28
|
-
type ListEmailTrackersInput = {
|
|
29
|
-
filter?: EmailTags;
|
|
30
|
-
sentAt?: {
|
|
31
|
-
$gte?: string;
|
|
32
|
-
$lt?: string;
|
|
33
|
-
};
|
|
34
|
-
cursor?: string;
|
|
35
|
-
limit?: number;
|
|
36
|
-
};
|
|
37
|
-
type ListEmailTrackersOutput = {
|
|
38
|
-
trackers: EmailTracker[];
|
|
39
|
-
nextCursor: string | null;
|
|
40
|
-
};
|
|
41
|
-
declare const emailTagKeySchema: z.ZodType<string, string>;
|
|
42
|
-
declare const emailTagsSchema: z.ZodType<EmailTags, EmailTags>;
|
|
43
|
-
declare const createEmailPixelInputSchema: z.ZodType<CreateEmailPixelInput, CreateEmailPixelInput>;
|
|
44
|
-
declare const createEmailPixelOutputSchema: z.ZodType<CreateEmailPixelOutput, CreateEmailPixelOutput>;
|
|
45
|
-
declare const getEmailTrackerInputSchema: z.ZodType<GetEmailTrackerInput, GetEmailTrackerInput>;
|
|
46
|
-
declare const markEmailTrackerSentInputSchema: z.ZodType<MarkEmailTrackerSentInput, MarkEmailTrackerSentInput>;
|
|
47
|
-
declare const markEmailTrackerSentBodySchema: z.ZodType<{
|
|
48
|
-
sentAt?: string;
|
|
49
|
-
}, {
|
|
50
|
-
sentAt?: string;
|
|
51
|
-
}>;
|
|
52
|
-
declare const emailTrackerSchema: z.ZodType<EmailTracker, EmailTracker>;
|
|
53
|
-
declare const listEmailTrackersInputSchema: z.ZodType<ListEmailTrackersInput, ListEmailTrackersInput>;
|
|
54
|
-
declare const listEmailTrackersOutputSchema: z.ZodType<ListEmailTrackersOutput, ListEmailTrackersOutput>;
|
|
55
|
-
type EmailContract = {
|
|
56
|
-
mailboxes: {
|
|
57
|
-
list: ContractProcedure<z.ZodType<void, void>, z.ZodType<HitchEmailMailboxesOutput, HitchEmailMailboxesOutput>, Record<never, never>, Meta>;
|
|
58
|
-
};
|
|
59
|
-
threads: {
|
|
60
|
-
list: ContractProcedure<z.ZodType<ListHitchEmailThreadsInput, ListHitchEmailThreadsInput>, z.ZodType<HitchEmailThreadsOutput, HitchEmailThreadsOutput>, Record<never, never>, Meta>;
|
|
61
|
-
get: ContractProcedure<z.ZodType<HitchEmailIdInput, HitchEmailIdInput>, z.ZodType<HitchEmailThread, HitchEmailThread>, Record<never, never>, Meta>;
|
|
62
|
-
};
|
|
63
|
-
messages: {
|
|
64
|
-
/** Newest first. Pass threadId to page through one thread. */
|
|
65
|
-
list: ContractProcedure<z.ZodType<ListHitchEmailMessagesInput, ListHitchEmailMessagesInput>, z.ZodType<HitchEmailMessagesOutput, HitchEmailMessagesOutput>, Record<never, never>, Meta>;
|
|
66
|
-
get: ContractProcedure<z.ZodType<HitchEmailIdInput, HitchEmailIdInput>, z.ZodType<HitchEmailMessage, HitchEmailMessage>, Record<never, never>, Meta>;
|
|
67
|
-
send: ContractProcedure<z.ZodType<SendHitchEmailInput, SendHitchEmailInput>, z.ZodType<HitchEmailMessage, HitchEmailMessage>, Record<never, never>, Meta>;
|
|
68
|
-
raw: ContractProcedure<z.ZodType<HitchEmailIdInput, HitchEmailIdInput>, z.ZodType<HitchEmailRawOutput, HitchEmailRawOutput>, Record<never, never>, Meta>;
|
|
69
|
-
};
|
|
70
|
-
attachments: {
|
|
71
|
-
get: ContractProcedure<z.ZodType<HitchEmailIdInput, HitchEmailIdInput>, z.ZodType<HitchEmailAttachmentOutput, HitchEmailAttachmentOutput>, Record<never, never>, Meta>;
|
|
72
|
-
};
|
|
73
|
-
tracking: {
|
|
74
|
-
createPixel: ContractProcedure<z.ZodType<CreateEmailPixelInput | undefined, CreateEmailPixelInput | undefined>, z.ZodType<CreateEmailPixelOutput, CreateEmailPixelOutput>, Record<never, never>, Meta>;
|
|
75
|
-
markSent: ContractProcedure<z.ZodType<MarkEmailTrackerSentInput, MarkEmailTrackerSentInput>, z.ZodType<EmailTracker, EmailTracker>, Record<never, never>, Meta>;
|
|
76
|
-
get: ContractProcedure<z.ZodType<GetEmailTrackerInput, GetEmailTrackerInput>, z.ZodType<EmailTracker, EmailTracker>, Record<never, never>, Meta>;
|
|
77
|
-
list: ContractProcedure<z.ZodType<ListEmailTrackersInput | undefined, ListEmailTrackersInput | undefined>, z.ZodType<ListEmailTrackersOutput, ListEmailTrackersOutput>, Record<never, never>, Meta>;
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
declare function emailContract(appletCode: string): EmailContract;
|
|
81
|
-
type HitchEmailAddress = {
|
|
82
|
-
address: string;
|
|
83
|
-
name: string | null;
|
|
84
|
-
};
|
|
85
|
-
type HitchMailbox = {
|
|
86
|
-
id: string;
|
|
87
|
-
address: string;
|
|
88
|
-
label: string;
|
|
89
|
-
enabled: boolean;
|
|
90
|
-
receive: boolean;
|
|
91
|
-
canRead: boolean;
|
|
92
|
-
canSend: boolean;
|
|
93
|
-
};
|
|
94
|
-
type HitchEmailAttachment = {
|
|
95
|
-
id: string;
|
|
96
|
-
filename: string;
|
|
97
|
-
contentType: string;
|
|
98
|
-
sizeBytes: number;
|
|
99
|
-
contentId: string | null;
|
|
100
|
-
inline: boolean;
|
|
101
|
-
};
|
|
102
|
-
type HitchEmailMessage = {
|
|
103
|
-
id: string;
|
|
104
|
-
mailboxId: string;
|
|
105
|
-
threadId: string;
|
|
106
|
-
direction: "inbound" | "outbound";
|
|
107
|
-
status: "received" | "unknown" | "sent" | "failed";
|
|
108
|
-
messageId: string | null;
|
|
109
|
-
inReplyTo: string | null;
|
|
110
|
-
references: string[];
|
|
111
|
-
from: HitchEmailAddress;
|
|
112
|
-
to: HitchEmailAddress[];
|
|
113
|
-
cc: HitchEmailAddress[];
|
|
114
|
-
bcc: HitchEmailAddress[];
|
|
115
|
-
replyTo: HitchEmailAddress[];
|
|
116
|
-
subject: string;
|
|
117
|
-
text: string | null;
|
|
118
|
-
html: string | null;
|
|
119
|
-
sentAt: string | null;
|
|
120
|
-
automated: string | null;
|
|
121
|
-
authentication: {
|
|
122
|
-
spf: string | null;
|
|
123
|
-
dkim: string | null;
|
|
124
|
-
dmarc: string | null;
|
|
125
|
-
} | null;
|
|
126
|
-
parseError: string | null;
|
|
127
|
-
attachments: HitchEmailAttachment[];
|
|
128
|
-
userId: string | null;
|
|
129
|
-
appletId: string | null;
|
|
130
|
-
requestId: string | null;
|
|
131
|
-
errorDetail: string | null;
|
|
132
|
-
createdAt: string;
|
|
133
|
-
};
|
|
134
|
-
type HitchEmailThread = {
|
|
135
|
-
id: string;
|
|
136
|
-
mailboxId: string;
|
|
137
|
-
subject: string;
|
|
138
|
-
messageCount: number;
|
|
139
|
-
lastMessageAt: string;
|
|
140
|
-
createdAt: string;
|
|
141
|
-
};
|
|
142
|
-
type ListHitchEmailThreadsInput = {
|
|
143
|
-
mailboxId?: string;
|
|
144
|
-
cursor?: string;
|
|
145
|
-
limit?: number;
|
|
146
|
-
};
|
|
147
|
-
type ListHitchEmailMessagesInput = {
|
|
148
|
-
mailboxId?: string;
|
|
149
|
-
address?: string;
|
|
150
|
-
threadId?: string;
|
|
151
|
-
direction?: "inbound" | "outbound";
|
|
152
|
-
since?: string;
|
|
153
|
-
until?: string;
|
|
154
|
-
cursor?: string;
|
|
155
|
-
limit?: number;
|
|
156
|
-
};
|
|
157
|
-
type SendHitchEmailInput = {
|
|
158
|
-
mailboxId: string;
|
|
159
|
-
to?: string[];
|
|
160
|
-
cc?: string[];
|
|
161
|
-
bcc?: string[];
|
|
162
|
-
subject?: string;
|
|
163
|
-
text?: string;
|
|
164
|
-
html?: string;
|
|
165
|
-
replyToMessageId?: string;
|
|
166
|
-
attachmentFileIds?: string[];
|
|
167
|
-
requestId?: string;
|
|
168
|
-
};
|
|
169
|
-
type HitchEmailIdInput = {
|
|
170
|
-
id: string;
|
|
171
|
-
};
|
|
172
|
-
type HitchEmailMailboxesOutput = {
|
|
173
|
-
data: HitchMailbox[];
|
|
174
|
-
};
|
|
175
|
-
type HitchEmailThreadsOutput = {
|
|
176
|
-
data: HitchEmailThread[];
|
|
177
|
-
nextCursor: string | null;
|
|
178
|
-
};
|
|
179
|
-
type HitchEmailMessagesOutput = {
|
|
180
|
-
data: HitchEmailMessage[];
|
|
181
|
-
nextCursor: string | null;
|
|
182
|
-
};
|
|
183
|
-
type HitchEmailRawOutput = {
|
|
184
|
-
url: string;
|
|
185
|
-
};
|
|
186
|
-
type HitchEmailAttachmentOutput = {
|
|
187
|
-
url: string;
|
|
188
|
-
filename: string;
|
|
189
|
-
contentType: string;
|
|
190
|
-
sizeBytes: number;
|
|
191
|
-
};
|
|
192
|
-
declare const hitchEmailAddressSchema: z.ZodType<HitchEmailAddress, HitchEmailAddress>;
|
|
193
|
-
declare const hitchMailboxSchema: z.ZodType<HitchMailbox, HitchMailbox>;
|
|
194
|
-
declare const hitchEmailAttachmentSchema: z.ZodType<HitchEmailAttachment, HitchEmailAttachment>;
|
|
195
|
-
declare const hitchEmailMessageSchema: z.ZodType<HitchEmailMessage, HitchEmailMessage>;
|
|
196
|
-
declare const hitchEmailThreadSchema: z.ZodType<HitchEmailThread, HitchEmailThread>;
|
|
197
|
-
declare const listHitchEmailMailboxesOutputSchema: z.ZodType<HitchEmailMailboxesOutput, HitchEmailMailboxesOutput>;
|
|
198
|
-
declare const listHitchEmailThreadsOutputSchema: z.ZodType<HitchEmailThreadsOutput, HitchEmailThreadsOutput>;
|
|
199
|
-
declare const listHitchEmailMessagesOutputSchema: z.ZodType<HitchEmailMessagesOutput, HitchEmailMessagesOutput>;
|
|
200
|
-
declare const getHitchEmailRawOutputSchema: z.ZodType<HitchEmailRawOutput, HitchEmailRawOutput>;
|
|
201
|
-
declare const getHitchEmailAttachmentOutputSchema: z.ZodType<HitchEmailAttachmentOutput, HitchEmailAttachmentOutput>;
|
|
202
|
-
declare const hitchEmailIdInputSchema: z.ZodType<HitchEmailIdInput, HitchEmailIdInput>;
|
|
203
|
-
declare const listHitchEmailThreadsInputSchema: z.ZodType<ListHitchEmailThreadsInput, ListHitchEmailThreadsInput>;
|
|
204
|
-
declare const listHitchEmailMessagesInputSchema: z.ZodType<ListHitchEmailMessagesInput, ListHitchEmailMessagesInput>;
|
|
205
|
-
declare const sendHitchEmailInputSchema: z.ZodType<SendHitchEmailInput, SendHitchEmailInput>;
|
|
206
|
-
//#endregion
|
|
207
|
-
//#region src/server/telephony-protocol.d.ts
|
|
208
|
-
/** Handle events at least once and without order. Use eventId for idempotency.
|
|
209
|
-
* Read the message with hitch.telephony.messages.get({ id: messageId }). */
|
|
210
|
-
type TelephonyMessageReceivedEvent = {
|
|
211
|
-
eventId: string;
|
|
212
|
-
type: "message.received";
|
|
213
|
-
messageId: string;
|
|
214
|
-
numberId: string;
|
|
215
|
-
occurredAt: string;
|
|
216
|
-
};
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region src/server/email-protocol.d.ts
|
|
219
|
-
/** Handle events at least once and without order. Use eventId for idempotency.
|
|
220
|
-
* Read the message with hitch.email.messages.get({ id: messageId }). */
|
|
221
|
-
type EmailMessageReceivedEvent = {
|
|
222
|
-
eventId: string;
|
|
223
|
-
type: "message.received";
|
|
224
|
-
messageId: string;
|
|
225
|
-
mailboxId: string;
|
|
226
|
-
threadId: string;
|
|
227
|
-
occurredAt: string;
|
|
228
|
-
};
|
|
229
|
-
//#endregion
|
|
230
|
-
export { listEmailTrackersOutputSchema as A, hitchEmailAddressSchema as C, hitchEmailThreadSchema as D, hitchEmailMessageSchema as E, listHitchEmailThreadsOutputSchema as F, markEmailTrackerSentBodySchema as I, markEmailTrackerSentInputSchema as L, listHitchEmailMessagesInputSchema as M, listHitchEmailMessagesOutputSchema as N, hitchMailboxSchema as O, listHitchEmailThreadsInputSchema as P, sendHitchEmailInputSchema as R, getHitchEmailRawOutputSchema as S, hitchEmailIdInputSchema as T, emailTagKeySchema as _, HitchEmailAddress as a, getEmailTrackerInputSchema as b, HitchEmailThread as c, ListHitchEmailMessagesInput as d, ListHitchEmailThreadsInput as f, emailContract as g, createEmailPixelOutputSchema as h, EmailTracker as i, listHitchEmailMailboxesOutputSchema as j, listEmailTrackersInputSchema as k, HitchMailbox as l, createEmailPixelInputSchema as m, TelephonyMessageReceivedEvent as n, HitchEmailAttachment as o, SendHitchEmailInput as p, EmailContract as r, HitchEmailMessage as s, EmailMessageReceivedEvent as t, ListEmailTrackersOutput as u, emailTagsSchema as v, hitchEmailAttachmentSchema as w, getHitchEmailAttachmentOutputSchema as x, emailTrackerSchema as y };
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { r as appletSourceDefinitionSchema } from "./manifest-CuY3ICpN.js";
|
|
2
|
-
import { t as resolveWorkspaceOrg } from "./workspace-D0dnnlxL.js";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
|
-
import { resolve } from "node:path";
|
|
5
|
-
import { loadConfigFromFile } from "vite";
|
|
6
|
-
//#region src/typegen/load-config.ts
|
|
7
|
-
async function loadAppletSourceDefinition(root) {
|
|
8
|
-
const path = resolve(root, "applet.manifest.ts");
|
|
9
|
-
if (!existsSync(path)) throw new Error(`No applet manifest found at ${path}.`);
|
|
10
|
-
const loaded = await loadConfigFromFile({
|
|
11
|
-
command: "build",
|
|
12
|
-
mode: "production"
|
|
13
|
-
}, path, root);
|
|
14
|
-
if (loaded === null) throw new Error(`No applet manifest found at ${path}.`);
|
|
15
|
-
const parsed = appletSourceDefinitionSchema.safeParse(loaded.config);
|
|
16
|
-
if (!parsed.success) throw new Error(`Invalid applet manifest at ${loaded.path}: ${parsed.error.message}`);
|
|
17
|
-
return parsed.data;
|
|
18
|
-
}
|
|
19
|
-
async function loadAppletConfig(root) {
|
|
20
|
-
const { dependencies: _dependencies, devDependencies: _devDependencies, ...definition } = await loadAppletSourceDefinition(root);
|
|
21
|
-
return {
|
|
22
|
-
org: resolveWorkspaceOrg(root),
|
|
23
|
-
...definition
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
//#endregion
|
|
27
|
-
export { loadAppletSourceDefinition as n, loadAppletConfig as t };
|
package/dist/me-BW7Paary.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { oc } from "@orpc/contract";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
//#region src/hitch/me.ts
|
|
4
|
-
const personSchema = z.object({
|
|
5
|
-
id: z.uuid(),
|
|
6
|
-
firstName: z.string(),
|
|
7
|
-
lastName: z.string(),
|
|
8
|
-
email: z.email()
|
|
9
|
-
});
|
|
10
|
-
const membershipSchema = z.object({
|
|
11
|
-
orgId: z.uuid(),
|
|
12
|
-
code: z.string(),
|
|
13
|
-
name: z.string(),
|
|
14
|
-
iconFileId: z.uuid().nullable(),
|
|
15
|
-
role: z.enum(["member", "owner"]),
|
|
16
|
-
capabilities: z.array(z.string())
|
|
17
|
-
});
|
|
18
|
-
const meSchema = z.object({
|
|
19
|
-
person: personSchema,
|
|
20
|
-
memberships: z.array(membershipSchema),
|
|
21
|
-
organization: z.object({
|
|
22
|
-
id: z.uuid(),
|
|
23
|
-
code: z.string()
|
|
24
|
-
}).nullable(),
|
|
25
|
-
multiOrg: z.boolean()
|
|
26
|
-
});
|
|
27
|
-
const meContract = { get: oc.route({
|
|
28
|
-
method: "GET",
|
|
29
|
-
path: "/v1/me"
|
|
30
|
-
}).input(z.void()).output(meSchema) };
|
|
31
|
-
//#endregion
|
|
32
|
-
export { meSchema as n, meContract as t };
|
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
import { createRequire } from "node:module";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import { homedir } from "node:os";
|
|
7
|
-
//#region ../shared/auth/src/store.mts
|
|
8
|
-
const DEFAULT_INSTANCE_URL = "https://app.hitch42.com";
|
|
9
|
-
var AuthenticationError = class extends Error {};
|
|
10
|
-
function isErrno(error, code) {
|
|
11
|
-
return error instanceof Error && "code" in error && error.code === code;
|
|
12
|
-
}
|
|
13
|
-
async function readJson(path) {
|
|
14
|
-
try {
|
|
15
|
-
return JSON.parse(await readFile(path, "utf8"));
|
|
16
|
-
} catch (error) {
|
|
17
|
-
if (isErrno(error, "ENOENT")) return void 0;
|
|
18
|
-
throw new Error(`Failed to read ${path}.`, { cause: error });
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
function isObject(value) {
|
|
22
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
23
|
-
}
|
|
24
|
-
function emptyCredentialStore() {
|
|
25
|
-
return { instances: {} };
|
|
26
|
-
}
|
|
27
|
-
async function healCredentialStore(credentialsPath, source, store, unrecognizedCount) {
|
|
28
|
-
const backupPath = `${credentialsPath}.bak`;
|
|
29
|
-
try {
|
|
30
|
-
try {
|
|
31
|
-
await writeFile(backupPath, source, {
|
|
32
|
-
flag: "wx",
|
|
33
|
-
mode: 384
|
|
34
|
-
});
|
|
35
|
-
} catch (error) {
|
|
36
|
-
if (!isErrno(error, "EEXIST")) throw error;
|
|
37
|
-
}
|
|
38
|
-
await chmod(backupPath, 384);
|
|
39
|
-
await writeFile(credentialsPath, `${JSON.stringify(store, null, 2)}\n`, { mode: 384 });
|
|
40
|
-
await chmod(credentialsPath, 384);
|
|
41
|
-
} catch {
|
|
42
|
-
console.error(unrecognizedCount === void 0 ? `hitch: failed to heal credential store at ${credentialsPath}; using an empty in-memory store.` : `hitch: failed to heal credential store at ${credentialsPath}; using recognized credentials in memory only.`);
|
|
43
|
-
return store;
|
|
44
|
-
}
|
|
45
|
-
console.error(unrecognizedCount === void 0 ? `hitch: reset unreadable credentials file (backup: ${backupPath}).` : unrecognizedCount === 0 ? `hitch: migrated credentials to per-organization storage (backup: ${backupPath}).` : `hitch: removed ${unrecognizedCount} unrecognized credential ${unrecognizedCount === 1 ? "entry" : "entries"} (backup: ${backupPath}).`);
|
|
46
|
-
return store;
|
|
47
|
-
}
|
|
48
|
-
async function readRawCredentialStore() {
|
|
49
|
-
const { credentialsPath } = storePaths();
|
|
50
|
-
let source;
|
|
51
|
-
try {
|
|
52
|
-
source = await readFile(credentialsPath, "utf8");
|
|
53
|
-
} catch (error) {
|
|
54
|
-
if (isErrno(error, "ENOENT")) return emptyCredentialStore();
|
|
55
|
-
throw new Error(`Failed to read ${credentialsPath}.`, { cause: error });
|
|
56
|
-
}
|
|
57
|
-
let value;
|
|
58
|
-
try {
|
|
59
|
-
value = JSON.parse(source);
|
|
60
|
-
} catch {
|
|
61
|
-
return healCredentialStore(credentialsPath, source, emptyCredentialStore());
|
|
62
|
-
}
|
|
63
|
-
if (!isObject(value) || !isObject(value.instances)) return healCredentialStore(credentialsPath, source, emptyCredentialStore());
|
|
64
|
-
const instances = Object.fromEntries(Object.entries(value.instances).flatMap(([instanceUrl, entry]) => {
|
|
65
|
-
if (isObject(entry) && typeof entry.organizationId === "string") {
|
|
66
|
-
const credentials = parseCredentials(entry);
|
|
67
|
-
return credentials === void 0 ? [] : [[instanceUrl, { [credentials.orgCode]: entry }]];
|
|
68
|
-
}
|
|
69
|
-
if (!isObject(entry)) return [];
|
|
70
|
-
return [[instanceUrl, Object.fromEntries(Object.entries(entry).filter(([orgCode, credentials]) => parseCredentials(credentials)?.orgCode === orgCode))]];
|
|
71
|
-
}));
|
|
72
|
-
const reshaped = Object.values(value.instances).some((entry) => !isObject(entry) || typeof entry.organizationId === "string");
|
|
73
|
-
const countLeaves = (store) => Object.values(store).reduce((total, entry) => total + (isObject(entry) && typeof entry.organizationId !== "string" ? Object.keys(entry).length : 1), 0);
|
|
74
|
-
const unrecognizedCount = countLeaves(value.instances) - countLeaves(instances);
|
|
75
|
-
if (!reshaped && unrecognizedCount === 0) return value;
|
|
76
|
-
return healCredentialStore(credentialsPath, source, { instances }, unrecognizedCount);
|
|
77
|
-
}
|
|
78
|
-
function parseCredentials(value) {
|
|
79
|
-
if (!isObject(value) || typeof value.organizationId !== "string" || typeof value.orgCode !== "string") return;
|
|
80
|
-
const organization = {
|
|
81
|
-
organizationId: value.organizationId,
|
|
82
|
-
orgCode: value.orgCode
|
|
83
|
-
};
|
|
84
|
-
if ((value.type === void 0 || value.type === "session") && typeof value.accessToken === "string" && (value.expiresAt === void 0 || typeof value.expiresAt === "number")) return {
|
|
85
|
-
type: "session",
|
|
86
|
-
accessToken: value.accessToken,
|
|
87
|
-
...value.expiresAt === void 0 ? {} : { expiresAt: value.expiresAt },
|
|
88
|
-
...organization
|
|
89
|
-
};
|
|
90
|
-
if (value.type === "apiKey" && typeof value.apiKey === "string") return {
|
|
91
|
-
type: "apiKey",
|
|
92
|
-
apiKey: value.apiKey,
|
|
93
|
-
...organization
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function normalizeInstanceUrl(instanceUrl) {
|
|
97
|
-
let url;
|
|
98
|
-
try {
|
|
99
|
-
url = new URL(instanceUrl);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
throw new Error(`Invalid Hitch instance URL: ${instanceUrl}`, { cause: error });
|
|
102
|
-
}
|
|
103
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error(`Invalid Hitch instance URL protocol: ${url.protocol}`);
|
|
104
|
-
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
105
|
-
url.search = "";
|
|
106
|
-
url.hash = "";
|
|
107
|
-
return url.toString().replace(/\/$/, "");
|
|
108
|
-
}
|
|
109
|
-
function organizationInstanceUrl(instanceUrl, orgCode) {
|
|
110
|
-
const url = new URL(normalizeInstanceUrl(instanceUrl));
|
|
111
|
-
const labels = url.hostname.split(".");
|
|
112
|
-
if (labels[0] !== "app" || labels.length < 2) return url.toString().replace(/\/$/, "");
|
|
113
|
-
url.hostname = [orgCode, ...labels.slice(1)].join(".");
|
|
114
|
-
return url.toString().replace(/\/$/, "");
|
|
115
|
-
}
|
|
116
|
-
function storePaths() {
|
|
117
|
-
const env = process.env;
|
|
118
|
-
const home = homedir();
|
|
119
|
-
const configDir = join(env.XDG_CONFIG_HOME || join(home, ".config"), "hitch");
|
|
120
|
-
return {
|
|
121
|
-
configDir,
|
|
122
|
-
cacheDir: join(env.XDG_CACHE_HOME || join(home, ".cache"), "hitch"),
|
|
123
|
-
configPath: join(configDir, "config.json"),
|
|
124
|
-
credentialsPath: join(configDir, "credentials.json")
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
async function resolveInstanceUrl(override) {
|
|
128
|
-
if (override !== void 0) return normalizeInstanceUrl(override);
|
|
129
|
-
const envInstanceUrl = process.env.HITCH_API_URL;
|
|
130
|
-
if (envInstanceUrl !== void 0 && envInstanceUrl.length > 0) return normalizeInstanceUrl(envInstanceUrl);
|
|
131
|
-
const { configPath } = storePaths();
|
|
132
|
-
const config = await readJson(configPath);
|
|
133
|
-
if (config === void 0) return DEFAULT_INSTANCE_URL;
|
|
134
|
-
if (!isObject(config) || config.instanceUrl !== void 0 && typeof config.instanceUrl !== "string") throw new Error(`${configPath}: expected { instanceUrl?: string }.`);
|
|
135
|
-
return normalizeInstanceUrl(config.instanceUrl ?? "https://app.hitch42.com");
|
|
136
|
-
}
|
|
137
|
-
async function readCredentialStore() {
|
|
138
|
-
const store = await readRawCredentialStore();
|
|
139
|
-
return { instances: Object.fromEntries(Object.entries(store.instances).map(([instanceUrl, credentialsByOrg]) => [instanceUrl, Object.fromEntries(Object.entries(credentialsByOrg).flatMap(([orgCode, value]) => {
|
|
140
|
-
const credentials = parseCredentials(value);
|
|
141
|
-
return credentials === void 0 ? [] : [[orgCode, credentials]];
|
|
142
|
-
}))])) };
|
|
143
|
-
}
|
|
144
|
-
async function getCredentialsForOrg(instanceUrl, orgCode) {
|
|
145
|
-
return (await readCredentialStore()).instances[normalizeInstanceUrl(instanceUrl)]?.[orgCode];
|
|
146
|
-
}
|
|
147
|
-
function environmentAuth() {
|
|
148
|
-
const apiKey = process.env.HITCH_API_KEY;
|
|
149
|
-
return apiKey !== void 0 && apiKey.length > 0 ? {
|
|
150
|
-
accessToken: apiKey,
|
|
151
|
-
source: "environment"
|
|
152
|
-
} : void 0;
|
|
153
|
-
}
|
|
154
|
-
function resolvedStoredAuth(credentials) {
|
|
155
|
-
return credentials === void 0 ? void 0 : {
|
|
156
|
-
accessToken: credentials.type === "apiKey" ? credentials.apiKey : credentials.accessToken,
|
|
157
|
-
credentialType: credentials.type,
|
|
158
|
-
organizationId: credentials.organizationId,
|
|
159
|
-
orgCode: credentials.orgCode,
|
|
160
|
-
source: "store"
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
function resolveStoredAuthForOrg(credentialsByOrg, orgCode) {
|
|
164
|
-
const exact = resolvedStoredAuth(credentialsByOrg[orgCode]);
|
|
165
|
-
if (exact !== void 0) return exact;
|
|
166
|
-
const sessions = Object.values(credentialsByOrg).filter((credentials) => credentials.type === "session").filter((credentials, index, all) => all.findIndex(({ accessToken }) => accessToken === credentials.accessToken) === index);
|
|
167
|
-
if (sessions.length === 1) return resolvedStoredAuth(sessions[0]);
|
|
168
|
-
if (sessions.length > 1) throw new AuthenticationError(`Multiple sessions are stored. Run hitch login for organization "${orgCode}".`);
|
|
169
|
-
const apiKeyOrgs = Object.values(credentialsByOrg).filter((credentials) => credentials.type === "apiKey").map(({ orgCode: storedOrg }) => storedOrg).sort();
|
|
170
|
-
if (apiKeyOrgs.length > 0) throw new AuthenticationError(`Stored API ${apiKeyOrgs.length === 1 ? "key is" : "keys are"} scoped to ${apiKeyOrgs.map((storedOrg) => `"${storedOrg}"`).join(", ")}, not "${orgCode}".`);
|
|
171
|
-
}
|
|
172
|
-
async function resolveAuthForOrg(instanceUrl, orgCode) {
|
|
173
|
-
const auth = environmentAuth();
|
|
174
|
-
if (auth !== void 0) return auth;
|
|
175
|
-
const normalizedUrl = normalizeInstanceUrl(instanceUrl);
|
|
176
|
-
const credentialsByOrg = Object.entries((await readCredentialStore()).instances).find(([instance]) => instance === normalizedUrl)?.[1];
|
|
177
|
-
return resolveStoredAuthForOrg(credentialsByOrg ?? {}, orgCode);
|
|
178
|
-
}
|
|
179
|
-
function rejectEnvironmentKey(response, auth) {
|
|
180
|
-
if (auth.source === "environment" && response.status === 401) throw new AuthenticationError("HITCH_API_KEY was rejected.");
|
|
181
|
-
}
|
|
182
|
-
function bearerToken(credentials) {
|
|
183
|
-
return "apiKey" in credentials ? credentials.apiKey : credentials.accessToken;
|
|
184
|
-
}
|
|
185
|
-
async function setCredentials(instanceUrl, credentials) {
|
|
186
|
-
const paths = storePaths();
|
|
187
|
-
const store = await readRawCredentialStore();
|
|
188
|
-
const normalizedUrl = normalizeInstanceUrl(instanceUrl);
|
|
189
|
-
const credentialsByOrg = store.instances[normalizedUrl];
|
|
190
|
-
store.instances[normalizedUrl] = {
|
|
191
|
-
...isObject(credentialsByOrg) ? credentialsByOrg : {},
|
|
192
|
-
[credentials.orgCode]: credentials
|
|
193
|
-
};
|
|
194
|
-
await mkdir(paths.configDir, { recursive: true });
|
|
195
|
-
await writeFile(paths.credentialsPath, `${JSON.stringify(store, null, 2)}\n`, { mode: 384 });
|
|
196
|
-
await chmod(paths.credentialsPath, 384);
|
|
197
|
-
}
|
|
198
|
-
//#endregion
|
|
199
|
-
//#region ../shared/auth/src/device.mts
|
|
200
|
-
const CLIENT_ID = "hitch-cli";
|
|
201
|
-
const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
202
|
-
function defaultOpenUrl(url) {
|
|
203
|
-
try {
|
|
204
|
-
const child = spawn(process.platform === "darwin" ? "open" : "xdg-open", [url], {
|
|
205
|
-
detached: true,
|
|
206
|
-
stdio: "ignore"
|
|
207
|
-
});
|
|
208
|
-
child.on("error", () => void 0);
|
|
209
|
-
child.unref();
|
|
210
|
-
} catch {}
|
|
211
|
-
}
|
|
212
|
-
function requiredObject(value, message) {
|
|
213
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(message);
|
|
214
|
-
return value;
|
|
215
|
-
}
|
|
216
|
-
async function jsonResponse(response) {
|
|
217
|
-
try {
|
|
218
|
-
return requiredObject(await response.json(), "Expected a JSON object response.");
|
|
219
|
-
} catch (error) {
|
|
220
|
-
throw new Error(`Invalid JSON response from ${response.url || "Hitch"}.`, { cause: error });
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
async function postJson(fetcher, url, body) {
|
|
224
|
-
const response = await fetcher(url, {
|
|
225
|
-
method: "POST",
|
|
226
|
-
headers: { "content-type": "application/json" },
|
|
227
|
-
body: JSON.stringify(body)
|
|
228
|
-
});
|
|
229
|
-
return {
|
|
230
|
-
body: await jsonResponse(response),
|
|
231
|
-
response
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
function parseDeviceCode(value) {
|
|
235
|
-
if (typeof value.device_code !== "string" || typeof value.user_code !== "string" || typeof value.verification_uri !== "string" || typeof value.verification_uri_complete !== "string" || typeof value.expires_in !== "number" || value.interval !== void 0 && typeof value.interval !== "number") throw new AuthenticationError("Hitch returned an invalid device authorization response.");
|
|
236
|
-
return value;
|
|
237
|
-
}
|
|
238
|
-
function parseToken(value) {
|
|
239
|
-
return typeof value.access_token === "string" && typeof value.token_type === "string" ? value : void 0;
|
|
240
|
-
}
|
|
241
|
-
function parseDeviceOrganization(value) {
|
|
242
|
-
if (typeof value.organizationId !== "string" || typeof value.orgCode !== "string") throw new AuthenticationError("Hitch returned an invalid device organization response.");
|
|
243
|
-
return value;
|
|
244
|
-
}
|
|
245
|
-
function parseMe(value) {
|
|
246
|
-
const person = requiredObject(value.person, "Hitch returned an invalid identity response.");
|
|
247
|
-
if (typeof person.id !== "string" || typeof person.firstName !== "string" || typeof person.lastName !== "string" || typeof person.email !== "string" || !Array.isArray(value.memberships)) throw new Error("Hitch returned an invalid identity response.");
|
|
248
|
-
const organization = value.organization === void 0 || value.organization === null ? null : requiredObject(value.organization, "Hitch returned an invalid identity response.");
|
|
249
|
-
if (organization !== null && (typeof organization.id !== "string" || typeof organization.code !== "string")) throw new Error("Hitch returned an invalid identity response.");
|
|
250
|
-
return {
|
|
251
|
-
memberships: value.memberships.map((membership) => {
|
|
252
|
-
const item = requiredObject(membership, "Hitch returned an invalid membership.");
|
|
253
|
-
if (typeof item.orgId !== "string" || typeof item.code !== "string" || typeof item.name !== "string") throw new Error("Hitch returned an invalid membership.");
|
|
254
|
-
return item;
|
|
255
|
-
}),
|
|
256
|
-
organization,
|
|
257
|
-
person
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
async function fetchMe(fetcher, instanceUrl, auth) {
|
|
261
|
-
const response = await fetcher(`${instanceUrl}/api/v1/me`, { headers: { Authorization: `Bearer ${auth.accessToken}` } });
|
|
262
|
-
rejectEnvironmentKey(response, auth);
|
|
263
|
-
if (auth.credentialType === "apiKey" && response.status === 401) throw new AuthenticationError("API key rejected.");
|
|
264
|
-
const body = await jsonResponse(response);
|
|
265
|
-
if (!response.ok) throw new AuthenticationError(typeof body.message === "string" ? body.message : `Failed to load the signed-in identity (${response.status}).`);
|
|
266
|
-
return parseMe(body);
|
|
267
|
-
}
|
|
268
|
-
async function pollForToken(fetcher, instanceUrl, device, now, sleep) {
|
|
269
|
-
const deadline = now() + device.expires_in * 1e3;
|
|
270
|
-
let interval = (device.interval ?? 5) * 1e3;
|
|
271
|
-
while (now() < deadline) {
|
|
272
|
-
await sleep(Math.min(interval, deadline - now()));
|
|
273
|
-
if (now() >= deadline) break;
|
|
274
|
-
const { body, response } = await postJson(fetcher, `${instanceUrl}/api/auth/device/token`, {
|
|
275
|
-
grant_type: DEVICE_GRANT,
|
|
276
|
-
device_code: device.device_code,
|
|
277
|
-
client_id: CLIENT_ID
|
|
278
|
-
});
|
|
279
|
-
const token = parseToken(body);
|
|
280
|
-
if (response.ok && token !== void 0) return token;
|
|
281
|
-
switch (body.error) {
|
|
282
|
-
case "authorization_pending": break;
|
|
283
|
-
case "slow_down":
|
|
284
|
-
interval += 5e3;
|
|
285
|
-
break;
|
|
286
|
-
case "expired_token": throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
287
|
-
case "access_denied": throw new AuthenticationError("Sign-in was denied.");
|
|
288
|
-
default: throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Sign-in failed (${response.status}).`);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
throw new AuthenticationError("The sign-in request expired. Run hitch login again.");
|
|
292
|
-
}
|
|
293
|
-
async function loginWithDevice(instanceUrl, options = {}) {
|
|
294
|
-
const fetcher = globalThis.fetch;
|
|
295
|
-
const now = Date.now;
|
|
296
|
-
const { body, response } = await postJson(fetcher, `${instanceUrl}/api/auth/device/code`, { client_id: CLIENT_ID });
|
|
297
|
-
if (!response.ok) throw new AuthenticationError(typeof body.error_description === "string" ? body.error_description : `Could not start sign-in (${response.status}).`);
|
|
298
|
-
const device = parseDeviceCode(body);
|
|
299
|
-
const verificationUrl = options.expectedOrg === void 0 ? device.verification_uri_complete : `${device.verification_uri_complete}&org=${encodeURIComponent(options.expectedOrg)}`;
|
|
300
|
-
console.log(`Open ${verificationUrl} and confirm code ${device.user_code}.`);
|
|
301
|
-
if (!options.noBrowser) try {
|
|
302
|
-
defaultOpenUrl(verificationUrl);
|
|
303
|
-
} catch {}
|
|
304
|
-
const token = await pollForToken(fetcher, instanceUrl, device, now, (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
305
|
-
const { body: organizationBody, response: organizationResponse } = await postJson(fetcher, `${instanceUrl}/api/auth/device/organization`, { device_code: device.device_code });
|
|
306
|
-
if (!organizationResponse.ok) throw new AuthenticationError("The sign-in did not resolve an organization.");
|
|
307
|
-
const organization = parseDeviceOrganization(organizationBody);
|
|
308
|
-
const me = await fetchMe(fetcher, instanceUrl, {
|
|
309
|
-
accessToken: token.access_token,
|
|
310
|
-
credentialType: "session",
|
|
311
|
-
source: "store"
|
|
312
|
-
});
|
|
313
|
-
const membership = me.memberships.find(({ orgId }) => orgId === organization.organizationId);
|
|
314
|
-
if (membership === void 0) throw new AuthenticationError("The device session is not scoped to a Hitch organization.");
|
|
315
|
-
const credentials = {
|
|
316
|
-
type: "session",
|
|
317
|
-
accessToken: token.access_token,
|
|
318
|
-
expiresAt: token.expires_in === void 0 ? void 0 : now() + token.expires_in * 1e3,
|
|
319
|
-
organizationId: organization.organizationId,
|
|
320
|
-
orgCode: organization.orgCode
|
|
321
|
-
};
|
|
322
|
-
await setCredentials(instanceUrl, credentials);
|
|
323
|
-
if (options.expectedOrg !== void 0 && organization.orgCode !== options.expectedOrg) throw new AuthenticationError(`logged in to "${organization.orgCode}" but this applet targets "${options.expectedOrg}" — confirm the right organization on the device page`);
|
|
324
|
-
return {
|
|
325
|
-
credentials,
|
|
326
|
-
me,
|
|
327
|
-
membership
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
//#endregion
|
|
331
|
-
//#region ../shared/auth/src/workspace.mts
|
|
332
|
-
const ORG_CODE_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
333
|
-
const require = createRequire(import.meta.url);
|
|
334
|
-
function readWorkspaceConfig(dir) {
|
|
335
|
-
const path = resolve(dir, "hitch.config.ts");
|
|
336
|
-
if (!existsSync(path)) return void 0;
|
|
337
|
-
let module;
|
|
338
|
-
try {
|
|
339
|
-
module = require(path);
|
|
340
|
-
} catch (error) {
|
|
341
|
-
throw new Error(`Failed to load ${path}.`, { cause: error });
|
|
342
|
-
}
|
|
343
|
-
const config = module !== null && typeof module === "object" && "default" in module ? module.default : module;
|
|
344
|
-
if (config === null || typeof config !== "object" || !("sdk" in config) || typeof config.sdk !== "string" || config.sdk.length === 0 || !("org" in config) || typeof config.org !== "string" || !ORG_CODE_PATTERN.test(config.org)) throw new Error(`Invalid Hitch config in ${path}: "sdk" must be a package spec and "org" an organization code.`);
|
|
345
|
-
const githubWorkflow = "githubWorkflow" in config ? config.githubWorkflow : void 0;
|
|
346
|
-
if (githubWorkflow !== void 0 && typeof githubWorkflow !== "boolean") throw new Error(`Invalid Hitch config in ${path}: "githubWorkflow" must be a boolean.`);
|
|
347
|
-
return {
|
|
348
|
-
sdk: config.sdk,
|
|
349
|
-
org: config.org,
|
|
350
|
-
githubWorkflow
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
function findWorkspaceConfig(cwd) {
|
|
354
|
-
const appletsDir = dirname(cwd);
|
|
355
|
-
return readWorkspaceConfig(cwd) ?? (basename(appletsDir) === "applets" ? readWorkspaceConfig(dirname(appletsDir)) : void 0);
|
|
356
|
-
}
|
|
357
|
-
//#endregion
|
|
358
|
-
//#region src/auth.ts
|
|
359
|
-
async function fetchWithOrgAuth(orgCode, request) {
|
|
360
|
-
const instanceUrl = await resolveInstanceUrl();
|
|
361
|
-
const organizationUrl = organizationInstanceUrl(instanceUrl, orgCode);
|
|
362
|
-
const auth = await resolveAuthForOrg(instanceUrl, orgCode);
|
|
363
|
-
if (auth !== void 0) {
|
|
364
|
-
const response = await request(organizationUrl, bearerToken(auth));
|
|
365
|
-
rejectEnvironmentKey(response, auth);
|
|
366
|
-
if (response.status !== 401) return response;
|
|
367
|
-
}
|
|
368
|
-
if (process.stdin.isTTY !== true) throw new AuthenticationError("Not logged in. Run applet login, or set HITCH_API_KEY.");
|
|
369
|
-
await loginWithDevice(instanceUrl, { expectedOrg: orgCode });
|
|
370
|
-
const credentials = await getCredentialsForOrg(instanceUrl, orgCode);
|
|
371
|
-
if (credentials === void 0) throw new Error(`login did not provide credentials for organization "${orgCode}"`);
|
|
372
|
-
return request(organizationUrl, bearerToken(credentials));
|
|
373
|
-
}
|
|
374
|
-
//#endregion
|
|
375
|
-
//#region src/workspace.ts
|
|
376
|
-
function resolveWorkspaceOrg(appletRoot) {
|
|
377
|
-
const appletsDir = dirname(appletRoot);
|
|
378
|
-
if (basename(appletsDir) === "applets") {
|
|
379
|
-
const config = readWorkspaceConfig(dirname(appletsDir));
|
|
380
|
-
if (config !== void 0) return config.org;
|
|
381
|
-
}
|
|
382
|
-
throw new Error(`No Hitch workspace found for ${appletRoot}. An applet must live at <workspace>/applets/<code> with hitch.config.ts in the workspace root.`);
|
|
383
|
-
}
|
|
384
|
-
//#endregion
|
|
385
|
-
export { loginWithDevice as a, bearerToken as c, resolveAuthForOrg as d, resolveInstanceUrl as f, readWorkspaceConfig as i, organizationInstanceUrl as l, fetchWithOrgAuth as n, AuthenticationError as o, findWorkspaceConfig as r, DEFAULT_INSTANCE_URL as s, resolveWorkspaceOrg as t, rejectEnvironmentKey as u };
|