@drawbridge/drawbridge-utils 0.0.159 → 0.0.161

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.
@@ -1450,7 +1450,6 @@ var organization = {
1450
1450
 
1451
1451
  // index.js
1452
1452
  var import_currency_codes = require("currency-codes");
1453
- var import_nanoid = require("nanoid");
1454
1453
 
1455
1454
  // lib/color.js
1456
1455
  var import_tinycolor2 = __toESM(require("tinycolor2"), 1);
@@ -1513,8 +1512,11 @@ var style = {
1513
1512
  }
1514
1513
  };
1515
1514
 
1515
+ // lib/nanoid.js
1516
+ var import_nanoid = require("nanoid");
1517
+ var generate = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
1518
+
1516
1519
  // index.js
1517
- var nanoid = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
1518
1520
  var infinite = 1e300;
1519
1521
  var megabyte = 1024 * 1024;
1520
1522
  var gigabyte = megabyte * 1024;
@@ -2664,8 +2666,8 @@ var drawbridge_default2 = {
2664
2666
  // owner is not a member document, so a solo merchant has nothing to
2665
2667
  // pick and could never save the step.
2666
2668
  members: { of: "string", type: "array" },
2667
- message: { required: true, type: "string" },
2668
- subject: { required: true, type: "string" }
2669
+ message: { max: 2e3, required: true, type: "string" },
2670
+ subject: { max: 150, required: true, type: "string" }
2669
2671
  },
2670
2672
  triggers: ["schedule.day", "schedule.week", "schedule.month"],
2671
2673
  usage: { actions: 0 }
