@openpolicy/cli 0.0.5 → 0.0.6

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/index.js CHANGED
@@ -1,965 +1,22 @@
1
- var __create = Object.create;
2
- var __getProtoOf = Object.getPrototypeOf;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __toESM = (mod, isNodeMode, target) => {
7
- target = mod != null ? __create(__getProtoOf(mod)) : {};
8
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
9
- for (let key of __getOwnPropNames(mod))
10
- if (!__hasOwnProp.call(to, key))
11
- __defProp(to, key, {
12
- get: () => mod[key],
13
- enumerable: true
14
- });
15
- return to;
16
- };
17
- var __export = (target, all) => {
18
- for (var name in all)
19
- __defProp(target, name, {
20
- get: all[name],
21
- enumerable: true,
22
- configurable: true,
23
- set: (newValue) => all[name] = () => newValue
24
- });
25
- };
26
- var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
27
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
28
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
29
- }) : x)(function(x) {
30
- if (typeof require !== "undefined")
31
- return require.apply(this, arguments);
32
- throw Error('Dynamic require of "' + x + '" is not supported');
33
- });
34
-
35
- // node:path
36
- function assertPath(path) {
37
- if (typeof path !== "string")
38
- throw new TypeError("Path must be a string. Received " + JSON.stringify(path));
39
- }
40
- function normalizeStringPosix(path, allowAboveRoot) {
41
- var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
42
- for (var i = 0;i <= path.length; ++i) {
43
- if (i < path.length)
44
- code = path.charCodeAt(i);
45
- else if (code === 47)
46
- break;
47
- else
48
- code = 47;
49
- if (code === 47) {
50
- if (lastSlash === i - 1 || dots === 1)
51
- ;
52
- else if (lastSlash !== i - 1 && dots === 2) {
53
- if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
54
- if (res.length > 2) {
55
- var lastSlashIndex = res.lastIndexOf("/");
56
- if (lastSlashIndex !== res.length - 1) {
57
- if (lastSlashIndex === -1)
58
- res = "", lastSegmentLength = 0;
59
- else
60
- res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
61
- lastSlash = i, dots = 0;
62
- continue;
63
- }
64
- } else if (res.length === 2 || res.length === 1) {
65
- res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
66
- continue;
67
- }
68
- }
69
- if (allowAboveRoot) {
70
- if (res.length > 0)
71
- res += "/..";
72
- else
73
- res = "..";
74
- lastSegmentLength = 2;
75
- }
76
- } else {
77
- if (res.length > 0)
78
- res += "/" + path.slice(lastSlash + 1, i);
79
- else
80
- res = path.slice(lastSlash + 1, i);
81
- lastSegmentLength = i - lastSlash - 1;
82
- }
83
- lastSlash = i, dots = 0;
84
- } else if (code === 46 && dots !== -1)
85
- ++dots;
86
- else
87
- dots = -1;
88
- }
89
- return res;
90
- }
91
- function _format(sep, pathObject) {
92
- var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
93
- if (!dir)
94
- return base;
95
- if (dir === pathObject.root)
96
- return dir + base;
97
- return dir + sep + base;
98
- }
99
- function resolve() {
100
- var resolvedPath = "", resolvedAbsolute = false, cwd;
101
- for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
102
- var path;
103
- if (i >= 0)
104
- path = arguments[i];
105
- else {
106
- if (cwd === undefined)
107
- cwd = process.cwd();
108
- path = cwd;
109
- }
110
- if (assertPath(path), path.length === 0)
111
- continue;
112
- resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
113
- }
114
- if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
115
- if (resolvedPath.length > 0)
116
- return "/" + resolvedPath;
117
- else
118
- return "/";
119
- else if (resolvedPath.length > 0)
120
- return resolvedPath;
121
- else
122
- return ".";
123
- }
124
- function normalize(path) {
125
- if (assertPath(path), path.length === 0)
126
- return ".";
127
- var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
128
- if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
129
- path = ".";
130
- if (path.length > 0 && trailingSeparator)
131
- path += "/";
132
- if (isAbsolute)
133
- return "/" + path;
134
- return path;
135
- }
136
- function isAbsolute(path) {
137
- return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
138
- }
139
- function join() {
140
- if (arguments.length === 0)
141
- return ".";
142
- var joined;
143
- for (var i = 0;i < arguments.length; ++i) {
144
- var arg = arguments[i];
145
- if (assertPath(arg), arg.length > 0)
146
- if (joined === undefined)
147
- joined = arg;
148
- else
149
- joined += "/" + arg;
150
- }
151
- if (joined === undefined)
152
- return ".";
153
- return normalize(joined);
154
- }
155
- function relative(from, to) {
156
- if (assertPath(from), assertPath(to), from === to)
157
- return "";
158
- if (from = resolve(from), to = resolve(to), from === to)
159
- return "";
160
- var fromStart = 1;
161
- for (;fromStart < from.length; ++fromStart)
162
- if (from.charCodeAt(fromStart) !== 47)
163
- break;
164
- var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
165
- for (;toStart < to.length; ++toStart)
166
- if (to.charCodeAt(toStart) !== 47)
167
- break;
168
- var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
169
- for (;i <= length; ++i) {
170
- if (i === length) {
171
- if (toLen > length) {
172
- if (to.charCodeAt(toStart + i) === 47)
173
- return to.slice(toStart + i + 1);
174
- else if (i === 0)
175
- return to.slice(toStart + i);
176
- } else if (fromLen > length) {
177
- if (from.charCodeAt(fromStart + i) === 47)
178
- lastCommonSep = i;
179
- else if (i === 0)
180
- lastCommonSep = 0;
181
- }
182
- break;
183
- }
184
- var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
185
- if (fromCode !== toCode)
186
- break;
187
- else if (fromCode === 47)
188
- lastCommonSep = i;
189
- }
190
- var out = "";
191
- for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
192
- if (i === fromEnd || from.charCodeAt(i) === 47)
193
- if (out.length === 0)
194
- out += "..";
195
- else
196
- out += "/..";
197
- if (out.length > 0)
198
- return out + to.slice(toStart + lastCommonSep);
199
- else {
200
- if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
201
- ++toStart;
202
- return to.slice(toStart);
203
- }
204
- }
205
- function _makeLong(path) {
206
- return path;
207
- }
208
- function dirname(path) {
209
- if (assertPath(path), path.length === 0)
210
- return ".";
211
- var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
212
- for (var i = path.length - 1;i >= 1; --i)
213
- if (code = path.charCodeAt(i), code === 47) {
214
- if (!matchedSlash) {
215
- end = i;
216
- break;
217
- }
218
- } else
219
- matchedSlash = false;
220
- if (end === -1)
221
- return hasRoot ? "/" : ".";
222
- if (hasRoot && end === 1)
223
- return "//";
224
- return path.slice(0, end);
225
- }
226
- function basename(path, ext) {
227
- if (ext !== undefined && typeof ext !== "string")
228
- throw new TypeError('"ext" argument must be a string');
229
- assertPath(path);
230
- var start = 0, end = -1, matchedSlash = true, i;
231
- if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
232
- if (ext.length === path.length && ext === path)
233
- return "";
234
- var extIdx = ext.length - 1, firstNonSlashEnd = -1;
235
- for (i = path.length - 1;i >= 0; --i) {
236
- var code = path.charCodeAt(i);
237
- if (code === 47) {
238
- if (!matchedSlash) {
239
- start = i + 1;
240
- break;
241
- }
242
- } else {
243
- if (firstNonSlashEnd === -1)
244
- matchedSlash = false, firstNonSlashEnd = i + 1;
245
- if (extIdx >= 0)
246
- if (code === ext.charCodeAt(extIdx)) {
247
- if (--extIdx === -1)
248
- end = i;
249
- } else
250
- extIdx = -1, end = firstNonSlashEnd;
251
- }
252
- }
253
- if (start === end)
254
- end = firstNonSlashEnd;
255
- else if (end === -1)
256
- end = path.length;
257
- return path.slice(start, end);
258
- } else {
259
- for (i = path.length - 1;i >= 0; --i)
260
- if (path.charCodeAt(i) === 47) {
261
- if (!matchedSlash) {
262
- start = i + 1;
263
- break;
264
- }
265
- } else if (end === -1)
266
- matchedSlash = false, end = i + 1;
267
- if (end === -1)
268
- return "";
269
- return path.slice(start, end);
270
- }
271
- }
272
- function extname(path) {
273
- assertPath(path);
274
- var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
275
- for (var i = path.length - 1;i >= 0; --i) {
276
- var code = path.charCodeAt(i);
277
- if (code === 47) {
278
- if (!matchedSlash) {
279
- startPart = i + 1;
280
- break;
281
- }
282
- continue;
283
- }
284
- if (end === -1)
285
- matchedSlash = false, end = i + 1;
286
- if (code === 46) {
287
- if (startDot === -1)
288
- startDot = i;
289
- else if (preDotState !== 1)
290
- preDotState = 1;
291
- } else if (startDot !== -1)
292
- preDotState = -1;
293
- }
294
- if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
295
- return "";
296
- return path.slice(startDot, end);
297
- }
298
- function format(pathObject) {
299
- if (pathObject === null || typeof pathObject !== "object")
300
- throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
301
- return _format("/", pathObject);
302
- }
303
- function parse(path) {
304
- assertPath(path);
305
- var ret = { root: "", dir: "", base: "", ext: "", name: "" };
306
- if (path.length === 0)
307
- return ret;
308
- var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
309
- if (isAbsolute2)
310
- ret.root = "/", start = 1;
311
- else
312
- start = 0;
313
- var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
314
- for (;i >= start; --i) {
315
- if (code = path.charCodeAt(i), code === 47) {
316
- if (!matchedSlash) {
317
- startPart = i + 1;
318
- break;
319
- }
320
- continue;
321
- }
322
- if (end === -1)
323
- matchedSlash = false, end = i + 1;
324
- if (code === 46) {
325
- if (startDot === -1)
326
- startDot = i;
327
- else if (preDotState !== 1)
328
- preDotState = 1;
329
- } else if (startDot !== -1)
330
- preDotState = -1;
331
- }
332
- if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
333
- if (end !== -1)
334
- if (startPart === 0 && isAbsolute2)
335
- ret.base = ret.name = path.slice(1, end);
336
- else
337
- ret.base = ret.name = path.slice(startPart, end);
338
- } else {
339
- if (startPart === 0 && isAbsolute2)
340
- ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
341
- else
342
- ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
343
- ret.ext = path.slice(startDot, end);
344
- }
345
- if (startPart > 0)
346
- ret.dir = path.slice(0, startPart - 1);
347
- else if (isAbsolute2)
348
- ret.dir = "/";
349
- return ret;
350
- }
351
- var sep = "/", delimiter = ":", posix;
352
- var init_path = __esm(() => {
353
- posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
354
- });
355
-
356
- // src/commands/init.ts
357
- var exports_init = {};
358
- __export(exports_init, {
359
- initCommand: () => initCommand
360
- });
361
1
  import { defineCommand } from "citty";
