@blamejs/blamejs-shop 0.5.19 → 0.5.21

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.
Files changed (194) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -0
  3. package/SECURITY.md +17 -0
  4. package/lib/addresses.js +2 -2
  5. package/lib/admin.js +49 -45
  6. package/lib/affiliates.js +7 -23
  7. package/lib/announcement-bar.js +5 -22
  8. package/lib/api-keys.js +4 -13
  9. package/lib/asset-manifest.json +1 -1
  10. package/lib/banner-ab-tests.js +5 -9
  11. package/lib/blog-articles.js +8 -26
  12. package/lib/captcha-gate.js +7 -17
  13. package/lib/carrier-accounts.js +3 -10
  14. package/lib/catalog-drafts.js +5 -12
  15. package/lib/category-navigation.js +4 -20
  16. package/lib/cms-blocks.js +4 -7
  17. package/lib/compliance-export.js +4 -11
  18. package/lib/consent-ledger.js +2 -4
  19. package/lib/cost-layers.js +56 -21
  20. package/lib/customer-import.js +2 -2
  21. package/lib/customer-notes.js +7 -23
  22. package/lib/customer-roles.js +3 -5
  23. package/lib/customer-segments.js +17 -14
  24. package/lib/customer-surveys.js +7 -14
  25. package/lib/customers.js +2 -4
  26. package/lib/dispute-resolution.js +5 -13
  27. package/lib/dropship-forwarding.js +3 -5
  28. package/lib/dunning.js +2 -7
  29. package/lib/email-ab-tests.js +4 -8
  30. package/lib/email-campaigns.js +25 -14
  31. package/lib/email-warmup.js +2 -7
  32. package/lib/experiments.js +6 -10
  33. package/lib/externaldb-d1.js +78 -44
  34. package/lib/geolocation.js +18 -28
  35. package/lib/gift-options.js +5 -23
  36. package/lib/knowledge-base.js +7 -22
  37. package/lib/line-gift-wrap.js +3 -17
  38. package/lib/live-chat.js +5 -18
  39. package/lib/metered-usage.js +3 -8
  40. package/lib/notifications.js +3 -7
  41. package/lib/operator-accounts.js +3 -5
  42. package/lib/operator-approvals.js +6 -8
  43. package/lib/operator-audit-log.js +2 -7
  44. package/lib/operator-help-center.js +5 -21
  45. package/lib/operator-inbox.js +4 -11
  46. package/lib/operator-roles.js +5 -7
  47. package/lib/order-escalation.js +2 -2
  48. package/lib/order-export.js +24 -20
  49. package/lib/order-notes.js +4 -14
  50. package/lib/order-ratings.js +4 -10
  51. package/lib/payment-methods.js +5 -13
  52. package/lib/payment-retries.js +2 -7
  53. package/lib/payment.js +103 -58
  54. package/lib/pixel-events.js +8 -23
  55. package/lib/plan-changes.js +2 -7
  56. package/lib/product-qa.js +4 -8
  57. package/lib/promo-banners.js +7 -15
  58. package/lib/purchase-orders.js +3 -6
  59. package/lib/push-notifications.js +7 -32
  60. package/lib/pwa-manifest.js +6 -11
  61. package/lib/quotes.js +5 -9
  62. package/lib/referrals.js +10 -6
  63. package/lib/reviews.js +4 -10
  64. package/lib/robots-config.js +6 -14
  65. package/lib/sales-tax-filings.js +2 -2
  66. package/lib/search-facets.js +5 -5
  67. package/lib/search-ranking.js +4 -7
  68. package/lib/search-synonyms.js +7 -21
  69. package/lib/security-middleware.js +125 -70
  70. package/lib/seller-signup.js +10 -26
  71. package/lib/sidebar-widgets.js +6 -15
  72. package/lib/site-redirects.js +49 -137
  73. package/lib/sitemap-generator.js +3 -7
  74. package/lib/sms-dispatcher.js +7 -23
  75. package/lib/stock-receipts.js +4 -10
  76. package/lib/storefront-dashboards.js +2 -10
  77. package/lib/storefront-forms.js +9 -22
  78. package/lib/storefront-pages.js +6 -20
  79. package/lib/storefront.js +21 -23
  80. package/lib/subscription-billing.js +3 -8
  81. package/lib/subscription-controls.js +2 -7
  82. package/lib/suggestion-box.js +9 -26
  83. package/lib/support-tickets.js +6 -24
  84. package/lib/tax-remittance.js +2 -2
  85. package/lib/tenants.js +2 -7
  86. package/lib/text-guard.js +137 -35
  87. package/lib/theme-assets.js +4 -16
  88. package/lib/translations.js +3 -6
  89. package/lib/trust-badges.js +4 -7
  90. package/lib/vendor/MANIFEST.json +107 -97
  91. package/lib/vendor/blamejs/CHANGELOG.md +180 -0
  92. package/lib/vendor/blamejs/NOTICE +14 -10
  93. package/lib/vendor/blamejs/README.md +17 -5
  94. package/lib/vendor/blamejs/index.js +2 -0
  95. package/lib/vendor/blamejs/lib/acme.js +9 -9
  96. package/lib/vendor/blamejs/lib/api-snapshot.js +35 -16
  97. package/lib/vendor/blamejs/lib/app-shutdown.js +1 -1
  98. package/lib/vendor/blamejs/lib/archive-adapters.js +1 -1
  99. package/lib/vendor/blamejs/lib/archive.js +13 -24
  100. package/lib/vendor/blamejs/lib/auth/access-lock.js +2 -1
  101. package/lib/vendor/blamejs/lib/auth/bot-challenge.js +3 -6
  102. package/lib/vendor/blamejs/lib/auth/ciba.js +32 -3
  103. package/lib/vendor/blamejs/lib/auth/oauth.js +65 -8
  104. package/lib/vendor/blamejs/lib/auth/password.js +1 -1
  105. package/lib/vendor/blamejs/lib/auth/saml.js +21 -3
  106. package/lib/vendor/blamejs/lib/auth-bot-challenge.js +3 -3
  107. package/lib/vendor/blamejs/lib/backup/index.js +5 -5
  108. package/lib/vendor/blamejs/lib/case-fold-classes.js +491 -0
  109. package/lib/vendor/blamejs/lib/codepoint-class.js +131 -0
  110. package/lib/vendor/blamejs/lib/constants.js +79 -0
  111. package/lib/vendor/blamejs/lib/db-declare-view.js +8 -2
  112. package/lib/vendor/blamejs/lib/error-page.js +20 -1
  113. package/lib/vendor/blamejs/lib/external-db.js +5 -1
  114. package/lib/vendor/blamejs/lib/flag-evaluation-context.js +24 -6
  115. package/lib/vendor/blamejs/lib/flag.js +28 -2
  116. package/lib/vendor/blamejs/lib/framework-schema.js +14 -3
  117. package/lib/vendor/blamejs/lib/guard-regex.js +2345 -89
  118. package/lib/vendor/blamejs/lib/http-client.js +217 -40
  119. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  120. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +3 -2
  121. package/lib/vendor/blamejs/lib/mail-dav.js +26 -26
  122. package/lib/vendor/blamejs/lib/mail-deploy.js +10 -10
  123. package/lib/vendor/blamejs/lib/mail-scan.js +3 -0
  124. package/lib/vendor/blamejs/lib/mail-store.js +7 -1
  125. package/lib/vendor/blamejs/lib/mail.js +5 -1
  126. package/lib/vendor/blamejs/lib/middleware/age-gate.js +3 -2
  127. package/lib/vendor/blamejs/lib/middleware/api-encrypt.js +1 -1
  128. package/lib/vendor/blamejs/lib/middleware/assetlinks.js +2 -1
  129. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +3 -2
  130. package/lib/vendor/blamejs/lib/middleware/bearer-auth.js +2 -1
  131. package/lib/vendor/blamejs/lib/middleware/compression.js +1 -1
  132. package/lib/vendor/blamejs/lib/middleware/cors.js +1 -1
  133. package/lib/vendor/blamejs/lib/middleware/csp-report.js +5 -5
  134. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +2 -1
  135. package/lib/vendor/blamejs/lib/middleware/daily-byte-quota.js +2 -2
  136. package/lib/vendor/blamejs/lib/middleware/deny-response.js +2 -1
  137. package/lib/vendor/blamejs/lib/middleware/dpop.js +2 -2
  138. package/lib/vendor/blamejs/lib/middleware/fetch-metadata.js +2 -1
  139. package/lib/vendor/blamejs/lib/middleware/flag-context.js +17 -0
  140. package/lib/vendor/blamejs/lib/middleware/idempotency-key.js +10 -8
  141. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +3 -2
  142. package/lib/vendor/blamejs/lib/middleware/require-aal.js +3 -2
  143. package/lib/vendor/blamejs/lib/middleware/require-auth.js +4 -3
  144. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +4 -3
  145. package/lib/vendor/blamejs/lib/middleware/require-content-type.js +3 -2
  146. package/lib/vendor/blamejs/lib/middleware/require-methods.js +3 -2
  147. package/lib/vendor/blamejs/lib/middleware/require-mtls.js +3 -2
  148. package/lib/vendor/blamejs/lib/middleware/security-txt.js +2 -1
  149. package/lib/vendor/blamejs/lib/middleware/web-app-manifest.js +2 -1
  150. package/lib/vendor/blamejs/lib/network-dns-resolver.js +1 -1
  151. package/lib/vendor/blamejs/lib/network-dns.js +3 -3
  152. package/lib/vendor/blamejs/lib/network-nts.js +35 -14
  153. package/lib/vendor/blamejs/lib/network-proxy.js +42 -4
  154. package/lib/vendor/blamejs/lib/network-smtp-policy.js +1 -1
  155. package/lib/vendor/blamejs/lib/network-tls.js +341 -11
  156. package/lib/vendor/blamejs/lib/nist-crosswalk.js +2 -2
  157. package/lib/vendor/blamejs/lib/ntp-check.js +30 -19
  158. package/lib/vendor/blamejs/lib/object-store/azure-blob.js +1 -1
  159. package/lib/vendor/blamejs/lib/object-store/gcs.js +1 -1
  160. package/lib/vendor/blamejs/lib/object-store/http-put.js +2 -1
  161. package/lib/vendor/blamejs/lib/object-store/sigv4-bucket-ops.js +5 -5
  162. package/lib/vendor/blamejs/lib/object-store/sigv4.js +2 -2
  163. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +4 -2
  164. package/lib/vendor/blamejs/lib/openapi.js +1 -1
  165. package/lib/vendor/blamejs/lib/pqc-agent.js +4 -7
  166. package/lib/vendor/blamejs/lib/problem-details.js +2 -1
  167. package/lib/vendor/blamejs/lib/redis-client.js +12 -1
  168. package/lib/vendor/blamejs/lib/regex-linear.js +1349 -0
  169. package/lib/vendor/blamejs/lib/render.js +531 -7
  170. package/lib/vendor/blamejs/lib/request-helpers.js +181 -5
  171. package/lib/vendor/blamejs/lib/router.js +37 -13
  172. package/lib/vendor/blamejs/lib/safe-async.js +142 -0
  173. package/lib/vendor/blamejs/lib/safe-icap.js +3 -0
  174. package/lib/vendor/blamejs/lib/safe-sql.js +15 -3
  175. package/lib/vendor/blamejs/lib/self-update.js +2 -2
  176. package/lib/vendor/blamejs/lib/testing.js +54 -7
  177. package/lib/vendor/blamejs/lib/validate-opts.js +56 -0
  178. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +62 -25
  179. package/lib/vendor/blamejs/lib/vendor/blamejs-pki.cjs +2004 -142
  180. package/lib/vendor/blamejs/lib/vendor/browser/noble-ciphers.mjs +727 -0
  181. package/lib/vendor/blamejs/lib/vendor/browser/noble-hashes.mjs +1070 -0
  182. package/lib/vendor/blamejs/lib/vendor/browser/noble-post-quantum.mjs +1090 -0
  183. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +510 -227
  184. package/lib/vendor/blamejs/lib/webhook-hmac.js +19 -2
  185. package/lib/vendor/blamejs/lib/webhook.js +1 -1
  186. package/lib/vendor/blamejs/lib/ws-client.js +24 -2
  187. package/lib/vendor/blamejs/package.json +1 -1
  188. package/lib/vendor/blamejs/sbom.cdx.json +6 -6
  189. package/lib/vendor-invoices.js +3 -6
  190. package/lib/vendors.js +5 -19
  191. package/lib/webhook-receiver.js +46 -83
  192. package/lib/webhook-subscriptions.js +3 -13
  193. package/lib/wishlist-sharing.js +5 -10
  194. package/package.json +1 -1
