sfobjects-basic-client 1.1.9 → 1.2.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/dist/index.d.ts CHANGED
@@ -34,10 +34,10 @@ export type SfProjection<OO, O extends OO, S> = {
34
34
  } ? (NonNullable<O[K]> extends OO ? SfProjection<OO, NonNullable<O[K]>, S['select'][0]> : (NonNullable<O[K]> extends ChildTable<OO> ? Readonly<ChildTable<SfProjection<OO, NonNullable<O[K]>['records'][0], S['select'][0]>>> : never)) : never));
35
35
  };
36
36
  declare const SINGULAR_OP_KEYS: readonly ["eq", "equals", "=", "==", "ne", "!=", "<>", "lt", "<", "less than", "gt", ">", "greater than", "lte", "<=", "less than or equal", "gte", ">=", "greater than or equal", "like", "nlike", "not like"];
37
- declare const PLURAL_OP_KEYS: readonly ["in", "nin", "not in"];
37
+ declare const PLURAL_OR_SJ_OP_KEYS: readonly ["in", "nin", "not in"];
38
38
  declare const LOGICAL_OP_KEYS: readonly ["__and", "__or", "__not"];
39
39
  type SfSingularOpKeys = typeof SINGULAR_OP_KEYS[number];
40
- type SfPluralOpKeys = typeof PLURAL_OP_KEYS[number];
40
+ type SfPluralOpKeys = typeof PLURAL_OR_SJ_OP_KEYS[number];
41
41
  type SfLogicalOpKeys = typeof LOGICAL_OP_KEYS[number];
42
42
  type SfValueOpKeys = SfSingularOpKeys | SfPluralOpKeys;
