@dbsp/core 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4872,6 +4872,12 @@ declare class UpsertBuilder<T = void> extends MutationBuilderBase<T, UpsertInten
4872
4872
  * const users = await orm.nql<{ name: string; email: string }>`users | select name, email`.all();
4873
4873
  * ```
4874
4874
  *
4875
+ * Each `${value}` interpolation is escaped into a safe NQL literal (string/number/boolean/null).
4876
+ * Untrusted string input cannot inject NQL structure because it is always quoted and
4877
+ * single-quotes inside are doubled (`''`). For dynamic structural fragments (table names,
4878
+ * column names, ORDER BY direction) use the builder API (`orm.select()`). See #134 for
4879
+ * upcoming `:param` binding and a `nqlRaw()` escape hatch.
4880
+ *
4875
4881
  * @module nql
4876
4882
  * @since DX-040
4877
4883
  */
@@ -4905,6 +4911,13 @@ type NqlTag = <T>(strings: TemplateStringsArray, ...values: unknown[]) => NqlBui
4905
4911
  /**
4906
4912
  * Create an NQL template tag function.
4907
4913
  *
4914
+ * Each `${value}` in the template is escaped into a safe NQL literal before parsing.
4915
+ * Supported interpolation types: `string`, `number`, `boolean`, `null`.
4916
+ * Untrusted string input is therefore safe from NQL-syntax injection — it is always
4917
+ * wrapped in single-quotes with embedded quotes doubled (`''`).
4918
+ * For dynamic structural fragments (table names, column names, ORDER BY direction)
4919
+ * use the builder API (`orm.select()`). See issue #134 for upcoming `:param` binding.
4920
+ *
4908
4921
  * @param schemaDefinition - Schema definition for validation
4909
4922
  * @param model - ModelIR for plan execution
4910
4923
  * @param adapter - Optional adapter for query execution
package/dist/index.js CHANGED
@@ -5992,11 +5992,49 @@ function negotiateFeatures(model, capabilities, behavior = "warning", checkers =
5992
5992
 
5993
5993
  // src/dx/nql.ts
5994
5994
  import { compile as nqlCompile } from "@dbsp/nql";
5995
+ function toNqlLiteral(value, index) {
5996
+ if (value === null) {
5997
+ return "null";
5998
+ }
5999
+ switch (typeof value) {
6000
+ case "boolean":
6001
+ return value ? "true" : "false";
6002
+ case "number": {
6003
+ if (!Number.isFinite(value)) {
6004
+ throw new Error(
6005
+ `nql\`...\`: cannot interpolate non-finite number (${value}) at position ${index}. Only finite numbers are supported. For dynamic NQL structure use the builder API (orm.select()). See issue #134.`
6006
+ );
6007
+ }
6008
+ const s = value < 0 ? `-${Math.abs(value)}` : String(value);
6009
+ if (/[eE]/.test(s)) {
6010
+ throw new Error(
6011
+ `nql\`...\`: number ${value} at position ${index} has no exact NQL numeric literal form (exponential notation). Convert it yourself or use the builder API (orm.select()). See issue #134.`
6012
+ );
6013
+ }
6014
+ return s;
6015
+ }
6016
+ case "string": {
6017
+ if (value.includes("\n") || value.includes("\r")) {
6018
+ throw new Error(
6019
+ `nql\`...\`: cannot interpolate a string containing a newline at position ${index}. NQL string literals do not support raw newline characters. For dynamic NQL structure use the builder API (orm.select()). See issue #134.`
6020
+ );
6021
+ }
6022
+ const escaped = value.replaceAll("'", "''");
6023
+ return `'${escaped}'`;
6024
+ }
6025
+ default: {
6026
+ const typeName = value === void 0 ? "undefined" : typeof value;
6027
+ throw new Error(
6028
+ `nql\`...\`: cannot interpolate value of type "${typeName}" at position ${index}. Only string, number, boolean, and null are supported; for dynamic NQL fragments use the builder API (orm.select()). See issue #134.`
6029
+ );
6030
+ }
6031
+ }
6032
+ }
5995
6033
  function createNqlTag(schemaDefinition, model, adapter, schemaName) {
5996
6034
  return function nql(strings, ...values) {
5997
6035
  let query = strings[0] ?? "";
5998
6036
  for (let i = 0; i < values.length; i++) {
5999
- query += String(values[i]) + (strings[i + 1] ?? "");
6037
+ query += toNqlLiteral(values[i], i) + (strings[i + 1] ?? "");
6000
6038
  }
6001
6039
  return new NqlBuilderImpl(
6002
6040
  query,