@siteoshq/cli 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -2
- package/dist/cli.js +518 -23
- package/dist/cli.js.map +1 -1
- package/package.json +19 -20
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,438 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __esm = (fn, res) => function __init() {
|
|
5
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
6
|
+
};
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/services/cookie-verification.ts
|
|
13
|
+
var cookie_verification_exports = {};
|
|
14
|
+
__export(cookie_verification_exports, {
|
|
15
|
+
VerificationInstallation: () => VerificationInstallation,
|
|
16
|
+
assessCookieObservations: () => assessCookieObservations,
|
|
17
|
+
verificationTarget: () => verificationTarget,
|
|
18
|
+
verifyCookieWebsite: () => verifyCookieWebsite
|
|
19
|
+
});
|
|
20
|
+
import { z as z14 } from "zod";
|
|
21
|
+
function verificationTarget(websiteUrl, candidate) {
|
|
22
|
+
const website = new URL(websiteUrl);
|
|
23
|
+
const target = new URL(candidate ?? websiteUrl, website);
|
|
24
|
+
if (target.origin !== website.origin || target.username || target.password || target.hash || !["https:", "http:"].includes(target.protocol))
|
|
25
|
+
throw new Error(
|
|
26
|
+
"Verify a URL on the selected Project environment's origin, without credentials or fragments."
|
|
27
|
+
);
|
|
28
|
+
return target.toString();
|
|
29
|
+
}
|
|
30
|
+
function matchesName(value, names) {
|
|
31
|
+
return Boolean(
|
|
32
|
+
names && (names.exact.includes(value) || names.prefixes.some((prefix) => value.startsWith(prefix)))
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function assessCookieObservations(input) {
|
|
36
|
+
const issues = [];
|
|
37
|
+
const unknownOrigins = /* @__PURE__ */ new Set();
|
|
38
|
+
const unknownStorage = /* @__PURE__ */ new Set();
|
|
39
|
+
const services = input.envelope.config.services;
|
|
40
|
+
for (const request of input.requests) {
|
|
41
|
+
const matches = services.filter(
|
|
42
|
+
(service) => service.lifecycle && [
|
|
43
|
+
...service.lifecycle.scriptOrigins,
|
|
44
|
+
...service.lifecycle.iframeOrigins,
|
|
45
|
+
...service.lifecycle.pixelOrigins
|
|
46
|
+
].some((url) => new URL(url).origin === request.origin)
|
|
47
|
+
);
|
|
48
|
+
const state = input.observations.find(
|
|
49
|
+
(item) => item.scenario === request.scenario
|
|
50
|
+
)?.state;
|
|
51
|
+
if (matches.length) {
|
|
52
|
+
const allowed = matches.some(
|
|
53
|
+
(service) => state?.services.find((item) => item.key === service.key)?.allowed
|
|
54
|
+
);
|
|
55
|
+
const advancedGoogle = input.envelope.config.integrations.googleConsentMode === "advanced" && matches.every(
|
|
56
|
+
(service) => ["google-analytics", "google-ads"].includes(service.key)
|
|
57
|
+
);
|
|
58
|
+
if (!allowed && !advancedGoogle)
|
|
59
|
+
issues.push({
|
|
60
|
+
code: "request_without_permission",
|
|
61
|
+
scenario: request.scenario,
|
|
62
|
+
detail: request.origin
|
|
63
|
+
});
|
|
64
|
+
} else if (request.origin !== input.firstPartyOrigin && !input.deliveryOrigins.includes(request.origin))
|
|
65
|
+
unknownOrigins.add(request.origin);
|
|
66
|
+
}
|
|
67
|
+
for (const observation of input.observations) {
|
|
68
|
+
for (const service of services) {
|
|
69
|
+
const allowed = observation.state.services.find(
|
|
70
|
+
(item) => item.key === service.key
|
|
71
|
+
)?.allowed;
|
|
72
|
+
const stored = observation.cookies.some(
|
|
73
|
+
(name) => matchesName(name, service.lifecycle?.firstPartyCookies)
|
|
74
|
+
) || observation.localStorage.some(
|
|
75
|
+
(name) => matchesName(name, service.lifecycle?.localStorage)
|
|
76
|
+
);
|
|
77
|
+
if (!allowed && stored)
|
|
78
|
+
issues.push({
|
|
79
|
+
code: "storage_without_permission",
|
|
80
|
+
scenario: observation.scenario,
|
|
81
|
+
detail: service.key
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
for (const name of observation.cookies) {
|
|
85
|
+
if (name !== "siteos_consent" && !services.some(
|
|
86
|
+
(service) => matchesName(name, service.lifecycle?.firstPartyCookies)
|
|
87
|
+
))
|
|
88
|
+
unknownStorage.add(`cookie:${name}`);
|
|
89
|
+
}
|
|
90
|
+
for (const name of observation.localStorage) {
|
|
91
|
+
if (!name.startsWith("siteos-cookie:") && !services.some(
|
|
92
|
+
(service) => matchesName(name, service.lifecycle?.localStorage)
|
|
93
|
+
))
|
|
94
|
+
unknownStorage.add(`localStorage:${name}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
issues,
|
|
99
|
+
unknownOrigins: [...unknownOrigins].sort(),
|
|
100
|
+
unknownStorage: [...unknownStorage].sort()
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
async function verifyCookieWebsite(input) {
|
|
104
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
105
|
+
const issues = [];
|
|
106
|
+
const requests = [];
|
|
107
|
+
const observations = [];
|
|
108
|
+
let envelope = null;
|
|
109
|
+
let scenario = "first-visit";
|
|
110
|
+
let overflow = false;
|
|
111
|
+
const installation = input.installation;
|
|
112
|
+
const browser = await (input.launch ?? (async () => {
|
|
113
|
+
const playwright = await import("playwright");
|
|
114
|
+
try {
|
|
115
|
+
return await playwright[input.browserName].launch({ headless: true });
|
|
116
|
+
} catch {
|
|
117
|
+
throw new Error(
|
|
118
|
+
`The ${input.browserName} browser is unavailable. Run npx playwright@1.61.1 install ${input.browserName}, then retry.`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}))();
|
|
122
|
+
const readState = async (page) => State.parse(
|
|
123
|
+
await page.evaluate(
|
|
124
|
+
() => window.SiteOSCookie.getDebugState()
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
const waitForRuntime = async (page) => {
|
|
128
|
+
await page.waitForFunction(
|
|
129
|
+
() => Boolean(
|
|
130
|
+
window.SiteOSCookie?.getDebugState().resolved
|
|
131
|
+
),
|
|
132
|
+
void 0,
|
|
133
|
+
{ timeout: 15e3 }
|
|
134
|
+
);
|
|
135
|
+
};
|
|
136
|
+
try {
|
|
137
|
+
for (const gpc of [false, true]) {
|
|
138
|
+
const context = await browser.newContext({
|
|
139
|
+
serviceWorkers: "block",
|
|
140
|
+
...gpc ? { extraHTTPHeaders: { "Sec-GPC": "1" } } : {}
|
|
141
|
+
});
|
|
142
|
+
if (gpc)
|
|
143
|
+
await context.addInitScript(
|
|
144
|
+
() => Object.defineProperty(navigator, "globalPrivacyControl", {
|
|
145
|
+
get: () => true
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
const page = await context.newPage();
|
|
149
|
+
page.setDefaultTimeout(15e3);
|
|
150
|
+
page.setDefaultNavigationTimeout(25e3);
|
|
151
|
+
const pending = /* @__PURE__ */ new Set();
|
|
152
|
+
page.on("request", (request) => {
|
|
153
|
+
if (!/^https?:/u.test(request.url())) return;
|
|
154
|
+
if (requests.length >= 2e3) {
|
|
155
|
+
overflow = true;
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
requests.push({
|
|
159
|
+
origin: new URL(request.url()).origin,
|
|
160
|
+
type: request.resourceType(),
|
|
161
|
+
scenario
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
page.on("response", (response) => {
|
|
165
|
+
const expectedUrl = new URL(installation.delivery.configUrl);
|
|
166
|
+
const responseUrl = new URL(response.url());
|
|
167
|
+
if (responseUrl.origin !== expectedUrl.origin || responseUrl.pathname !== expectedUrl.pathname)
|
|
168
|
+
return;
|
|
169
|
+
const responseScenario = scenario;
|
|
170
|
+
const reading = (async () => {
|
|
171
|
+
let timeout;
|
|
172
|
+
try {
|
|
173
|
+
const raw = await Promise.race([
|
|
174
|
+
response.body(),
|
|
175
|
+
new Promise((_, reject) => {
|
|
176
|
+
timeout = setTimeout(() => reject(new Error("timeout")), 5e3);
|
|
177
|
+
})
|
|
178
|
+
]);
|
|
179
|
+
if (raw.byteLength > 512 * 1024) throw new Error("size");
|
|
180
|
+
const parsed = Envelope.parse(JSON.parse(raw.toString()));
|
|
181
|
+
if (parsed.publicKey !== installation.publicKey || parsed.revision !== installation.currentPublishedRevision)
|
|
182
|
+
throw new Error("revision");
|
|
183
|
+
envelope = parsed;
|
|
184
|
+
} catch {
|
|
185
|
+
issues.push({
|
|
186
|
+
code: "configuration_mismatch",
|
|
187
|
+
scenario: responseScenario,
|
|
188
|
+
detail: "Configuration is unavailable, invalid, or differs from the published revision."
|
|
189
|
+
});
|
|
190
|
+
} finally {
|
|
191
|
+
clearTimeout(timeout);
|
|
192
|
+
}
|
|
193
|
+
})();
|
|
194
|
+
pending.add(reading);
|
|
195
|
+
void reading.finally(() => pending.delete(reading));
|
|
196
|
+
});
|
|
197
|
+
scenario = gpc ? "gpc-first-visit" : "first-visit";
|
|
198
|
+
try {
|
|
199
|
+
await page.goto(input.url, { waitUntil: "domcontentloaded" });
|
|
200
|
+
if (new URL(page.url()).origin !== new URL(input.url).origin)
|
|
201
|
+
throw new Error("The website redirected to another origin.");
|
|
202
|
+
await waitForRuntime(page);
|
|
203
|
+
await Promise.all([...pending]);
|
|
204
|
+
const capture = async () => {
|
|
205
|
+
await page.waitForTimeout(1500);
|
|
206
|
+
if (new URL(page.url()).origin !== new URL(input.url).origin)
|
|
207
|
+
throw new Error("The website navigated to another origin.");
|
|
208
|
+
await waitForRuntime(page);
|
|
209
|
+
const state = await readState(page);
|
|
210
|
+
if (state.preview || state.resolved?.publicKey !== installation.publicKey || state.resolved?.revision !== installation.currentPublishedRevision)
|
|
211
|
+
issues.push({
|
|
212
|
+
code: "runtime_mismatch",
|
|
213
|
+
scenario,
|
|
214
|
+
detail: "The loaded runtime is a preview or uses another publication."
|
|
215
|
+
});
|
|
216
|
+
if (Number(state.runtimeVersion.split(".")[0]) < 11)
|
|
217
|
+
issues.push({
|
|
218
|
+
code: "runtime_outdated",
|
|
219
|
+
scenario,
|
|
220
|
+
detail: state.runtimeVersion
|
|
221
|
+
});
|
|
222
|
+
observations.push({
|
|
223
|
+
scenario,
|
|
224
|
+
state,
|
|
225
|
+
cookies: [
|
|
226
|
+
...new Set(
|
|
227
|
+
(await context.cookies()).map((cookie) => cookie.name)
|
|
228
|
+
)
|
|
229
|
+
].sort(),
|
|
230
|
+
localStorage: await page.evaluate(
|
|
231
|
+
() => Object.keys(localStorage).sort()
|
|
232
|
+
)
|
|
233
|
+
});
|
|
234
|
+
};
|
|
235
|
+
await capture();
|
|
236
|
+
if (gpc) {
|
|
237
|
+
const state = observations.at(-1).state;
|
|
238
|
+
if (!state.consent.globalPrivacyControl || !state.consent.privacyChoices.saleOrShareOptOut || !state.consent.privacyChoices.targetedAdvertisingOptOut)
|
|
239
|
+
issues.push({
|
|
240
|
+
code: "gpc_not_applied",
|
|
241
|
+
scenario,
|
|
242
|
+
detail: "GPC must be visible and both privacy opt-outs applied."
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
for (const action of [
|
|
246
|
+
"reject",
|
|
247
|
+
"accept",
|
|
248
|
+
"granular",
|
|
249
|
+
"withdraw"
|
|
250
|
+
]) {
|
|
251
|
+
scenario = action;
|
|
252
|
+
try {
|
|
253
|
+
await page.evaluate(async (choice) => {
|
|
254
|
+
const api = window.SiteOSCookie;
|
|
255
|
+
if (choice === "accept") await api.acceptAll();
|
|
256
|
+
else if (choice === "granular")
|
|
257
|
+
await api.updateConsent(
|
|
258
|
+
api.getConsent().categories.filter((key) => key !== "necessary").slice(0, 1)
|
|
259
|
+
);
|
|
260
|
+
else await api.rejectAll();
|
|
261
|
+
}, action);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (!(error instanceof Error) || !/Execution context was destroyed/u.test(error.message))
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
await capture();
|
|
267
|
+
const state = observations.at(-1).state;
|
|
268
|
+
if ((action === "reject" || action === "withdraw") && state.consent.categories.some((key) => key !== "necessary"))
|
|
269
|
+
issues.push({
|
|
270
|
+
code: "refusal_not_applied",
|
|
271
|
+
scenario,
|
|
272
|
+
detail: "Optional categories remain granted."
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
scenario = "returning-after-refusal";
|
|
276
|
+
await page.reload({ waitUntil: "domcontentloaded" });
|
|
277
|
+
await capture();
|
|
278
|
+
if (observations.at(-1).state.consent.categories.some((key) => key !== "necessary"))
|
|
279
|
+
issues.push({
|
|
280
|
+
code: "refusal_not_persisted",
|
|
281
|
+
scenario,
|
|
282
|
+
detail: "Refusal was not preserved across reload."
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
} catch {
|
|
286
|
+
issues.push({
|
|
287
|
+
code: "scenario_incomplete",
|
|
288
|
+
scenario,
|
|
289
|
+
detail: "The page or Cookie runtime did not complete this scenario within the time limit."
|
|
290
|
+
});
|
|
291
|
+
} finally {
|
|
292
|
+
await context.close();
|
|
293
|
+
await Promise.all([...pending]);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
} finally {
|
|
297
|
+
await browser.close();
|
|
298
|
+
}
|
|
299
|
+
const assessment = envelope ? assessCookieObservations({
|
|
300
|
+
envelope,
|
|
301
|
+
observations,
|
|
302
|
+
requests,
|
|
303
|
+
firstPartyOrigin: new URL(input.url).origin,
|
|
304
|
+
deliveryOrigins: Object.values(installation.delivery).filter((url) => typeof url === "string").map((url) => new URL(url).origin)
|
|
305
|
+
}) : { issues: [], unknownOrigins: [], unknownStorage: [] };
|
|
306
|
+
issues.push(...assessment.issues);
|
|
307
|
+
if (!envelope)
|
|
308
|
+
issues.push({
|
|
309
|
+
code: "configuration_not_observed",
|
|
310
|
+
scenario: "all",
|
|
311
|
+
detail: "No matching public configuration response was observed."
|
|
312
|
+
});
|
|
313
|
+
if (overflow)
|
|
314
|
+
issues.push({
|
|
315
|
+
code: "request_limit",
|
|
316
|
+
scenario: "all",
|
|
317
|
+
detail: "The request limit was reached; this run is incomplete."
|
|
318
|
+
});
|
|
319
|
+
const config = envelope;
|
|
320
|
+
const status = issues.length ? "failed" : assessment.unknownOrigins.length || assessment.unknownStorage.length || config?.config.integrations.googleConsentMode === "advanced" ? "needs-review" : "passed";
|
|
321
|
+
return {
|
|
322
|
+
schemaVersion: 1,
|
|
323
|
+
status,
|
|
324
|
+
startedAt,
|
|
325
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
326
|
+
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString(),
|
|
327
|
+
target: {
|
|
328
|
+
origin: new URL(input.url).origin,
|
|
329
|
+
path: new URL(input.url).pathname
|
|
330
|
+
},
|
|
331
|
+
browser: input.browserName,
|
|
332
|
+
publicKey: installation.publicKey,
|
|
333
|
+
revision: installation.currentPublishedRevision,
|
|
334
|
+
region: config?.trustedSignals?.region ?? null,
|
|
335
|
+
issues: [
|
|
336
|
+
...new Map(
|
|
337
|
+
issues.map((issue) => [JSON.stringify(issue), issue])
|
|
338
|
+
).values()
|
|
339
|
+
],
|
|
340
|
+
unknownOrigins: assessment.unknownOrigins,
|
|
341
|
+
unknownStorage: assessment.unknownStorage,
|
|
342
|
+
observations,
|
|
343
|
+
requestCounts: [
|
|
344
|
+
...new Set(requests.map((item) => `${item.scenario} ${item.origin}`))
|
|
345
|
+
].map((key) => ({
|
|
346
|
+
scenario: key.split(" ")[0],
|
|
347
|
+
origin: key.split(" ")[1],
|
|
348
|
+
count: requests.filter(
|
|
349
|
+
(item) => `${item.scenario} ${item.origin}` === key
|
|
350
|
+
).length
|
|
351
|
+
})),
|
|
352
|
+
limits: [
|
|
353
|
+
"One route, fresh local browser, 1.5-second observation per scenario, at most 2000 requests.",
|
|
354
|
+
"Consent actions use the public runtime API. Visual, keyboard and GTM Tag Assistant acceptance remain separate.",
|
|
355
|
+
"Unknown origins/storage need classification. First-party or server-side tracking and delayed/interaction-only resources require a source audit.",
|
|
356
|
+
"Geography is this browser's actual Edge location. Use regions resolve for simulations; do not spoof production geography.",
|
|
357
|
+
"No cookie values, request query strings, bodies, credentials or visitor identifiers are included. A pass covers only the observed scope, not legal compliance."
|
|
358
|
+
]
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
var Names, Service, Envelope, State, VerificationInstallation;
|
|
362
|
+
var init_cookie_verification = __esm({
|
|
363
|
+
"src/services/cookie-verification.ts"() {
|
|
364
|
+
"use strict";
|
|
365
|
+
Names = z14.object({
|
|
366
|
+
exact: z14.array(z14.string()),
|
|
367
|
+
prefixes: z14.array(z14.string())
|
|
368
|
+
});
|
|
369
|
+
Service = z14.object({
|
|
370
|
+
key: z14.string(),
|
|
371
|
+
purposeKey: z14.string(),
|
|
372
|
+
lifecycle: z14.object({
|
|
373
|
+
scriptOrigins: z14.array(z14.string()),
|
|
374
|
+
iframeOrigins: z14.array(z14.string()),
|
|
375
|
+
pixelOrigins: z14.array(z14.string()),
|
|
376
|
+
firstPartyCookies: Names,
|
|
377
|
+
localStorage: Names
|
|
378
|
+
}).optional()
|
|
379
|
+
});
|
|
380
|
+
Envelope = z14.object({
|
|
381
|
+
publicKey: z14.string(),
|
|
382
|
+
revision: z14.number(),
|
|
383
|
+
ruleKey: z14.string(),
|
|
384
|
+
profileKey: z14.string(),
|
|
385
|
+
trustedSignals: z14.object({
|
|
386
|
+
region: z14.object({
|
|
387
|
+
countryCode: z14.string().nullable(),
|
|
388
|
+
subdivisionCode: z14.string().nullable()
|
|
389
|
+
}).optional()
|
|
390
|
+
}).optional(),
|
|
391
|
+
config: z14.object({
|
|
392
|
+
services: z14.array(Service),
|
|
393
|
+
categories: z14.array(z14.object({ key: z14.string(), required: z14.boolean() })),
|
|
394
|
+
integrations: z14.object({ googleConsentMode: z14.string() })
|
|
395
|
+
})
|
|
396
|
+
});
|
|
397
|
+
State = z14.object({
|
|
398
|
+
runtimeVersion: z14.string(),
|
|
399
|
+
preview: z14.boolean(),
|
|
400
|
+
resolved: z14.object({
|
|
401
|
+
publicKey: z14.string(),
|
|
402
|
+
revision: z14.number(),
|
|
403
|
+
ruleKey: z14.string(),
|
|
404
|
+
profileKey: z14.string()
|
|
405
|
+
}).nullable(),
|
|
406
|
+
consent: z14.object({
|
|
407
|
+
categories: z14.array(z14.string()),
|
|
408
|
+
decision: z14.string(),
|
|
409
|
+
globalPrivacyControl: z14.boolean(),
|
|
410
|
+
privacyChoices: z14.object({
|
|
411
|
+
saleOrShareOptOut: z14.boolean(),
|
|
412
|
+
targetedAdvertisingOptOut: z14.boolean()
|
|
413
|
+
})
|
|
414
|
+
}),
|
|
415
|
+
services: z14.array(
|
|
416
|
+
z14.object({
|
|
417
|
+
key: z14.string(),
|
|
418
|
+
allowed: z14.boolean(),
|
|
419
|
+
footprintPresent: z14.boolean()
|
|
420
|
+
})
|
|
421
|
+
)
|
|
422
|
+
});
|
|
423
|
+
VerificationInstallation = z14.object({
|
|
424
|
+
publicKey: z14.string(),
|
|
425
|
+
currentPublishedRevision: z14.number().int().positive(),
|
|
426
|
+
delivery: z14.object({
|
|
427
|
+
runtimeUrl: z14.string().url(),
|
|
428
|
+
configUrl: z14.string().url(),
|
|
429
|
+
analyticsUrl: z14.string().url().nullable(),
|
|
430
|
+
receiptsUrl: z14.string().url(),
|
|
431
|
+
handshakeUrl: z14.string().url()
|
|
432
|
+
})
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
});
|
|
2
436
|
|
|
3
437
|
// src/health-check.ts
|
|
4
438
|
import path10 from "path";
|
|
@@ -11,7 +445,7 @@ import os2 from "os";
|
|
|
11
445
|
|
|
12
446
|
// src/siteos-auth-api.ts
|
|
13
447
|
import { z } from "zod";
|
|
14
|
-
var DEFAULT_SITEOS_AUTH_BASE_URL = "https://
|
|
448
|
+
var DEFAULT_SITEOS_AUTH_BASE_URL = "https://app.siteos.sh";
|
|
15
449
|
var SITEOS_AUTH_BASE_URL_ENV = "SITEOS_AUTH_BASE_URL";
|
|
16
450
|
var siteOSCliSessionStatusSchema = z.object({
|
|
17
451
|
contractVersion: z.literal(1),
|
|
@@ -2502,7 +2936,7 @@ import { z as z10 } from "zod";
|
|
|
2502
2936
|
|
|
2503
2937
|
// src/siteos-forms-api.ts
|
|
2504
2938
|
import { z as z9 } from "zod";
|
|
2505
|
-
var DEFAULT_SITEOS_FORMS_BASE_URL = "https://
|
|
2939
|
+
var DEFAULT_SITEOS_FORMS_BASE_URL = "https://app.siteos.sh";
|
|
2506
2940
|
var SITEOS_FORMS_BASE_URL_ENV = "SITEOS_FORMS_PUBLIC_URL";
|
|
2507
2941
|
var opaqueIdentifierSchema = z9.string().trim().min(1).max(255);
|
|
2508
2942
|
var formsProjectSchema = z9.object({
|
|
@@ -4616,7 +5050,7 @@ import path14 from "path";
|
|
|
4616
5050
|
import { z as z12 } from "zod";
|
|
4617
5051
|
|
|
4618
5052
|
// src/pulse/constants.ts
|
|
4619
|
-
var DEFAULT_SITEOS_PULSE_API_URL = "https://
|
|
5053
|
+
var DEFAULT_SITEOS_PULSE_API_URL = "https://app.siteos.sh";
|
|
4620
5054
|
function normalizeApiUrl(value) {
|
|
4621
5055
|
let url;
|
|
4622
5056
|
try {
|
|
@@ -6562,7 +6996,7 @@ import path27 from "path";
|
|
|
6562
6996
|
|
|
6563
6997
|
// src/siteos-search-api.ts
|
|
6564
6998
|
import { z as z13 } from "zod";
|
|
6565
|
-
var DEFAULT_SITEOS_SEARCH_BASE_URL = "https://
|
|
6999
|
+
var DEFAULT_SITEOS_SEARCH_BASE_URL = "https://app.siteos.sh";
|
|
6566
7000
|
var SITEOS_SEARCH_BASE_URL_ENV = "SITEOS_SEARCH_PUBLIC_URL";
|
|
6567
7001
|
var permissiveObjectSchema = z13.record(z13.unknown());
|
|
6568
7002
|
var environmentSlugSchema = z13.string().min(2).max(30).regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/);
|
|
@@ -8563,13 +8997,18 @@ async function runEnvironmentCommand3(options) {
|
|
|
8563
8997
|
import { readFile as readFile16, stat } from "fs/promises";
|
|
8564
8998
|
import path28 from "path";
|
|
8565
8999
|
import { parseArgs as parseArgs3 } from "util";
|
|
8566
|
-
import { z as
|
|
9000
|
+
import { z as z15 } from "zod";
|
|
8567
9001
|
var SERVICE_HELP = {
|
|
8568
9002
|
cookie: `Manage Cookie for the selected SiteOS Project.
|
|
8569
9003
|
|
|
8570
9004
|
Usage:
|
|
8571
9005
|
siteos cookie status [--json]
|
|
8572
9006
|
siteos cookie installation [--json]
|
|
9007
|
+
siteos cookie schema [--json]
|
|
9008
|
+
siteos cookie validate --input <draft.json> [--json]
|
|
9009
|
+
siteos cookie regions resolve [--country <ISO>] [--subdivision <code>] [--source <draft|published>] [--json]
|
|
9010
|
+
siteos cookie verify [--url <same-origin-url>] [--browser <chromium|webkit>] [--json]
|
|
9011
|
+
siteos cookie restore --input <restore.json> [--json]
|
|
8573
9012
|
siteos cookie draft get [--json]
|
|
8574
9013
|
siteos cookie draft save --input <draft.json> [--json]
|
|
8575
9014
|
siteos cookie publish --input <publication.json> [--json]
|
|
@@ -8618,7 +9057,12 @@ async function runServiceCommand(service, options) {
|
|
|
8618
9057
|
"range-days": { type: "string" },
|
|
8619
9058
|
query: { type: "string" },
|
|
8620
9059
|
cursor: { type: "string" },
|
|
8621
|
-
channel: { type: "string" }
|
|
9060
|
+
channel: { type: "string" },
|
|
9061
|
+
country: { type: "string" },
|
|
9062
|
+
subdivision: { type: "string" },
|
|
9063
|
+
source: { type: "string" },
|
|
9064
|
+
url: { type: "string" },
|
|
9065
|
+
browser: { type: "string" }
|
|
8622
9066
|
}
|
|
8623
9067
|
});
|
|
8624
9068
|
const [action, subaction] = positionals;
|
|
@@ -8627,6 +9071,11 @@ async function runServiceCommand(service, options) {
|
|
|
8627
9071
|
cookie: {
|
|
8628
9072
|
status: [],
|
|
8629
9073
|
installation: [],
|
|
9074
|
+
schema: [],
|
|
9075
|
+
validate: ["input"],
|
|
9076
|
+
"regions resolve": ["country", "subdivision", "source"],
|
|
9077
|
+
verify: ["url", "browser"],
|
|
9078
|
+
restore: ["input"],
|
|
8630
9079
|
"draft get": [],
|
|
8631
9080
|
"draft save": ["input"],
|
|
8632
9081
|
publish: ["input"],
|
|
@@ -8706,8 +9155,8 @@ async function runServiceCommand(service, options) {
|
|
|
8706
9155
|
);
|
|
8707
9156
|
const result2 = await response.json();
|
|
8708
9157
|
if (!response.ok) {
|
|
8709
|
-
const error =
|
|
8710
|
-
error:
|
|
9158
|
+
const error = z15.object({
|
|
9159
|
+
error: z15.object({ code: z15.string(), message: z15.string().max(500) })
|
|
8711
9160
|
}).safeParse(result2);
|
|
8712
9161
|
throw new SiteOSAuthApiError({
|
|
8713
9162
|
code: error.success ? error.data.error.code : "SERVICE_REQUEST_FAILED",
|
|
@@ -8731,14 +9180,60 @@ async function runServiceCommand(service, options) {
|
|
|
8731
9180
|
if (service === "cookie") {
|
|
8732
9181
|
if (action === "status" && positionals.length === 1)
|
|
8733
9182
|
result = await request(site);
|
|
8734
|
-
else if (action === "
|
|
9183
|
+
else if (action === "schema") result = await request(`${site}/schema`);
|
|
9184
|
+
else if (action === "validate") {
|
|
9185
|
+
result = await request(
|
|
9186
|
+
`${site}/validate`,
|
|
9187
|
+
"POST",
|
|
9188
|
+
await inputFile(),
|
|
9189
|
+
"cookie:workspace:read"
|
|
9190
|
+
);
|
|
9191
|
+
const validation = z15.object({
|
|
9192
|
+
valid: z15.boolean(),
|
|
9193
|
+
draftVersionMatches: z15.boolean().optional()
|
|
9194
|
+
}).parse(result);
|
|
9195
|
+
if (!validation.valid || validation.draftVersionMatches === false)
|
|
9196
|
+
return { exitCode: 2, stdout: JSON.stringify(result, null, 2) };
|
|
9197
|
+
} else if (action === "restore")
|
|
9198
|
+
result = await request(`${site}/restore`, "POST", await inputFile());
|
|
9199
|
+
else if (action === "regions") {
|
|
9200
|
+
const query = new URLSearchParams();
|
|
9201
|
+
for (const key of ["country", "subdivision", "source"])
|
|
9202
|
+
if (values[key]) query.set(key, values[key]);
|
|
9203
|
+
result = await request(`${site}/regions?${query}`);
|
|
9204
|
+
} else if (action === "verify") {
|
|
9205
|
+
const {
|
|
9206
|
+
VerificationInstallation: VerificationInstallation2,
|
|
9207
|
+
verificationTarget: verificationTarget2,
|
|
9208
|
+
verifyCookieWebsite: verifyCookieWebsite2
|
|
9209
|
+
} = await Promise.resolve().then(() => (init_cookie_verification(), cookie_verification_exports));
|
|
9210
|
+
const browserName = values.browser ?? "chromium";
|
|
9211
|
+
if (browserName !== "chromium" && browserName !== "webkit")
|
|
9212
|
+
throw new Error("Choose chromium or webkit.");
|
|
9213
|
+
if (!common.environment.url)
|
|
9214
|
+
throw new Error(
|
|
9215
|
+
"Set the selected Project environment URL before verification."
|
|
9216
|
+
);
|
|
9217
|
+
const url = verificationTarget2(common.environment.url, values.url);
|
|
9218
|
+
result = await verifyCookieWebsite2({
|
|
9219
|
+
installation: VerificationInstallation2.parse(
|
|
9220
|
+
await request(`${site}/installation`)
|
|
9221
|
+
),
|
|
9222
|
+
url,
|
|
9223
|
+
browserName
|
|
9224
|
+
});
|
|
9225
|
+
return {
|
|
9226
|
+
exitCode: result.status === "passed" ? 0 : 1,
|
|
9227
|
+
stdout: JSON.stringify(result, null, 2)
|
|
9228
|
+
};
|
|
9229
|
+
} else if (action === "installation")
|
|
8735
9230
|
result = await request(`${site}/installation`);
|
|
8736
9231
|
else if (action === "draft" && subaction === "get" && positionals.length === 2) {
|
|
8737
|
-
const response =
|
|
8738
|
-
name:
|
|
8739
|
-
hostname:
|
|
8740
|
-
draftVersion:
|
|
8741
|
-
draft:
|
|
9232
|
+
const response = z15.object({
|
|
9233
|
+
name: z15.string(),
|
|
9234
|
+
hostname: z15.string(),
|
|
9235
|
+
draftVersion: z15.number(),
|
|
9236
|
+
draft: z15.unknown()
|
|
8742
9237
|
}).parse(await request(site));
|
|
8743
9238
|
result = {
|
|
8744
9239
|
name: response.name,
|
|
@@ -8770,9 +9265,9 @@ async function runServiceCommand(service, options) {
|
|
|
8770
9265
|
else if (action === "environments" && positionals.length === 1)
|
|
8771
9266
|
result = await request(`${site}/environments`);
|
|
8772
9267
|
else if (action === "report" || action === "installation" || action === "tracking-plan") {
|
|
8773
|
-
const response =
|
|
8774
|
-
environments:
|
|
8775
|
-
|
|
9268
|
+
const response = z15.object({
|
|
9269
|
+
environments: z15.array(
|
|
9270
|
+
z15.object({ id: z15.string(), slug: z15.string() })
|
|
8776
9271
|
)
|
|
8777
9272
|
}).parse(await request(`${site}/environments`));
|
|
8778
9273
|
const environment = common.overview.project.environments.find(
|
|
@@ -8797,11 +9292,11 @@ async function runServiceCommand(service, options) {
|
|
|
8797
9292
|
);
|
|
8798
9293
|
const base = `/environments/${encodeURIComponent(matches[0].id)}`;
|
|
8799
9294
|
if (action === "report" && positionals.length === 1) {
|
|
8800
|
-
const detail =
|
|
8801
|
-
site:
|
|
8802
|
-
id:
|
|
8803
|
-
environments:
|
|
8804
|
-
|
|
9295
|
+
const detail = z15.object({
|
|
9296
|
+
site: z15.object({
|
|
9297
|
+
id: z15.literal(common.resourceId),
|
|
9298
|
+
environments: z15.array(
|
|
9299
|
+
z15.object({ id: z15.string(), evidence: z15.unknown() })
|
|
8805
9300
|
)
|
|
8806
9301
|
})
|
|
8807
9302
|
}).parse(await request(site));
|
|
@@ -8859,7 +9354,7 @@ async function runServiceCommand(service, options) {
|
|
|
8859
9354
|
} catch (cause) {
|
|
8860
9355
|
return {
|
|
8861
9356
|
exitCode: cause instanceof SiteOSAuthApiError ? 1 : 2,
|
|
8862
|
-
stderr: cause instanceof SiteOSAuthApiError || !(cause instanceof
|
|
9357
|
+
stderr: cause instanceof SiteOSAuthApiError || !(cause instanceof z15.ZodError) && cause instanceof Error ? cause.message : "The service returned an invalid response."
|
|
8863
9358
|
};
|
|
8864
9359
|
}
|
|
8865
9360
|
}
|