43
43
  interface SfWhereOp<OP extends SfValueOpKeys, V> {
@@ -47,15 +47,26 @@ interface SfWhereOp<OP extends SfValueOpKeys, V> {
47
47
  type ParentOrPrimitiveProps<OO, O extends OO> = {
48
48
  [K in KeyOf<O>]: NonNullable<O[K]> extends SfPrimitiveType ? K : NonNullable<O[K]> extends OO ? K : never;
49
49
  }[KeyOf<O>];
50
- type SfWhere<OO, O extends OO> = {
50
+ type SfWhere<OO, O extends OO, OI = never> = {
51
51
  [K in ParentOrPrimitiveProps<OO, O>]+?: (NonNullable<O[K]> extends SfPrimitiveType ? (O[K] | O[K][] | {
52
52
  [OPK in SfSingularOpKeys]: SfWhereOp<OPK, O[K]>;
53
53
  }[SfSingularOpKeys] | {
54
- [OPK in SfPluralOpKeys]: SfWhereOp<OPK, O[K][]>;
54
+ [OPK in SfPluralOpKeys]: SfWhereOp<OPK, O[K][] | (OI extends never ? never : SfWhereSemiJoinOps<OI>)>;
55
55
  }[SfPluralOpKeys]) : (NonNullable<O[K]> extends OO ? SfWhere<OO, NonNullable<O[K]>> : never));
56
56
  } | {
57
57
  [K in SfLogicalOpKeys]+?: SfWhere<OO, O>;
58
58
  } | SfWhere<OO, O>[];
59
+ type SfWhereSemiJoinOpSelect<O> = {
60
+ [K in KeyOf<O>]: NonNullable<O[K]> extends string ? K : never;
61
+ }[KeyOf<O>];
62
+ interface SfWhereSemiJoinOp<OI, N extends KeyOf<OI>> {
63
+ from: N;
64
+ select: SfWhereSemiJoinOpSelect<OI[N]>;
65
+ where?: SfWhere<GetObjectTypes<OI>, OI[N]>;
66
+ }
67
+ type SfWhereSemiJoinOps<OI> = {
68
+ [N in KeyOf<OI>]: SfWhereSemiJoinOp<OI, N>;
69
+ }[KeyOf<OI>];
59
70
  type SfOrderType = 'asc' | 'desc';
60
71
  type SfOrderBy<OO, O extends OO> = {
61
72
  [K in ParentOrPrimitiveProps<OO, O>]+?: NonNullable<O[K]> extends SfPrimitiveType ? SfOrderType : (NonNullable<O[K]> extends OO ? SfOrderBy<OO, NonNullable<O[K]>> : never);
@@ -82,7 +93,7 @@ type UpdateableProps<O> = {
82
93
  }, K>) : never;
83
94
  }[KeyOf<O>];
84
95
  export type SfRootSelect<OI, N extends KeyOf<OI>> = SfSelect<GetObjectTypes<OI>, OI[N]>;
85
- export type SfRootWhere<OI, N extends KeyOf<OI>> = SfWhere<GetObjectTypes<OI>, OI[N]>;
96
+ export type SfRootWhere<OI, N extends KeyOf<OI>> = SfWhere<GetObjectTypes<OI>, OI[N], OI>;
86
97
  export type SfRootOrderBy<OI, N extends KeyOf<OI>> = SfOrderBy<GetObjectTypes<OI>, OI[N]>;
87
98
  export type SfRootSelectProjection<OI, N extends KeyOf<OI>, S extends SfRootSelect<OI, N>> = SfProjection<GetObjectTypes<OI>, OI[N], S>;
88
99
  export type SfCreate<O> = {
@@ -172,7 +183,7 @@ export interface SfOrderByAction<OI, N extends KeyOf<OI>, S extends SfRootSelect
172
183
  orderBy: <R extends SfRootOrderBy<OI, N>>(orderBy: R) => (SfQueryActions<OI, N, S> & SfLimitAction<OI, N, S>);
173
184
  }
174
185
  export interface SfWhereActions<OI, N extends KeyOf<OI>, S extends SfRootSelect<OI, N>> {
175
- where: <W extends SfRootWhere<OI, N>>(where: W) => (SfQueryActions<OI, N, S> & SfOrderByAction<OI, N, S>);
186
+ where: <W extends SfRootWhere<OI, N>>(where: W) => (SfQueryActions<OI, N, S> & SfOrderByAction<OI, N, S> & SfLimitAction<OI, N, S>);
176
187
  }
177
188
  export interface SfQueryAditionalActions<OI, N extends KeyOf<OI>, S extends SfRootSelect<OI, N>> {
178
189
  find: (id: string, options?: SfQueryOptions) => Promise<SfRootSelectProjection<OI, N, S> | undefined>;
package/dist/index.js CHANGED
@@ -49,7 +49,7 @@ const SINGULAR_OP_KEYS = [
49
49
  ...OP_KEYS_LIKE,
50
50
  ...OP_KEYS_NLIKE
51
51
  ];
52
- const PLURAL_OP_KEYS = [
52
+ const PLURAL_OR_SJ_OP_KEYS = [
53
53
  ...OP_KEYS_IN,
54
54
  ...OP_KEYS_NIN
55
55
  ];
@@ -65,10 +65,10 @@ const OP_RULES = [
65
65
  { ops: OP_KEYS_LTE, soqlOp: '<=' },
66
66
  { ops: OP_KEYS_GT, soqlOp: '>' },
67
67
  { ops: OP_KEYS_GTE, soqlOp: '>=' },
68
- { ops: OP_KEYS_IN, soqlOp: 'in', isPlural: true },
69
- { ops: OP_KEYS_NIN, soqlOp: 'in', isNot: true, isPlural: true },
68
+ { ops: OP_KEYS_IN, soqlOp: 'in', isPlural: true, isSemiJoin: true },
69
+ { ops: OP_KEYS_NIN, soqlOp: 'in', isNot: true, isPlural: true, isSemiJoin: true },
70
70
  { ops: OP_KEYS_LIKE, soqlOp: 'like' },
71
- { ops: OP_KEYS_NLIKE, soqlOp: 'like', isNot: true },
71
+ { ops: OP_KEYS_NLIKE, soqlOp: 'like', isNot: true }
72
72
  ];
73
73
  class SfBasicClientSaveError extends Error {
74
74
  constructor(errors) {
@@ -177,6 +177,12 @@ function constructSoql(_cfg) {
177
177
  .filter(Boolean)
178
178
  .join(', ');
179
179
  }
180
+ function _constructSemiJoinStatement(sj) {
181
+ const { from, select, where } = sj;
182
+ if (typeof from === 'string' && typeof select === 'string' && from && select) {
183
+ return `(${_constructFullQuery(from, from, [select], where)})`;
184
+ }
185
+ }
180
186
  function _constructWhereStatement(objName, where, o) {
181
187
  if (typeof where === 'string') {
182
188
  return where;
@@ -199,13 +205,21 @@ function constructSoql(_cfg) {
199
205
  if (op !== undefined && value !== undefined) {
200
206
  const opRule = OP_RULES.find(r => r.ops.some(rop => (rop === op)));
201
207
  if (opRule) {
202
- const { soqlOp, isNot, isPlural } = opRule;
203
- if ((isPlural !== null && isPlural !== void 0 ? isPlural : false) === Array.isArray(value)) {
208
+ const { soqlOp, isNot, isPlural, isSemiJoin } = opRule;
209
+ if (isSemiJoin && isPlainObject(value)) {
210
+ return [
211
+ keyWithPrefix,
212
+ `${isNot ? 'not ' : ''}${soqlOp}`,
213
+ _constructSemiJoinStatement(value)
214
+ ]
215
+ .join(' ');
216
+ }
217
+ else if ((isPlural !== null && isPlural !== void 0 ? isPlural : false) === Array.isArray(value)) {
204
218
  return [
205
219
  isNot ? 'not (' : '',
206
220
  keyWithPrefix,
207
221
  soqlOp,
208
- Array.isArray(value) ? `( ${value.map(v => _escapeVal(objName, propName, v)).join(',')} )` : _escapeVal(objName, propName, value),
222
+ Array.isArray(value) ? `( ${value.map(v => _escapeVal(objName, propName, v)).join(', ')} )` : _escapeVal(objName, propName, value),
209
223
  isNot ? ')' : '',
210
224
  ]
211
225
  .filter(Boolean)
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "name": "sfobjects-basic-client",
3
- "version": "1.1.9",
4
- "description": "Basic Salesforce Client to use together with sfobjects-to-typescript lib",
5
- "license": "ISC",
6
- "author": "Murad Aliyev",
7
- "main": "dist/index.js",
8
- "repository": {
9
- "type": "git",
10
- "url": "https://github.com/muradaliyev/sfobjects-basic-client"
11
- },
12
- "scripts": {
13
- "build": "npm run clean && tsc",
14
- "clean": "rimraf dist"
15
- },
16
- "devDependencies": {
17
- "@types/node": "^25.9.4",
18
- "rimraf": "^6.1.2",
19
- "typescript": "^5.9.3"
20
- }
21
- }
1
+ {
2
+ "name": "sfobjects-basic-client",
3
+ "version": "1.2.0",
4
+ "description": "Basic Salesforce Client to use together with sfobjects-to-typescript lib",
5
+ "license": "ISC",
6
+ "author": "Murad Aliyev",
7
+ "main": "dist/index.js",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/muradaliyev/sfobjects-basic-client"
11
+ },
12
+ "scripts": {
13
+ "build": "npm run clean && tsc",
14
+ "clean": "rimraf dist"
15
+ },
16
+ "devDependencies": {
17
+ "@types/node": "^25.9.4",
18
+ "rimraf": "^6.1.2",
19
+ "typescript": "^5.9.3"
20
+ }
21
+ }
package/src/index.ts CHANGED
@@ -67,7 +67,7 @@ const SINGULAR_OP_KEYS = [
67
67
  ...OP_KEYS_NLIKE
68
68
  ] as const;
69
69
 
70
- const PLURAL_OP_KEYS = [
70
+ const PLURAL_OR_SJ_OP_KEYS = [
71
71
  ...OP_KEYS_IN,
72
72
  ...OP_KEYS_NIN
73
73
  ] as const;
@@ -78,15 +78,18 @@ const LOGICAL_OP_KEYS = [
78
78
  OP_KEY_NOT
79
79
  ] as const;
80
80
 
81
+
81
82
  type SfSingularOpKeys = typeof SINGULAR_OP_KEYS[number];
82
- type SfPluralOpKeys = typeof PLURAL_OP_KEYS[number];
83
+ type SfPluralOpKeys = typeof PLURAL_OR_SJ_OP_KEYS[number];
83
84
  type SfLogicalOpKeys = typeof LOGICAL_OP_KEYS[number];
85
+
84
86
  type SfValueOpKeys = SfSingularOpKeys | SfPluralOpKeys;
85
87
 
86
88
  interface SfOpRule {
87
89
  ops: readonly SfValueOpKeys[];
88
90
  isNot?: boolean;
89
91
  isPlural?: boolean;
92
+ isSemiJoin?: boolean;
90
93
  soqlOp: string;
91
94
  }
92
95
 
@@ -97,20 +100,23 @@ const OP_RULES: SfOpRule[] = [
97
100
  { ops: OP_KEYS_LTE, soqlOp: '<=' },
98
101
  { ops: OP_KEYS_GT, soqlOp: '>' },
99
102
  { ops: OP_KEYS_GTE, soqlOp: '>=' },
100
- { ops: OP_KEYS_IN, soqlOp: 'in', isPlural: true },
101
- { ops: OP_KEYS_NIN, soqlOp: 'in', isNot: true, isPlural: true },
103
+ { ops: OP_KEYS_IN, soqlOp: 'in', isPlural: true, isSemiJoin: true },
104
+ { ops: OP_KEYS_NIN, soqlOp: 'in', isNot: true, isPlural: true, isSemiJoin: true },
102
105
  { ops: OP_KEYS_LIKE, soqlOp: 'like' },
103
- { ops: OP_KEYS_NLIKE, soqlOp: 'like', isNot: true },
106
+ { ops: OP_KEYS_NLIKE, soqlOp: 'like', isNot: true }
104
107
  ]
105
108
 
106
109
  interface SfWhereOp<OP extends SfValueOpKeys, V> { op: OP; value: V; }
107
110
 
108
111
  type ParentOrPrimitiveProps<OO, O extends OO> = { [K in KeyOf<O>]: NonNullable<O[K]> extends SfPrimitiveType ? K : NonNullable<O[K]> extends OO ? K : never }[KeyOf<O>];
109
112
 
110
- type SfWhere<OO, O extends OO> = {
113
+ type SfWhere<OO, O extends OO, OI = never> = {
111
114
  [K in ParentOrPrimitiveProps<OO, O>]+?: (
112
115
  NonNullable<O[K]> extends SfPrimitiveType ? (
113
- O[K] | O[K][] | { [OPK in SfSingularOpKeys]: SfWhereOp<OPK, O[K]> }[SfSingularOpKeys] | { [OPK in SfPluralOpKeys]: SfWhereOp<OPK, O[K][]> }[SfPluralOpKeys]
116
+ O[K] |
117
+ O[K][] |
118
+ { [OPK in SfSingularOpKeys]: SfWhereOp<OPK, O[K]> }[SfSingularOpKeys] |
119
+ { [OPK in SfPluralOpKeys]: SfWhereOp<OPK, O[K][] | (OI extends never ? never : SfWhereSemiJoinOps<OI>)> }[SfPluralOpKeys]
114
120
  ) : (
115
121
  NonNullable<O[K]> extends OO ? SfWhere<OO, NonNullable<O[K]>> : never
116
122
  )
@@ -118,6 +124,15 @@ type SfWhere<OO, O extends OO> = {
118
124
  } | { [K in SfLogicalOpKeys]+?: SfWhere<OO, O> } | SfWhere<OO, O>[];
119
125
 
120
126
 
127
+ type SfWhereSemiJoinOpSelect<O> = { [K in KeyOf<O>]: NonNullable<O[K]> extends string ? K : never }[KeyOf<O>]
128
+
129
+ interface SfWhereSemiJoinOp<OI, N extends KeyOf<OI>> {
130
+ from: N;
131
+ select: SfWhereSemiJoinOpSelect<OI[N]>;
132
+ where?: SfWhere<GetObjectTypes<OI>, OI[N]>;
133
+ }
134
+
135
+ type SfWhereSemiJoinOps<OI> = { [N in KeyOf<OI>]: SfWhereSemiJoinOp<OI, N> }[KeyOf<OI>];
121
136
 
122
137
  // order by
123
138
 
@@ -164,7 +179,7 @@ type UpdateableProps<O> = {
164
179
 
165
180
  export type SfRootSelect<OI, N extends KeyOf<OI>> = SfSelect<GetObjectTypes<OI>, OI[N]>;
166
181
 
167
- export type SfRootWhere<OI, N extends KeyOf<OI>> = SfWhere<GetObjectTypes<OI>, OI[N]>;
182
+ export type SfRootWhere<OI, N extends KeyOf<OI>> = SfWhere<GetObjectTypes<OI>, OI[N], OI>;// | SfWhereSemiJoin<OI, OI[N]>;
168
183
 
169
184
  export type SfRootOrderBy<OI, N extends KeyOf<OI>> = SfOrderBy<GetObjectTypes<OI>, OI[N]>;
170
185
 
@@ -274,7 +289,7 @@ export interface SfOrderByAction<OI, N extends KeyOf<OI>, S extends SfRootSelect
274
289
  }
275
290
 
276
291
  export interface SfWhereActions<OI, N extends KeyOf<OI>, S extends SfRootSelect<OI, N>> {
277
- where: <W extends SfRootWhere<OI, N>>(where: W) => (SfQueryActions<OI, N, S> & SfOrderByAction<OI, N, S>);
292
+ where: <W extends SfRootWhere<OI, N>>(where: W) => (SfQueryActions<OI, N, S> & SfOrderByAction<OI, N, S> & SfLimitAction<OI, N, S>);
278
293
  }
279
294
 
280
295
  export interface SfQueryAditionalActions<OI, N extends KeyOf<OI>, S extends SfRootSelect<OI, N>> {
@@ -357,9 +372,9 @@ export function constructSoql<OI>(_cfg: SfObjCfgIndex<OI>) {
357
372
  }
358
373
 
359
374
  throw `Unupported value type for where statement`;
360
-
361
375
  }
362
376
 
377
+
363
378
  function _constructFullQuery(
364
379
  objName: string,
365
380
  from: string,
@@ -448,6 +463,16 @@ export function constructSoql<OI>(_cfg: SfObjCfgIndex<OI>) {
448
463
  .join(', ');
449
464
  }
450
465
 
466
+ function _constructSemiJoinStatement(sj: Record<string, any>) {
467
+
468
+ const { from, select, where } = sj;
469
+
470
+ if (typeof from === 'string' && typeof select === 'string' && from && select) {
471
+ return `(${_constructFullQuery(from, from, [select], where)})`;
472
+ }
473
+ }
474
+
475
+
451
476
  function _constructWhereStatement(
452
477
  objName: string,
453
478
  where: string | Record<string, any>,
@@ -490,15 +515,24 @@ export function constructSoql<OI>(_cfg: SfObjCfgIndex<OI>) {
490
515
 
491
516
  if (opRule) {
492
517
 
493
- const { soqlOp, isNot, isPlural } = opRule;
518
+ const { soqlOp, isNot, isPlural, isSemiJoin } = opRule;
519
+
520
+ if (isSemiJoin && isPlainObject(value)) {
521
+ return [
522
+ keyWithPrefix,
523
+ `${isNot ? 'not ' : ''}${soqlOp}`,
524
+ _constructSemiJoinStatement(value)
525
+ ]
526
+ .join(' ');
527
+ }
494
528
 
495
- if ((isPlural ?? false) === Array.isArray(value)) {
529
+ else if ((isPlural ?? false) === Array.isArray(value)) {
496
530
 
497
531
  return [
498
532
  isNot ? 'not (' : '',
499
533
  keyWithPrefix,
500
534
  soqlOp,
501
- Array.isArray(value) ? `( ${value.map(v => _escapeVal(objName, propName, v)).join(',')} )` : _escapeVal(objName, propName, value),
535
+ Array.isArray(value) ? `( ${value.map(v => _escapeVal(objName, propName, v)).join(', ')} )` : _escapeVal(objName, propName, value),
502
536
  isNot ? ')' : '',
503
537
  ]
504
538
  .filter(Boolean)