@snowtop/ent 0.0.22 → 0.0.28-alpha

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.
@@ -16,16 +16,34 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
16
16
  this.id = options.src;
17
17
  }
18
18
  }
19
+ async idVisible() {
20
+ const ids = await this.genIDInfosToFetch();
21
+ if (ids.length !== 1) {
22
+ throw new Error("invalid number of IDInfo");
23
+ }
24
+ return !ids[0].invalidated;
25
+ }
19
26
  async queryRawCount() {
27
+ const idVisible = await this.idVisible();
28
+ if (!idVisible) {
29
+ return 0;
30
+ }
20
31
  return await this.options.countLoaderFactory
21
32
  .createLoader(this.viewer.context)
22
33
  .load(this.id);
23
34
  }
24
35
  async queryAllRawCount() {
25
- const count = await this.queryRawCount();
36
+ let count = 0;
37
+ const idVisible = await this.idVisible();
38
+ if (idVisible) {
39
+ count = await this.queryRawCount();
40
+ }
26
41
  return new Map([[this.id, count]]);
27
42
  }
28
- async loadRawData(options) {
43
+ async loadRawIDs(addID) {
44
+ addID(this.options.src);
45
+ }
46
+ async loadRawData(infos, options) {
29
47
  const loader = this.options.dataLoaderFactory.createConfigurableLoader(options, this.viewer.context);
30
48
  if (!options.orderby) {
31
49
  options.orderby = `${this.options.sortColumn} DESC`;
@@ -33,6 +51,14 @@ class CustomEdgeQueryBase extends query_1.BaseEdgeQuery {
33
51
  if (!options.limit) {
34
52
  options.limit = ent_1.DefaultLimit;
35
53
  }
54
+ if (infos.length !== 1) {
55
+ throw new Error(`expected 1 info passed to loadRawData. ${infos.length} passed`);
56
+ }
57
+ const info = infos[0];
58
+ if (info.invalidated) {
59
+ this.edges.set(this.id, []);
60
+ return;
61
+ }
36
62
  const rows = await loader.load(this.id);
37
63
  this.edges.set(this.id, rows);
38
64
  }
@@ -1,4 +1,4 @@
1
- import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data } from "../base";
1
+ import { ID, Ent, Viewer, EdgeQueryableDataOptions, Data, PrivacyPolicy } from "../base";
2
2
  export interface EdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> {
3
3
  queryEdges(): Promise<TEdge[]>;
4
4
  queryAllEdges(): Promise<Map<ID, TEdge[]>>;
@@ -15,6 +15,8 @@ export interface EdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends
15
15
  paginationInfo(): Map<ID, PaginationInfo>;
16
16
  getCursor(row: TEdge): string;
17
17
  dataToID(edge: TEdge): ID;
18
+ getPrivacyPolicy(): PrivacyPolicy;
19
+ sourceEnt(id: ID): Promise<Ent | null>;
18
20
  }
19
21
  export interface EdgeQueryFilter<T extends Data> {
20
22
  filter?(id: ID, edges: T[]): T[];
@@ -27,7 +29,7 @@ export interface PaginationInfo {
27
29
  startCursor: string;
28
30
  endCursor: string;
29
31
  }
30
- export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Data> {
32
+ export declare abstract class BaseEdgeQuery<TSource extends Ent, TDest extends Ent, TEdge extends Data> implements EdgeQuery<TSource, TDest, TEdge> {
31
33
  viewer: Viewer;
32
34
  private sortCol;
33
35
  private filters;
@@ -35,11 +37,18 @@ export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Dat
35
37
  protected edges: Map<ID, TEdge[]>;
36
38
  private pagination;
37
39
  private memoizedloadEdges;
40
+ protected genIDInfosToFetch: () => Promise<IDInfo[]>;
41
+ private idMap;
42
+ private idsToFetch;
38
43
  constructor(viewer: Viewer, sortCol: string);
44
+ getPrivacyPolicy(): PrivacyPolicy;
45
+ abstract sourceEnt(id: ID): Promise<Ent | null>;
39
46
  first(n: number, after?: string): this;
40
47
  last(n: number, before?: string): this;
41
48
  private querySingleEdge;
42
49
  readonly queryEdges: () => Promise<TEdge[]>;
50
+ abstract queryRawCount(): Promise<number>;
51
+ abstract queryAllRawCount(): Promise<Map<ID, number>>;
43
52
  readonly queryAllEdges: () => Promise<Map<ID, TEdge[]>>;
44
53
  abstract dataToID(edge: TEdge): ID;
45
54
  readonly queryIDs: () => Promise<ID[]>;
@@ -52,7 +61,14 @@ export declare abstract class BaseEdgeQuery<TDest extends Ent, TEdge extends Dat
52
61
  paginationInfo(): Map<ID, PaginationInfo>;
53
62
  private assertQueryDispatched;
54
63
  private assertQueryNotDispatched;
55
- protected abstract loadRawData(options: EdgeQueryableDataOptions): Promise<void>;
64
+ protected abstract loadRawIDs(addID: (src: ID | TSource) => void): Promise<void>;
65
+ protected abstract loadRawData(infos: IDInfo[], options: EdgeQueryableDataOptions): Promise<void>;
66
+ private addID;
67
+ protected genIDInfosToFetchImpl(): Promise<IDInfo[]>;
56
68
  private loadEdges;
57
69
  getCursor(row: TEdge): string;
58
70
  }
71
+ export interface IDInfo {
72
+ id: ID;
73
+ invalidated?: boolean;
74
+ }
@@ -26,6 +26,7 @@ exports.BaseEdgeQuery = void 0;
26
26
  const ent_1 = require("../ent");
27
27
  const clause = __importStar(require("../clause"));
28
28
  const memoizee_1 = __importDefault(require("memoizee"));
29
+ const privacy_1 = require("../privacy");
29
30
  // TODO can we generalize EdgeQuery to support any clause
30
31
  function assertPositive(n) {
31
32
  if (n < 0) {
@@ -173,6 +174,8 @@ class BaseEdgeQuery {
173
174
  this.filters = [];
174
175
  this.edges = new Map();
175
176
  this.pagination = new Map();
177
+ this.idMap = new Map();
178
+ this.idsToFetch = [];
176
179
  // this is basically just raw rows
177
180
  this.queryEdges = async () => {
178
181
  return await this.querySingleEdge("queryEdges");
@@ -224,6 +227,11 @@ class BaseEdgeQuery {
224
227
  return results;
225
228
  };
226
229
  this.memoizedloadEdges = (0, memoizee_1.default)(this.loadEdges.bind(this));
230
+ this.genIDInfosToFetch = (0, memoizee_1.default)(this.genIDInfosToFetchImpl.bind(this));
231
+ }
232
+ getPrivacyPolicy() {
233
+ // default PrivacyPolicy is always allow. nothing to do here
234
+ return privacy_1.AlwaysAllowPrivacyPolicy;
227
235
  }
228
236
  first(n, after) {
229
237
  this.assertQueryNotDispatched("first");
@@ -269,9 +277,23 @@ class BaseEdgeQuery {
269
277
  throw new Error(`cannot call ${str} after query is dispatched`);
270
278
  }
271
279
  }
280
+ addID(id) {
281
+ if (typeof id === "object") {
282
+ this.idMap.set(id.id, id);
283
+ this.idsToFetch.push(id.id);
284
+ }
285
+ else {
286
+ this.idsToFetch.push(id);
287
+ }
288
+ }
289
+ async genIDInfosToFetchImpl() {
290
+ await this.loadRawIDs(this.addID.bind(this));
291
+ return applyPrivacyPolicyForEdgeQ(this.viewer, this, this.idsToFetch, this.idMap);
292
+ }
272
293
  async loadEdges() {
273
- // if no filter, we add the firstN filter to ensure we get pagination info
294
+ const idsInfo = await this.genIDInfosToFetch();
274
295
  if (!this.filters.length) {
296
+ // if no filter, we add the firstN filter to ensure we get pagination info
275
297
  this.first(ent_1.DefaultLimit);
276
298
  }
277
299
  let options = {};
@@ -283,7 +305,7 @@ class BaseEdgeQuery {
283
305
  options = filter.query(options);
284
306
  }
285
307
  });
286
- await this.loadRawData(options);
308
+ await this.loadRawData(idsInfo, options);
287
309
  // no filters. nothing to do here.
288
310
  if (!this.filters.length) {
289
311
  return this.edges;
@@ -324,3 +346,18 @@ class BaseEdgeQuery {
324
346
  }
325
347
  }
326
348
  exports.BaseEdgeQuery = BaseEdgeQuery;
349
+ async function applyPrivacyPolicyForEdgeQ(viewer, edgeQ, ids, map) {
350
+ const result = [];
351
+ await Promise.all(ids.map(async (id) => {
352
+ let ent = map.get(id);
353
+ if (!ent) {
354
+ ent = await edgeQ.sourceEnt(id);
355
+ }
356
+ const r = await (0, privacy_1.applyPrivacyPolicy)(viewer, edgeQ.getPrivacyPolicy(), ent || undefined);
357
+ result.push({
358
+ id,
359
+ invalidated: !r,
360
+ });
361
+ }));
362
+ return result;
363
+ }
@@ -92,6 +92,8 @@ function assocTests() {
92
92
  expect(query.qs?.whereClause).toBe(`id1 = $1 AND edge_type = $2`);
93
93
  }
94
94
  }
95
+ // TODO need to test multi-ids with id1s that aren't visible...
96
+ // so 2 user's friend requests at the same time
95
97
  class MultiIDsTestQueryFilter {
96
98
  constructor(filter, ents, limit) {
97
99
  this.filter = filter;
@@ -565,5 +567,107 @@ function assocTests() {
565
567
  await filter.testEnts();
566
568
  });
567
569
  });
570
+ describe("privacy", () => {
571
+ let user;
572
+ let friendRequests;
573
+ let user2;
574
+ beforeEach(async () => {
575
+ [user, friendRequests] = await (0, test_helpers_1.createUserPlusFriendRequests)();
576
+ user2 = await (0, test_helpers_1.createTestUser)();
577
+ });
578
+ function getQuery(viewer) {
579
+ return index_1.UserToIncomingFriendRequestsQuery.query(viewer, user.id);
580
+ }
581
+ test("ids", async () => {
582
+ const ids = await getQuery(user2.viewer).queryIDs();
583
+ expect(ids.length).toBe(0);
584
+ const idsFromUser = await getQuery(user.viewer).queryIDs();
585
+ expect(idsFromUser.length).toBe(friendRequests.length);
586
+ });
587
+ test("count", async () => {
588
+ const count = await getQuery(user2.viewer).queryCount();
589
+ expect(count).toBe(0);
590
+ const countFromUser = await getQuery(user.viewer).queryCount();
591
+ expect(countFromUser).toBe(friendRequests.length);
592
+ });
593
+ test("rawCount", async () => {
594
+ const rawCount = await getQuery(user2.viewer).queryRawCount();
595
+ expect(rawCount).toBe(0);
596
+ const rawCountFromUser = await getQuery(user.viewer).queryRawCount();
597
+ expect(rawCountFromUser).toBe(friendRequests.length);
598
+ });
599
+ test("edges", async () => {
600
+ const edges = await getQuery(user2.viewer).queryEdges();
601
+ expect(edges.length).toBe(0);
602
+ const edgesFromUser = await getQuery(user.viewer).queryEdges();
603
+ expect(edgesFromUser.length).toBe(friendRequests.length);
604
+ });
605
+ test("ents", async () => {
606
+ const ents = await getQuery(user2.viewer).queryEnts();
607
+ expect(ents.length).toBe(0);
608
+ const entsFromUser = await getQuery(user.viewer).queryEnts();
609
+ expect(entsFromUser.length).toBe(0);
610
+ const entsFromUserVCToken = await getQuery(new index_1.ViewerWithAccessToken(user.id, {
611
+ tokens: {
612
+ allow_incoming_friend_request: true,
613
+ },
614
+ })).queryEnts();
615
+ expect(entsFromUserVCToken.length).toBe(friendRequests.length);
616
+ });
617
+ });
618
+ describe("multi-ids privacy", () => {
619
+ let user;
620
+ let friendRequests;
621
+ let user2;
622
+ let friendRequests2;
623
+ beforeEach(async () => {
624
+ [user, friendRequests] = await (0, test_helpers_1.createUserPlusFriendRequests)();
625
+ [user2, friendRequests2] = await (0, test_helpers_1.createUserPlusFriendRequests)();
626
+ });
627
+ function getQuery(viewer) {
628
+ return index_1.UserToIncomingFriendRequestsQuery.query(viewer || user.viewer, [
629
+ user.id,
630
+ user2.id,
631
+ ]);
632
+ }
633
+ test("ids", async () => {
634
+ const idsMap = await getQuery().queryAllIDs();
635
+ expect(idsMap.size).toBe(2);
636
+ expect(idsMap.get(user.id)?.length).toBe(friendRequests.length);
637
+ expect(idsMap.get(user2.id)?.length).toBe(0);
638
+ });
639
+ test("count", async () => {
640
+ const countMap = await getQuery().queryAllCount();
641
+ expect(countMap.size).toBe(2);
642
+ expect(countMap.get(user.id)).toBe(friendRequests.length);
643
+ expect(countMap.get(user2.id)).toBe(0);
644
+ });
645
+ test("count", async () => {
646
+ const countMap = await getQuery().queryAllRawCount();
647
+ expect(countMap.size).toBe(2);
648
+ expect(countMap.get(user.id)).toBe(friendRequests.length);
649
+ expect(countMap.get(user2.id)).toBe(0);
650
+ });
651
+ test("edges", async () => {
652
+ const edgesMap = await getQuery().queryAllEdges();
653
+ expect(edgesMap.size).toBe(2);
654
+ expect(edgesMap.get(user.id)?.length).toBe(friendRequests.length);
655
+ expect(edgesMap.get(user2.id)?.length).toBe(0);
656
+ });
657
+ test("ents", async () => {
658
+ const entsMap = await getQuery().queryAllEnts();
659
+ expect(entsMap.size).toBe(2);
660
+ expect(entsMap.get(user.id)?.length).toBe(0);
661
+ expect(entsMap.get(user2.id)?.length).toBe(0);
662
+ const entsMapFromUserVCToken = await getQuery(new index_1.ViewerWithAccessToken(user.id, {
663
+ tokens: {
664
+ allow_incoming_friend_request: true,
665
+ },
666
+ })).queryAllEnts();
667
+ expect(entsMapFromUserVCToken.size).toBe(2);
668
+ expect(entsMapFromUserVCToken.get(user.id)?.length).toBe(friendRequests.length);
669
+ expect(entsMapFromUserVCToken.get(user2.id)?.length).toBe(0);
670
+ });
671
+ });
568
672
  }
569
673
  exports.assocTests = assocTests;
package/core/viewer.js CHANGED
@@ -4,6 +4,7 @@ exports.IDViewer = exports.LoggedOutViewer = void 0;
4
4
  class LoggedOutViewer {
5
5
  constructor(context) {
6
6
  this.context = context;
7
+ this.viewerID = null;
7
8
  }
8
9
  async viewer() {
9
10
  return null;
@@ -10,7 +10,7 @@ interface classResult {
10
10
  class: classInfo;
11
11
  file: file;
12
12
  }
13
- export declare function parseCustomInput(filePath: string, opts?: Options): PathResult;
13
+ export declare function parseCustomImports(filePath: string, opts?: Options): PathResult;
14
14
  export declare function findTSConfigFile(filePath: string): string | null;
15
15
  export interface importInfo {
16
16
  name: string;
package/imports/index.js CHANGED
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.findTSConfigFile = exports.parseCustomInput = void 0;
25
+ exports.findTSConfigFile = exports.parseCustomImports = void 0;
26
26
  const glob_1 = __importDefault(require("glob"));
27
27
  const typescript_1 = __importDefault(require("typescript"));
28
28
  const json5_1 = __importDefault(require("json5"));
@@ -42,10 +42,9 @@ function getFiles(filePath, opts) {
42
42
  }
43
43
  return files;
44
44
  }
45
- function parseCustomInput(filePath, opts) {
45
+ function parseCustomImports(filePath, opts) {
46
46
  const files = getFiles(filePath, opts);
47
47
  const options = readCompilerOptions(filePath);
48
- // classMap
49
48
  let classMap = new Map();
50
49
  files.forEach((file) => {
51
50
  const sourceFile = typescript_1.default.createSourceFile(file, fs.readFileSync(file).toString(), options.target || typescript_1.default.ScriptTarget.ES2015);
@@ -77,7 +76,7 @@ function parseCustomInput(filePath, opts) {
77
76
  },
78
77
  };
79
78
  }
80
- exports.parseCustomInput = parseCustomInput;
79
+ exports.parseCustomImports = parseCustomImports;
81
80
  function findTSConfigFile(filePath) {
82
81
  while (filePath != "/") {
83
82
  let configPath = `${filePath}/tsconfig.json`;
@@ -95,7 +94,6 @@ function readCompilerOptions(filePath) {
95
94
  if (!configPath) {
96
95
  return {};
97
96
  }
98
- const root = path.join(filePath, "..");
99
97
  let json = {};
100
98
  try {
101
99
  json = json5_1.default.parse(fs.readFileSync(configPath, {
package/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { loadEnt, loadCustomData, loadCustomEnts, loadEntX, loadEnts, CustomQuer
3
3
  import DB from "./core/db";
4
4
  export * from "./core/loaders";
5
5
  export { DB };
6
- export { EntPrivacyError, AlwaysAllowRule, AlwaysDenyRule, DenyIfLoggedInRule, DenyIfLoggedOutRule, AllowIfHasIdentity, AllowIfViewerRule, AllowIfFuncRule, AllowIfViewerIsRule, AllowIfViewerEqualsRule, DenyIfViewerEqualsRule, AllowIfEdgeExistsRule, AllowIfViewerInboundEdgeExistsRule, AllowIfViewerOutboundEdgeExistsRule, DenyIfEdgeExistsRule, DenyIfViewerInboundEdgeExistsRule, DenyIfViewerOutboundEdgeExistsRule, DenyIfEdgeDoesNotExistRule, DenyIfViewerInboundEdgeDoesNotExistRule, DenyIfViewerOutboundEdgeDoesNotExistRule, AllowIfEntIsVisibleRule, AllowIfEntIsNotVisibleRule, DenyIfEntIsVisibleRule, DenyIfEntIsNotVisibleRule, AllowIfEntIsVisiblePolicy, DenyIfEntIsVisiblePolicy, DelayedResultRule, applyPrivacyPolicy, applyPrivacyPolicyX, AlwaysAllowPrivacyPolicy, AlwaysDenyPrivacyPolicy, AllowIfConditionAppliesRule, AllowIfSubPolicyAllowsRule, AllowIfViewerPrivacyPolicy, AllowIfViewerHasIdentityPrivacyPolicy, } from "./core/privacy";
6
+ export { EntPrivacyError, AlwaysAllowRule, AlwaysDenyRule, DenyIfLoggedInRule, DenyIfLoggedOutRule, AllowIfHasIdentity, AllowIfViewerRule, AllowIfFuncRule, AllowIfViewerIsRule, AllowIfViewerIsEntPropertyRule, AllowIfEntPropertyIsRule, DenyIfEntPropertyIsRule, AllowIfViewerEqualsRule, DenyIfViewerEqualsRule, AllowIfEdgeExistsRule, AllowIfViewerInboundEdgeExistsRule, AllowIfViewerOutboundEdgeExistsRule, DenyIfEdgeExistsRule, DenyIfViewerInboundEdgeExistsRule, DenyIfViewerOutboundEdgeExistsRule, DenyIfEdgeDoesNotExistRule, DenyIfViewerInboundEdgeDoesNotExistRule, DenyIfViewerOutboundEdgeDoesNotExistRule, AllowIfEntIsVisibleRule, AllowIfEntIsNotVisibleRule, DenyIfEntIsVisibleRule, DenyIfEntIsNotVisibleRule, AllowIfEntIsVisiblePolicy, DenyIfEntIsVisiblePolicy, DelayedResultRule, applyPrivacyPolicy, applyPrivacyPolicyX, AlwaysAllowPrivacyPolicy, AlwaysDenyPrivacyPolicy, AllowIfConditionAppliesRule, AllowIfSubPolicyAllowsRule, AllowIfViewerPrivacyPolicy, AllowIfViewerHasIdentityPrivacyPolicy, } from "./core/privacy";
7
7
  export * from "./core/query";
8
8
  export * from "./schema/";
9
9
  import * as q from "./core/clause";
package/index.js CHANGED
@@ -25,8 +25,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
25
25
  return (mod && mod.__esModule) ? mod : { "default": mod };
26
26
  };
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.AllowIfViewerIsRule = exports.AllowIfFuncRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedOutRule = exports.DenyIfLoggedInRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = exports.DB = exports.getEdgeTypeInGroup = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadEdges = exports.loadEdgeDatas = exports.loadEdgeData = exports.AssocEdgeData = exports.AssocEdge = exports.DeleteNodeOperation = exports.EdgeOperation = exports.EditNodeOperation = exports.loadRows = exports.loadRow = exports.loadRowX = exports.performRawQuery = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadEntXViaKey = exports.loadEntViaKey = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadEnts = exports.loadEntX = exports.loadCustomEnts = exports.loadCustomData = exports.loadEnt = void 0;
29
- exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = void 0;
28
+ exports.DenyIfViewerOutboundEdgeExistsRule = exports.DenyIfViewerInboundEdgeExistsRule = exports.DenyIfEdgeExistsRule = exports.AllowIfViewerOutboundEdgeExistsRule = exports.AllowIfViewerInboundEdgeExistsRule = exports.AllowIfEdgeExistsRule = exports.DenyIfViewerEqualsRule = exports.AllowIfViewerEqualsRule = exports.DenyIfEntPropertyIsRule = exports.AllowIfEntPropertyIsRule = exports.AllowIfViewerIsEntPropertyRule = exports.AllowIfViewerIsRule = exports.AllowIfFuncRule = exports.AllowIfViewerRule = exports.AllowIfHasIdentity = exports.DenyIfLoggedOutRule = exports.DenyIfLoggedInRule = exports.AlwaysDenyRule = exports.AlwaysAllowRule = exports.EntPrivacyError = exports.DB = exports.getEdgeTypeInGroup = exports.loadNodesByEdge = exports.loadEdgeForID2 = exports.loadRawEdgeCountX = exports.loadUniqueNode = exports.loadUniqueEdge = exports.loadEdges = exports.loadEdgeDatas = exports.loadEdgeData = exports.AssocEdgeData = exports.AssocEdge = exports.DeleteNodeOperation = exports.EdgeOperation = exports.EditNodeOperation = exports.loadRows = exports.loadRow = exports.loadRowX = exports.performRawQuery = exports.applyPrivacyPolicyForEntX = exports.applyPrivacyPolicyForEnt = exports.loadEntXViaKey = exports.loadEntViaKey = exports.loadDerivedEntX = exports.loadDerivedEnt = exports.loadEnts = exports.loadEntX = exports.loadCustomEnts = exports.loadCustomData = exports.loadEnt = void 0;
29
+ exports.setLogLevels = exports.loadConfig = exports.LoggedOutViewer = exports.IDViewer = exports.ContextCache = exports.query = exports.AllowIfViewerHasIdentityPrivacyPolicy = exports.AllowIfViewerPrivacyPolicy = exports.AllowIfSubPolicyAllowsRule = exports.AllowIfConditionAppliesRule = exports.AlwaysDenyPrivacyPolicy = exports.AlwaysAllowPrivacyPolicy = exports.applyPrivacyPolicyX = exports.applyPrivacyPolicy = exports.DelayedResultRule = exports.DenyIfEntIsVisiblePolicy = exports.AllowIfEntIsVisiblePolicy = exports.DenyIfEntIsNotVisibleRule = exports.DenyIfEntIsVisibleRule = exports.AllowIfEntIsNotVisibleRule = exports.AllowIfEntIsVisibleRule = exports.DenyIfViewerOutboundEdgeDoesNotExistRule = exports.DenyIfViewerInboundEdgeDoesNotExistRule = exports.DenyIfEdgeDoesNotExistRule = void 0;
30
30
  __exportStar(require("./core/base"), exports);
31
31
  var ent_1 = require("./core/ent");
32
32
  Object.defineProperty(exports, "loadEnt", { enumerable: true, get: function () { return ent_1.loadEnt; } });
@@ -73,6 +73,9 @@ Object.defineProperty(exports, "AllowIfHasIdentity", { enumerable: true, get: fu
73
73
  Object.defineProperty(exports, "AllowIfViewerRule", { enumerable: true, get: function () { return privacy_1.AllowIfViewerRule; } });
74
74
  Object.defineProperty(exports, "AllowIfFuncRule", { enumerable: true, get: function () { return privacy_1.AllowIfFuncRule; } });
75
75
  Object.defineProperty(exports, "AllowIfViewerIsRule", { enumerable: true, get: function () { return privacy_1.AllowIfViewerIsRule; } });
76
+ Object.defineProperty(exports, "AllowIfViewerIsEntPropertyRule", { enumerable: true, get: function () { return privacy_1.AllowIfViewerIsEntPropertyRule; } });
77
+ Object.defineProperty(exports, "AllowIfEntPropertyIsRule", { enumerable: true, get: function () { return privacy_1.AllowIfEntPropertyIsRule; } });
78
+ Object.defineProperty(exports, "DenyIfEntPropertyIsRule", { enumerable: true, get: function () { return privacy_1.DenyIfEntPropertyIsRule; } });
76
79
  Object.defineProperty(exports, "AllowIfViewerEqualsRule", { enumerable: true, get: function () { return privacy_1.AllowIfViewerEqualsRule; } });
77
80
  Object.defineProperty(exports, "DenyIfViewerEqualsRule", { enumerable: true, get: function () { return privacy_1.DenyIfViewerEqualsRule; } });
78
81
  Object.defineProperty(exports, "AllowIfEdgeExistsRule", { enumerable: true, get: function () { return privacy_1.AllowIfEdgeExistsRule; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snowtop/ent",
3
- "version": "0.0.22",
3
+ "version": "0.0.28-alpha",
4
4
  "description": "snowtop ent framework",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -9,6 +9,7 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "@types/node": "^15.0.2",
12
+ "camel-case": "^4.1.2",
12
13
  "dataloader": "^2.0.0",
13
14
  "glob": "^7.1.6",
14
15
  "graph-data-structure": "^1.12.0",
@@ -30,7 +31,7 @@
30
31
  },
31
32
  "peerDependencies": {
32
33
  "better-sqlite3": "^7.4.1",
33
- "graphql": ">= 15.3.0"
34
+ "graphql": "^15.5"
34
35
  },
35
36
  "peerDependenciesMeta": {
36
37
  "better-sqlite3": {
@@ -52,9 +53,6 @@
52
53
  "type": "git",
53
54
  "url": "git+ssh://git@github.com/lolopinto/ent.git"
54
55
  },
55
- "resolutions": {
56
- "graphql": "^15.3.0"
57
- },
58
56
  "bugs": {
59
57
  "url": "https://github.com/lolopinto/ent/issues"
60
58
  },
package/schema/field.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Type, Field, FieldOptions, PolymorphicOptions, ForeignKey } from "./schema";
1
+ import { Field, FieldOptions, ForeignKey, PolymorphicOptions, Type } from "./schema";
2
2
  export declare abstract class BaseField {
3
3
  name: string;
4
4
  nullable?: boolean;
@@ -21,10 +21,23 @@ export declare class UUIDField extends BaseField implements Field {
21
21
  constructor(options: FieldOptions);
22
22
  }
23
23
  export declare function UUIDType(options: FieldOptions): UUIDField;
24
+ export interface IntegerOptions extends FieldOptions {
25
+ min?: number;
26
+ max?: number;
27
+ }
24
28
  export declare class IntegerField extends BaseField implements Field {
25
29
  type: Type;
30
+ private validators;
31
+ private options;
32
+ constructor(options?: IntegerOptions);
33
+ getOptions(): IntegerOptions;
34
+ private handleOptions;
35
+ min(l: number): this;
36
+ max(l: number): this;
37
+ valid(val: any): boolean;
38
+ validate(validator: (str: number) => boolean): this;
26
39
  }
27
- export declare function IntegerType(options: FieldOptions): IntegerField;
40
+ export declare function IntegerType(options: IntegerOptions): IntegerField;
28
41
  export declare class BigIntegerField extends BaseField implements Field {
29
42
  type: Type;
30
43
  }
@@ -53,23 +66,24 @@ export declare class StringField extends BaseField implements Field {
53
66
  type: Type;
54
67
  private validators;
55
68
  private formatters;
69
+ private options;
56
70
  constructor(options?: StringOptions);
57
71
  getOptions(): StringOptions;
58
72
  private handleOptions;
59
- minLen(l: number): StringField;
60
- maxLen(l: number): StringField;
61
- length(l: number): StringField;
73
+ minLen(l: number): this;
74
+ maxLen(l: number): this;
75
+ length(l: number): this;
62
76
  valid(val: any): boolean;
63
77
  format(val: any): any;
64
- validate(validator: (str: string) => boolean): StringField;
65
- formatter(formatter: (str: string) => string): StringField;
66
- match(pattern: string | RegExp): StringField;
67
- doesNotMatch(pattern: string | RegExp): StringField;
68
- toLowerCase(): StringField;
69
- toUpperCase(): StringField;
70
- trim(): StringField;
71
- trimLeft(): StringField;
72
- trimRight(): StringField;
78
+ validate(validator: (str: string) => boolean): this;
79
+ formatter(formatter: (str: string) => string): this;
80
+ match(pattern: string | RegExp): this;
81
+ doesNotMatch(pattern: string | RegExp): this;
82
+ toLowerCase(): this;
83
+ toUpperCase(): this;
84
+ trim(): this;
85
+ trimLeft(): this;
86
+ trimRight(): this;
73
87
  }
74
88
  export declare function StringType(options: StringOptions): StringField;
75
89
  export interface TimestampOptions extends FieldOptions {
package/schema/field.js CHANGED
@@ -20,10 +20,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
22
  exports.UUIDListType = exports.EnumListType = exports.DateListType = exports.TimetzListType = exports.TimeListType = exports.TimestamptzListType = exports.TimestampListType = exports.BooleanListType = exports.BigIntegerListType = exports.FloatListType = exports.IntegerListType = exports.IntListType = exports.StringListType = exports.ListField = exports.EnumType = exports.EnumField = exports.DateType = exports.DateField = exports.TimetzType = exports.TimeType = exports.TimeField = exports.leftPad = exports.TimestamptzType = exports.TimestampType = exports.TimestampField = exports.StringType = exports.StringField = exports.BooleanType = exports.BooleanField = exports.FloatType = exports.FloatField = exports.BigIntegerType = exports.BigIntegerField = exports.IntegerType = exports.IntegerField = exports.UUIDType = exports.UUIDField = exports.BaseField = void 0;
23
- const schema_1 = require("./schema");
24
- const snake_case_1 = require("snake-case");
25
23
  const luxon_1 = require("luxon");
24
+ const snake_case_1 = require("snake-case");
26
25
  const db_1 = __importStar(require("../core/db"));
26
+ const schema_1 = require("./schema");
27
27
  class BaseField {
28
28
  logValue(val) {
29
29
  if (this.sensitive) {
@@ -89,14 +89,52 @@ function UUIDType(options) {
89
89
  }
90
90
  exports.UUIDType = UUIDType;
91
91
  class IntegerField extends BaseField {
92
- constructor() {
93
- super(...arguments);
92
+ constructor(options) {
93
+ super();
94
94
  this.type = { dbType: schema_1.DBType.Int };
95
+ this.validators = [];
96
+ this.options = { name: "field" };
97
+ // for legacy callers
98
+ this.handleOptions(options || this.options);
99
+ }
100
+ getOptions() {
101
+ return this.options;
102
+ }
103
+ handleOptions(options) {
104
+ const params = {
105
+ min: this.min,
106
+ max: this.max,
107
+ };
108
+ for (const k in params) {
109
+ const v = options[k];
110
+ if (v !== undefined) {
111
+ params[k].apply(this, [v]);
112
+ }
113
+ }
114
+ this.options = options;
115
+ }
116
+ min(l) {
117
+ return this.validate((val) => val >= l);
118
+ }
119
+ max(l) {
120
+ return this.validate((val) => val <= l);
121
+ }
122
+ valid(val) {
123
+ for (const validator of this.validators) {
124
+ if (!validator(val)) {
125
+ return false;
126
+ }
127
+ }
128
+ return true;
129
+ }
130
+ validate(validator) {
131
+ this.validators.push(validator);
132
+ return this;
95
133
  }
96
134
  }
97
135
  exports.IntegerField = IntegerField;
98
136
  function IntegerType(options) {
99
- let result = new IntegerField();
137
+ let result = new IntegerField(options);
100
138
  return Object.assign(result, options);
101
139
  }
102
140
  exports.IntegerType = IntegerType;
@@ -142,11 +180,12 @@ class StringField extends BaseField {
142
180
  this.type = { dbType: schema_1.DBType.String };
143
181
  this.validators = [];
144
182
  this.formatters = [];
183
+ this.options = { name: "field" };
145
184
  // for legacy callers
146
185
  this.handleOptions(options || { name: "field" });
147
186
  }
148
187
  getOptions() {
149
- return this.getOptions;
188
+ return this.options;
150
189
  }
151
190
  handleOptions(options) {
152
191
  const noParams = {
@@ -174,6 +213,7 @@ class StringField extends BaseField {
174
213
  noParams[k].apply(this);
175
214
  }
176
215
  }
216
+ this.options = options;
177
217
  }
178
218
  minLen(l) {
179
219
  return this.validate((val) => {
@@ -52,7 +52,17 @@ async function readInputs() {
52
52
  });
53
53
  });
54
54
  }
55
- async function captureCustom(filePath) {
55
+ async function captureCustom(filePath, filesCsv) {
56
+ if (filesCsv !== undefined) {
57
+ let files = filesCsv.split(",");
58
+ for (let i = 0; i < files.length; i++) {
59
+ // TODO fix. we have "src" in the path we get here
60
+ files[i] = path.join(filePath, "..", files[i]);
61
+ }
62
+ await requireFiles(files);
63
+ return;
64
+ }
65
+ // TODO delete all of this eventually
56
66
  // TODO configurable paths eventually
57
67
  // for now only files that are in the include path of the roots are allowed
58
68
  const rootFiles = [
@@ -81,18 +91,28 @@ async function captureCustom(filePath) {
81
91
  ignore: ignore,
82
92
  });
83
93
  const files = rootFiles.concat(customGQLResolvers, customGQLMutations);
84
- //console.log(files);
85
- let promises = [];
86
- files.forEach((file) => {
94
+ await requireFiles(files);
95
+ }
96
+ async function requireFiles(files) {
97
+ await Promise.all(files.map(async (file) => {
87
98
  if (fs.existsSync(file)) {
88
- promises.push(require(file));
99
+ try {
100
+ await require(file);
101
+ }
102
+ catch (e) {
103
+ throw new Error(`${e.message} loading ${file}`);
104
+ }
105
+ }
106
+ else {
107
+ throw new Error(`file ${file} doesn't exist`);
89
108
  }
109
+ })).catch((err) => {
110
+ throw new Error(err);
90
111
  });
91
- await Promise.all(promises);
92
112
  }
93
113
  async function parseImports(filePath) {
94
114
  // only do graphql files...
95
- return (0, imports_1.parseCustomInput)(path.join(filePath, "graphql"), {
115
+ return (0, imports_1.parseCustomImports)(path.join(filePath, "graphql"), {
96
116
  ignore: ["**/generated/**", "**/tests/**"],
97
117
  });
98
118
  }
@@ -126,7 +146,7 @@ async function main() {
126
146
  GQLCapture.enable(true);
127
147
  const [inputsRead, _, imports] = await Promise.all([
128
148
  readInputs(),
129
- captureCustom(options.path),
149
+ captureCustom(options.path, options.files),
130
150
  parseImports(options.path),
131
151
  ]);
132
152
  const { nodes, nodesMap } = inputsRead;
@@ -9,6 +9,7 @@ export declare class User implements Ent {
9
9
  accountID: string;
10
10
  nodeType: string;
11
11
  privacyPolicy: import("../core/base").PrivacyPolicy;
12
+ firstName: string;
12
13
  constructor(viewer: Viewer, data: Data);
13
14
  }
14
15
  export declare class Event implements Ent {