362
- import consola from "consola";
363
- function toJurisdictions(choice) {
364
- if (choice === "gdpr")
365
- return ["eu"];
366
- if (choice === "ccpa")
367
- return ["ca"];
368
- if (choice === "both")
369
- return ["eu", "ca"];
370
- return ["us"];
371
- }
372
- function toDataCollected(categories) {
373
- const groups = {};
374
- for (const cat of categories) {
375
- const mapping = DATA_CATEGORY_MAP[cat];
376
- if (!mapping)
377
- continue;
378
- groups[mapping.group] = [...groups[mapping.group] ?? [], mapping.label];
379
- }
380
- return Object.keys(groups).length > 0 ? groups : { "Personal Information": ["Email address"] };
381
- }
382
- function toUserRights(jurisdictions) {
383
- const rights = new Set(["access", "erasure"]);
384
- if (jurisdictions.includes("eu")) {
385
- for (const r of [
386
- "rectification",
387
- "portability",
388
- "restriction",
389
- "objection"
390
- ])
391
- rights.add(r);
392
- }
393
- if (jurisdictions.includes("ca")) {
394
- for (const r of ["opt_out_sale", "non_discrimination"])
395
- rights.add(r);
396
- }
397
- return Array.from(rights);
398
- }
399
- function renderConfig(values) {
400
- const dataLines = Object.entries(values.dataCollected).map(([k, v]) => ` ${JSON.stringify(k)}: ${JSON.stringify(v)},`).join(`
401
- `);
402
- const today = new Date().toISOString().slice(0, 10);
403
- return `import { definePrivacyPolicy } from "@openpolicy/sdk";
404
-
405
- export default definePrivacyPolicy({
406
- effectiveDate: "${today}",
407
- company: {
408
- name: ${JSON.stringify(values.companyName)},
409
- legalName: ${JSON.stringify(values.legalName)},
410
- address: ${JSON.stringify(values.address)},
411
- contact: ${JSON.stringify(values.contact)},
412
- },
413
- dataCollected: {
414
- ${dataLines}
415
- },
416
- legalBasis: ${JSON.stringify(values.legalBasis)},
417
- retention: {
418
- "All personal data": "As long as necessary for the purposes described in this policy",
419
- },
420
- cookies: {
421
- essential: true,
422
- analytics: ${values.hasCookies},
423
- marketing: false,
424
- },
425
- thirdParties: [],
426
- userRights: ${JSON.stringify(values.userRights)},
427
- jurisdictions: ${JSON.stringify(values.jurisdictions)},
428
- });
429
- `;
430
- }
431
- var DATA_CATEGORY_MAP, initCommand;
432
- var init_init = __esm(() => {
433
- init_path();
434
- DATA_CATEGORY_MAP = {
435
- name: { group: "Personal Information", label: "Full name" },
436
- email: { group: "Personal Information", label: "Email address" },
437
- ip_address: { group: "Technical Data", label: "IP address" },
438
- device_info: { group: "Technical Data", label: "Device type and browser" },
439
- location: { group: "Location Data", label: "Approximate location" },
440
- payment_info: { group: "Financial Data", label: "Payment card details" },
441
- usage_data: { group: "Usage Data", label: "Pages visited and features used" }
442
- };
443
- initCommand = defineCommand({
444
- meta: {
445
- name: "init",
446
- description: "Interactively create a policy config file"
447
- },
448
- args: {
449
- out: {
450
- type: "string",
451
- description: "Output path for generated config",
452
- default: "./policy.config.ts"
453
- },
454
- yes: {
455
- type: "boolean",
456
- description: "Skip prompts and use defaults (CI mode)",
457
- default: false
458
- }
459
- },
460
- async run({ args }) {
461
- consola.start("OpenPolicy init wizard");
462
- const companyName = String(await consola.prompt("Company name?", { type: "text", cancel: "reject" }));
463
- const legalName = String(await consola.prompt("Legal entity name?", {
464
- type: "text",
465
- cancel: "reject",
466
- initial: companyName
467
- }));
468
- const address = String(await consola.prompt("Company address?", {
469
- type: "text",
470
- cancel: "reject"
471
- }));
472
- const contact = String(await consola.prompt("Privacy contact email?", {
473
- type: "text",
474
- cancel: "reject"
475
- }));
476
- const jurisdictionChoice = String(await consola.prompt("Jurisdiction?", {
477
- type: "select",
478
- cancel: "reject",
479
- options: ["gdpr", "ccpa", "both"]
480
- }));
481
- const dataCategories = await consola.prompt("Data categories collected?", {
482
- type: "multiselect",
483
- cancel: "reject",
484
- options: [
485
- "name",
486
- "email",
487
- "ip_address",
488
- "device_info",
489
- "location",
490
- "payment_info",
491
- "usage_data"
492
- ]
493
- });
494
- const hasCookies = Boolean(await consola.prompt("Does your app use cookies?", {
495
- type: "confirm",
496
- cancel: "reject",
497
- initial: true
498
- }));
499
- const jurisdictions = toJurisdictions(jurisdictionChoice);
500
- const dataCollected = toDataCollected(dataCategories);
501
- const userRights = toUserRights(jurisdictions);
502
- const legalBasis = jurisdictions.includes("eu") ? "Legitimate interests and consent" : "";
503
- const source = renderConfig({
504
- companyName,
505
- legalName,
506
- address,
507
- contact,
508
- jurisdictions,
509
- dataCollected,
510
- legalBasis,
511
- hasCookies,
512
- userRights
513
- });
514
- const outPath = resolve(args.out ?? "./policy.config.ts");
515
- await Bun.write(outPath, source);
516
- consola.success(`Config written to ${outPath}`);
517
- }
518
- });
519
- });
520
-
521
- // ../core/src/renderers/markdown.ts
522
- function renderMarkdown(sections) {
523
- return sections.map((section) => `## ${section.title}
524
-
525
- ${section.body}`).join(`
526
-
527
- ---
528
-
529
- `);
530
- }
531
-
532
- // ../core/src/templates/privacy/ccpa-supplement.ts
533
- function buildCcpaSupplement(config) {
534
- if (!config.jurisdictions.includes("ca"))
535
- return null;
536
- return {
537
- id: "ccpa-supplement",
538
- title: "California Privacy Rights (CCPA)",
539
- body: `This section applies to California residents under the California Consumer Privacy Act (CCPA) and the California Privacy Rights Act (CPRA).
540
-
541
- **Categories of Personal Information Collected:** We collect the categories of personal information described in the "Information We Collect" section above.
542
-
543
- **Your California Rights:**
544
- - **Right to Know:** You may request information about the personal information we have collected about you, including the categories of sources, the business purpose for collection, and the categories of third parties with whom we share information.
545
- - **Right to Delete:** You may request deletion of personal information we have collected from you, subject to certain exceptions.
546
- - **Right to Opt-Out:** You may opt out of the sale or sharing of your personal information.
547
- - **Right to Non-Discrimination:** We will not discriminate against you for exercising your California privacy rights.
548
-
549
- To exercise your rights, contact us at ${config.company.contact}.`
550
- };
551
- }
552
-
553
- // ../core/src/templates/privacy/contact.ts
554
- function buildContact(config) {
555
- return {
556
- id: "contact",
557
- title: "Contact Us",
558
- body: `If you have questions or concerns about this Privacy Policy or our data practices, please contact us:
559
-
560
- **${config.company.legalName}**
561
- ${config.company.address}
562
-
563
- Email: ${config.company.contact}`
564
- };
565
- }
566
-
567
- // ../core/src/templates/privacy/cookies.ts
568
- function buildCookies(config) {
569
- const enabled = [];
570
- if (config.cookies.essential)
571
- enabled.push("**Essential cookies** — required for the service to function");
572
- if (config.cookies.analytics)
573
- enabled.push("**Analytics cookies** — help us understand how visitors interact with our service");
574
- if (config.cookies.marketing)
575
- enabled.push("**Marketing cookies** — used to deliver relevant advertisements");
576
- const body = enabled.length > 0 ? `We use the following types of cookies and tracking technologies:
577
-
578
- ${enabled.map((e) => `- ${e}`).join(`
579
- `)}` : "We do not use cookies or tracking technologies on our service.";
580
- return {
581
- id: "cookies",
582
- title: "Cookies and Tracking",
583
- body
584
- };
585
- }
586
-
587
- // ../core/src/templates/privacy/data-collected.ts
588
- function buildDataCollected(config) {
589
- const entries = Object.entries(config.dataCollected);
590
- const lines = entries.map(([category, items]) => {
591
- const itemList = items.map((item) => ` - ${item}`).join(`
592
- `);
593
- return `**${category}:**
594
- ${itemList}`;
595
- });
596
- return {
597
- id: "data-collected",
598
- title: "Information We Collect",
599
- body: `We collect the following categories of information:
600
-
601
- ${lines.join(`
602
-
603
- `)}`
604
- };
605
- }
606
-
607
- // ../core/src/templates/privacy/data-retention.ts
608
- function buildDataRetention(config) {
609
- const entries = Object.entries(config.retention);
610
- const lines = entries.map(([category, period]) => `- **${category}:** ${period}`);
611
- return {
612
- id: "data-retention",
613
- title: "Data Retention",
614
- body: `We retain your information for the following periods:
615
-
616
- ${lines.join(`
617
- `)}`
618
- };
619
- }
620
-
621
- // ../core/src/templates/privacy/gdpr-supplement.ts
622
- function buildGdprSupplement(config) {
623
- if (!config.jurisdictions.includes("eu"))
624
- return null;
625
- return {
626
- id: "gdpr-supplement",
627
- title: "GDPR Supplemental Disclosures",
628
- body: `This section applies to individuals in the European Economic Area (EEA) under the General Data Protection Regulation (GDPR).
629
-
630
- **Data Controller:** ${config.company.legalName}, ${config.company.address}
631
-
632
- **Your GDPR Rights:** In addition to the rights listed above, you have the right to lodge a complaint with your local data protection authority if you believe we have not handled your data in accordance with applicable law.
633
-
634
- **International Transfers:** If we transfer your personal data outside the EEA, we ensure adequate safeguards are in place in accordance with GDPR requirements.`
635
- };
636
- }
637
-
638
- // ../core/src/templates/privacy/introduction.ts
639
- function buildIntroduction(config) {
640
- return {
641
- id: "introduction",
642
- title: "Introduction",
643
- body: `This Privacy Policy describes how ${config.company.name} ("we", "us", or "our") collects, uses, and shares information about you when you use our services.
644
-
645
- **Effective Date:** ${config.effectiveDate}
646
-
647
- If you have questions about this policy, please contact us at ${config.company.contact}.`
648
- };
649
- }
650
-
651
- // ../core/src/templates/privacy/legal-basis.ts
652
- function buildLegalBasis(config) {
653
- if (!config.jurisdictions.includes("eu"))
654
- return null;
655
- return {
656
- id: "legal-basis",
657
- title: "Legal Basis for Processing",
658
- body: `We process your personal data under the following legal basis:
659
-
660
- ${config.legalBasis}`
661
- };
662
- }
663
-
664
- // ../core/src/templates/privacy/third-parties.ts
665
- function buildThirdParties(config) {
666
- const lines = config.thirdParties.map((tp) => `- **${tp.name}** — ${tp.purpose}`);
667
- const body = lines.length > 0 ? `We share data with the following third-party services:
668
-
669
- ${lines.join(`
670
- `)}` : "We do not share your data with third-party services.";
671
- return {
672
- id: "third-parties",
673
- title: "Third-Party Services",
674
- body
675
- };
676
- }
677
-
678
- // ../core/src/templates/privacy/user-rights.ts
679
- function buildUserRights(config) {
680
- const lines = config.userRights.map((right) => {
681
- const label = RIGHTS_LABELS[right] ?? right;
682
- return `- ${label}`;
683
- });
684
- return {
685
- id: "user-rights",
686
- title: "Your Rights",
687
- body: `You have the following rights regarding your personal data:
688
-
689
- ${lines.join(`
690
- `)}`
691
- };
692
- }
693
- var RIGHTS_LABELS;
694
- var init_user_rights = __esm(() => {
695
- RIGHTS_LABELS = {
696
- access: "Right to access your personal data",
697
- rectification: "Right to correct inaccurate data",
698
- erasure: "Right to request deletion of your data",
699
- portability: "Right to receive your data in a portable format",
700
- restriction: "Right to restrict how we process your data",
701
- objection: "Right to object to processing",
702
- opt_out_sale: "Right to opt out of the sale of your personal information",
703
- non_discrimination: "Right to non-discriminatory treatment for exercising your rights"
704
- };
705
- });
706
-
707
- // ../core/src/privacy.ts
708
- function compilePrivacyPolicy(config, options = { formats: ["markdown"] }) {
709
- const sections = SECTION_BUILDERS.map((builder) => builder(config)).filter((s) => s !== null);
710
- return options.formats.map((format2) => {
711
- switch (format2) {
712
- case "markdown":
713
- return { format: format2, content: renderMarkdown(sections), sections };
714
- case "pdf":
715
- throw new Error("pdf format is not yet implemented");
716
- case "jsx":
717
- throw new Error("jsx format is not yet implemented");
718
- default:
719
- throw new Error(`Unsupported format: ${format2}`);
720
- }
721
- });
722
- }
723
- var SECTION_BUILDERS;
724
- var init_privacy = __esm(() => {
725
- init_user_rights();
726
- SECTION_BUILDERS = [
727
- buildIntroduction,
728
- buildDataCollected,
729
- buildLegalBasis,
730
- buildDataRetention,
731
- buildCookies,
732
- buildThirdParties,
733
- buildUserRights,
734
- buildGdprSupplement,
735
- buildCcpaSupplement,
736
- buildContact
737
- ];
738
- });
739
-
740
- // ../core/src/validate.ts
741
- function validatePrivacyPolicy(config) {
742
- const issues = [];
743
- if (!config.effectiveDate)
744
- issues.push({ level: "error", message: "effectiveDate is required" });
745
- if (!config.company.name)
746
- issues.push({ level: "error", message: "company.name is required" });
747
- if (!config.company.legalName)
748
- issues.push({ level: "error", message: "company.legalName is required" });
749
- if (!config.company.address)
750
- issues.push({ level: "error", message: "company.address is required" });
751
- if (!config.company.contact)
752
- issues.push({ level: "error", message: "company.contact is required" });
753
- if (Object.keys(config.dataCollected).length === 0)
754
- issues.push({
755
- level: "error",
756
- message: "dataCollected must have at least one entry"
757
- });
758
- if (config.userRights.length === 0)
759
- issues.push({
760
- level: "warning",
761
- message: "userRights is empty — consider listing applicable rights"
762
- });
763
- if (config.jurisdictions.includes("eu")) {
764
- if (!config.legalBasis)
765
- issues.push({ level: "error", message: "GDPR requires a legalBasis" });
766
- for (const right of [
767
- "access",
768
- "rectification",
769
- "erasure",
770
- "portability",
771
- "restriction",
772
- "objection"
773
- ]) {
774
- if (!config.userRights.includes(right))
775
- issues.push({
776
- level: "warning",
777
- message: `GDPR recommends including the "${right}" right`
778
- });
779
- }
780
- }
781
- if (config.jurisdictions.includes("ca")) {
782
- for (const right of [
783
- "access",
784
- "erasure",
785
- "opt_out_sale",
786
- "non_discrimination"
787
- ]) {
788
- if (!config.userRights.includes(right))
789
- issues.push({
790
- level: "warning",
791
- message: `CCPA recommends including the "${right}" right`
792
- });
793
- }
794
- }
795
- return issues;
796
- }
797
-
798
- // ../core/src/index.ts
799
- function compilePolicy(input, options) {
800
- switch (input.type) {
801
- case "privacy": {
802
- const { type: _, ...config } = input;
803
- return compilePrivacyPolicy(config, options);
804
- }
805
- }
806
- }
807
- var init_src = __esm(() => {
808
- init_privacy();
809
- init_privacy();
810
- });
811
-
812
- // src/utils/load-config.ts
813
- import consola2 from "consola";
814
- async function loadConfig(configPath) {
815
- const absPath = resolve(configPath);
816
- if (!await Bun.file(absPath).exists()) {
817
- consola2.error(`Config file not found: ${absPath}`);
818
- process.exit(1);
819
- }
820
- let mod;
821
- try {
822
- mod = await import(absPath);
823
- } catch (err) {
824
- consola2.error(`Failed to load config: ${absPath}`);
825
- consola2.error(err);
826
- process.exit(1);
827
- }
828
- const config = mod["default"] ?? mod["module.exports"] ?? mod;
829
- if (config === null || config === undefined || typeof config !== "object") {
830
- consola2.error(`Config must export a non-null object: ${absPath}`);
831
- process.exit(1);
832
- }
833
- return config;
834
- }
835
- var init_load_config = __esm(() => {
836
- init_path();
837
- });
838
-
839
- // src/commands/generate.ts
840
- var exports_generate = {};
841
- __export(exports_generate, {
842
- generateCommand: () => generateCommand
843
- });
844
- import { defineCommand as defineCommand2 } from "citty";
845
- import consola3 from "consola";
846
- var generateCommand;
847
- var init_generate = __esm(() => {
848
- init_path();
849
- init_src();
850
- init_load_config();
851
- generateCommand = defineCommand2({
852
- meta: {
853
- name: "generate",
854
- description: "Compile a policy config to one or more output formats"
855
- },
856
- args: {
857
- config: {
858
- type: "positional",
859
- description: "Path to policy config file",
860
- default: "./policy.config.ts"
861
- },
862
- format: {
863
- type: "string",
864
- description: "Comma-separated output formats: markdown,pdf,jsx",
865
- default: "markdown"
866
- },
867
- out: {
868
- type: "string",
869
- description: "Output directory",
870
- default: "./output"
871
- }
872
- },
873
- async run({ args }) {
874
- const formats = (args.format ?? "markdown").split(",").map((f) => f.trim()).filter(Boolean);
875
- const outDir = args.out ?? "./output";
876
- consola3.start(`Generating policy from ${args.config} → formats: ${formats.join(", ")}`);
877
- const config = await loadConfig(args.config ?? "./policy.config.ts");
878
- const results = compilePolicy({ type: "privacy", ...config }, { formats });
879
- for (const result of results) {
880
- const ext = result.format === "markdown" ? "md" : result.format;
881
- const outPath = join(outDir, `privacy-policy.${ext}`);
882
- await Bun.write(outPath, result.content);
883
- consola3.success(`Written: ${outPath}`);
884
- }
885
- consola3.success(`Policy generation complete → ${outDir}`);
886
- }
887
- });
888
- });
889
-
890
- // src/commands/validate.ts
891
- var exports_validate = {};
892
- __export(exports_validate, {
893
- validateCommand: () => validateCommand
894
- });
895
- import { defineCommand as defineCommand3 } from "citty";
896
- import consola4 from "consola";
897
- var validateCommand;
898
- var init_validate = __esm(() => {
899
- init_src();
900
- init_load_config();
901
- validateCommand = defineCommand3({
902
- meta: {
903
- name: "validate",
904
- description: "Validate a policy config for compliance"
905
- },
906
- args: {
907
- config: {
908
- type: "positional",
909
- description: "Path to policy config file",
910
- default: "./policy.config.ts"
911
- },
912
- jurisdiction: {
913
- type: "string",
914
- description: "Jurisdiction to validate against: gdpr, ccpa, or all",
915
- default: "all"
916
- }
917
- },
918
- async run({ args }) {
919
- const configPath = args.config ?? "./policy.config.ts";
920
- consola4.start(`Validating ${configPath}`);
921
- const config = await loadConfig(configPath);
922
- const issues = validatePrivacyPolicy(config);
923
- if (issues.length === 0) {
924
- consola4.success("Config is valid — no issues found.");
925
- return;
926
- }
927
- for (const issue of issues) {
928
- if (issue.level === "error") {
929
- consola4.error(issue.message);
930
- } else {
931
- consola4.warn(issue.message);
932
- }
933
- }
934
- const errors = issues.filter((i) => i.level === "error");
935
- if (errors.length > 0) {
936
- consola4.fail(`Validation failed with ${errors.length} error(s).`);
937
- process.exit(1);
938
- }
939
- consola4.success("Validation passed with warnings.");
940
- }
941
- });
942
- });
943
-
944
- // src/index.ts
945
- import { defineCommand as defineCommand4 } from "citty";
946
- var mainCommand = defineCommand4({
947
- meta: {
948
- name: "openpolicy",
949
- version: "0.0.1",
950
- description: "Generate and validate privacy policy documents"
951
- },
952
- subCommands: {
953
- init: () => Promise.resolve().then(() => (init_init(), exports_init)).then((m) => m.initCommand),
954
- generate: () => Promise.resolve().then(() => (init_generate(), exports_generate)).then((m) => m.generateCommand),
955
- validate: () => Promise.resolve().then(() => (init_validate(), exports_validate)).then((m) => m.validateCommand)
956
- }
2
+ //#region src/index.ts
3
+ const mainCommand = defineCommand({
4
+ meta: {
5
+ name: "openpolicy",
6
+ version: "0.0.1",
7
+ description: "Generate and validate privacy policy documents"
8
+ },
9
+ subCommands: {
10
+ init: () => import("./_lib-MI0GKJMR.js").then((m) => m.initCommand),
11
+ generate: () => import("./_lib-D2LkleUQ.js").then((m) => m.generateCommand),
12
+ validate: () => import("./_lib-D2I-M4OU.js").then((m) => m.validateCommand)
13
+ }
957
14
  });
958
15
  async function run() {
959
- const { runMain } = await import("citty");
960
- await runMain(mainCommand);
16
+ const { runMain } = await import("citty");
17
+ await runMain(mainCommand);
961
18
  }
962
- export {
963
- run,
964
- mainCommand
965
- };
19
+ //#endregion
20
+ export { mainCommand, run };
21
+
22
+ //# sourceMappingURL=index.js.map