@levrbet/shared 0.5.71 → 0.5.72
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/core/config/urls.d.ts +4 -0
- package/dist/core/config/urls.js +8 -0
- package/dist/core/config/urls.js.map +1 -1
- package/dist/core/constants/index.d.ts +1 -0
- package/dist/core/constants/index.js +18 -0
- package/dist/core/constants/index.js.map +1 -0
- package/dist/core/constants/promo.constants.d.ts +18 -0
- package/dist/core/constants/promo.constants.js +25 -0
- package/dist/core/constants/promo.constants.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/validators/index.d.ts +1 -0
- package/dist/core/validators/index.js +1 -0
- package/dist/core/validators/index.js.map +1 -1
- package/dist/core/validators/promo.validators.d.ts +188 -0
- package/dist/core/validators/promo.validators.js +137 -0
- package/dist/core/validators/promo.validators.js.map +1 -0
- package/dist/server/config/urls.d.ts +2 -0
- package/package.json +1 -1
|
@@ -16,6 +16,10 @@ type EnvUrls = {
|
|
|
16
16
|
lambda: string;
|
|
17
17
|
liquidationEngine: string;
|
|
18
18
|
leaderboard: string;
|
|
19
|
+
/** client-v1 app base origin (e.g. revalidate target). PROD also serves on levr.bet. */
|
|
20
|
+
client: string;
|
|
21
|
+
/** Public base URL of the promo S3 bucket (deterministic name per stage). */
|
|
22
|
+
promoBucket: string;
|
|
19
23
|
indexers: IndexersMap;
|
|
20
24
|
};
|
|
21
25
|
export declare const allUrls: Record<LevrEnv, EnvUrls>;
|
package/dist/core/config/urls.js
CHANGED
|
@@ -15,6 +15,8 @@ exports.allUrls = {
|
|
|
15
15
|
lambda: "https://lambda.dev.levr.bet",
|
|
16
16
|
liquidationEngine: "https://liquidation-engine.dev.levr.bet",
|
|
17
17
|
leaderboard: "https://leaderboard.dev.levr.bet",
|
|
18
|
+
client: "http://localhost:3000",
|
|
19
|
+
promoBucket: "https://client-dev-promo-bucket.s3.ap-south-1.amazonaws.com",
|
|
18
20
|
indexers: {
|
|
19
21
|
[types_1.LevrChain.MONAD_TESTNET]: [
|
|
20
22
|
{ type: indexers_types_1.LevrIndexer.ENVIO, url: "https://indexer.dev.hyperindex.xyz/a07fcc5/v1/graphql" },
|
|
@@ -33,6 +35,8 @@ exports.allUrls = {
|
|
|
33
35
|
lambda: "https://lambda.dev.levr.bet",
|
|
34
36
|
liquidationEngine: "https://liquidation-engine.dev.levr.bet",
|
|
35
37
|
leaderboard: "https://leaderboard.dev.levr.bet",
|
|
38
|
+
client: "https://app.dev.levr.bet",
|
|
39
|
+
promoBucket: "https://client-dev-promo-bucket.s3.ap-south-1.amazonaws.com",
|
|
36
40
|
indexers: {
|
|
37
41
|
[types_1.LevrChain.MONAD_TESTNET]: [
|
|
38
42
|
{ type: indexers_types_1.LevrIndexer.ENVIO, url: "https://indexer.dev.hyperindex.xyz/79ae9a8/v1/graphql" },
|
|
@@ -51,6 +55,8 @@ exports.allUrls = {
|
|
|
51
55
|
lambda: "https://lambda.staging.levr.bet",
|
|
52
56
|
liquidationEngine: "https://liquidation-engine.staging.levr.bet",
|
|
53
57
|
leaderboard: "https://leaderboard.staging.levr.bet",
|
|
58
|
+
client: "https://app.staging.levr.bet",
|
|
59
|
+
promoBucket: "https://client-staging-promo-bucket.s3.ap-south-1.amazonaws.com",
|
|
54
60
|
indexers: {
|
|
55
61
|
[types_1.LevrChain.MONAD_MAINNET]: [
|
|
56
62
|
{ type: indexers_types_1.LevrIndexer.ENVIO, url: "https://indexer.hyperindex.xyz/afda1ae/v1/graphql" },
|
|
@@ -69,6 +75,8 @@ exports.allUrls = {
|
|
|
69
75
|
lambda: "https://lambda.api.levr.bet",
|
|
70
76
|
liquidationEngine: "https://liquidation-engine.api.levr.bet",
|
|
71
77
|
leaderboard: "https://leaderboard.api.levr.bet",
|
|
78
|
+
client: "https://app.levr.bet",
|
|
79
|
+
promoBucket: "https://client-prod-promo-bucket.s3.ap-south-1.amazonaws.com",
|
|
72
80
|
indexers: {
|
|
73
81
|
[types_1.LevrChain.MONAD_MAINNET]: [
|
|
74
82
|
{ type: indexers_types_1.LevrIndexer.ENVIO, url: "https://indexer.hyperindex.xyz/ee081a3/v1/graphql" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../src/core/config/urls.ts"],"names":[],"mappings":";;;AAAA,oCAA6C;AAC7C,4DAAqD;
|
|
1
|
+
{"version":3,"file":"urls.js","sourceRoot":"","sources":["../../../src/core/config/urls.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./promo.constants";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./promo.constants"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/constants/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAiC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Default banner render width in CSS pixels (1x) */
|
|
2
|
+
export declare const PROMO_BANNER_W = 387;
|
|
3
|
+
/** Banner height in CSS pixels */
|
|
4
|
+
export declare const PROMO_BANNER_H = 153;
|
|
5
|
+
/** Minimum recommended upload width (2× / retina) */
|
|
6
|
+
export declare const PROMO_RETINA_W = 774;
|
|
7
|
+
/** Minimum recommended upload height (2× / retina) */
|
|
8
|
+
export declare const PROMO_RETINA_H = 306;
|
|
9
|
+
/** Accent / CTA colour */
|
|
10
|
+
export declare const PROMO_MINT = "#1FE08C";
|
|
11
|
+
/** Lightbox backdrop colour */
|
|
12
|
+
export declare const PROMO_BACKDROP = "rgba(0,0,0,0.7)";
|
|
13
|
+
/** Lightbox modal max-width in CSS pixels */
|
|
14
|
+
export declare const PROMO_LIGHTBOX_MAXW = 750;
|
|
15
|
+
/** Default value for the `width` field when not specified */
|
|
16
|
+
export declare const PROMO_DEFAULT_WIDTH = 387;
|
|
17
|
+
/** Maximum accepted image binary size in bytes (5 MB — admin-gated upload, not user-facing) */
|
|
18
|
+
export declare const PROMO_MAX_IMAGE_BYTES: number;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Promo banner visual constants (decision #11 — shared between client-v1 components
|
|
3
|
+
// and the dashboard-v1 native preview so the numbers can never diverge).
|
|
4
|
+
// Plain values only — no React.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PROMO_MAX_IMAGE_BYTES = exports.PROMO_DEFAULT_WIDTH = exports.PROMO_LIGHTBOX_MAXW = exports.PROMO_BACKDROP = exports.PROMO_MINT = exports.PROMO_RETINA_H = exports.PROMO_RETINA_W = exports.PROMO_BANNER_H = exports.PROMO_BANNER_W = void 0;
|
|
7
|
+
/** Default banner render width in CSS pixels (1x) */
|
|
8
|
+
exports.PROMO_BANNER_W = 387;
|
|
9
|
+
/** Banner height in CSS pixels */
|
|
10
|
+
exports.PROMO_BANNER_H = 153;
|
|
11
|
+
/** Minimum recommended upload width (2× / retina) */
|
|
12
|
+
exports.PROMO_RETINA_W = 774;
|
|
13
|
+
/** Minimum recommended upload height (2× / retina) */
|
|
14
|
+
exports.PROMO_RETINA_H = 306;
|
|
15
|
+
/** Accent / CTA colour */
|
|
16
|
+
exports.PROMO_MINT = "#1FE08C";
|
|
17
|
+
/** Lightbox backdrop colour */
|
|
18
|
+
exports.PROMO_BACKDROP = "rgba(0,0,0,0.7)";
|
|
19
|
+
/** Lightbox modal max-width in CSS pixels */
|
|
20
|
+
exports.PROMO_LIGHTBOX_MAXW = 750;
|
|
21
|
+
/** Default value for the `width` field when not specified */
|
|
22
|
+
exports.PROMO_DEFAULT_WIDTH = 387;
|
|
23
|
+
/** Maximum accepted image binary size in bytes (5 MB — admin-gated upload, not user-facing) */
|
|
24
|
+
exports.PROMO_MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
25
|
+
//# sourceMappingURL=promo.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promo.constants.js","sourceRoot":"","sources":["../../../src/core/constants/promo.constants.ts"],"names":[],"mappings":";AAAA,oFAAoF;AACpF,yEAAyE;AACzE,gCAAgC;;;AAEhC,qDAAqD;AACxC,QAAA,cAAc,GAAG,GAAG,CAAA;AAEjC,kCAAkC;AACrB,QAAA,cAAc,GAAG,GAAG,CAAA;AAEjC,qDAAqD;AACxC,QAAA,cAAc,GAAG,GAAG,CAAA;AAEjC,sDAAsD;AACzC,QAAA,cAAc,GAAG,GAAG,CAAA;AAEjC,0BAA0B;AACb,QAAA,UAAU,GAAG,SAAS,CAAA;AAEnC,+BAA+B;AAClB,QAAA,cAAc,GAAG,iBAAiB,CAAA;AAE/C,6CAA6C;AAChC,QAAA,mBAAmB,GAAG,GAAG,CAAA;AAEtC,6DAA6D;AAChD,QAAA,mBAAmB,GAAG,GAAG,CAAA;AAEtC,+FAA+F;AAClF,QAAA,qBAAqB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAA"}
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
|
@@ -16,6 +16,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./alerts"), exports);
|
|
18
18
|
__exportStar(require("./config"), exports);
|
|
19
|
+
__exportStar(require("./constants"), exports);
|
|
19
20
|
__exportStar(require("./contracts"), exports);
|
|
20
21
|
__exportStar(require("./indexers"), exports);
|
|
21
22
|
__exportStar(require("./prisma"), exports);
|
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,2CAAwB;AACxB,8CAA2B;AAC3B,6CAA0B;AAC1B,2CAAwB;AACxB,0CAAuB;AACvB,8CAA2B;AAC3B,0CAAuB;AACvB,0CAAuB;AACvB,+CAA4B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,2CAAwB;AACxB,8CAA2B;AAC3B,8CAA2B;AAC3B,6CAA0B;AAC1B,2CAAwB;AACxB,0CAAuB;AACvB,8CAA2B;AAC3B,0CAAuB;AACvB,0CAAuB;AACvB,+CAA4B"}
|
|
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./bytes.validators"), exports);
|
|
18
18
|
__exportStar(require("./mongo.validators"), exports);
|
|
19
|
+
__exportStar(require("./promo.validators"), exports);
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/validators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC;AAClC,qDAAkC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/validators/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAkC;AAClC,qDAAkC;AAClC,qDAAkC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Returns true when `url` is an acceptable promo destination or terms URL.
|
|
4
|
+
*
|
|
5
|
+
* Decision #6 rules (open-redirect guard included):
|
|
6
|
+
* - Internal path: single leading "/" NOT followed by "/" or "\" (blocks //evil.com, /\evil.com)
|
|
7
|
+
* - https URL whose host suffix-matches ".levr.bet" or equals "levr.bet"
|
|
8
|
+
* - https URL whose host suffix-matches ".amplifyapp.com"
|
|
9
|
+
* - localhost / 127.0.0.1 on any port, http OR https
|
|
10
|
+
* - Everything else (including javascript:, data:, other hosts) is rejected.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isAllowedPromoUrl(url: string): boolean;
|
|
13
|
+
export declare const promoTermsBlockSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
14
|
+
type: z.ZodLiteral<"heading">;
|
|
15
|
+
text: z.ZodString;
|
|
16
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
17
|
+
type: z.ZodLiteral<"paragraph">;
|
|
18
|
+
text: z.ZodString;
|
|
19
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
20
|
+
type: z.ZodLiteral<"bullets">;
|
|
21
|
+
items: z.ZodArray<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
23
|
+
type: z.ZodLiteral<"ordered">;
|
|
24
|
+
items: z.ZodArray<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>], "type">;
|
|
26
|
+
export type PromoTermsBlock = z.infer<typeof promoTermsBlockSchema>;
|
|
27
|
+
export declare const promoTermsSchema: z.ZodObject<{
|
|
28
|
+
eyebrow: z.ZodOptional<z.ZodString>;
|
|
29
|
+
title: z.ZodString;
|
|
30
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
31
|
+
blocks: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
32
|
+
type: z.ZodLiteral<"heading">;
|
|
33
|
+
text: z.ZodString;
|
|
34
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
35
|
+
type: z.ZodLiteral<"paragraph">;
|
|
36
|
+
text: z.ZodString;
|
|
37
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
38
|
+
type: z.ZodLiteral<"bullets">;
|
|
39
|
+
items: z.ZodArray<z.ZodString>;
|
|
40
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
41
|
+
type: z.ZodLiteral<"ordered">;
|
|
42
|
+
items: z.ZodArray<z.ZodString>;
|
|
43
|
+
}, z.core.$strip>], "type">>;
|
|
44
|
+
}, z.core.$strip>;
|
|
45
|
+
export type PromoTerms = z.infer<typeof promoTermsSchema>;
|
|
46
|
+
export declare const promoConfigSchema: z.ZodObject<{
|
|
47
|
+
id: z.ZodString;
|
|
48
|
+
slug: z.ZodString;
|
|
49
|
+
imageKey: z.ZodString;
|
|
50
|
+
imageUrl: z.ZodString;
|
|
51
|
+
destinationUrl: z.ZodString;
|
|
52
|
+
termsUrl: z.ZodOptional<z.ZodString>;
|
|
53
|
+
hasTerms: z.ZodBoolean;
|
|
54
|
+
altText: z.ZodString;
|
|
55
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
56
|
+
activeStart: z.ZodOptional<z.ZodString>;
|
|
57
|
+
activeEnd: z.ZodOptional<z.ZodString>;
|
|
58
|
+
published: z.ZodBoolean;
|
|
59
|
+
sortOrder: z.ZodNumber;
|
|
60
|
+
createdAt: z.ZodString;
|
|
61
|
+
updatedAt: z.ZodString;
|
|
62
|
+
}, z.core.$strip>;
|
|
63
|
+
export type PromoConfig = z.infer<typeof promoConfigSchema>;
|
|
64
|
+
export declare const promoRecordSchema: z.ZodObject<{
|
|
65
|
+
id: z.ZodString;
|
|
66
|
+
slug: z.ZodString;
|
|
67
|
+
imageKey: z.ZodString;
|
|
68
|
+
imageUrl: z.ZodString;
|
|
69
|
+
destinationUrl: z.ZodString;
|
|
70
|
+
termsUrl: z.ZodOptional<z.ZodString>;
|
|
71
|
+
hasTerms: z.ZodBoolean;
|
|
72
|
+
altText: z.ZodString;
|
|
73
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
74
|
+
activeStart: z.ZodOptional<z.ZodString>;
|
|
75
|
+
activeEnd: z.ZodOptional<z.ZodString>;
|
|
76
|
+
published: z.ZodBoolean;
|
|
77
|
+
sortOrder: z.ZodNumber;
|
|
78
|
+
createdAt: z.ZodString;
|
|
79
|
+
updatedAt: z.ZodString;
|
|
80
|
+
terms: z.ZodOptional<z.ZodObject<{
|
|
81
|
+
eyebrow: z.ZodOptional<z.ZodString>;
|
|
82
|
+
title: z.ZodString;
|
|
83
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
84
|
+
blocks: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
85
|
+
type: z.ZodLiteral<"heading">;
|
|
86
|
+
text: z.ZodString;
|
|
87
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
88
|
+
type: z.ZodLiteral<"paragraph">;
|
|
89
|
+
text: z.ZodString;
|
|
90
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
91
|
+
type: z.ZodLiteral<"bullets">;
|
|
92
|
+
items: z.ZodArray<z.ZodString>;
|
|
93
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
94
|
+
type: z.ZodLiteral<"ordered">;
|
|
95
|
+
items: z.ZodArray<z.ZodString>;
|
|
96
|
+
}, z.core.$strip>], "type">>;
|
|
97
|
+
}, z.core.$strip>>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
export type PromoRecord = z.infer<typeof promoRecordSchema>;
|
|
100
|
+
/** Private manifest.json — full records including terms */
|
|
101
|
+
export declare const promoManifestSchema: z.ZodArray<z.ZodObject<{
|
|
102
|
+
id: z.ZodString;
|
|
103
|
+
slug: z.ZodString;
|
|
104
|
+
imageKey: z.ZodString;
|
|
105
|
+
imageUrl: z.ZodString;
|
|
106
|
+
destinationUrl: z.ZodString;
|
|
107
|
+
termsUrl: z.ZodOptional<z.ZodString>;
|
|
108
|
+
hasTerms: z.ZodBoolean;
|
|
109
|
+
altText: z.ZodString;
|
|
110
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
111
|
+
activeStart: z.ZodOptional<z.ZodString>;
|
|
112
|
+
activeEnd: z.ZodOptional<z.ZodString>;
|
|
113
|
+
published: z.ZodBoolean;
|
|
114
|
+
sortOrder: z.ZodNumber;
|
|
115
|
+
createdAt: z.ZodString;
|
|
116
|
+
updatedAt: z.ZodString;
|
|
117
|
+
terms: z.ZodOptional<z.ZodObject<{
|
|
118
|
+
eyebrow: z.ZodOptional<z.ZodString>;
|
|
119
|
+
title: z.ZodString;
|
|
120
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
121
|
+
blocks: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
122
|
+
type: z.ZodLiteral<"heading">;
|
|
123
|
+
text: z.ZodString;
|
|
124
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
125
|
+
type: z.ZodLiteral<"paragraph">;
|
|
126
|
+
text: z.ZodString;
|
|
127
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
128
|
+
type: z.ZodLiteral<"bullets">;
|
|
129
|
+
items: z.ZodArray<z.ZodString>;
|
|
130
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
131
|
+
type: z.ZodLiteral<"ordered">;
|
|
132
|
+
items: z.ZodArray<z.ZodString>;
|
|
133
|
+
}, z.core.$strip>], "type">>;
|
|
134
|
+
}, z.core.$strip>>;
|
|
135
|
+
}, z.core.$strip>>;
|
|
136
|
+
/** Public public.json — published-only, banner fields only (no terms) */
|
|
137
|
+
export declare const promoPublicListSchema: z.ZodArray<z.ZodObject<{
|
|
138
|
+
id: z.ZodString;
|
|
139
|
+
slug: z.ZodString;
|
|
140
|
+
imageKey: z.ZodString;
|
|
141
|
+
imageUrl: z.ZodString;
|
|
142
|
+
destinationUrl: z.ZodString;
|
|
143
|
+
termsUrl: z.ZodOptional<z.ZodString>;
|
|
144
|
+
hasTerms: z.ZodBoolean;
|
|
145
|
+
altText: z.ZodString;
|
|
146
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
147
|
+
activeStart: z.ZodOptional<z.ZodString>;
|
|
148
|
+
activeEnd: z.ZodOptional<z.ZodString>;
|
|
149
|
+
published: z.ZodBoolean;
|
|
150
|
+
sortOrder: z.ZodNumber;
|
|
151
|
+
createdAt: z.ZodString;
|
|
152
|
+
updatedAt: z.ZodString;
|
|
153
|
+
}, z.core.$strip>>;
|
|
154
|
+
export declare const promoUploadInputSchema: z.ZodObject<{
|
|
155
|
+
slug: z.ZodString;
|
|
156
|
+
destinationUrl: z.ZodString;
|
|
157
|
+
termsUrl: z.ZodOptional<z.ZodString>;
|
|
158
|
+
altText: z.ZodString;
|
|
159
|
+
width: z.ZodOptional<z.ZodNumber>;
|
|
160
|
+
activeStart: z.ZodOptional<z.ZodString>;
|
|
161
|
+
activeEnd: z.ZodOptional<z.ZodString>;
|
|
162
|
+
published: z.ZodDefault<z.ZodBoolean>;
|
|
163
|
+
sortOrder: z.ZodDefault<z.ZodNumber>;
|
|
164
|
+
imageBase64: z.ZodOptional<z.ZodString>;
|
|
165
|
+
imageContentType: z.ZodOptional<z.ZodEnum<{
|
|
166
|
+
"image/jpeg": "image/jpeg";
|
|
167
|
+
"image/png": "image/png";
|
|
168
|
+
}>>;
|
|
169
|
+
terms: z.ZodOptional<z.ZodObject<{
|
|
170
|
+
eyebrow: z.ZodOptional<z.ZodString>;
|
|
171
|
+
title: z.ZodString;
|
|
172
|
+
subtitle: z.ZodOptional<z.ZodString>;
|
|
173
|
+
blocks: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
174
|
+
type: z.ZodLiteral<"heading">;
|
|
175
|
+
text: z.ZodString;
|
|
176
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
177
|
+
type: z.ZodLiteral<"paragraph">;
|
|
178
|
+
text: z.ZodString;
|
|
179
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
180
|
+
type: z.ZodLiteral<"bullets">;
|
|
181
|
+
items: z.ZodArray<z.ZodString>;
|
|
182
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
183
|
+
type: z.ZodLiteral<"ordered">;
|
|
184
|
+
items: z.ZodArray<z.ZodString>;
|
|
185
|
+
}, z.core.$strip>], "type">>;
|
|
186
|
+
}, z.core.$strip>>;
|
|
187
|
+
}, z.core.$strip>;
|
|
188
|
+
export type PromoUploadInput = z.infer<typeof promoUploadInputSchema>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promoUploadInputSchema = exports.promoPublicListSchema = exports.promoManifestSchema = exports.promoRecordSchema = exports.promoConfigSchema = exports.promoTermsSchema = exports.promoTermsBlockSchema = void 0;
|
|
4
|
+
exports.isAllowedPromoUrl = isAllowedPromoUrl;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const promo_constants_1 = require("../constants/promo.constants");
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Internal helpers
|
|
9
|
+
// ============================================================================
|
|
10
|
+
const slugSchema = zod_1.z
|
|
11
|
+
.string()
|
|
12
|
+
.min(3, "Slug must be at least 3 characters")
|
|
13
|
+
.max(60, "Slug must be at most 60 characters")
|
|
14
|
+
.regex(/^[a-z0-9-]+$/, "Slug must contain only lowercase letters, digits, and hyphens");
|
|
15
|
+
const isoDateSchema = zod_1.z.string().datetime({ message: "Must be a valid ISO 8601 datetime string" });
|
|
16
|
+
/**
|
|
17
|
+
* Returns true when `url` is an acceptable promo destination or terms URL.
|
|
18
|
+
*
|
|
19
|
+
* Decision #6 rules (open-redirect guard included):
|
|
20
|
+
* - Internal path: single leading "/" NOT followed by "/" or "\" (blocks //evil.com, /\evil.com)
|
|
21
|
+
* - https URL whose host suffix-matches ".levr.bet" or equals "levr.bet"
|
|
22
|
+
* - https URL whose host suffix-matches ".amplifyapp.com"
|
|
23
|
+
* - localhost / 127.0.0.1 on any port, http OR https
|
|
24
|
+
* - Everything else (including javascript:, data:, other hosts) is rejected.
|
|
25
|
+
*/
|
|
26
|
+
function isAllowedPromoUrl(url) {
|
|
27
|
+
// Internal path: starts with "/" but NOT "//" or "/\"
|
|
28
|
+
if (url.startsWith("/")) {
|
|
29
|
+
if (url.startsWith("//") || url.startsWith("/\\")) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
// Must be http or https for everything below
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = new URL(url);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const { protocol, hostname } = parsed;
|
|
43
|
+
// localhost / 127.0.0.1 — http or https allowed (dev)
|
|
44
|
+
if (protocol === "http:" || protocol === "https:") {
|
|
45
|
+
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Everything else must be https
|
|
50
|
+
if (protocol !== "https:") {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
// levr.bet domain (exact match or any subdomain)
|
|
54
|
+
if (hostname === "levr.bet" || hostname.endsWith(".levr.bet")) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
// Amplify preview deploys
|
|
58
|
+
if (hostname.endsWith(".amplifyapp.com")) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const allowedPromoUrlSchema = zod_1.z.string().refine(isAllowedPromoUrl, {
|
|
64
|
+
message: "URL must be an internal path (/...), an https *.levr.bet or levr.bet URL, an https *.amplifyapp.com URL, or localhost/127.0.0.1",
|
|
65
|
+
});
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Terms shapes
|
|
68
|
+
// ============================================================================
|
|
69
|
+
exports.promoTermsBlockSchema = zod_1.z.discriminatedUnion("type", [
|
|
70
|
+
zod_1.z.object({ type: zod_1.z.literal("heading"), text: zod_1.z.string() }),
|
|
71
|
+
zod_1.z.object({ type: zod_1.z.literal("paragraph"), text: zod_1.z.string() }),
|
|
72
|
+
zod_1.z.object({ type: zod_1.z.literal("bullets"), items: zod_1.z.array(zod_1.z.string()) }),
|
|
73
|
+
zod_1.z.object({ type: zod_1.z.literal("ordered"), items: zod_1.z.array(zod_1.z.string()) }),
|
|
74
|
+
]);
|
|
75
|
+
exports.promoTermsSchema = zod_1.z.object({
|
|
76
|
+
eyebrow: zod_1.z.string().optional(),
|
|
77
|
+
title: zod_1.z.string(),
|
|
78
|
+
subtitle: zod_1.z.string().optional(),
|
|
79
|
+
blocks: zod_1.z.array(exports.promoTermsBlockSchema),
|
|
80
|
+
});
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Public banner entry — element of public.json
|
|
83
|
+
// ============================================================================
|
|
84
|
+
exports.promoConfigSchema = zod_1.z.object({
|
|
85
|
+
id: zod_1.z.string(),
|
|
86
|
+
slug: slugSchema,
|
|
87
|
+
imageKey: zod_1.z.string(),
|
|
88
|
+
imageUrl: zod_1.z.string(),
|
|
89
|
+
destinationUrl: allowedPromoUrlSchema,
|
|
90
|
+
termsUrl: allowedPromoUrlSchema.optional(),
|
|
91
|
+
hasTerms: zod_1.z.boolean(),
|
|
92
|
+
altText: zod_1.z.string().min(10, "altText must be at least 10 characters").max(200, "altText must be at most 200 characters"),
|
|
93
|
+
width: zod_1.z.number().int().min(200).max(800).optional(),
|
|
94
|
+
activeStart: isoDateSchema.optional(),
|
|
95
|
+
activeEnd: isoDateSchema.optional(),
|
|
96
|
+
published: zod_1.z.boolean(),
|
|
97
|
+
sortOrder: zod_1.z.number().int().min(0).max(999),
|
|
98
|
+
createdAt: isoDateSchema,
|
|
99
|
+
updatedAt: isoDateSchema,
|
|
100
|
+
});
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Private manifest entry — PromoConfig + optional inline terms
|
|
103
|
+
// ============================================================================
|
|
104
|
+
exports.promoRecordSchema = exports.promoConfigSchema.extend({
|
|
105
|
+
terms: exports.promoTermsSchema.optional(),
|
|
106
|
+
});
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Manifest list shapes
|
|
109
|
+
// ============================================================================
|
|
110
|
+
/** Private manifest.json — full records including terms */
|
|
111
|
+
exports.promoManifestSchema = zod_1.z.array(exports.promoRecordSchema);
|
|
112
|
+
/** Public public.json — published-only, banner fields only (no terms) */
|
|
113
|
+
exports.promoPublicListSchema = zod_1.z.array(exports.promoConfigSchema);
|
|
114
|
+
// ============================================================================
|
|
115
|
+
// Upload input — what dashboard POSTs to the Lambda
|
|
116
|
+
// ============================================================================
|
|
117
|
+
const MAX_IMAGE_BYTES = promo_constants_1.PROMO_MAX_IMAGE_BYTES;
|
|
118
|
+
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
119
|
+
exports.promoUploadInputSchema = zod_1.z.object({
|
|
120
|
+
slug: slugSchema,
|
|
121
|
+
destinationUrl: allowedPromoUrlSchema,
|
|
122
|
+
termsUrl: allowedPromoUrlSchema.optional(),
|
|
123
|
+
altText: zod_1.z.string().min(10, "altText must be at least 10 characters").max(200, "altText must be at most 200 characters"),
|
|
124
|
+
width: zod_1.z.number().int().min(200).max(800).optional(),
|
|
125
|
+
activeStart: isoDateSchema.optional(),
|
|
126
|
+
activeEnd: isoDateSchema.optional(),
|
|
127
|
+
published: zod_1.z.boolean().default(true),
|
|
128
|
+
sortOrder: zod_1.z.number().int().min(0).max(999).default(0),
|
|
129
|
+
imageBase64: zod_1.z
|
|
130
|
+
.string()
|
|
131
|
+
.refine((data) => BASE64_REGEX.test(data), "imageBase64 must be valid base64")
|
|
132
|
+
.refine((data) => Math.ceil((data.length * 3) / 4) <= MAX_IMAGE_BYTES, `Image must be at most ${MAX_IMAGE_BYTES / (1024 * 1024)}MB`)
|
|
133
|
+
.optional(),
|
|
134
|
+
imageContentType: zod_1.z.enum(["image/png", "image/jpeg"]).optional(),
|
|
135
|
+
terms: exports.promoTermsSchema.optional(),
|
|
136
|
+
});
|
|
137
|
+
//# sourceMappingURL=promo.validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promo.validators.js","sourceRoot":"","sources":["../../../src/core/validators/promo.validators.ts"],"names":[],"mappings":"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"}
|