@@ -297,8 +297,14 @@ function declareView(opts) {
297
297
  // resolves the backend at apply time (operator may set spec.backend
298
298
  // explicitly OR rely on the migrate runner's default backend).
299
299
  var description = "declareView " + spec.schema + "." + spec.name;
300
- var qView = safeSql.quoteQualified([spec.schema, spec.name], "postgres");
301
- var qSource = safeSql.quoteQualified([spec.source.schema, spec.source.name], "postgres");
300
+ // The schema and view names are the operator's, and the column list two
301
+ // hunks down already quotes reserved words the way `b.db.from()` does. These
302
+ // were the stricter half of the same statement: a view in a schema named
303
+ // after a keyword was accepted at the front door and refused here.
304
+ var qView = safeSql.quoteQualified([spec.schema, spec.name], "postgres",
305
+ { allowReserved: true });
306
+ var qSource = safeSql.quoteQualified([spec.source.schema, spec.source.name], "postgres",
307
+ { allowReserved: true });
302
308
 
303
309
  async function up(xdb, ctx) {
304
310
  // Boundary throw: confirm we're on Postgres before any DDL leaves the process.
@@ -259,6 +259,13 @@ function _renderDevHtml(info, opts, ctx) {
259
259
 
260
260
  function _writeResponse(res, status, contentType, body) {
261
261
  if (res.writableEnded) return;
262
+ // Once the status line is on the wire it cannot be replaced, and pretending
263
+ // otherwise produces the worst of both: writeHead throws
264
+ // ERR_HTTP_HEADERS_SENT, the catch below falls through to a plain-text end,
265
+ // and the client receives a 200 whose last bytes are the words "Internal
266
+ // Server Error" appended to a partial body. failAfterHeaders owns what to do
267
+ // instead, per protocol and per response shape.
268
+ if (requestHelpers.failAfterHeaders(res)) return;
262
269
  try {
263
270
  var headers = { "Content-Type": contentType, "Cache-Control": "no-store" };
264
271
  // Prefer writeHead so the status survives under both real Node
@@ -462,8 +469,20 @@ function create(opts) {
462
469
  code: info.code || (info.status >= 500 ? "internal_error" : "error"),
463
470
  });
464
471
  if (res && res.writableEnded) return;
472
+ // The same wire truth as the envelope below: a response whose headers
473
+ // are already sent cannot be given a problem+json body. Left to
474
+ // itself, respond() would call setHeader, throw ERR_HTTP_HEADERS_SENT,
475
+ // and the catch would swallow it without ending OR destroying — a
476
+ // pinned socket and a client that waits forever, which is worse than
477
+ // the truncation this branch was meant to avoid.
478
+ if (requestHelpers.failAfterHeaders(res)) return;
465
479
  try { problemDetails.respond(res, problem, req); }
466
- catch (_e) { /* response already torn down */ }
480
+ catch (_e) {
481
+ // It still failed to write: end the response rather than leave the
482
+ // client hanging on a request nothing will ever answer.
483
+ try { if (!res.writableEnded && typeof res.end === "function") res.end(); }
484
+ catch (_e2) { /* socket already gone */ }
485
+ }
467
486
  return;
468
487
  }
469
488
 
@@ -1636,7 +1636,11 @@ function _buildSessionGucsStatements(sessionGucs) {
1636
1636
  // and the dot-quoted rendering.
1637
1637
  var qName;
1638
1638
  try {
1639
- qName = safeSql.quoteQualified(name, "postgres");
1639
+ // The GUC name is the operator's, so it is quoted rather than refused for
1640
+ // being a keyword — the same rule every other operator-supplied
1641
+ // identifier answers to. The shape is still enforced: a quote, a
1642
+ // semicolon or a null byte in a GUC name fails here as it always did.
1643
+ qName = safeSql.quoteQualified(name, "postgres", { allowReserved: true });
1640
1644
  } catch (e) {
1641
1645
  throw _err("INVALID_SESSION_GUCS",
1642
1646
  "sessionGucs: name '" + name + "' is not a valid identifier: " +
@@ -26,6 +26,7 @@ var { defineClass } = require("./framework-error");
26
26
  var FlagError = defineClass("FlagError", { alwaysPermanent: true });
27
27
 
28
28
  var bCrypto = lazyRequire(function () { return require("./crypto"); });
29
+ var requestHelpers = lazyRequire(function () { return require("./request-helpers"); });
29
30
 
30
31
  function _normalize(input, label) {
31
32
  if (input == null) return {};
@@ -65,7 +66,9 @@ function merge(base, overlay) {
65
66
 
66
67
  function fromRequest(req, opts) {
67
68
  opts = opts || {};
68
- validateOpts(opts, ["userKey", "tenantKey", "extra"], "flag.context.fromRequest");
69
+ validateOpts(opts, ["userKey", "tenantKey", "extra",
70
+ "trustedProxies", "forwardedHeaders", "clientIpResolver"],
71
+ "flag.context.fromRequest");
69
72
  if (!req || typeof req !== "object") {
70
73
  return create({});
71
74
  }
@@ -98,11 +101,26 @@ function fromRequest(req, opts) {
98
101
  } else if (req.user && typeof req.user.id === "string") {
99
102
  tk = req.user.id;
100
103
  } else {
101
- var ip = (typeof headers["x-forwarded-for"] === "string" &&
102
- headers["x-forwarded-for"].split(",")[0].trim()) ||
103
- (req.connection && req.connection.remoteAddress) || "";
104
- var ua = headers["user-agent"] || "";
105
- tk = "anon:" + bCrypto().sha3Hash(ip + ":" + ua).slice(0, 16); // base16 prefix len
104
+ // The anonymous targeting key decides which bucket an unauthenticated
105
+ // caller lands in, so whoever controls it controls their own rollout
106
+ // assignment. Reading X-Forwarded-For directly let any client set it:
107
+ // resending with a different value moved them to a different bucket until
108
+ // one served the variant they wanted. Resolution goes through the same
109
+ // peer-gated helper every other client-address decision uses, so forwarded
110
+ // headers are honored only from a proxy the operator has declared.
111
+ var ip = requestHelpers().trustedClientIp({
112
+ trustedProxies: opts.trustedProxies,
113
+ forwardedHeaders: opts.forwardedHeaders,
114
+ clientIpResolver: opts.clientIpResolver,
115
+ }).resolve(req) || "";
116
+ // Derived from the address alone. The User-Agent was mixed in for spread,
117
+ // but a client sets it outright, so it gave the caller the same free hand
118
+ // over their own bucket that the unguarded forwarded header did — and
119
+ // closing one while leaving the other open closes nothing. The cost is
120
+ // coarser distribution: anonymous callers sharing an address now share a
121
+ // bucket, which is the honest resolution when nothing else about them can
122
+ // be trusted. Identify callers whose spread matters and pass `userKey`.
123
+ tk = "anon:" + bCrypto().sha3Hash(ip).slice(0, 16); // base16 prefix len
106
124
  }
107
125
  ctx.targetingKey = tk;
108
126
 
@@ -43,6 +43,7 @@ var validateOpts = require("./validate-opts");
43
43
  var lazyRequire = require("./lazy-require");
44
44
  var providersMod = require("./flag-providers");
45
45
  var contextMod = require("./flag-evaluation-context");
46
+ var requestHelpers = lazyRequire(function () { return require("./request-helpers"); });
46
47
  var targeting = require("./flag-targeting");
47
48
  var cacheMod = require("./flag-cache");
48
49
  var { defineClass } = require("./framework-error");
@@ -88,6 +89,19 @@ function _validateHooks(rawHooks) {
88
89
  * `getDetailsAll`), provider mutation (`addProvider` / `removeProvider`),
89
90
  * and `middleware({ userKey })` for per-request binding.
90
91
  *
92
+ * A request with no identified user gets an anonymous targeting key derived
93
+ * from its client address ALONE. That key decides which bucket the caller
94
+ * lands in, so it is built only from what the caller cannot choose: the
95
+ * User-Agent does not contribute, and the address is resolved peer-gated —
96
+ * forwarded headers are ignored unless `middleware` is given `trustedProxies`
97
+ * (CIDRs of your reverse proxies), optionally with `forwardedHeaders` when the
98
+ * address arrives as something other than `X-Forwarded-For`, or
99
+ * `clientIpResolver` to own resolution outright.
100
+ *
101
+ * Anonymous callers sharing an address therefore share a bucket. Behind a NAT,
102
+ * or behind a proxy with no `trustedProxies` configured, that can be all of
103
+ * them — pass `userKey` for callers whose distribution has to be per-user.
104
+ *
91
105
  * Throws `FlagError` at config time on a missing provider, hooks not
92
106
  * shaped as `{ before?, after?, error?, finally? }` functions, or a
93
107
  * provider lacking `.evaluate(flagKey, ctx)`.
@@ -317,11 +331,23 @@ function create(opts) {
317
331
  },
318
332
  middleware: function (mwOpts) {
319
333
  mwOpts = mwOpts || {};
320
- validateOpts(mwOpts, ["userKey"], "flag.middleware");
334
+ validateOpts(mwOpts, ["userKey", "trustedProxies", "forwardedHeaders", "clientIpResolver"],
335
+ "flag.middleware");
336
+ // One peer-gated resolver built here rather than per request: a
337
+ // malformed CIDR then fails at boot instead of on the first request,
338
+ // and the list is validated once. Without any trust configured this
339
+ // reads the socket address and ignores forwarded headers, so an
340
+ // anonymous caller cannot pick their own rollout bucket.
341
+ var trustedIp = requestHelpers().trustedClientIp({
342
+ trustedProxies: mwOpts.trustedProxies,
343
+ forwardedHeaders: mwOpts.forwardedHeaders,
344
+ clientIpResolver: mwOpts.clientIpResolver,
345
+ });
321
346
  var self = this;
322
347
  return function flagMiddleware(req, res, next) {
323
348
  var reqCtx = contextMod.fromRequest(req, {
324
- userKey: mwOpts.userKey,
349
+ userKey: mwOpts.userKey,
350
+ clientIpResolver: trustedIp.resolve,
325
351
  });
326
352
  req.flag = {
327
353
  getBoolean: function (k, def) { return self.getBoolean(k, reqCtx, def); },
@@ -357,13 +357,22 @@ function _qd(dialect) {
357
357
 
358
358
  function _buildCreate(name, dialect, columns) {
359
359
  var qd = _qd(dialect);
360
+ // Quoted the way `b.db.from()` quotes: a name in identifier POSITION is safe
361
+ // once quoted, keyword or not, so a column called `order` is a name rather
362
+ // than a refusal. These names are the framework's own literals and none of
363
+ // them is a keyword today — the point is that every identifier the framework
364
+ // quotes answers to one rule, so a path cannot end up stricter than the query
365
+ // builder without anybody noticing. `allowReserved` still enforces the SHAPE
366
+ // of an identifier: a quote, a semicolon or a null byte is refused either way.
360
367
  var parts = columns.map(function (c) {
361
368
  if (c.raw) return " " + c.raw;
362
369
  if (c.pk) {
363
370
  return " PRIMARY KEY (" +
364
- c.pk.map(function (k) { return safeSql.quoteIdentifier(k, qd); }).join(", ") + ")";
371
+ c.pk.map(function (k) {
372
+ return safeSql.quoteIdentifier(k, qd, { allowReserved: true });
373
+ }).join(", ") + ")";
365
374
  }
366
- return " " + safeSql.quoteIdentifier(c.col, qd) + " " + c.def;
375
+ return " " + safeSql.quoteIdentifier(c.col, qd, { allowReserved: true }) + " " + c.def;
367
376
  });
368
377
  return "CREATE TABLE IF NOT EXISTS " + name + " (" + parts.join(",") + ")";
369
378
  }
@@ -398,7 +407,9 @@ function _buildIndexes(name, dialect, indexes) {
398
407
  return (indexes || []).map(function (ix) {
399
408
  var idxName = _capIndexName("idx_" + name + "_" + ix.suffix);
400
409
  return (ix.unique ? createUnique : createIndex) + idxName + " ON " + name +
401
- " (" + ix.cols.map(function (col) { return safeSql.quoteIdentifier(col, qd); }).join(", ") + ")";
410
+ " (" + ix.cols.map(function (col) {
411
+ return safeSql.quoteIdentifier(col, qd, { allowReserved: true });
412
+ }).join(", ") + ")";
402
413
  });
403
414
  }
404
415