sfobjects-basic-client 1.1.10 → 1.2.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
@@ -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> = {
@@ -203,11 +214,22 @@ export declare class SfBasicClientReadError extends Error {
203
214
  export declare function isPlainObject(value: unknown): value is Record<string, any>;
204
215
  export declare function constructSoql<OI>(_cfg: SfObjCfgIndex<OI>): (objName: string, from: string, select: (string | {})[], where?: string | Record<string, any>, orderBy?: Record<string, any>, limit?: number) => string;
205
216
  export declare function getSfObject<OI>(_cfg: SfObjCfgIndex<OI>, o?: SfClientOptions): <N extends KeyOf<OI>>(from: N, _conn: ISfConnection) => SfObjActions<OI, N>;
206
- export declare const getSfObjects: <OI>(cfg: SfObjCfgIndex<OI>) => (conn: ISfConnection, options?: SfClientOptions) => { [N in KeyOf<OI>]: SfObjActions<OI, N>; } & {
207
- __getObject: <N_1 extends KeyOf<OI>>(from: N_1) => SfObjActions<OI, N_1>;
217
+ export type SfObjectsIndex<OI> = {
218
+ [N in KeyOf<OI>]: SfObjActions<OI, N>;
219
+ } & {
220
+ __getObject: <N extends KeyOf<OI>>(from: N) => SfObjActions<OI, N>;
221
+ };
222
+ export type SfObjectFlat<O> = {
223
+ [K in KeyOf<O>]: NonNullable<O[K]> extends SfPrimitiveType ? O[K] : NonNullable<O[K]> extends ChildTable<infer CO> ? SfObjectFlat<CO> : SfObjectFlat<NonNullable<O[K]>>;
208
224
  };
225
+ export declare const getSfObjects: <OI>(cfg: SfObjCfgIndex<OI>) => (conn: ISfConnection, options?: SfClientOptions) => SfObjectsIndex<OI>;
209
226
  export declare const sfObject: <OI, N extends KeyOf<OI>>(cfg: SfObjCfgIndex<OI>, n: N) => {
210
227
  info: SfObjCfgIndex<OI>[N];
211
228
  select: <S extends SfRootSelect<OI, N>>(s: S[]) => S[];
229
+ wrapSelection: <S extends SfRootSelect<OI, N>>(value: S[]) => {
230
+ value: S[];
231
+ asProjection: (v: any) => SfRootSelectProjection<OI, N, S>;
232
+ asFlatProjection: (v: any) => SfObjectFlat<SfRootSelectProjection<OI, N, S>>;
233
+ };
212
234
  };
213
235
  export {};
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)
@@ -301,5 +315,13 @@ const getSfObjects = (cfg) => (conn, options) => {
301
315
  return Object.assign(Object.assign({}, Object.keys(cfg).reduce((p, n) => (Object.assign(Object.assign({}, p), { [n]: __getObject(n) })), {})), { __getObject });
302
316
  };
303
317
  exports.getSfObjects = getSfObjects;
304
- const sfObject = (cfg, n) => ({ info: cfg[n], select: (s) => s });
318
+ const sfObject = (cfg, n) => ({
319
+ info: cfg[n],
320
+ select: (s) => s,
321
+ wrapSelection: (value) => ({
322
+ value,
323
+ asProjection: (v) => v,
324
+ asFlatProjection: (v) => v
325
+ })
326
+ });
305
327
  exports.sfObject = sfObject;
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
- {
2
- "name": "sfobjects-basic-client",
3
- "version": "1.1.10",
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.2",
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
 
@@ -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;
494
519
 
495
- if ((isPlural ?? false) === Array.isArray(value)) {
520
+ if (isSemiJoin && isPlainObject(value)) {
521
+ return [
522
+ keyWithPrefix,
523
+ `${isNot ? 'not ' : ''}${soqlOp}`,
524
+ _constructSemiJoinStatement(value)
525
+ ]
526
+ .join(' ');
527
+ }
528
+
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)
@@ -671,8 +705,16 @@ export function getSfObject<OI>(_cfg: SfObjCfgIndex<OI>, o?: SfClientOptions) {
671
705
 
672
706
  }
673
707
 
708
+ export type SfObjectsIndex<OI> = { [N in KeyOf<OI>]: SfObjActions<OI, N> } & { __getObject: <N extends KeyOf<OI>>(from: N) => SfObjActions<OI, N> };
709
+
710
+ export type SfObjectFlat<O> = {
711
+ [K in KeyOf<O>]:
712
+ NonNullable<O[K]> extends SfPrimitiveType ? O[K] :
713
+ NonNullable<O[K]> extends ChildTable<infer CO> ? SfObjectFlat<CO> :
714
+ SfObjectFlat<NonNullable<O[K]>>
715
+ }
674
716
 
675
- export const getSfObjects = <OI>(cfg: SfObjCfgIndex<OI>) => (conn: ISfConnection, options?: SfClientOptions) => {
717
+ export const getSfObjects = <OI>(cfg: SfObjCfgIndex<OI>) => (conn: ISfConnection, options?: SfClientOptions): SfObjectsIndex<OI> => {
676
718
 
677
719
  const __getObject = <N extends KeyOf<OI>>(from: N) => getSfObject<OI>(cfg, options)(from, conn);
678
720
 
@@ -682,4 +724,12 @@ export const getSfObjects = <OI>(cfg: SfObjCfgIndex<OI>) => (conn: ISfConnection
682
724
  };
683
725
  }
684
726
 
685
- export const sfObject = <OI, N extends KeyOf<OI>>(cfg: SfObjCfgIndex<OI>, n: N) => ({ info: cfg[n], select: <S extends SfRootSelect<OI, N>>(s: S[]) => s });
727
+ export const sfObject = <OI, N extends KeyOf<OI>>(cfg: SfObjCfgIndex<OI>, n: N) => ({
728
+ info: cfg[n],
729
+ select: <S extends SfRootSelect<OI, N>>(s: S[]) => s,
730
+ wrapSelection: <S extends SfRootSelect<OI, N>>(value: S[]) => ({
731
+ value,
732
+ asProjection: (v: any) => v as SfRootSelectProjection<OI, N, S>,
733
+ asFlatProjection: (v: any) => v as SfObjectFlat<SfRootSelectProjection<OI, N, S>>
734
+ })
735
+ });