@@ -2688,8 +2690,8 @@ var drawbridge_default2 = {
2688
2690
  queue: "notification",
2689
2691
  settings: {
2690
2692
  members: { of: "string", type: "array" },
2691
- message: { type: "string" },
2692
- subject: { type: "string" }
2693
+ message: { max: 2e3, type: "string" },
2694
+ subject: { max: 150, type: "string" }
2693
2695
  },
2694
2696
  triggers: ["lead.insert"],
2695
2697
  // Zero is a PRICE, and a deliberate one. Declared rather than omitted
@@ -2703,8 +2705,8 @@ var drawbridge_default2 = {
2703
2705
  key: "Email \u2014 Send email",
2704
2706
  queue: "notification",
2705
2707
  settings: {
2706
- message: { required: true, type: "string" },
2707
- subject: { required: true, type: "string" }
2708
+ message: { max: 2e3, required: true, type: "string" },
2709
+ subject: { max: 150, required: true, type: "string" }
2708
2710
  },
2709
2711
  triggers: ["lead.insert"],
2710
2712
  // ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
@@ -2733,8 +2735,8 @@ var drawbridge_default2 = {
2733
2735
  key: "Send an SMS",
2734
2736
  queue: "notification",
2735
2737
  settings: {
2736
- message: { required: true, type: "string" },
2737
- subject: { required: true, type: "string" }
2738
+ message: { max: 1600, required: true, type: "string" },
2739
+ subject: { max: 150, required: true, type: "string" }
2738
2740
  },
2739
2741
  // Priced per SEGMENT and billed from the first, which the send
2740
2742
  // resolves from the message length. This is the floor.
@@ -3697,7 +3699,7 @@ var mailchimp_default2 = {
3697
3699
 
3698
3700
  // lib/connections/providers/shopify.js
3699
3701
  var import_node_crypto5 = require("crypto");
3700
- var import_nanoid2 = require("nanoid");
3702
+ var import_nanoid3 = require("nanoid");
3701
3703
 
3702
3704
  // lib/connections/icons/shopify.js
3703
3705
  var shopify_default = `<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -3792,7 +3794,7 @@ var attributeLineItems = (lineItems = []) => lineItems.reduce(
3792
3794
  },
3793
3795
  { attrMap: {}, attributedGross: 0, attributedLines: [] }
3794
3796
  );
3795
- var generateDiscountCode = (0, import_nanoid2.customAlphabet)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8);
3797
+ var generateDiscountCode = (0, import_nanoid3.customAlphabet)("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8);
3796
3798
  var ORDER_EVENT_HANDLE = slugify("drawbridge-orders");
3797
3799
  var REFRESH_TOKEN_FRESHNESS_BUFFER_MS = 5 * 24 * 60 * 60 * 1e3;
3798
3800
  var OAUTH_ERROR_SOURCE = "oauth";
@@ -20,6 +20,7 @@ import '../index.cjs';
20
20
  import 'currency-codes';
21
21
  import '../color.cjs';
22
22
  import 'tinycolor2';
23
+ import '../nanoid.cjs';
23
24
  import 'crypto';
24
25
  import '../token.cjs';
25
26
  import 'slugify';
@@ -2984,8 +2985,8 @@ var drawbridge = {
2984
2985
  // owner is not a member document, so a solo merchant has nothing to
2985
2986
  // pick and could never save the step.
2986
2987
  members : { of : 'string', type : 'array' },
2987
- message : { required : true, type : 'string' },
2988
- subject : { required : true, type : 'string' }
2988
+ message : { max : 2000, required : true, type : 'string' },
2989
+ subject : { max : 150, required : true, type : 'string' }
2989
2990
  },
2990
2991
  triggers : [ 'schedule.day', 'schedule.week', 'schedule.month' ],
2991
2992
  usage : { actions : 0 }
@@ -3009,8 +3010,8 @@ var drawbridge = {
3009
3010
  queue : 'notification',
3010
3011
  settings : {
3011
3012
  members : { of : 'string', type : 'array' },
3012
- message : { type : 'string' },
3013
- subject : { type : 'string' }
3013
+ message : { max : 2000, type : 'string' },
3014
+ subject : { max : 150, type : 'string' }
3014
3015
  },
3015
3016
  triggers : [ 'lead.insert' ],
3016
3017
  // Zero is a PRICE, and a deliberate one. Declared rather than omitted
@@ -3025,8 +3026,8 @@ var drawbridge = {
3025
3026
  key : 'Email — Send email',
3026
3027
  queue : 'notification',
3027
3028
  settings : {
3028
- message : { required : true, type : 'string' },
3029
- subject : { required : true, type : 'string' }
3029
+ message : { max : 2000, required : true, type : 'string' },
3030
+ subject : { max : 150, required : true, type : 'string' }
3030
3031
  },
3031
3032
  triggers : [ 'lead.insert' ],
3032
3033
  // ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
@@ -3058,8 +3059,8 @@ var drawbridge = {
3058
3059
  key : 'Send an SMS',
3059
3060
  queue : 'notification',
3060
3061
  settings : {
3061
- message : { required : true, type : 'string' },
3062
- subject : { required : true, type : 'string' }
3062
+ message : { max : 1600, required : true, type : 'string' },
3063
+ subject : { max : 150, required : true, type : 'string' }
3063
3064
  },
3064
3065
  // Priced per SEGMENT and billed from the first, which the send
3065
3066
  // resolves from the message length. This is the floor.
@@ -20,6 +20,7 @@ import '../index.js';
20
20
  import 'currency-codes';
21
21
  import '../color.js';
22
22
  import 'tinycolor2';
23
+ import '../nanoid.js';
23
24
  import 'crypto';
24
25
  import '../token.js';
25
26
  import 'slugify';
@@ -2984,8 +2985,8 @@ var drawbridge = {
2984
2985
  // owner is not a member document, so a solo merchant has nothing to
2985
2986
  // pick and could never save the step.
2986
2987
  members : { of : 'string', type : 'array' },
2987
- message : { required : true, type : 'string' },
2988
- subject : { required : true, type : 'string' }
2988
+ message : { max : 2000, required : true, type : 'string' },
2989
+ subject : { max : 150, required : true, type : 'string' }
2989
2990
  },
2990
2991
  triggers : [ 'schedule.day', 'schedule.week', 'schedule.month' ],
2991
2992
  usage : { actions : 0 }
@@ -3009,8 +3010,8 @@ var drawbridge = {
3009
3010
  queue : 'notification',
3010
3011
  settings : {
3011
3012
  members : { of : 'string', type : 'array' },
3012
- message : { type : 'string' },
3013
- subject : { type : 'string' }
3013
+ message : { max : 2000, type : 'string' },
3014
+ subject : { max : 150, type : 'string' }
3014
3015
  },
3015
3016
  triggers : [ 'lead.insert' ],
3016
3017
  // Zero is a PRICE, and a deliberate one. Declared rather than omitted
@@ -3025,8 +3026,8 @@ var drawbridge = {
3025
3026
  key : 'Email — Send email',
3026
3027
  queue : 'notification',
3027
3028
  settings : {
3028
- message : { required : true, type : 'string' },
3029
- subject : { required : true, type : 'string' }
3029
+ message : { max : 2000, required : true, type : 'string' },
3030
+ subject : { max : 150, required : true, type : 'string' }
3030
3031
  },
3031
3032
  triggers : [ 'lead.insert' ],
3032
3033
  // ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
@@ -3058,8 +3059,8 @@ var drawbridge = {
3058
3059
  key : 'Send an SMS',
3059
3060
  queue : 'notification',
3060
3061
  settings : {
3061
- message : { required : true, type : 'string' },
3062
- subject : { required : true, type : 'string' }
3062
+ message : { max : 1600, required : true, type : 'string' },
3063
+ subject : { max : 150, required : true, type : 'string' }
3063
3064
  },
3064
3065
  // Priced per SEGMENT and billed from the first, which the send
3065
3066
  // resolves from the message length. This is the floor.
@@ -1374,7 +1374,6 @@ var organization = {
1374
1374
 
1375
1375
  // index.js
1376
1376
  import { code, data } from "currency-codes";
1377
- import { customAlphabet } from "nanoid";
1378
1377
 
1379
1378
  // lib/color.js
1380
1379
  import tinycolor from "tinycolor2";
@@ -1437,8 +1436,11 @@ var style = {
1437
1436
  }
1438
1437
  };
1439
1438
 
1439
+ // lib/nanoid.js
1440
+ import { customAlphabet } from "nanoid";
1441
+ var generate = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 8);
1442
+
1440
1443
  // index.js
1441
- var nanoid = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 8);
1442
1444
  var infinite = 1e300;
1443
1445
  var megabyte = 1024 * 1024;
1444
1446
  var gigabyte = megabyte * 1024;
@@ -2588,8 +2590,8 @@ var drawbridge_default2 = {
2588
2590
  // owner is not a member document, so a solo merchant has nothing to
2589
2591
  // pick and could never save the step.
2590
2592
  members: { of: "string", type: "array" },
2591
- message: { required: true, type: "string" },
2592
- subject: { required: true, type: "string" }
2593
+ message: { max: 2e3, required: true, type: "string" },
2594
+ subject: { max: 150, required: true, type: "string" }
2593
2595
  },
2594
2596
  triggers: ["schedule.day", "schedule.week", "schedule.month"],
2595
2597
  usage: { actions: 0 }
@@ -2612,8 +2614,8 @@ var drawbridge_default2 = {
2612
2614
  queue: "notification",
2613
2615
  settings: {
2614
2616
  members: { of: "string", type: "array" },
2615
- message: { type: "string" },
2616
- subject: { type: "string" }
2617
+ message: { max: 2e3, type: "string" },
2618
+ subject: { max: 150, type: "string" }
2617
2619
  },
2618
2620
  triggers: ["lead.insert"],
2619
2621
  // Zero is a PRICE, and a deliberate one. Declared rather than omitted
@@ -2627,8 +2629,8 @@ var drawbridge_default2 = {
2627
2629
  key: "Email \u2014 Send email",
2628
2630
  queue: "notification",
2629
2631
  settings: {
2630
- message: { required: true, type: "string" },
2631
- subject: { required: true, type: "string" }
2632
+ message: { max: 2e3, required: true, type: "string" },
2633
+ subject: { max: 150, required: true, type: "string" }
2632
2634
  },
2633
2635
  triggers: ["lead.insert"],
2634
2636
  // ONE SOURCE FOR THE PRICE. lib/pricing.js is the index of every
@@ -2657,8 +2659,8 @@ var drawbridge_default2 = {
2657
2659
  key: "Send an SMS",
2658
2660
  queue: "notification",
2659
2661
  settings: {
2660
- message: { required: true, type: "string" },
2661
- subject: { required: true, type: "string" }
2662
+ message: { max: 1600, required: true, type: "string" },
2663
+ subject: { max: 150, required: true, type: "string" }
2662
2664
  },
2663
2665
  // Priced per SEGMENT and billed from the first, which the send
2664
2666
  // resolves from the message length. This is the floor.
package/dist/html.cjs ADDED
@@ -0,0 +1,29 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // lib/html.js
20
+ var html_exports = {};
21
+ __export(html_exports, {
22
+ escapeHtml: () => escapeHtml
23
+ });
24
+ module.exports = __toCommonJS(html_exports);
25
+ var escapeHtml = (value) => String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
26
+ // Annotate the CommonJS export names for ESM import in node:
27
+ 0 && (module.exports = {
28
+ escapeHtml
29
+ });
@@ -0,0 +1,32 @@
1
+ // Escaping for values interpolated into HTML we generate ourselves.
2
+ //
3
+ // ITS OWN MODULE, not part of sanitize.js, because that one imports the
4
+ // ~120K-entry disposable-domain set at load — about 6MB of RSS its own comment
5
+ // flags as a footprint to watch. Every email sync renders would have paid that
6
+ // to escape five characters.
7
+ //
8
+ // Three copies of this existed before it moved here: drawbridge-api's oembed
9
+ // route, drawbridge-sync's email renderer, and drawbridge-emails' signature
10
+ // builder. They had already drifted — the signature builder escapes four
11
+ // characters and omits the apostrophe. Harmless where it sits (its output lands
12
+ // in text content and one double-quoted href, and the input is a config of our
13
+ // own staff), which is exactly why it survived: a divergence with no symptom is
14
+ // the kind that is only found by looking.
15
+
16
+ // The five characters that change meaning inside markup. `&` FIRST — escaping it
17
+ // after the others would re-escape the ampersands they just introduced and turn
18
+ // `&lt;` into `&amp;lt;`.
19
+ //
20
+ // Escapes for BOTH contexts, text and attribute, rather than asking callers
21
+ // which they are in: `"` and `'` are inert in text content and cost nothing to
22
+ // escape there, while getting it wrong in an attribute is an injection. A single
23
+ // function nobody has to think about beats two that are chosen correctly most of
24
+ // the time.
25
+ const escapeHtml = ( value ) => String( value ?? '' )
26
+ .replace( /&/g, '&amp;' )
27
+ .replace( /</g, '&lt;' )
28
+ .replace( />/g, '&gt;' )
29
+ .replace( /"/g, '&quot;' )
30
+ .replace( /'/g, '&#39;' );
31
+
32
+ export { escapeHtml };
package/dist/html.d.ts ADDED
@@ -0,0 +1,32 @@
1
+ // Escaping for values interpolated into HTML we generate ourselves.
2
+ //
3
+ // ITS OWN MODULE, not part of sanitize.js, because that one imports the
4
+ // ~120K-entry disposable-domain set at load — about 6MB of RSS its own comment
5
+ // flags as a footprint to watch. Every email sync renders would have paid that
6
+ // to escape five characters.
7
+ //
8
+ // Three copies of this existed before it moved here: drawbridge-api's oembed
9
+ // route, drawbridge-sync's email renderer, and drawbridge-emails' signature
10
+ // builder. They had already drifted — the signature builder escapes four
11
+ // characters and omits the apostrophe. Harmless where it sits (its output lands
12
+ // in text content and one double-quoted href, and the input is a config of our
13
+ // own staff), which is exactly why it survived: a divergence with no symptom is
14
+ // the kind that is only found by looking.
15
+
16
+ // The five characters that change meaning inside markup. `&` FIRST — escaping it
17
+ // after the others would re-escape the ampersands they just introduced and turn
18
+ // `&lt;` into `&amp;lt;`.
19
+ //
20
+ // Escapes for BOTH contexts, text and attribute, rather than asking callers
21
+ // which they are in: `"` and `'` are inert in text content and cost nothing to
22
+ // escape there, while getting it wrong in an attribute is an injection. A single
23
+ // function nobody has to think about beats two that are chosen correctly most of
24
+ // the time.
25
+ const escapeHtml = ( value ) => String( value ?? '' )
26
+ .replace( /&/g, '&amp;' )
27
+ .replace( /</g, '&lt;' )
28
+ .replace( />/g, '&gt;' )
29
+ .replace( /"/g, '&quot;' )
30
+ .replace( /'/g, '&#39;' );
31
+
32
+ export { escapeHtml };
package/dist/html.js ADDED
@@ -0,0 +1,5 @@
1
+ // lib/html.js
2
+ var escapeHtml = (value) => String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3
+ export {
4
+ escapeHtml
5
+ };
package/dist/index.cjs CHANGED
@@ -55,7 +55,6 @@ __export(index_exports, {
55
55
  });
56
56
  module.exports = __toCommonJS(index_exports);
57
57
  var import_currency_codes = require("currency-codes");
58
- var import_nanoid = require("nanoid");
59
58
 
60
59
  // lib/color.js
61
60
  var import_tinycolor2 = __toESM(require("tinycolor2"), 1);
@@ -144,10 +143,24 @@ var constants_default = {
144
143
  rejection: "You have already submitted",
145
144
  email: "You were selected"
146
145
  },
146
+ // THE COPY EVERY DRAW NOTIFICATION SHIPS WITH, and — because no merchant
147
+ // had ever edited it — the copy every winner email had actually been sent
148
+ // with. It is seeded onto the campaign at creation, so changing it here
149
+ // only reaches NEW campaigns; the existing ones are moved by
150
+ // backfillDrawNotifications in drawbridge-api/scripts.js.
151
+ //
152
+ // `message`, not `body`: every other notification in the product names
153
+ // this field message — the workflow step settings, the notification
154
+ // document the draw route writes, and sync's render.notification().
155
+ //
156
+ // Both strings pass the notificationWarnings rules the form applies to
157
+ // the merchant's own copy, which would be a poor rule set if the shipped
158
+ // default failed it. Neither names a brand because a static default
159
+ // cannot know one; the form's brand rule is what asks for that.
147
160
  notifications: {
148
161
  draw: {
149
- subject: "You have been selected",
150
- body: "Thanks for being part of our giveaway"
162
+ subject: "Your prize is ready to claim",
163
+ message: "You were selected in our giveaway. Follow the link to confirm your details and claim your prize."
151
164
  }
152
165
  },
153
166
  settings: {
@@ -285,6 +298,20 @@ var constants_default = {
285
298
  }
286
299
  };
287
300
 
301
+ // lib/nanoid.js
302
+ var import_nanoid = require("nanoid");
303
+ var generate = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
304
+ var NOVOWEL = /[bcdfgjklmnpqrstvwxz]{7}/i;
305
+ var ATTEMPTS = 10;
306
+ var nanoid = () => {
307
+ let value = generate();
308
+ for (let attempt = 1; attempt < ATTEMPTS && NOVOWEL.test(value); attempt++) {
309
+ value = generate();
310
+ }
311
+ ;
312
+ return value;
313
+ };
314
+
288
315
  // lib/usage.js
289
316
  var incrementUsageTotals = async ({ controller, usageId, $inc, session }) => {
290
317
  if (!usageId || !$inc) return;
@@ -308,7 +335,6 @@ var incrementUsageTotals = async ({ controller, usageId, $inc, session }) => {
308
335
  var isDuplicateKey = (error) => (error == null ? void 0 : error.code) === 11e3 || (error == null ? void 0 : error.code) === "11000" || /E11000|duplicate key/i.test((error == null ? void 0 : error.message) || "");
309
336
 
310
337
  // index.js
311
- var nanoid = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
312
338
  var constants = constants_default;
313
339
  var infinite = 1e300;
314
340
  var isInfinite = (value) => value === infinite;
package/dist/index.d.cts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { data, code } from 'currency-codes';
2
- import { customAlphabet } from 'nanoid';
3
2
  import { colorFormatted, colorAccessible } from './color.cjs';
3
+ export { nanoid } from './nanoid.cjs';
4
4
  export { incrementUsageTotals, isDuplicateKey } from './usage.cjs';
5
5
  import 'tinycolor2';
6
+ import 'nanoid';
6
7
 
7
8
  const font = {
8
9
  family : 'Roboto Flex',
@@ -67,10 +68,24 @@ var constantsData = {
67
68
  rejection : 'You have already submitted',
68
69
  email : 'You were selected'
69
70
  },
71
+ // THE COPY EVERY DRAW NOTIFICATION SHIPS WITH, and — because no merchant
72
+ // had ever edited it — the copy every winner email had actually been sent
73
+ // with. It is seeded onto the campaign at creation, so changing it here
74
+ // only reaches NEW campaigns; the existing ones are moved by
75
+ // backfillDrawNotifications in drawbridge-api/scripts.js.
76
+ //
77
+ // `message`, not `body`: every other notification in the product names
78
+ // this field message — the workflow step settings, the notification
79
+ // document the draw route writes, and sync's render.notification().
80
+ //
81
+ // Both strings pass the notificationWarnings rules the form applies to
82
+ // the merchant's own copy, which would be a poor rule set if the shipped
83
+ // default failed it. Neither names a brand because a static default
84
+ // cannot know one; the form's brand rule is what asks for that.
70
85
  notifications : {
71
86
  draw : {
72
- subject : 'You have been selected',
73
- body : 'Thanks for being part of our giveaway'
87
+ subject : 'Your prize is ready to claim',
88
+ message : 'You were selected in our giveaway. Follow the link to confirm your details and claim your prize.'
74
89
  }
75
90
  },
76
91
  settings : {
@@ -208,8 +223,6 @@ var constantsData = {
208
223
  }
209
224
  };
210
225
 
211
- const nanoid = customAlphabet( '0123456789abcdefghijklmnopqrstuvwxyz', 8 );
212
-
213
226
  const constants = constantsData;
214
227
 
215
228
  const infinite = 1e300;
@@ -441,4 +454,4 @@ const currencies = data.map( ( item ) => ({
441
454
 
442
455
  const currency = ( val ) => code( val );
443
456
 
444
- export { bytesToGB, bytesToMB, capitalize, constants, currencies, currency, expiredPaymentMethod, formatCurrency, formatDateString, formatNumber, getPlanFeature, gigabyte, infinite, isInfinite, megabyte, nanoid, percentage, reducers, regex, shareUrls, urlRoot };
457
+ export { bytesToGB, bytesToMB, capitalize, constants, currencies, currency, expiredPaymentMethod, formatCurrency, formatDateString, formatNumber, getPlanFeature, gigabyte, infinite, isInfinite, megabyte, percentage, reducers, regex, shareUrls, urlRoot };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { data, code } from 'currency-codes';
2
- import { customAlphabet } from 'nanoid';
3
2
  import { colorFormatted, colorAccessible } from './color.js';
3
+ export { nanoid } from './nanoid.js';
4
4
  export { incrementUsageTotals, isDuplicateKey } from './usage.js';
5
5
  import 'tinycolor2';
6
+ import 'nanoid';
6
7
 
7
8
  const font = {
8
9
  family : 'Roboto Flex',
@@ -67,10 +68,24 @@ var constantsData = {
67
68
  rejection : 'You have already submitted',
68
69
  email : 'You were selected'
69
70
  },
71
+ // THE COPY EVERY DRAW NOTIFICATION SHIPS WITH, and — because no merchant
72
+ // had ever edited it — the copy every winner email had actually been sent
73
+ // with. It is seeded onto the campaign at creation, so changing it here
74
+ // only reaches NEW campaigns; the existing ones are moved by
75
+ // backfillDrawNotifications in drawbridge-api/scripts.js.
76
+ //
77
+ // `message`, not `body`: every other notification in the product names
78
+ // this field message — the workflow step settings, the notification
79
+ // document the draw route writes, and sync's render.notification().
80
+ //
81
+ // Both strings pass the notificationWarnings rules the form applies to
82
+ // the merchant's own copy, which would be a poor rule set if the shipped
83
+ // default failed it. Neither names a brand because a static default
84
+ // cannot know one; the form's brand rule is what asks for that.
70
85
  notifications : {
71
86
  draw : {
72
- subject : 'You have been selected',
73
- body : 'Thanks for being part of our giveaway'
87
+ subject : 'Your prize is ready to claim',
88
+ message : 'You were selected in our giveaway. Follow the link to confirm your details and claim your prize.'
74
89
  }
75
90
  },
76
91
  settings : {
@@ -208,8 +223,6 @@ var constantsData = {
208
223
  }
209
224
  };
210
225
 
211
- const nanoid = customAlphabet( '0123456789abcdefghijklmnopqrstuvwxyz', 8 );
212
-
213
226
  const constants = constantsData;
214
227
 
215
228
  const infinite = 1e300;
@@ -441,4 +454,4 @@ const currencies = data.map( ( item ) => ({
441
454
 
442
455
  const currency = ( val ) => code( val );
443
456
 
444
- export { bytesToGB, bytesToMB, capitalize, constants, currencies, currency, expiredPaymentMethod, formatCurrency, formatDateString, formatNumber, getPlanFeature, gigabyte, infinite, isInfinite, megabyte, nanoid, percentage, reducers, regex, shareUrls, urlRoot };
457
+ export { bytesToGB, bytesToMB, capitalize, constants, currencies, currency, expiredPaymentMethod, formatCurrency, formatDateString, formatNumber, getPlanFeature, gigabyte, infinite, isInfinite, megabyte, percentage, reducers, regex, shareUrls, urlRoot };
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  // index.js
2
2
  import { code, data } from "currency-codes";
3
- import { customAlphabet } from "nanoid";
4
3
 
5
4
  // lib/color.js
6
5
  import tinycolor from "tinycolor2";
@@ -89,10 +88,24 @@ var constants_default = {
89
88
  rejection: "You have already submitted",
90
89
  email: "You were selected"
91
90
  },
91
+ // THE COPY EVERY DRAW NOTIFICATION SHIPS WITH, and — because no merchant
92
+ // had ever edited it — the copy every winner email had actually been sent
93
+ // with. It is seeded onto the campaign at creation, so changing it here
94
+ // only reaches NEW campaigns; the existing ones are moved by
95
+ // backfillDrawNotifications in drawbridge-api/scripts.js.
96
+ //
97
+ // `message`, not `body`: every other notification in the product names
98
+ // this field message — the workflow step settings, the notification
99
+ // document the draw route writes, and sync's render.notification().
100
+ //
101
+ // Both strings pass the notificationWarnings rules the form applies to
102
+ // the merchant's own copy, which would be a poor rule set if the shipped
103
+ // default failed it. Neither names a brand because a static default
104
+ // cannot know one; the form's brand rule is what asks for that.
92
105
  notifications: {
93
106
  draw: {
94
- subject: "You have been selected",
95
- body: "Thanks for being part of our giveaway"
107
+ subject: "Your prize is ready to claim",
108
+ message: "You were selected in our giveaway. Follow the link to confirm your details and claim your prize."
96
109
  }
97
110
  },
98
111
  settings: {
@@ -230,6 +243,20 @@ var constants_default = {
230
243
  }
231
244
  };
232
245
 
246
+ // lib/nanoid.js
247
+ import { customAlphabet } from "nanoid";
248
+ var generate = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 8);
249
+ var NOVOWEL = /[bcdfgjklmnpqrstvwxz]{7}/i;
250
+ var ATTEMPTS = 10;
251
+ var nanoid = () => {
252
+ let value = generate();
253
+ for (let attempt = 1; attempt < ATTEMPTS && NOVOWEL.test(value); attempt++) {
254
+ value = generate();
255
+ }
256
+ ;
257
+ return value;
258
+ };
259
+
233
260
  // lib/usage.js
234
261
  var incrementUsageTotals = async ({ controller, usageId, $inc, session }) => {
235
262
  if (!usageId || !$inc) return;
@@ -253,7 +280,6 @@ var incrementUsageTotals = async ({ controller, usageId, $inc, session }) => {
253
280
  var isDuplicateKey = (error) => (error == null ? void 0 : error.code) === 11e3 || (error == null ? void 0 : error.code) === "11000" || /E11000|duplicate key/i.test((error == null ? void 0 : error.message) || "");
254
281
 
255
282
  // index.js
256
- var nanoid = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz", 8);
257
283
  var constants = constants_default;
258
284
  var infinite = 1e300;
259
285
  var isInfinite = (value) => value === infinite;
package/dist/nanoid.cjs CHANGED
@@ -24,7 +24,17 @@ __export(nanoid_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(nanoid_exports);
26
26
  var import_nanoid = require("nanoid");
27
- var nanoid = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
27
+ var generate = (0, import_nanoid.customAlphabet)("0123456789abcdefghijklmnopqrstuvwxyz", 8);
28
+ var NOVOWEL = /[bcdfgjklmnpqrstvwxz]{7}/i;
29
+ var ATTEMPTS = 10;
30
+ var nanoid = () => {
31
+ let value = generate();
32
+ for (let attempt = 1; attempt < ATTEMPTS && NOVOWEL.test(value); attempt++) {
33
+ value = generate();
34
+ }
35
+ ;
36
+ return value;
37
+ };
28
38
  var DEFAULT_MAX_RETRIES = 5;
29
39
  var retry = async ({
30
40
  field,
package/dist/nanoid.d.cts CHANGED
@@ -11,7 +11,47 @@ import { customAlphabet } from 'nanoid';
11
11
  // New code should prefer this subpath, which also exposes `retry`:
12
12
  // const { nanoid, retry } = require( '@drawbridge/drawbridge-utils/nanoid' );
13
13
 
14
- const nanoid = customAlphabet( '0123456789abcdefghijklmnopqrstuvwxyz', 8 );
14
+ const generate = customAlphabet( '0123456789abcdefghijklmnopqrstuvwxyz', 8 );
15
+
16
+ // SpamAssassin's FROM_LOCAL_NOVOWEL scores any From address whose LOCAL PART
17
+ // carries seven consecutive letters from this class:
18
+ //
19
+ // header FROM_LOCAL_NOVOWEL From =~ /[bcdfgjklmnpqrstvwxz]{7}\S*\@/i
20
+ //
21
+ // organization.shortId becomes exactly that: lead mail sends from
22
+ // org+<shortId>@<sending domain> (lib/email.js subAddress). Nineteen of the
23
+ // thirty-six characters in the alphabet above are in the class, so a run of
24
+ // seven inside eight characters is not rare — measured at 1.67% of generated
25
+ // ids, which is roughly one organization in sixty penalised on every lead email
26
+ // it will ever send, decided by nothing but the draw.
27
+ //
28
+ // Rejecting those costs a re-roll on 1.7% of calls and a slice of the keyspace
29
+ // far too small to matter against 36⁸. Applied to EVERY nanoid rather than only
30
+ // the organization's: the rest become slugs in urls where the rule is
31
+ // irrelevant and the cost is nil, and doing it here means no future caller can
32
+ // put an id in an address and quietly reintroduce this.
33
+ //
34
+ // Existing ids are untouched — this only shapes new ones.
35
+ const NOVOWEL = /[bcdfgjklmnpqrstvwxz]{7}/i;
36
+
37
+ // Bounded rather than looping until clean. At a 1.67% rejection rate the odds
38
+ // of ten consecutive rejections are about 1 in 10^18, so the cap is never
39
+ // reached — but a generator that CANNOT hang is worth more than one that is
40
+ // merely very unlikely to, and returning a slightly penalised id beats spinning.
41
+ const ATTEMPTS = 10;
42
+
43
+ const nanoid = () => {
44
+
45
+ let value = generate();
46
+
47
+ for( let attempt = 1; attempt < ATTEMPTS && NOVOWEL.test( value ); attempt++ ){
48
+
49
+ value = generate();
50
+
51
+ }
52
+ return value;
53
+
54
+ };
15
55
 
16
56
  // Retry an async operation when Mongo rejects an insert because of a
17
57
  // duplicate-key error on a specific field. The operation receives a fresh