@openpolicy/core 0.0.4 → 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.d.ts +147 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +530 -240
- package/dist/index.js.map +1 -0
- package/dist/templates/terms/acceptance.d.ts +3 -0
- package/dist/templates/terms/acceptance.d.ts.map +1 -0
- package/dist/templates/terms/accounts.d.ts +3 -0
- package/dist/templates/terms/accounts.d.ts.map +1 -0
- package/dist/templates/terms/availability.d.ts +3 -0
- package/dist/templates/terms/availability.d.ts.map +1 -0
- package/dist/templates/terms/changes-to-terms.d.ts +3 -0
- package/dist/templates/terms/changes-to-terms.d.ts.map +1 -0
- package/dist/templates/terms/contact.d.ts +3 -0
- package/dist/templates/terms/contact.d.ts.map +1 -0
- package/dist/templates/terms/disclaimers.d.ts +3 -0
- package/dist/templates/terms/disclaimers.d.ts.map +1 -0
- package/dist/templates/terms/dispute-resolution.d.ts +3 -0
- package/dist/templates/terms/dispute-resolution.d.ts.map +1 -0
- package/dist/templates/terms/eligibility.d.ts +3 -0
- package/dist/templates/terms/eligibility.d.ts.map +1 -0
- package/dist/templates/terms/governing-law.d.ts +3 -0
- package/dist/templates/terms/governing-law.d.ts.map +1 -0
- package/dist/templates/terms/indemnification.d.ts +3 -0
- package/dist/templates/terms/indemnification.d.ts.map +1 -0
- package/dist/templates/terms/intellectual-property.d.ts +3 -0
- package/dist/templates/terms/intellectual-property.d.ts.map +1 -0
- package/dist/templates/terms/introduction.d.ts +3 -0
- package/dist/templates/terms/introduction.d.ts.map +1 -0
- package/dist/templates/terms/limitation-of-liability.d.ts +3 -0
- package/dist/templates/terms/limitation-of-liability.d.ts.map +1 -0
- package/dist/templates/terms/payments.d.ts +3 -0
- package/dist/templates/terms/payments.d.ts.map +1 -0
- package/dist/templates/terms/prohibited-use.d.ts +3 -0
- package/dist/templates/terms/prohibited-use.d.ts.map +1 -0
- package/dist/templates/terms/termination.d.ts +3 -0
- package/dist/templates/terms/termination.d.ts.map +1 -0
- package/dist/templates/terms/third-party-services.d.ts +3 -0
- package/dist/templates/terms/third-party-services.d.ts.map +1 -0
- package/dist/templates/terms/user-content.d.ts +3 -0
- package/dist/templates/terms/user-content.d.ts.map +1 -0
- package/dist/terms.d.ts +7 -0
- package/dist/terms.d.ts.map +1 -0
- package/dist/terms.test.d.ts +2 -0
- package/dist/terms.test.d.ts.map +1 -0
- package/dist/types.d.ts +80 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/validate-terms.d.ts +3 -0
- package/dist/validate-terms.d.ts.map +1 -0
- package/dist/validate-terms.test.d.ts +2 -0
- package/dist/validate-terms.test.d.ts.map +1 -0
- package/package.json +6 -3
package/dist/index.js
CHANGED
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return sections.map((section) => `<h2>${section.title}</h2><p>${section.body}</p>`).join(`
|
|
4
|
-
`);
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// src/renderers/markdown.ts
|
|
1
|
+
import { marked } from "marked";
|
|
2
|
+
//#region src/renderers/markdown.ts
|
|
8
3
|
function renderMarkdown(sections) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
${section.body}`).join(`
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
`);
|
|
4
|
+
return sections.map((section) => `## ${section.title}\n\n${section.body}`).join("\n\n---\n\n");
|
|
16
5
|
}
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/renderers/html.ts
|
|
8
|
+
function renderHTML(sections) {
|
|
9
|
+
return marked(renderMarkdown(sections));
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/templates/privacy/ccpa-supplement.ts
|
|
19
13
|
function buildCcpaSupplement(config) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
body: `This section applies to California residents under the California Consumer Privacy Act (CCPA) and the California Privacy Rights Act (CPRA).
|
|
14
|
+
if (!config.jurisdictions.includes("ca")) return null;
|
|
15
|
+
return {
|
|
16
|
+
id: "ccpa-supplement",
|
|
17
|
+
title: "California Privacy Rights (CCPA)",
|
|
18
|
+
body: `This section applies to California residents under the California Consumer Privacy Act (CCPA) and the California Privacy Rights Act (CPRA).
|
|
26
19
|
|
|
27
20
|
**Categories of Personal Information Collected:** We collect the categories of personal information described in the "Information We Collect" section above.
|
|
28
21
|
|
|
@@ -33,258 +26,555 @@ function buildCcpaSupplement(config) {
|
|
|
33
26
|
- **Right to Non-Discrimination:** We will not discriminate against you for exercising your California privacy rights.
|
|
34
27
|
|
|
35
28
|
To exercise your rights, contact us at ${config.company.contact}.`
|
|
36
|
-
|
|
29
|
+
};
|
|
37
30
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
function buildContact(config) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/templates/privacy/contact.ts
|
|
33
|
+
function buildContact$1(config) {
|
|
34
|
+
return {
|
|
35
|
+
id: "contact",
|
|
36
|
+
title: "Contact Us",
|
|
37
|
+
body: `If you have questions or concerns about this Privacy Policy or our data practices, please contact us:
|
|
45
38
|
|
|
46
39
|
**${config.company.legalName}**
|
|
47
40
|
${config.company.address}
|
|
48
41
|
|
|
49
42
|
Email: ${config.company.contact}`
|
|
50
|
-
|
|
43
|
+
};
|
|
51
44
|
}
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region src/templates/privacy/cookies.ts
|
|
54
47
|
function buildCookies(config) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
${enabled.map((e) => `- ${e}`).join(`
|
|
65
|
-
`)}` : "We do not use cookies or tracking technologies on our service.";
|
|
66
|
-
return {
|
|
67
|
-
id: "cookies",
|
|
68
|
-
title: "Cookies and Tracking",
|
|
69
|
-
body
|
|
70
|
-
};
|
|
48
|
+
const enabled = [];
|
|
49
|
+
if (config.cookies.essential) enabled.push("**Essential cookies** — required for the service to function");
|
|
50
|
+
if (config.cookies.analytics) enabled.push("**Analytics cookies** — help us understand how visitors interact with our service");
|
|
51
|
+
if (config.cookies.marketing) enabled.push("**Marketing cookies** — used to deliver relevant advertisements");
|
|
52
|
+
return {
|
|
53
|
+
id: "cookies",
|
|
54
|
+
title: "Cookies and Tracking",
|
|
55
|
+
body: enabled.length > 0 ? `We use the following types of cookies and tracking technologies:\n\n${enabled.map((e) => `- ${e}`).join("\n")}` : "We do not use cookies or tracking technologies on our service."
|
|
56
|
+
};
|
|
71
57
|
}
|
|
72
|
-
|
|
73
|
-
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/templates/privacy/data-collected.ts
|
|
74
60
|
function buildDataCollected(config) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
`)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
id: "data-collected",
|
|
84
|
-
title: "Information We Collect",
|
|
85
|
-
body: `We collect the following categories of information:
|
|
86
|
-
|
|
87
|
-
${lines.join(`
|
|
88
|
-
|
|
89
|
-
`)}`
|
|
90
|
-
};
|
|
61
|
+
return {
|
|
62
|
+
id: "data-collected",
|
|
63
|
+
title: "Information We Collect",
|
|
64
|
+
body: `We collect the following categories of information:\n\n${Object.entries(config.dataCollected).map(([category, items]) => {
|
|
65
|
+
return `**${category}:**\n${items.map((item) => ` - ${item}`).join("\n")}`;
|
|
66
|
+
}).join("\n\n")}`
|
|
67
|
+
};
|
|
91
68
|
}
|
|
92
|
-
|
|
93
|
-
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/templates/privacy/data-retention.ts
|
|
94
71
|
function buildDataRetention(config) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
body: `We retain your information for the following periods:
|
|
101
|
-
|
|
102
|
-
${lines.join(`
|
|
103
|
-
`)}`
|
|
104
|
-
};
|
|
72
|
+
return {
|
|
73
|
+
id: "data-retention",
|
|
74
|
+
title: "Data Retention",
|
|
75
|
+
body: `We retain your information for the following periods:\n\n${Object.entries(config.retention).map(([category, period]) => `- **${category}:** ${period}`).join("\n")}`
|
|
76
|
+
};
|
|
105
77
|
}
|
|
106
|
-
|
|
107
|
-
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/templates/privacy/gdpr-supplement.ts
|
|
108
80
|
function buildGdprSupplement(config) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
body: `This section applies to individuals in the European Economic Area (EEA) under the General Data Protection Regulation (GDPR).
|
|
81
|
+
if (!config.jurisdictions.includes("eu")) return null;
|
|
82
|
+
return {
|
|
83
|
+
id: "gdpr-supplement",
|
|
84
|
+
title: "GDPR Supplemental Disclosures",
|
|
85
|
+
body: `This section applies to individuals in the European Economic Area (EEA) under the General Data Protection Regulation (GDPR).
|
|
115
86
|
|
|
116
87
|
**Data Controller:** ${config.company.legalName}, ${config.company.address}
|
|
117
88
|
|
|
118
89
|
**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.
|
|
119
90
|
|
|
120
91
|
**International Transfers:** If we transfer your personal data outside the EEA, we ensure adequate safeguards are in place in accordance with GDPR requirements.`
|
|
121
|
-
|
|
92
|
+
};
|
|
122
93
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
function buildIntroduction(config) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/templates/privacy/introduction.ts
|
|
96
|
+
function buildIntroduction$1(config) {
|
|
97
|
+
return {
|
|
98
|
+
id: "introduction",
|
|
99
|
+
title: "Introduction",
|
|
100
|
+
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.
|
|
130
101
|
|
|
131
102
|
**Effective Date:** ${config.effectiveDate}
|
|
132
103
|
|
|
133
104
|
If you have questions about this policy, please contact us at ${config.company.contact}.`
|
|
134
|
-
|
|
105
|
+
};
|
|
135
106
|
}
|
|
136
|
-
|
|
137
|
-
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/templates/privacy/legal-basis.ts
|
|
138
109
|
function buildLegalBasis(config) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
${config.legalBasis}`
|
|
147
|
-
};
|
|
110
|
+
if (!config.jurisdictions.includes("eu")) return null;
|
|
111
|
+
return {
|
|
112
|
+
id: "legal-basis",
|
|
113
|
+
title: "Legal Basis for Processing",
|
|
114
|
+
body: `We process your personal data under the following legal basis:\n\n${config.legalBasis}`
|
|
115
|
+
};
|
|
148
116
|
}
|
|
149
|
-
|
|
150
|
-
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/templates/privacy/third-parties.ts
|
|
151
119
|
function buildThirdParties(config) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
`)}` : "We do not share your data with third-party services."
|
|
157
|
-
|
|
158
|
-
id: "third-parties",
|
|
159
|
-
title: "Third-Party Services",
|
|
160
|
-
body
|
|
161
|
-
};
|
|
120
|
+
const lines = config.thirdParties.map((tp) => `- **${tp.name}** — ${tp.purpose}`);
|
|
121
|
+
return {
|
|
122
|
+
id: "third-parties",
|
|
123
|
+
title: "Third-Party Services",
|
|
124
|
+
body: lines.length > 0 ? `We share data with the following third-party services:\n\n${lines.join("\n")}` : "We do not share your data with third-party services."
|
|
125
|
+
};
|
|
162
126
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/templates/privacy/user-rights.ts
|
|
129
|
+
const RIGHTS_LABELS = {
|
|
130
|
+
access: "Right to access your personal data",
|
|
131
|
+
rectification: "Right to correct inaccurate data",
|
|
132
|
+
erasure: "Right to request deletion of your data",
|
|
133
|
+
portability: "Right to receive your data in a portable format",
|
|
134
|
+
restriction: "Right to restrict how we process your data",
|
|
135
|
+
objection: "Right to object to processing",
|
|
136
|
+
opt_out_sale: "Right to opt out of the sale of your personal information",
|
|
137
|
+
non_discrimination: "Right to non-discriminatory treatment for exercising your rights"
|
|
174
138
|
};
|
|
175
139
|
function buildUserRights(config) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
body: `You have the following rights regarding your personal data:
|
|
184
|
-
|
|
185
|
-
${lines.join(`
|
|
186
|
-
`)}`
|
|
187
|
-
};
|
|
140
|
+
return {
|
|
141
|
+
id: "user-rights",
|
|
142
|
+
title: "Your Rights",
|
|
143
|
+
body: `You have the following rights regarding your personal data:\n\n${config.userRights.map((right) => {
|
|
144
|
+
return `- ${RIGHTS_LABELS[right] ?? right}`;
|
|
145
|
+
}).join("\n")}`
|
|
146
|
+
};
|
|
188
147
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
148
|
+
//#endregion
|
|
149
|
+
//#region src/privacy.ts
|
|
150
|
+
const SECTION_BUILDERS$1 = [
|
|
151
|
+
buildIntroduction$1,
|
|
152
|
+
buildDataCollected,
|
|
153
|
+
buildLegalBasis,
|
|
154
|
+
buildDataRetention,
|
|
155
|
+
buildCookies,
|
|
156
|
+
buildThirdParties,
|
|
157
|
+
buildUserRights,
|
|
158
|
+
buildGdprSupplement,
|
|
159
|
+
buildCcpaSupplement,
|
|
160
|
+
buildContact$1
|
|
202
161
|
];
|
|
203
162
|
function compilePrivacyPolicy(config, options = { formats: ["markdown"] }) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
|
|
163
|
+
const sections = SECTION_BUILDERS$1.map((builder) => builder(config)).filter((s) => s !== null);
|
|
164
|
+
return options.formats.map((format) => {
|
|
165
|
+
switch (format) {
|
|
166
|
+
case "markdown": return {
|
|
167
|
+
format,
|
|
168
|
+
content: renderMarkdown(sections),
|
|
169
|
+
sections
|
|
170
|
+
};
|
|
171
|
+
case "html": return {
|
|
172
|
+
format,
|
|
173
|
+
content: renderHTML(sections),
|
|
174
|
+
sections
|
|
175
|
+
};
|
|
176
|
+
case "pdf": throw new Error("pdf format is not yet implemented");
|
|
177
|
+
case "jsx": throw new Error("jsx format is not yet implemented");
|
|
178
|
+
default: throw new Error(`Unsupported format: ${format}`);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
//#endregion
|
|
183
|
+
//#region src/templates/terms/acceptance.ts
|
|
184
|
+
function buildAcceptance(config) {
|
|
185
|
+
return {
|
|
186
|
+
id: "tos-acceptance",
|
|
187
|
+
title: "Acceptance of Terms",
|
|
188
|
+
body: `By accessing or using our services, you agree to be bound by these Terms. You accept these Terms by:\n\n${config.acceptance.methods.map((m) => `- ${m}`).join("\n")}\n\nIf you do not agree to these Terms, you may not use our services.`
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/templates/terms/accounts.ts
|
|
193
|
+
function buildAccounts(config) {
|
|
194
|
+
if (!config.accounts) return null;
|
|
195
|
+
const { registrationRequired, userResponsibleForCredentials, companyCanTerminate } = config.accounts;
|
|
196
|
+
const lines = [];
|
|
197
|
+
if (registrationRequired) lines.push("You must create an account to access certain features of our services. You agree to provide accurate, current, and complete information during registration.");
|
|
198
|
+
if (userResponsibleForCredentials) lines.push("You are responsible for maintaining the confidentiality of your account credentials and for all activities that occur under your account. You must notify us immediately of any unauthorized use of your account.");
|
|
199
|
+
if (companyCanTerminate) lines.push(`${config.company.name} reserves the right to suspend or terminate your account at any time, with or without notice, for any reason including violation of these Terms.`);
|
|
200
|
+
return {
|
|
201
|
+
id: "tos-accounts",
|
|
202
|
+
title: "Accounts",
|
|
203
|
+
body: lines.join("\n\n")
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
//#region src/templates/terms/availability.ts
|
|
208
|
+
function buildAvailability(config) {
|
|
209
|
+
if (!config.availability) return null;
|
|
210
|
+
const lines = [];
|
|
211
|
+
if (config.availability.noUptimeGuarantee) lines.push("We do not guarantee that our services will be available at all times. Our services may be subject to interruptions, delays, or errors.");
|
|
212
|
+
if (config.availability.maintenanceWindows) lines.push(`**Maintenance:** ${config.availability.maintenanceWindows}`);
|
|
213
|
+
return {
|
|
214
|
+
id: "tos-availability",
|
|
215
|
+
title: "Service Availability",
|
|
216
|
+
body: lines.join("\n\n")
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/templates/terms/changes-to-terms.ts
|
|
221
|
+
function buildChangesToTerms(config) {
|
|
222
|
+
if (!config.changesPolicy) return null;
|
|
223
|
+
const { noticeMethod, noticePeriodDays } = config.changesPolicy;
|
|
224
|
+
return {
|
|
225
|
+
id: "tos-changes",
|
|
226
|
+
title: "Changes to These Terms",
|
|
227
|
+
body: `We may update these Terms from time to time. We will notify you of material changes via ${noticeMethod}${noticePeriodDays ? ` at least **${noticePeriodDays} days** before they take effect` : " before they take effect"}. Your continued use of our services after changes become effective constitutes your acceptance of the revised Terms.`
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/templates/terms/contact.ts
|
|
232
|
+
function buildContact(config) {
|
|
233
|
+
return {
|
|
234
|
+
id: "tos-contact",
|
|
235
|
+
title: "Contact Us",
|
|
236
|
+
body: `If you have any questions about these Terms, please contact us at:
|
|
237
|
+
|
|
238
|
+
**${config.company.legalName}**
|
|
239
|
+
${config.company.address}
|
|
240
|
+
${config.company.contact}`
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
//#region src/templates/terms/disclaimers.ts
|
|
245
|
+
function buildDisclaimers(config) {
|
|
246
|
+
if (!config.disclaimers) return null;
|
|
247
|
+
const lines = [];
|
|
248
|
+
if (config.disclaimers.serviceProvidedAsIs) lines.push("OUR SERVICES ARE PROVIDED \"AS IS\" AND \"AS AVAILABLE\" WITHOUT WARRANTIES OF ANY KIND.");
|
|
249
|
+
if (config.disclaimers.noWarranties) lines.push(`${config.company.legalName} EXPRESSLY DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.`);
|
|
250
|
+
return {
|
|
251
|
+
id: "tos-disclaimers",
|
|
252
|
+
title: "Disclaimer of Warranties",
|
|
253
|
+
body: lines.join("\n\n")
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/templates/terms/dispute-resolution.ts
|
|
258
|
+
function buildDisputeResolution(config) {
|
|
259
|
+
if (!config.disputeResolution) return null;
|
|
260
|
+
const { method, venue, classActionWaiver } = config.disputeResolution;
|
|
261
|
+
const lines = [{
|
|
262
|
+
arbitration: "Any disputes arising out of or relating to these Terms or our services shall be resolved by binding arbitration rather than in court.",
|
|
263
|
+
litigation: "Any disputes arising out of or relating to these Terms or our services shall be resolved through litigation in a court of competent jurisdiction.",
|
|
264
|
+
mediation: "Any disputes arising out of or relating to these Terms or our services shall first be submitted to non-binding mediation before pursuing other remedies."
|
|
265
|
+
}[method] ?? "Disputes arising out of or relating to these Terms shall be resolved as described below."];
|
|
266
|
+
if (venue) lines.push(`**Venue:** ${venue}`);
|
|
267
|
+
if (classActionWaiver) lines.push("**Class Action Waiver:** You agree that any dispute resolution proceedings will be conducted only on an individual basis and not in a class, consolidated, or representative action.");
|
|
268
|
+
return {
|
|
269
|
+
id: "tos-dispute-resolution",
|
|
270
|
+
title: "Dispute Resolution",
|
|
271
|
+
body: lines.join("\n\n")
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
//#endregion
|
|
275
|
+
//#region src/templates/terms/eligibility.ts
|
|
276
|
+
function buildEligibility(config) {
|
|
277
|
+
if (!config.eligibility) return null;
|
|
278
|
+
const { minimumAge, jurisdictionRestrictions } = config.eligibility;
|
|
279
|
+
let body = `You must be at least **${minimumAge} years old** to use our services. By using our services, you represent and warrant that you meet this age requirement.`;
|
|
280
|
+
if (jurisdictionRestrictions && jurisdictionRestrictions.length > 0) {
|
|
281
|
+
const list = jurisdictionRestrictions.map((r) => `- ${r}`).join("\n");
|
|
282
|
+
body += `\n\nOur services are not available in the following jurisdictions:\n\n${list}`;
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
id: "tos-eligibility",
|
|
286
|
+
title: "Eligibility",
|
|
287
|
+
body
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
291
|
+
//#region src/templates/terms/governing-law.ts
|
|
292
|
+
function buildGoverningLaw(config) {
|
|
293
|
+
return {
|
|
294
|
+
id: "tos-governing-law",
|
|
295
|
+
title: "Governing Law",
|
|
296
|
+
body: `These Terms shall be governed by and construed in accordance with the laws of **${config.governingLaw.jurisdiction}**, without regard to its conflict of law provisions.`
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/templates/terms/indemnification.ts
|
|
301
|
+
function buildIndemnification(config) {
|
|
302
|
+
if (!config.indemnification) return null;
|
|
303
|
+
const lines = [];
|
|
304
|
+
if (config.indemnification.userIndemnifiesCompany) lines.push(`You agree to indemnify and hold harmless ${config.company.legalName} and its officers, directors, employees, and agents from and against any claims, liabilities, damages, losses, and expenses arising out of or in any way connected with your access to or use of our services.`);
|
|
305
|
+
if (config.indemnification.scope) lines.push(`**Scope:** ${config.indemnification.scope}`);
|
|
306
|
+
return {
|
|
307
|
+
id: "tos-indemnification",
|
|
308
|
+
title: "Indemnification",
|
|
309
|
+
body: lines.join("\n\n")
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
//#endregion
|
|
313
|
+
//#region src/templates/terms/intellectual-property.ts
|
|
314
|
+
function buildIntellectualProperty(config) {
|
|
315
|
+
if (!config.intellectualProperty) return null;
|
|
316
|
+
const { companyOwnsService, usersMayNotCopy } = config.intellectualProperty;
|
|
317
|
+
const lines = [];
|
|
318
|
+
if (companyOwnsService) lines.push(`The services and all content, features, and functionality (including but not limited to text, graphics, logos, and software) are owned by ${config.company.legalName} and are protected by intellectual property laws.`);
|
|
319
|
+
if (usersMayNotCopy) lines.push("You may not copy, modify, distribute, sell, or lease any part of our services or included software, nor may you reverse engineer or attempt to extract the source code of that software.");
|
|
320
|
+
return {
|
|
321
|
+
id: "tos-intellectual-property",
|
|
322
|
+
title: "Intellectual Property",
|
|
323
|
+
body: lines.join("\n\n")
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
//#endregion
|
|
327
|
+
//#region src/templates/terms/introduction.ts
|
|
328
|
+
function buildIntroduction(config) {
|
|
329
|
+
const privacyLine = config.privacyPolicyUrl ? `\n\nFor information about how we collect and use your data, please review our [Privacy Policy](${config.privacyPolicyUrl}).` : "";
|
|
330
|
+
return {
|
|
331
|
+
id: "tos-introduction",
|
|
332
|
+
title: "Terms of Service",
|
|
333
|
+
body: `These Terms of Service ("Terms") govern your access to and use of the services provided by ${config.company.name} ("${config.company.name}", "we", "us", or "our"). By using our services, you agree to these Terms.
|
|
334
|
+
|
|
335
|
+
**Effective Date:** ${config.effectiveDate}${privacyLine}`
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/templates/terms/limitation-of-liability.ts
|
|
340
|
+
function buildLimitationOfLiability(config) {
|
|
341
|
+
if (!config.limitationOfLiability) return null;
|
|
342
|
+
const lines = [];
|
|
343
|
+
if (config.limitationOfLiability.excludesIndirectDamages) lines.push(`TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, ${config.company.legalName.toUpperCase()} SHALL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR ANY LOSS OF PROFITS OR REVENUES, WHETHER INCURRED DIRECTLY OR INDIRECTLY, OR ANY LOSS OF DATA, USE, GOODWILL, OR OTHER INTANGIBLE LOSSES.`);
|
|
344
|
+
if (config.limitationOfLiability.liabilityCap) lines.push(`**Liability Cap:** ${config.limitationOfLiability.liabilityCap}`);
|
|
345
|
+
return {
|
|
346
|
+
id: "tos-limitation-of-liability",
|
|
347
|
+
title: "Limitation of Liability",
|
|
348
|
+
body: lines.join("\n\n")
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
//#endregion
|
|
352
|
+
//#region src/templates/terms/payments.ts
|
|
353
|
+
function buildPayments(config) {
|
|
354
|
+
if (!config.payments || !config.payments.hasPaidFeatures) return null;
|
|
355
|
+
const lines = ["Some features of our services require payment. By selecting a paid plan, you agree to pay all applicable fees."];
|
|
356
|
+
if (config.payments.refundPolicy) lines.push(`**Refunds:** ${config.payments.refundPolicy}`);
|
|
357
|
+
if (config.payments.priceChangesNotice) lines.push(`**Price Changes:** ${config.payments.priceChangesNotice}`);
|
|
358
|
+
return {
|
|
359
|
+
id: "tos-payments",
|
|
360
|
+
title: "Payments and Billing",
|
|
361
|
+
body: lines.join("\n\n")
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
//#endregion
|
|
365
|
+
//#region src/templates/terms/prohibited-use.ts
|
|
366
|
+
function buildProhibitedUse(config) {
|
|
367
|
+
if (!config.prohibitedUses || config.prohibitedUses.length === 0) return null;
|
|
368
|
+
return {
|
|
369
|
+
id: "tos-prohibited-use",
|
|
370
|
+
title: "Prohibited Uses",
|
|
371
|
+
body: `You agree not to use our services for any of the following purposes:\n\n${config.prohibitedUses.map((u) => `- ${u}`).join("\n")}`
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
//#endregion
|
|
375
|
+
//#region src/templates/terms/termination.ts
|
|
376
|
+
function buildTermination(config) {
|
|
377
|
+
if (!config.termination) return null;
|
|
378
|
+
const { companyCanTerminate, userCanTerminate, effectOfTermination } = config.termination;
|
|
379
|
+
const lines = [];
|
|
380
|
+
if (companyCanTerminate) lines.push(`${config.company.name} may suspend or terminate your access to the services at any time, with or without cause, and with or without notice.`);
|
|
381
|
+
if (userCanTerminate) lines.push("You may terminate your account at any time by discontinuing use of our services or by contacting us to close your account.");
|
|
382
|
+
if (effectOfTermination) lines.push(`**Effect of Termination:** ${effectOfTermination}`);
|
|
383
|
+
return {
|
|
384
|
+
id: "tos-termination",
|
|
385
|
+
title: "Termination",
|
|
386
|
+
body: lines.join("\n\n")
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
//#endregion
|
|
390
|
+
//#region src/templates/terms/third-party-services.ts
|
|
391
|
+
function buildThirdPartyServices(config) {
|
|
392
|
+
if (!config.thirdPartyServices || config.thirdPartyServices.length === 0) return null;
|
|
393
|
+
return {
|
|
394
|
+
id: "tos-third-party-services",
|
|
395
|
+
title: "Third-Party Services",
|
|
396
|
+
body: `Our services may integrate with or link to third-party services. Your use of those services is governed by their own terms and policies.\n\n${config.thirdPartyServices.map((s) => `- **${s.name}** — ${s.purpose}`).join("\n")}`
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
//#endregion
|
|
400
|
+
//#region src/templates/terms/user-content.ts
|
|
401
|
+
function buildUserContent(config) {
|
|
402
|
+
if (!config.userContent) return null;
|
|
403
|
+
const { usersOwnContent, licenseGrantedToCompany, licenseDescription, companyCanRemoveContent } = config.userContent;
|
|
404
|
+
const lines = [];
|
|
405
|
+
if (usersOwnContent) lines.push("You retain ownership of any content you submit, post, or display on or through our services (\"User Content\").");
|
|
406
|
+
if (licenseGrantedToCompany) {
|
|
407
|
+
const desc = licenseDescription ? licenseDescription : "a worldwide, royalty-free, non-exclusive license to use, reproduce, modify, and distribute your User Content in connection with operating and improving our services";
|
|
408
|
+
lines.push(`By submitting User Content, you grant ${config.company.name} ${desc}.`);
|
|
409
|
+
}
|
|
410
|
+
if (companyCanRemoveContent) lines.push(`${config.company.name} reserves the right to remove any User Content that violates these Terms or that we find objectionable, at our sole discretion.`);
|
|
411
|
+
return {
|
|
412
|
+
id: "tos-user-content",
|
|
413
|
+
title: "User Content",
|
|
414
|
+
body: lines.join("\n\n")
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region src/terms.ts
|
|
419
|
+
const SECTION_BUILDERS = [
|
|
420
|
+
buildIntroduction,
|
|
421
|
+
buildAcceptance,
|
|
422
|
+
buildEligibility,
|
|
423
|
+
buildAccounts,
|
|
424
|
+
buildProhibitedUse,
|
|
425
|
+
buildUserContent,
|
|
426
|
+
buildIntellectualProperty,
|
|
427
|
+
buildPayments,
|
|
428
|
+
buildAvailability,
|
|
429
|
+
buildTermination,
|
|
430
|
+
buildDisclaimers,
|
|
431
|
+
buildLimitationOfLiability,
|
|
432
|
+
buildIndemnification,
|
|
433
|
+
buildThirdPartyServices,
|
|
434
|
+
buildDisputeResolution,
|
|
435
|
+
buildGoverningLaw,
|
|
436
|
+
buildChangesToTerms,
|
|
437
|
+
buildContact
|
|
438
|
+
];
|
|
439
|
+
function compileTermsOfService(config, options = { formats: ["markdown"] }) {
|
|
440
|
+
const sections = SECTION_BUILDERS.map((builder) => builder(config)).filter((s) => s !== null);
|
|
441
|
+
return options.formats.map((format) => {
|
|
442
|
+
switch (format) {
|
|
443
|
+
case "markdown": return {
|
|
444
|
+
format,
|
|
445
|
+
content: renderMarkdown(sections),
|
|
446
|
+
sections
|
|
447
|
+
};
|
|
448
|
+
case "html": return {
|
|
449
|
+
format,
|
|
450
|
+
content: renderHTML(sections),
|
|
451
|
+
sections
|
|
452
|
+
};
|
|
453
|
+
case "pdf": throw new Error("pdf format is not yet implemented");
|
|
454
|
+
case "jsx": throw new Error("jsx format is not yet implemented");
|
|
455
|
+
default: throw new Error(`Unsupported format: ${format}`);
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region src/validate.ts
|
|
221
461
|
function validatePrivacyPolicy(config) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
462
|
+
const issues = [];
|
|
463
|
+
if (!config.effectiveDate) issues.push({
|
|
464
|
+
level: "error",
|
|
465
|
+
message: "effectiveDate is required"
|
|
466
|
+
});
|
|
467
|
+
if (!config.company.name) issues.push({
|
|
468
|
+
level: "error",
|
|
469
|
+
message: "company.name is required"
|
|
470
|
+
});
|
|
471
|
+
if (!config.company.legalName) issues.push({
|
|
472
|
+
level: "error",
|
|
473
|
+
message: "company.legalName is required"
|
|
474
|
+
});
|
|
475
|
+
if (!config.company.address) issues.push({
|
|
476
|
+
level: "error",
|
|
477
|
+
message: "company.address is required"
|
|
478
|
+
});
|
|
479
|
+
if (!config.company.contact) issues.push({
|
|
480
|
+
level: "error",
|
|
481
|
+
message: "company.contact is required"
|
|
482
|
+
});
|
|
483
|
+
if (Object.keys(config.dataCollected).length === 0) issues.push({
|
|
484
|
+
level: "error",
|
|
485
|
+
message: "dataCollected must have at least one entry"
|
|
486
|
+
});
|
|
487
|
+
if (config.userRights.length === 0) issues.push({
|
|
488
|
+
level: "warning",
|
|
489
|
+
message: "userRights is empty — consider listing applicable rights"
|
|
490
|
+
});
|
|
491
|
+
if (config.jurisdictions.includes("eu")) {
|
|
492
|
+
if (!config.legalBasis) issues.push({
|
|
493
|
+
level: "error",
|
|
494
|
+
message: "GDPR requires a legalBasis"
|
|
495
|
+
});
|
|
496
|
+
for (const right of [
|
|
497
|
+
"access",
|
|
498
|
+
"rectification",
|
|
499
|
+
"erasure",
|
|
500
|
+
"portability",
|
|
501
|
+
"restriction",
|
|
502
|
+
"objection"
|
|
503
|
+
]) if (!config.userRights.includes(right)) issues.push({
|
|
504
|
+
level: "warning",
|
|
505
|
+
message: `GDPR recommends including the "${right}" right`
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
if (config.jurisdictions.includes("ca")) {
|
|
509
|
+
for (const right of [
|
|
510
|
+
"access",
|
|
511
|
+
"erasure",
|
|
512
|
+
"opt_out_sale",
|
|
513
|
+
"non_discrimination"
|
|
514
|
+
]) if (!config.userRights.includes(right)) issues.push({
|
|
515
|
+
level: "warning",
|
|
516
|
+
message: `CCPA recommends including the "${right}" right`
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
return issues;
|
|
520
|
+
}
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region src/validate-terms.ts
|
|
523
|
+
function validateTermsOfService(config) {
|
|
524
|
+
const issues = [];
|
|
525
|
+
if (!config.effectiveDate) issues.push({
|
|
526
|
+
level: "error",
|
|
527
|
+
message: "effectiveDate is required"
|
|
528
|
+
});
|
|
529
|
+
if (!config.company.name) issues.push({
|
|
530
|
+
level: "error",
|
|
531
|
+
message: "company.name is required"
|
|
532
|
+
});
|
|
533
|
+
if (!config.company.legalName) issues.push({
|
|
534
|
+
level: "error",
|
|
535
|
+
message: "company.legalName is required"
|
|
536
|
+
});
|
|
537
|
+
if (!config.company.address) issues.push({
|
|
538
|
+
level: "error",
|
|
539
|
+
message: "company.address is required"
|
|
540
|
+
});
|
|
541
|
+
if (!config.company.contact) issues.push({
|
|
542
|
+
level: "error",
|
|
543
|
+
message: "company.contact is required"
|
|
544
|
+
});
|
|
545
|
+
if (!config.governingLaw.jurisdiction) issues.push({
|
|
546
|
+
level: "error",
|
|
547
|
+
message: "governingLaw.jurisdiction is required"
|
|
548
|
+
});
|
|
549
|
+
if (!config.disclaimers) issues.push({
|
|
550
|
+
level: "warning",
|
|
551
|
+
message: "disclaimers is missing — consider adding a disclaimer of warranties"
|
|
552
|
+
});
|
|
553
|
+
if (!config.limitationOfLiability) issues.push({
|
|
554
|
+
level: "warning",
|
|
555
|
+
message: "limitationOfLiability is missing — consider adding a limitation of liability clause"
|
|
556
|
+
});
|
|
557
|
+
if (config.acceptance.methods.length === 0) issues.push({
|
|
558
|
+
level: "warning",
|
|
559
|
+
message: "acceptance.methods is empty — consider listing how users accept these Terms"
|
|
560
|
+
});
|
|
561
|
+
return issues;
|
|
562
|
+
}
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/index.ts
|
|
278
565
|
function compilePolicy(input, options) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
566
|
+
switch (input.type) {
|
|
567
|
+
case "privacy": {
|
|
568
|
+
const { type: _, ...config } = input;
|
|
569
|
+
return compilePrivacyPolicy(config, options);
|
|
570
|
+
}
|
|
571
|
+
case "terms": {
|
|
572
|
+
const { type: _, ...config } = input;
|
|
573
|
+
return compileTermsOfService(config, options);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
//#endregion
|
|
578
|
+
export { compilePolicy, compilePrivacyPolicy, compileTermsOfService, validatePrivacyPolicy, validateTermsOfService };
|
|
579
|
+
|
|
580
|
+
//# sourceMappingURL=index.js.map
|