@contractspec/bundle.marketing 1.12.0 → 1.14.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/.turbo/turbo-build.log +146 -175
- package/.turbo/turbo-prebuild.log +1 -0
- package/CHANGELOG.md +57 -0
- package/dist/browser/components/marketing/ChangelogPage.js +92 -0
- package/dist/browser/components/marketing/CofounderPage.js +581 -0
- package/dist/browser/components/marketing/ContactClient.js +1379 -0
- package/dist/browser/components/marketing/ContributePage.js +487 -0
- package/dist/browser/components/marketing/DesignPartnerPage.js +272 -0
- package/dist/browser/components/marketing/LandingPage.js +629 -0
- package/dist/browser/components/marketing/PricingClient.js +1972 -0
- package/dist/browser/components/marketing/ProductClientPage.js +563 -0
- package/dist/browser/components/marketing/index.js +4818 -0
- package/dist/browser/components/marketing/pricing-thinking-modal.js +258 -0
- package/dist/browser/components/marketing/sections/AudienceSection.js +90 -0
- package/dist/browser/components/marketing/sections/CorePositioningSection.js +72 -0
- package/dist/browser/components/marketing/sections/CtaSection.js +67 -0
- package/dist/browser/components/marketing/sections/DevelopersSection.js +50 -0
- package/dist/browser/components/marketing/sections/FearsSection.js +105 -0
- package/dist/browser/components/marketing/sections/HeroMarketingSection.js +93 -0
- package/dist/browser/components/marketing/sections/IconGridSection.js +63 -0
- package/dist/browser/components/marketing/sections/OutputsSection.js +116 -0
- package/dist/browser/components/marketing/sections/ProblemSection.js +103 -0
- package/dist/browser/components/marketing/sections/SolutionSection.js +103 -0
- package/dist/browser/components/marketing/sections/StepsSection.js +109 -0
- package/dist/browser/components/marketing/waitlist-section.js +1104 -0
- package/dist/browser/components/templates/TemplatesClientPage.js +5662 -0
- package/dist/browser/components/templates/TemplatesPage.js +177 -0
- package/dist/browser/components/templates/TemplatesPreviewModal.js +124 -0
- package/dist/browser/components/templates/index.js +5831 -0
- package/dist/browser/index.js +6485 -0
- package/dist/browser/libs/email/client.js +122 -0
- package/dist/browser/libs/email/contact.js +190 -0
- package/dist/browser/libs/email/newsletter.js +215 -0
- package/dist/browser/libs/email/types.js +2 -0
- package/dist/browser/libs/email/utils.js +16 -0
- package/dist/browser/libs/email/waitlist-application.js +295 -0
- package/dist/browser/libs/email/waitlist.js +225 -0
- package/dist/browser/libs/pricing-examples.js +26 -0
- package/dist/browser/registry/engine.js +5293 -0
- package/dist/browser/registry/factory.js +52 -0
- package/dist/browser/registry/index.js +5358 -0
- package/dist/browser/registry/registry-docs.js +343 -0
- package/dist/browser/registry/registry-landing.js +4937 -0
- package/dist/browser/registry/registry.js +5279 -0
- package/dist/browser/registry/types.js +0 -0
- package/dist/browser/registry/utils.js +5340 -0
- package/dist/components/marketing/ChangelogPage.d.ts +11 -17
- package/dist/components/marketing/ChangelogPage.d.ts.map +1 -1
- package/dist/components/marketing/ChangelogPage.js +84 -62
- package/dist/components/marketing/CofounderPage.d.ts +1 -6
- package/dist/components/marketing/CofounderPage.d.ts.map +1 -1
- package/dist/components/marketing/CofounderPage.js +544 -436
- package/dist/components/marketing/ContactClient.d.ts +1 -6
- package/dist/components/marketing/ContactClient.d.ts.map +1 -1
- package/dist/components/marketing/ContactClient.js +1371 -155
- package/dist/components/marketing/ContributePage.d.ts +3 -8
- package/dist/components/marketing/ContributePage.d.ts.map +1 -1
- package/dist/components/marketing/ContributePage.js +478 -358
- package/dist/components/marketing/DesignPartnerPage.d.ts +3 -8
- package/dist/components/marketing/DesignPartnerPage.d.ts.map +1 -1
- package/dist/components/marketing/DesignPartnerPage.js +263 -211
- package/dist/components/marketing/LandingPage.d.ts +1 -6
- package/dist/components/marketing/LandingPage.d.ts.map +1 -1
- package/dist/components/marketing/LandingPage.js +623 -37
- package/dist/components/marketing/PricingClient.d.ts +1 -6
- package/dist/components/marketing/PricingClient.d.ts.map +1 -1
- package/dist/components/marketing/PricingClient.js +1962 -516
- package/dist/components/marketing/ProductClientPage.d.ts +1 -6
- package/dist/components/marketing/ProductClientPage.d.ts.map +1 -1
- package/dist/components/marketing/ProductClientPage.js +556 -458
- package/dist/components/marketing/index.d.ts +11 -11
- package/dist/components/marketing/index.d.ts.map +1 -0
- package/dist/components/marketing/index.js +4813 -12
- package/dist/components/marketing/pricing-thinking-modal.d.ts +5 -13
- package/dist/components/marketing/pricing-thinking-modal.d.ts.map +1 -1
- package/dist/components/marketing/pricing-thinking-modal.js +248 -197
- package/dist/components/marketing/sections/AudienceSection.d.ts +1 -6
- package/dist/components/marketing/sections/AudienceSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/AudienceSection.js +80 -63
- package/dist/components/marketing/sections/CorePositioningSection.d.ts +1 -6
- package/dist/components/marketing/sections/CorePositioningSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/CorePositioningSection.js +62 -54
- package/dist/components/marketing/sections/CtaSection.d.ts +1 -6
- package/dist/components/marketing/sections/CtaSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/CtaSection.js +58 -50
- package/dist/components/marketing/sections/DevelopersSection.d.ts +1 -6
- package/dist/components/marketing/sections/DevelopersSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/DevelopersSection.js +40 -40
- package/dist/components/marketing/sections/FearsSection.d.ts +1 -6
- package/dist/components/marketing/sections/FearsSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/FearsSection.js +96 -44
- package/dist/components/marketing/sections/HeroMarketingSection.d.ts +1 -6
- package/dist/components/marketing/sections/HeroMarketingSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/HeroMarketingSection.js +82 -71
- package/dist/components/marketing/sections/IconGridSection.d.ts +25 -39
- package/dist/components/marketing/sections/IconGridSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/IconGridSection.js +55 -41
- package/dist/components/marketing/sections/OutputsSection.d.ts +1 -6
- package/dist/components/marketing/sections/OutputsSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/OutputsSection.js +107 -55
- package/dist/components/marketing/sections/ProblemSection.d.ts +1 -6
- package/dist/components/marketing/sections/ProblemSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/ProblemSection.js +94 -42
- package/dist/components/marketing/sections/SolutionSection.d.ts +1 -6
- package/dist/components/marketing/sections/SolutionSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/SolutionSection.js +94 -42
- package/dist/components/marketing/sections/StepsSection.d.ts +1 -6
- package/dist/components/marketing/sections/StepsSection.d.ts.map +1 -1
- package/dist/components/marketing/sections/StepsSection.js +100 -48
- package/dist/components/marketing/waitlist-section.d.ts +5 -12
- package/dist/components/marketing/waitlist-section.d.ts.map +1 -1
- package/dist/components/marketing/waitlist-section.js +1089 -568
- package/dist/components/templates/TemplatesClientPage.d.ts +1 -6
- package/dist/components/templates/TemplatesClientPage.d.ts.map +1 -1
- package/dist/components/templates/TemplatesClientPage.js +5649 -617
- package/dist/components/templates/TemplatesPage.d.ts +1 -6
- package/dist/components/templates/TemplatesPage.d.ts.map +1 -1
- package/dist/components/templates/TemplatesPage.js +163 -116
- package/dist/components/templates/TemplatesPreviewModal.d.ts +5 -12
- package/dist/components/templates/TemplatesPreviewModal.d.ts.map +1 -1
- package/dist/components/templates/TemplatesPreviewModal.js +113 -131
- package/dist/components/templates/index.d.ts +4 -4
- package/dist/components/templates/index.d.ts.map +1 -0
- package/dist/components/templates/index.js +5825 -4
- package/dist/index.d.ts +9 -29
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6480 -28
- package/dist/libs/email/client.d.ts +9 -12
- package/dist/libs/email/client.d.ts.map +1 -1
- package/dist/libs/email/client.js +109 -105
- package/dist/libs/email/client.test.d.ts +2 -0
- package/dist/libs/email/client.test.d.ts.map +1 -0
- package/dist/libs/email/contact.d.ts +2 -6
- package/dist/libs/email/contact.d.ts.map +1 -1
- package/dist/libs/email/contact.js +155 -41
- package/dist/libs/email/newsletter.d.ts +2 -6
- package/dist/libs/email/newsletter.d.ts.map +1 -1
- package/dist/libs/email/newsletter.js +169 -54
- package/dist/libs/email/types.d.ts +48 -52
- package/dist/libs/email/types.d.ts.map +1 -1
- package/dist/libs/email/types.js +3 -1
- package/dist/libs/email/utils.d.ts +2 -5
- package/dist/libs/email/utils.d.ts.map +1 -1
- package/dist/libs/email/utils.js +10 -6
- package/dist/libs/email/waitlist-application.d.ts +2 -6
- package/dist/libs/email/waitlist-application.d.ts.map +1 -1
- package/dist/libs/email/waitlist-application.js +191 -71
- package/dist/libs/email/waitlist.d.ts +2 -6
- package/dist/libs/email/waitlist.d.ts.map +1 -1
- package/dist/libs/email/waitlist.js +171 -56
- package/dist/libs/pricing-examples.d.ts +13 -16
- package/dist/libs/pricing-examples.d.ts.map +1 -1
- package/dist/libs/pricing-examples.js +20 -20
- package/dist/node/components/marketing/ChangelogPage.js +87 -0
- package/dist/node/components/marketing/CofounderPage.js +576 -0
- package/dist/node/components/marketing/ContactClient.js +1374 -0
- package/dist/node/components/marketing/ContributePage.js +482 -0
- package/dist/node/components/marketing/DesignPartnerPage.js +267 -0
- package/dist/node/components/marketing/LandingPage.js +624 -0
- package/dist/node/components/marketing/PricingClient.js +1967 -0
- package/dist/node/components/marketing/ProductClientPage.js +558 -0
- package/dist/node/components/marketing/index.js +4813 -0
- package/dist/node/components/marketing/pricing-thinking-modal.js +253 -0
- package/dist/node/components/marketing/sections/AudienceSection.js +85 -0
- package/dist/node/components/marketing/sections/CorePositioningSection.js +67 -0
- package/dist/node/components/marketing/sections/CtaSection.js +62 -0
- package/dist/node/components/marketing/sections/DevelopersSection.js +45 -0
- package/dist/node/components/marketing/sections/FearsSection.js +100 -0
- package/dist/node/components/marketing/sections/HeroMarketingSection.js +88 -0
- package/dist/node/components/marketing/sections/IconGridSection.js +58 -0
- package/dist/node/components/marketing/sections/OutputsSection.js +111 -0
- package/dist/node/components/marketing/sections/ProblemSection.js +98 -0
- package/dist/node/components/marketing/sections/SolutionSection.js +98 -0
- package/dist/node/components/marketing/sections/StepsSection.js +104 -0
- package/dist/node/components/marketing/waitlist-section.js +1099 -0
- package/dist/node/components/templates/TemplatesClientPage.js +5657 -0
- package/dist/node/components/templates/TemplatesPage.js +172 -0
- package/dist/node/components/templates/TemplatesPreviewModal.js +119 -0
- package/dist/node/components/templates/index.js +5826 -0
- package/dist/node/index.js +6480 -0
- package/dist/node/libs/email/client.js +117 -0
- package/dist/node/libs/email/contact.js +185 -0
- package/dist/node/libs/email/newsletter.js +210 -0
- package/dist/node/libs/email/types.js +2 -0
- package/dist/node/libs/email/utils.js +11 -0
- package/dist/node/libs/email/waitlist-application.js +290 -0
- package/dist/node/libs/email/waitlist.js +220 -0
- package/dist/node/libs/pricing-examples.js +21 -0
- package/dist/node/registry/engine.js +5288 -0
- package/dist/node/registry/factory.js +47 -0
- package/dist/node/registry/index.js +5353 -0
- package/dist/node/registry/registry-docs.js +338 -0
- package/dist/node/registry/registry-landing.js +4932 -0
- package/dist/node/registry/registry.js +5274 -0
- package/dist/node/registry/types.js +0 -0
- package/dist/node/registry/utils.js +5335 -0
- package/dist/registry/engine.d.ts +4 -8
- package/dist/registry/engine.d.ts.map +1 -1
- package/dist/registry/engine.js +5287 -23
- package/dist/registry/factory.d.ts +30 -34
- package/dist/registry/factory.d.ts.map +1 -1
- package/dist/registry/factory.js +42 -56
- package/dist/registry/index.d.ts +8 -8
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +5353 -8
- package/dist/registry/registry-docs.d.ts +4 -8
- package/dist/registry/registry-docs.d.ts.map +1 -1
- package/dist/registry/registry-docs.js +242 -209
- package/dist/registry/registry-landing.d.ts +5 -9
- package/dist/registry/registry-landing.d.ts.map +1 -1
- package/dist/registry/registry-landing.js +4930 -93
- package/dist/registry/registry.d.ts +7 -11
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +5262 -49
- package/dist/registry/types.d.ts +6 -10
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/types.js +1 -0
- package/dist/registry/utils.d.ts +10 -14
- package/dist/registry/utils.d.ts.map +1 -1
- package/dist/registry/utils.js +5330 -49
- package/package.json +355 -73
- package/tsdown.config.js +1 -2
- package/.turbo/turbo-build$colon$types.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/dist/components/marketing/ChangelogPage.js.map +0 -1
- package/dist/components/marketing/CofounderPage.js.map +0 -1
- package/dist/components/marketing/ContactClient.js.map +0 -1
- package/dist/components/marketing/ContributePage.js.map +0 -1
- package/dist/components/marketing/DesignPartnerPage.js.map +0 -1
- package/dist/components/marketing/LandingPage.js.map +0 -1
- package/dist/components/marketing/PricingClient.js.map +0 -1
- package/dist/components/marketing/ProductClientPage.js.map +0 -1
- package/dist/components/marketing/pricing-thinking-modal.js.map +0 -1
- package/dist/components/marketing/sections/AudienceSection.js.map +0 -1
- package/dist/components/marketing/sections/CorePositioningSection.js.map +0 -1
- package/dist/components/marketing/sections/CtaSection.js.map +0 -1
- package/dist/components/marketing/sections/DevelopersSection.js.map +0 -1
- package/dist/components/marketing/sections/FearsSection.js.map +0 -1
- package/dist/components/marketing/sections/HeroMarketingSection.js.map +0 -1
- package/dist/components/marketing/sections/IconGridSection.js.map +0 -1
- package/dist/components/marketing/sections/OutputsSection.js.map +0 -1
- package/dist/components/marketing/sections/ProblemSection.js.map +0 -1
- package/dist/components/marketing/sections/SolutionSection.js.map +0 -1
- package/dist/components/marketing/sections/StepsSection.js.map +0 -1
- package/dist/components/marketing/waitlist-section.js.map +0 -1
- package/dist/components/templates/TemplatesClientPage.js.map +0 -1
- package/dist/components/templates/TemplatesPage.js.map +0 -1
- package/dist/components/templates/TemplatesPreviewModal.js.map +0 -1
- package/dist/libs/email/client.js.map +0 -1
- package/dist/libs/email/contact.js.map +0 -1
- package/dist/libs/email/newsletter.js.map +0 -1
- package/dist/libs/email/utils.js.map +0 -1
- package/dist/libs/email/waitlist-application.js.map +0 -1
- package/dist/libs/email/waitlist.js.map +0 -1
- package/dist/libs/pricing-examples.js.map +0 -1
- package/dist/registry/engine.js.map +0 -1
- package/dist/registry/factory.js.map +0 -1
- package/dist/registry/registry-docs.js.map +0 -1
- package/dist/registry/registry-landing.js.map +0 -1
- package/dist/registry/registry.js.map +0 -1
- package/dist/registry/utils.js.map +0 -1
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/libs/email/client.ts
|
|
5
|
+
import { createClient, Temv1alpha1 } from "@scaleway/sdk";
|
|
6
|
+
import { Logger } from "@contractspec/lib.logger";
|
|
7
|
+
var DEFAULT_FROM = {
|
|
8
|
+
email: "noreply@transactional.contractspec.io",
|
|
9
|
+
name: "ContractSpec"
|
|
10
|
+
};
|
|
11
|
+
var DEFAULT_TEAM_INBOX = {
|
|
12
|
+
email: "contact@contractspec.io",
|
|
13
|
+
name: "ContractSpec Team"
|
|
14
|
+
};
|
|
15
|
+
var DEFAULT_REGION = "fr-par";
|
|
16
|
+
var cachedConfig = null;
|
|
17
|
+
var cachedClient = null;
|
|
18
|
+
var apiFactory = (client) => new Temv1alpha1.API(client);
|
|
19
|
+
var mapRegion = (value) => {
|
|
20
|
+
const normalized = value?.trim().toLowerCase();
|
|
21
|
+
if (normalized === "par" || normalized === "fr-par")
|
|
22
|
+
return "fr-par";
|
|
23
|
+
if (normalized === "ams" || normalized === "nl-ams")
|
|
24
|
+
return "nl-ams";
|
|
25
|
+
if (normalized === "waw" || normalized === "pl-waw")
|
|
26
|
+
return "pl-waw";
|
|
27
|
+
return DEFAULT_REGION;
|
|
28
|
+
};
|
|
29
|
+
var getEmailConfig = () => {
|
|
30
|
+
if (cachedConfig) {
|
|
31
|
+
return { ok: true, config: cachedConfig };
|
|
32
|
+
}
|
|
33
|
+
const accessKey = process.env.SCALEWAY_ACCESS_KEY || process.env.SCALEWAY_ACCESS_KEY_QUEUE;
|
|
34
|
+
const secretKey = process.env.SCALEWAY_SECRET_KEY || process.env.SCALEWAY_SECRET_KEY_QUEUE;
|
|
35
|
+
const projectId = process.env.SCALEWAY_PROJECT_ID;
|
|
36
|
+
if (!accessKey || !secretKey || !projectId) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
errorMessage: "Email service is not configured. Please contact us directly at contact@contractspec.io."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const region = mapRegion(process.env.SCALEWAY_REGION);
|
|
43
|
+
cachedConfig = {
|
|
44
|
+
accessKey,
|
|
45
|
+
secretKey,
|
|
46
|
+
projectId,
|
|
47
|
+
region,
|
|
48
|
+
defaultZone: `${region}-1`,
|
|
49
|
+
from: {
|
|
50
|
+
email: process.env.SCALEWAY_EMAIL_FROM_EMAIL ?? DEFAULT_FROM.email,
|
|
51
|
+
name: process.env.SCALEWAY_EMAIL_FROM_NAME ?? DEFAULT_FROM.name
|
|
52
|
+
},
|
|
53
|
+
teamInbox: {
|
|
54
|
+
email: process.env.SCALEWAY_EMAIL_TEAM_EMAIL ?? DEFAULT_TEAM_INBOX.email,
|
|
55
|
+
name: process.env.SCALEWAY_EMAIL_TEAM_NAME ?? DEFAULT_TEAM_INBOX.name
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return { ok: true, config: cachedConfig };
|
|
59
|
+
};
|
|
60
|
+
var getTemClient = (config) => {
|
|
61
|
+
if (cachedClient) {
|
|
62
|
+
return cachedClient;
|
|
63
|
+
}
|
|
64
|
+
const client = createClient({
|
|
65
|
+
accessKey: config.accessKey,
|
|
66
|
+
secretKey: config.secretKey,
|
|
67
|
+
defaultProjectId: config.projectId,
|
|
68
|
+
defaultRegion: config.region,
|
|
69
|
+
defaultZone: config.defaultZone
|
|
70
|
+
});
|
|
71
|
+
cachedClient = apiFactory(client);
|
|
72
|
+
return cachedClient;
|
|
73
|
+
};
|
|
74
|
+
var sendEmail = async (config, request) => {
|
|
75
|
+
try {
|
|
76
|
+
const client = getTemClient(config);
|
|
77
|
+
await client.createEmail({
|
|
78
|
+
region: config.region,
|
|
79
|
+
projectId: config.projectId,
|
|
80
|
+
from: config.from,
|
|
81
|
+
to: request.to,
|
|
82
|
+
subject: request.subject,
|
|
83
|
+
text: request.text,
|
|
84
|
+
html: request.html || request.text,
|
|
85
|
+
additionalHeaders: request.replyTo ? [{ key: "Reply-To", value: request.replyTo }] : undefined
|
|
86
|
+
});
|
|
87
|
+
return { success: true };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
new Logger().error("scaleway_tem_email_send_failed", {
|
|
90
|
+
context: request.context ?? "email",
|
|
91
|
+
error: error instanceof Error ? error.message : error
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error,
|
|
96
|
+
errorMessage: "Failed to send email via Scaleway."
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var __internal = {
|
|
101
|
+
resetCaches() {
|
|
102
|
+
cachedClient = null;
|
|
103
|
+
cachedConfig = null;
|
|
104
|
+
apiFactory = (client) => new Temv1alpha1.API(client);
|
|
105
|
+
},
|
|
106
|
+
setApiFactory(factory) {
|
|
107
|
+
apiFactory = factory;
|
|
108
|
+
},
|
|
109
|
+
setClient(client) {
|
|
110
|
+
cachedClient = client;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
export {
|
|
114
|
+
sendEmail,
|
|
115
|
+
getEmailConfig,
|
|
116
|
+
__internal
|
|
117
|
+
};
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/libs/email/client.ts
|
|
5
|
+
import { createClient, Temv1alpha1 } from "@scaleway/sdk";
|
|
6
|
+
import { Logger } from "@contractspec/lib.logger";
|
|
7
|
+
var DEFAULT_FROM = {
|
|
8
|
+
email: "noreply@transactional.contractspec.io",
|
|
9
|
+
name: "ContractSpec"
|
|
10
|
+
};
|
|
11
|
+
var DEFAULT_TEAM_INBOX = {
|
|
12
|
+
email: "contact@contractspec.io",
|
|
13
|
+
name: "ContractSpec Team"
|
|
14
|
+
};
|
|
15
|
+
var DEFAULT_REGION = "fr-par";
|
|
16
|
+
var cachedConfig = null;
|
|
17
|
+
var cachedClient = null;
|
|
18
|
+
var apiFactory = (client) => new Temv1alpha1.API(client);
|
|
19
|
+
var mapRegion = (value) => {
|
|
20
|
+
const normalized = value?.trim().toLowerCase();
|
|
21
|
+
if (normalized === "par" || normalized === "fr-par")
|
|
22
|
+
return "fr-par";
|
|
23
|
+
if (normalized === "ams" || normalized === "nl-ams")
|
|
24
|
+
return "nl-ams";
|
|
25
|
+
if (normalized === "waw" || normalized === "pl-waw")
|
|
26
|
+
return "pl-waw";
|
|
27
|
+
return DEFAULT_REGION;
|
|
28
|
+
};
|
|
29
|
+
var getEmailConfig = () => {
|
|
30
|
+
if (cachedConfig) {
|
|
31
|
+
return { ok: true, config: cachedConfig };
|
|
32
|
+
}
|
|
33
|
+
const accessKey = process.env.SCALEWAY_ACCESS_KEY || process.env.SCALEWAY_ACCESS_KEY_QUEUE;
|
|
34
|
+
const secretKey = process.env.SCALEWAY_SECRET_KEY || process.env.SCALEWAY_SECRET_KEY_QUEUE;
|
|
35
|
+
const projectId = process.env.SCALEWAY_PROJECT_ID;
|
|
36
|
+
if (!accessKey || !secretKey || !projectId) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
errorMessage: "Email service is not configured. Please contact us directly at contact@contractspec.io."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const region = mapRegion(process.env.SCALEWAY_REGION);
|
|
43
|
+
cachedConfig = {
|
|
44
|
+
accessKey,
|
|
45
|
+
secretKey,
|
|
46
|
+
projectId,
|
|
47
|
+
region,
|
|
48
|
+
defaultZone: `${region}-1`,
|
|
49
|
+
from: {
|
|
50
|
+
email: process.env.SCALEWAY_EMAIL_FROM_EMAIL ?? DEFAULT_FROM.email,
|
|
51
|
+
name: process.env.SCALEWAY_EMAIL_FROM_NAME ?? DEFAULT_FROM.name
|
|
52
|
+
},
|
|
53
|
+
teamInbox: {
|
|
54
|
+
email: process.env.SCALEWAY_EMAIL_TEAM_EMAIL ?? DEFAULT_TEAM_INBOX.email,
|
|
55
|
+
name: process.env.SCALEWAY_EMAIL_TEAM_NAME ?? DEFAULT_TEAM_INBOX.name
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return { ok: true, config: cachedConfig };
|
|
59
|
+
};
|
|
60
|
+
var getTemClient = (config) => {
|
|
61
|
+
if (cachedClient) {
|
|
62
|
+
return cachedClient;
|
|
63
|
+
}
|
|
64
|
+
const client = createClient({
|
|
65
|
+
accessKey: config.accessKey,
|
|
66
|
+
secretKey: config.secretKey,
|
|
67
|
+
defaultProjectId: config.projectId,
|
|
68
|
+
defaultRegion: config.region,
|
|
69
|
+
defaultZone: config.defaultZone
|
|
70
|
+
});
|
|
71
|
+
cachedClient = apiFactory(client);
|
|
72
|
+
return cachedClient;
|
|
73
|
+
};
|
|
74
|
+
var sendEmail = async (config, request) => {
|
|
75
|
+
try {
|
|
76
|
+
const client = getTemClient(config);
|
|
77
|
+
await client.createEmail({
|
|
78
|
+
region: config.region,
|
|
79
|
+
projectId: config.projectId,
|
|
80
|
+
from: config.from,
|
|
81
|
+
to: request.to,
|
|
82
|
+
subject: request.subject,
|
|
83
|
+
text: request.text,
|
|
84
|
+
html: request.html || request.text,
|
|
85
|
+
additionalHeaders: request.replyTo ? [{ key: "Reply-To", value: request.replyTo }] : undefined
|
|
86
|
+
});
|
|
87
|
+
return { success: true };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
new Logger().error("scaleway_tem_email_send_failed", {
|
|
90
|
+
context: request.context ?? "email",
|
|
91
|
+
error: error instanceof Error ? error.message : error
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error,
|
|
96
|
+
errorMessage: "Failed to send email via Scaleway."
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var __internal = {
|
|
101
|
+
resetCaches() {
|
|
102
|
+
cachedClient = null;
|
|
103
|
+
cachedConfig = null;
|
|
104
|
+
apiFactory = (client) => new Temv1alpha1.API(client);
|
|
105
|
+
},
|
|
106
|
+
setApiFactory(factory) {
|
|
107
|
+
apiFactory = factory;
|
|
108
|
+
},
|
|
109
|
+
setClient(client) {
|
|
110
|
+
cachedClient = client;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/libs/email/utils.ts
|
|
115
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
116
|
+
var formatMultilineHtml = (value) => escapeHtml(value).replaceAll(`
|
|
117
|
+
`, "<br />");
|
|
118
|
+
|
|
119
|
+
// src/libs/email/contact.ts
|
|
120
|
+
"use server";
|
|
121
|
+
var CONTACT_MISSING_CONFIG = "Email service is not configured. Please contact us directly at contact@contractspec.io.";
|
|
122
|
+
var CONTACT_SEND_ERROR = "Failed to send message. Please contact us directly at contact@contractspec.io.";
|
|
123
|
+
var submitContactForm = async (formData) => {
|
|
124
|
+
const name = (formData.get("name") ?? "").toString().trim();
|
|
125
|
+
const email = (formData.get("email") ?? "").toString().trim();
|
|
126
|
+
const message = (formData.get("message") ?? "").toString().trim();
|
|
127
|
+
if (!email) {
|
|
128
|
+
return {
|
|
129
|
+
success: false,
|
|
130
|
+
text: "Please fill in all required fields."
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const configResult = getEmailConfig();
|
|
134
|
+
if (!configResult.ok || !configResult.config) {
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
text: configResult.errorMessage ?? CONTACT_MISSING_CONFIG
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const senderName = name || email;
|
|
141
|
+
const emailContentText = `
|
|
142
|
+
New contact form submission from ${senderName}
|
|
143
|
+
|
|
144
|
+
Contact Information:
|
|
145
|
+
- Name: ${name || "Not provided"}
|
|
146
|
+
- Email: ${email}
|
|
147
|
+
|
|
148
|
+
Message:
|
|
149
|
+
${message || "No message provided"}
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
Submitted via ContractSpec contact form
|
|
153
|
+
`.trim();
|
|
154
|
+
const emailContentHtml = `
|
|
155
|
+
<div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
|
|
156
|
+
<h1 style="color: #8b5cf6; margin-bottom: 12px;">New contact form submission</h1>
|
|
157
|
+
<p style="margin: 0 0 12px;">From ${escapeHtml(senderName)}</p>
|
|
158
|
+
<h2 style="color: #8b5cf6; margin: 16px 0 8px;">Contact Information</h2>
|
|
159
|
+
<ul style="padding-left: 16px; line-height: 1.6; margin: 0 0 16px;">
|
|
160
|
+
<li>Name: ${escapeHtml(name || "Not provided")}</li>
|
|
161
|
+
<li>Email: ${escapeHtml(email)}</li>
|
|
162
|
+
</ul>
|
|
163
|
+
<h2 style="color: #8b5cf6; margin: 16px 0 8px;">Message</h2>
|
|
164
|
+
<div style="border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; background: #f9fafb; white-space: pre-wrap; line-height: 1.6;">
|
|
165
|
+
${message ? formatMultilineHtml(message) : "No message provided"}
|
|
166
|
+
</div>
|
|
167
|
+
<p style="color: #6b7280; font-size: 12px; margin-top: 20px;">Submitted via ContractSpec contact form</p>
|
|
168
|
+
</div>
|
|
169
|
+
`;
|
|
170
|
+
const sendResult = await sendEmail(configResult.config, {
|
|
171
|
+
to: [configResult.config.teamInbox],
|
|
172
|
+
subject: `New Contact Form Message from ${senderName}`,
|
|
173
|
+
text: emailContentText,
|
|
174
|
+
html: emailContentHtml,
|
|
175
|
+
replyTo: email,
|
|
176
|
+
context: "contact-form"
|
|
177
|
+
});
|
|
178
|
+
if (!sendResult.success) {
|
|
179
|
+
return { success: false, text: CONTACT_SEND_ERROR };
|
|
180
|
+
}
|
|
181
|
+
return { success: true, text: "Message sent successfully!" };
|
|
182
|
+
};
|
|
183
|
+
export {
|
|
184
|
+
submitContactForm
|
|
185
|
+
};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/libs/email/client.ts
|
|
5
|
+
import { createClient, Temv1alpha1 } from "@scaleway/sdk";
|
|
6
|
+
import { Logger } from "@contractspec/lib.logger";
|
|
7
|
+
var DEFAULT_FROM = {
|
|
8
|
+
email: "noreply@transactional.contractspec.io",
|
|
9
|
+
name: "ContractSpec"
|
|
10
|
+
};
|
|
11
|
+
var DEFAULT_TEAM_INBOX = {
|
|
12
|
+
email: "contact@contractspec.io",
|
|
13
|
+
name: "ContractSpec Team"
|
|
14
|
+
};
|
|
15
|
+
var DEFAULT_REGION = "fr-par";
|
|
16
|
+
var cachedConfig = null;
|
|
17
|
+
var cachedClient = null;
|
|
18
|
+
var apiFactory = (client) => new Temv1alpha1.API(client);
|
|
19
|
+
var mapRegion = (value) => {
|
|
20
|
+
const normalized = value?.trim().toLowerCase();
|
|
21
|
+
if (normalized === "par" || normalized === "fr-par")
|
|
22
|
+
return "fr-par";
|
|
23
|
+
if (normalized === "ams" || normalized === "nl-ams")
|
|
24
|
+
return "nl-ams";
|
|
25
|
+
if (normalized === "waw" || normalized === "pl-waw")
|
|
26
|
+
return "pl-waw";
|
|
27
|
+
return DEFAULT_REGION;
|
|
28
|
+
};
|
|
29
|
+
var getEmailConfig = () => {
|
|
30
|
+
if (cachedConfig) {
|
|
31
|
+
return { ok: true, config: cachedConfig };
|
|
32
|
+
}
|
|
33
|
+
const accessKey = process.env.SCALEWAY_ACCESS_KEY || process.env.SCALEWAY_ACCESS_KEY_QUEUE;
|
|
34
|
+
const secretKey = process.env.SCALEWAY_SECRET_KEY || process.env.SCALEWAY_SECRET_KEY_QUEUE;
|
|
35
|
+
const projectId = process.env.SCALEWAY_PROJECT_ID;
|
|
36
|
+
if (!accessKey || !secretKey || !projectId) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
errorMessage: "Email service is not configured. Please contact us directly at contact@contractspec.io."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const region = mapRegion(process.env.SCALEWAY_REGION);
|
|
43
|
+
cachedConfig = {
|
|
44
|
+
accessKey,
|
|
45
|
+
secretKey,
|
|
46
|
+
projectId,
|
|
47
|
+
region,
|
|
48
|
+
defaultZone: `${region}-1`,
|
|
49
|
+
from: {
|
|
50
|
+
email: process.env.SCALEWAY_EMAIL_FROM_EMAIL ?? DEFAULT_FROM.email,
|
|
51
|
+
name: process.env.SCALEWAY_EMAIL_FROM_NAME ?? DEFAULT_FROM.name
|
|
52
|
+
},
|
|
53
|
+
teamInbox: {
|
|
54
|
+
email: process.env.SCALEWAY_EMAIL_TEAM_EMAIL ?? DEFAULT_TEAM_INBOX.email,
|
|
55
|
+
name: process.env.SCALEWAY_EMAIL_TEAM_NAME ?? DEFAULT_TEAM_INBOX.name
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return { ok: true, config: cachedConfig };
|
|
59
|
+
};
|
|
60
|
+
var getTemClient = (config) => {
|
|
61
|
+
if (cachedClient) {
|
|
62
|
+
return cachedClient;
|
|
63
|
+
}
|
|
64
|
+
const client = createClient({
|
|
65
|
+
accessKey: config.accessKey,
|
|
66
|
+
secretKey: config.secretKey,
|
|
67
|
+
defaultProjectId: config.projectId,
|
|
68
|
+
defaultRegion: config.region,
|
|
69
|
+
defaultZone: config.defaultZone
|
|
70
|
+
});
|
|
71
|
+
cachedClient = apiFactory(client);
|
|
72
|
+
return cachedClient;
|
|
73
|
+
};
|
|
74
|
+
var sendEmail = async (config, request) => {
|
|
75
|
+
try {
|
|
76
|
+
const client = getTemClient(config);
|
|
77
|
+
await client.createEmail({
|
|
78
|
+
region: config.region,
|
|
79
|
+
projectId: config.projectId,
|
|
80
|
+
from: config.from,
|
|
81
|
+
to: request.to,
|
|
82
|
+
subject: request.subject,
|
|
83
|
+
text: request.text,
|
|
84
|
+
html: request.html || request.text,
|
|
85
|
+
additionalHeaders: request.replyTo ? [{ key: "Reply-To", value: request.replyTo }] : undefined
|
|
86
|
+
});
|
|
87
|
+
return { success: true };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
new Logger().error("scaleway_tem_email_send_failed", {
|
|
90
|
+
context: request.context ?? "email",
|
|
91
|
+
error: error instanceof Error ? error.message : error
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error,
|
|
96
|
+
errorMessage: "Failed to send email via Scaleway."
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var __internal = {
|
|
101
|
+
resetCaches() {
|
|
102
|
+
cachedClient = null;
|
|
103
|
+
cachedConfig = null;
|
|
104
|
+
apiFactory = (client) => new Temv1alpha1.API(client);
|
|
105
|
+
},
|
|
106
|
+
setApiFactory(factory) {
|
|
107
|
+
apiFactory = factory;
|
|
108
|
+
},
|
|
109
|
+
setClient(client) {
|
|
110
|
+
cachedClient = client;
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/libs/email/utils.ts
|
|
115
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
116
|
+
var formatMultilineHtml = (value) => escapeHtml(value).replaceAll(`
|
|
117
|
+
`, "<br />");
|
|
118
|
+
|
|
119
|
+
// src/libs/email/newsletter.ts
|
|
120
|
+
"use server";
|
|
121
|
+
var NEWSLETTER_MISSING_CONFIG = "Newsletter service is not configured. Please try again later.";
|
|
122
|
+
var NEWSLETTER_SEND_ERROR = "Failed to subscribe. Please try again later or contact us directly.";
|
|
123
|
+
var subscribeToNewsletter = async (formData) => {
|
|
124
|
+
const email = (formData.get("email") ?? "").toString().trim();
|
|
125
|
+
if (!email || !email.includes("@")) {
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
text: "Please enter a valid email address."
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const configResult = getEmailConfig();
|
|
132
|
+
if (!configResult.ok || !configResult.config) {
|
|
133
|
+
return {
|
|
134
|
+
success: false,
|
|
135
|
+
text: configResult.errorMessage ?? NEWSLETTER_MISSING_CONFIG
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const welcomeText = `
|
|
139
|
+
Welcome to ContractSpec!
|
|
140
|
+
|
|
141
|
+
Thanks for subscribing to our newsletter. You'll receive updates on:
|
|
142
|
+
|
|
143
|
+
• New integrations (Stripe, OpenAI, Qdrant, and more)
|
|
144
|
+
• Product features and improvements
|
|
145
|
+
• New templates and examples
|
|
146
|
+
• Architecture insights and best practices
|
|
147
|
+
• Documentation updates
|
|
148
|
+
|
|
149
|
+
Stay tuned for exciting updates!
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
ContractSpec Team
|
|
153
|
+
https://contractspec.io
|
|
154
|
+
|
|
155
|
+
Unsubscribe: Reply to this email with "unsubscribe"
|
|
156
|
+
`.trim();
|
|
157
|
+
const welcomeHtml = `
|
|
158
|
+
<div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
|
|
159
|
+
<h1 style="color: #8b5cf6;">Welcome to ContractSpec!</h1>
|
|
160
|
+
<p>Thanks for subscribing to our newsletter. You'll receive updates on:</p>
|
|
161
|
+
<ul style="line-height: 1.8;">
|
|
162
|
+
<li>New integrations (Stripe, OpenAI, Qdrant, and more)</li>
|
|
163
|
+
<li>Product features and improvements</li>
|
|
164
|
+
<li>New templates and examples</li>
|
|
165
|
+
<li>Architecture insights and best practices</li>
|
|
166
|
+
<li>Documentation updates</li>
|
|
167
|
+
</ul>
|
|
168
|
+
<p>Stay tuned for exciting updates!</p>
|
|
169
|
+
<hr style="margin: 30px 0; border: none; border-top: 1px solid #e5e7eb;" />
|
|
170
|
+
<p style="color: #6b7280; font-size: 14px;">
|
|
171
|
+
ContractSpec Team<br />
|
|
172
|
+
<a href="https://contractspec.io" style="color: #8b5cf6;">contractspec.io</a>
|
|
173
|
+
</p>
|
|
174
|
+
<p style="color: #9ca3af; font-size: 12px;">
|
|
175
|
+
To unsubscribe, reply to this email with "unsubscribe"
|
|
176
|
+
</p>
|
|
177
|
+
</div>
|
|
178
|
+
`;
|
|
179
|
+
const userSend = await sendEmail(configResult.config, {
|
|
180
|
+
to: [{ email }],
|
|
181
|
+
subject: "Welcome to ContractSpec Newsletter",
|
|
182
|
+
text: welcomeText,
|
|
183
|
+
html: welcomeHtml,
|
|
184
|
+
context: "newsletter-welcome"
|
|
185
|
+
});
|
|
186
|
+
if (!userSend.success) {
|
|
187
|
+
return { success: false, text: NEWSLETTER_SEND_ERROR };
|
|
188
|
+
}
|
|
189
|
+
const teamNotificationText = `New newsletter subscription from: ${email}`;
|
|
190
|
+
const teamNotificationHtml = `
|
|
191
|
+
<div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
|
|
192
|
+
<p style="margin: 0 0 8px;">New newsletter subscription</p>
|
|
193
|
+
<p style="margin: 0;"><strong>Email:</strong> ${formatMultilineHtml(email)}</p>
|
|
194
|
+
</div>
|
|
195
|
+
`;
|
|
196
|
+
const teamSend = await sendEmail(configResult.config, {
|
|
197
|
+
to: [configResult.config.teamInbox],
|
|
198
|
+
subject: `New Newsletter Subscription: ${email}`,
|
|
199
|
+
text: teamNotificationText,
|
|
200
|
+
html: teamNotificationHtml,
|
|
201
|
+
context: "newsletter-team-notification"
|
|
202
|
+
});
|
|
203
|
+
if (!teamSend.success) {
|
|
204
|
+
return { success: false, text: NEWSLETTER_SEND_ERROR };
|
|
205
|
+
}
|
|
206
|
+
return { success: true, text: "Successfully subscribed!" };
|
|
207
|
+
};
|
|
208
|
+
export {
|
|
209
|
+
subscribeToNewsletter
|
|
210
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/libs/email/utils.ts
|
|
5
|
+
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
6
|
+
var formatMultilineHtml = (value) => escapeHtml(value).replaceAll(`
|
|
7
|
+
`, "<br />");
|
|
8
|
+
export {
|
|
9
|
+
formatMultilineHtml,
|
|
10
|
+
escapeHtml
|
|
11
|
+
};
|