instant-cli 0.22.156 → 0.22.157-branch-cli-query.22963839427.1
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/.turbo/turbo-build.log +1 -1
- package/__tests__/e2e/cli.e2e.test.ts +544 -1
- package/__tests__/e2e/helpers.ts +44 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/index.js +88 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
2
3
|
import { readFile } from 'fs/promises';
|
|
3
4
|
import { join } from 'path';
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
runCli,
|
|
7
|
+
createTestProject,
|
|
8
|
+
createTempApp,
|
|
9
|
+
adminTransact,
|
|
10
|
+
createAppUser,
|
|
11
|
+
} from './helpers';
|
|
5
12
|
|
|
6
13
|
const SCHEMA_FILE = `
|
|
7
14
|
import { i } from "@instantdb/core";
|
|
@@ -494,6 +501,542 @@ export default _schema;
|
|
|
494
501
|
});
|
|
495
502
|
});
|
|
496
503
|
|
|
504
|
+
describe('query', () => {
|
|
505
|
+
it('queries data from an app', async () => {
|
|
506
|
+
const { appId, adminToken } = await createTempApp();
|
|
507
|
+
const project = await createTestProject({
|
|
508
|
+
appId,
|
|
509
|
+
schemaFile: SCHEMA_FILE,
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
try {
|
|
513
|
+
const pushResult = await runCli(['push', 'schema', '--yes'], {
|
|
514
|
+
cwd: project.dir,
|
|
515
|
+
env: {
|
|
516
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
517
|
+
INSTANT_APP_ID: appId,
|
|
518
|
+
},
|
|
519
|
+
});
|
|
520
|
+
expect(pushResult.exitCode).toBe(0);
|
|
521
|
+
|
|
522
|
+
await adminTransact(appId, adminToken, [
|
|
523
|
+
['update', 'posts', randomUUID(), { title: 'Hello', body: 'World' }],
|
|
524
|
+
['update', 'posts', randomUUID(), { title: 'Second', body: 'Post' }],
|
|
525
|
+
]);
|
|
526
|
+
|
|
527
|
+
const result = await runCli(
|
|
528
|
+
['query', '--admin', JSON.stringify({ posts: {} })],
|
|
529
|
+
{
|
|
530
|
+
cwd: project.dir,
|
|
531
|
+
env: {
|
|
532
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
533
|
+
INSTANT_APP_ID: appId,
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
);
|
|
537
|
+
|
|
538
|
+
expect(result.exitCode).toBe(0);
|
|
539
|
+
const data = JSON.parse(result.stdout);
|
|
540
|
+
expect(data.posts).toHaveLength(2);
|
|
541
|
+
expect(data.posts.map((p: any) => p.title).sort()).toEqual([
|
|
542
|
+
'Hello',
|
|
543
|
+
'Second',
|
|
544
|
+
]);
|
|
545
|
+
} finally {
|
|
546
|
+
await project.cleanup();
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
it('queries with filters', async () => {
|
|
551
|
+
const { appId, adminToken } = await createTempApp();
|
|
552
|
+
const project = await createTestProject({
|
|
553
|
+
appId,
|
|
554
|
+
schemaFile: SCHEMA_FILE,
|
|
555
|
+
});
|
|
556
|
+
|
|
557
|
+
try {
|
|
558
|
+
const pushResult = await runCli(['push', 'schema', '--yes'], {
|
|
559
|
+
cwd: project.dir,
|
|
560
|
+
env: {
|
|
561
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
562
|
+
INSTANT_APP_ID: appId,
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
expect(pushResult.exitCode).toBe(0);
|
|
566
|
+
|
|
567
|
+
await adminTransact(appId, adminToken, [
|
|
568
|
+
['update', 'posts', randomUUID(), { title: 'Match', body: 'Yes' }],
|
|
569
|
+
['update', 'posts', randomUUID(), { title: 'Nope', body: 'No' }],
|
|
570
|
+
]);
|
|
571
|
+
|
|
572
|
+
const query = {
|
|
573
|
+
posts: { $: { where: { title: 'Match' } } },
|
|
574
|
+
};
|
|
575
|
+
const result = await runCli(
|
|
576
|
+
['query', '--admin', JSON.stringify(query)],
|
|
577
|
+
{
|
|
578
|
+
cwd: project.dir,
|
|
579
|
+
env: {
|
|
580
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
581
|
+
INSTANT_APP_ID: appId,
|
|
582
|
+
},
|
|
583
|
+
},
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
expect(result.exitCode).toBe(0);
|
|
587
|
+
const data = JSON.parse(result.stdout);
|
|
588
|
+
expect(data.posts).toHaveLength(1);
|
|
589
|
+
expect(data.posts[0].title).toBe('Match');
|
|
590
|
+
} finally {
|
|
591
|
+
await project.cleanup();
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
it('returns empty arrays for entities with no data', async () => {
|
|
596
|
+
const { appId, adminToken } = await createTempApp();
|
|
597
|
+
const project = await createTestProject({
|
|
598
|
+
appId,
|
|
599
|
+
schemaFile: SCHEMA_FILE,
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
try {
|
|
603
|
+
const pushResult = await runCli(['push', 'schema', '--yes'], {
|
|
604
|
+
cwd: project.dir,
|
|
605
|
+
env: {
|
|
606
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
607
|
+
INSTANT_APP_ID: appId,
|
|
608
|
+
},
|
|
609
|
+
});
|
|
610
|
+
expect(pushResult.exitCode).toBe(0);
|
|
611
|
+
|
|
612
|
+
const result = await runCli(
|
|
613
|
+
['query', '--admin', JSON.stringify({ posts: {} })],
|
|
614
|
+
{
|
|
615
|
+
cwd: project.dir,
|
|
616
|
+
env: {
|
|
617
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
618
|
+
INSTANT_APP_ID: appId,
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
expect(result.exitCode).toBe(0);
|
|
624
|
+
const data = JSON.parse(result.stdout);
|
|
625
|
+
expect(data.posts).toEqual([]);
|
|
626
|
+
} finally {
|
|
627
|
+
await project.cleanup();
|
|
628
|
+
}
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('works with --app flag', async () => {
|
|
632
|
+
const { appId, adminToken } = await createTempApp();
|
|
633
|
+
const project = await createTestProject({
|
|
634
|
+
schemaFile: SCHEMA_FILE,
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
try {
|
|
638
|
+
const pushResult = await runCli(
|
|
639
|
+
['push', 'schema', '--app', appId, '--yes'],
|
|
640
|
+
{
|
|
641
|
+
cwd: project.dir,
|
|
642
|
+
env: { INSTANT_CLI_AUTH_TOKEN: adminToken },
|
|
643
|
+
},
|
|
644
|
+
);
|
|
645
|
+
expect(pushResult.exitCode).toBe(0);
|
|
646
|
+
|
|
647
|
+
const result = await runCli(
|
|
648
|
+
['query', '--admin', '--app', appId, JSON.stringify({ posts: {} })],
|
|
649
|
+
{
|
|
650
|
+
cwd: project.dir,
|
|
651
|
+
env: { INSTANT_CLI_AUTH_TOKEN: adminToken },
|
|
652
|
+
},
|
|
653
|
+
);
|
|
654
|
+
|
|
655
|
+
expect(result.exitCode).toBe(0);
|
|
656
|
+
const data = JSON.parse(result.stdout);
|
|
657
|
+
expect(data.posts).toEqual([]);
|
|
658
|
+
} finally {
|
|
659
|
+
await project.cleanup();
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
it('fails with invalid JSON', async () => {
|
|
664
|
+
const { appId, adminToken } = await createTempApp();
|
|
665
|
+
const project = await createTestProject({ appId });
|
|
666
|
+
|
|
667
|
+
try {
|
|
668
|
+
const result = await runCli(['query', '--admin', 'not valid json'], {
|
|
669
|
+
cwd: project.dir,
|
|
670
|
+
env: {
|
|
671
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
672
|
+
INSTANT_APP_ID: appId,
|
|
673
|
+
},
|
|
674
|
+
});
|
|
675
|
+
|
|
676
|
+
expect(result.exitCode).not.toBe(0);
|
|
677
|
+
} finally {
|
|
678
|
+
await project.cleanup();
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
|
|
682
|
+
it('accepts JSON5 syntax (unquoted keys)', async () => {
|
|
683
|
+
const { appId, adminToken } = await createTempApp();
|
|
684
|
+
const project = await createTestProject({ appId });
|
|
685
|
+
|
|
686
|
+
try {
|
|
687
|
+
const result = await runCli(['query', '--admin', '{ $users: {} }'], {
|
|
688
|
+
cwd: project.dir,
|
|
689
|
+
env: {
|
|
690
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
691
|
+
INSTANT_APP_ID: appId,
|
|
692
|
+
},
|
|
693
|
+
});
|
|
694
|
+
|
|
695
|
+
expect(result.exitCode).toBe(0);
|
|
696
|
+
const data = JSON.parse(result.stdout);
|
|
697
|
+
expect(data.$users).toEqual([]);
|
|
698
|
+
} finally {
|
|
699
|
+
await project.cleanup();
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it('fails without context flag', async () => {
|
|
704
|
+
const { appId, adminToken } = await createTempApp();
|
|
705
|
+
const project = await createTestProject({ appId });
|
|
706
|
+
|
|
707
|
+
try {
|
|
708
|
+
const result = await runCli(['query', JSON.stringify({ posts: {} })], {
|
|
709
|
+
cwd: project.dir,
|
|
710
|
+
env: {
|
|
711
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
712
|
+
INSTANT_APP_ID: appId,
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
expect(result.exitCode).not.toBe(0);
|
|
717
|
+
const output = result.stdout + result.stderr;
|
|
718
|
+
expect(output).toMatch(/--admin|--as-email|--as-guest/);
|
|
719
|
+
} finally {
|
|
720
|
+
await project.cleanup();
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
it('fails with multiple context flags', async () => {
|
|
725
|
+
const { appId, adminToken } = await createTempApp();
|
|
726
|
+
const project = await createTestProject({ appId });
|
|
727
|
+
|
|
728
|
+
try {
|
|
729
|
+
const result = await runCli(
|
|
730
|
+
[
|
|
731
|
+
'query',
|
|
732
|
+
'--as-email',
|
|
733
|
+
'alice@example.com',
|
|
734
|
+
'--as-guest',
|
|
735
|
+
JSON.stringify({ posts: {} }),
|
|
736
|
+
],
|
|
737
|
+
{
|
|
738
|
+
cwd: project.dir,
|
|
739
|
+
env: {
|
|
740
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
741
|
+
INSTANT_APP_ID: appId,
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
);
|
|
745
|
+
|
|
746
|
+
expect(result.exitCode).not.toBe(0);
|
|
747
|
+
const output = result.stdout + result.stderr;
|
|
748
|
+
expect(output).toMatch(/exactly one context/);
|
|
749
|
+
} finally {
|
|
750
|
+
await project.cleanup();
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
it('fails without auth', async () => {
|
|
755
|
+
const { appId } = await createTempApp();
|
|
756
|
+
const project = await createTestProject({ appId });
|
|
757
|
+
|
|
758
|
+
try {
|
|
759
|
+
const result = await runCli(
|
|
760
|
+
['query', '--admin', JSON.stringify({ posts: {} })],
|
|
761
|
+
{
|
|
762
|
+
cwd: project.dir,
|
|
763
|
+
env: {
|
|
764
|
+
INSTANT_CLI_AUTH_TOKEN: '',
|
|
765
|
+
INSTANT_APP_ADMIN_TOKEN: '',
|
|
766
|
+
INSTANT_ADMIN_TOKEN: '',
|
|
767
|
+
INSTANT_APP_ID: appId,
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
expect(result.exitCode).not.toBe(0);
|
|
773
|
+
const output = result.stdout + result.stderr;
|
|
774
|
+
expect(output).toMatch(/not logged in/i);
|
|
775
|
+
} finally {
|
|
776
|
+
await project.cleanup();
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
it('queries nested associations', async () => {
|
|
781
|
+
const { appId, adminToken } = await createTempApp();
|
|
782
|
+
const project = await createTestProject({
|
|
783
|
+
appId,
|
|
784
|
+
schemaFile: SCHEMA_FILE,
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
try {
|
|
788
|
+
const pushResult = await runCli(['push', 'schema', '--yes'], {
|
|
789
|
+
cwd: project.dir,
|
|
790
|
+
env: {
|
|
791
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
792
|
+
INSTANT_APP_ID: appId,
|
|
793
|
+
},
|
|
794
|
+
});
|
|
795
|
+
expect(pushResult.exitCode).toBe(0);
|
|
796
|
+
|
|
797
|
+
const postId = randomUUID();
|
|
798
|
+
const commentId = randomUUID();
|
|
799
|
+
await adminTransact(appId, adminToken, [
|
|
800
|
+
['update', 'posts', postId, { title: 'My Post', body: 'Content' }],
|
|
801
|
+
['update', 'comments', commentId, { text: 'Great post!' }],
|
|
802
|
+
['link', 'posts', postId, { comments: commentId }],
|
|
803
|
+
]);
|
|
804
|
+
|
|
805
|
+
const result = await runCli(
|
|
806
|
+
['query', '--admin', JSON.stringify({ posts: { comments: {} } })],
|
|
807
|
+
{
|
|
808
|
+
cwd: project.dir,
|
|
809
|
+
env: {
|
|
810
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
811
|
+
INSTANT_APP_ID: appId,
|
|
812
|
+
},
|
|
813
|
+
},
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
expect(result.exitCode).toBe(0);
|
|
817
|
+
const data = JSON.parse(result.stdout);
|
|
818
|
+
expect(data.posts).toHaveLength(1);
|
|
819
|
+
expect(data.posts[0].comments).toHaveLength(1);
|
|
820
|
+
expect(data.posts[0].comments[0].text).toBe('Great post!');
|
|
821
|
+
} finally {
|
|
822
|
+
await project.cleanup();
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
|
|
826
|
+
it('--as-email runs query as a specific user with perms applied', async () => {
|
|
827
|
+
const { appId, adminToken } = await createTempApp();
|
|
828
|
+
|
|
829
|
+
const schemaWithCreator = `
|
|
830
|
+
import { i } from "@instantdb/core";
|
|
831
|
+
const _schema = i.schema({
|
|
832
|
+
entities: {
|
|
833
|
+
posts: i.entity({
|
|
834
|
+
title: i.string(),
|
|
835
|
+
creatorEmail: i.string(),
|
|
836
|
+
}),
|
|
837
|
+
},
|
|
838
|
+
});
|
|
839
|
+
export default _schema;
|
|
840
|
+
`;
|
|
841
|
+
|
|
842
|
+
// Only allow users to view posts they created
|
|
843
|
+
const restrictedPerms = `export default {
|
|
844
|
+
posts: {
|
|
845
|
+
allow: {
|
|
846
|
+
view: "auth.email == data.creatorEmail",
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
};
|
|
850
|
+
`;
|
|
851
|
+
|
|
852
|
+
const project = await createTestProject({
|
|
853
|
+
appId,
|
|
854
|
+
schemaFile: schemaWithCreator,
|
|
855
|
+
permsFile: restrictedPerms,
|
|
856
|
+
});
|
|
857
|
+
|
|
858
|
+
try {
|
|
859
|
+
const pushResult = await runCli(['push', '--yes'], {
|
|
860
|
+
cwd: project.dir,
|
|
861
|
+
env: {
|
|
862
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
863
|
+
INSTANT_APP_ID: appId,
|
|
864
|
+
},
|
|
865
|
+
});
|
|
866
|
+
expect(pushResult.exitCode).toBe(0);
|
|
867
|
+
|
|
868
|
+
await createAppUser(appId, adminToken, 'alice@test.com');
|
|
869
|
+
await createAppUser(appId, adminToken, 'bob@test.com');
|
|
870
|
+
|
|
871
|
+
await adminTransact(appId, adminToken, [
|
|
872
|
+
[
|
|
873
|
+
'update',
|
|
874
|
+
'posts',
|
|
875
|
+
randomUUID(),
|
|
876
|
+
{ title: "Alice's Post", creatorEmail: 'alice@test.com' },
|
|
877
|
+
],
|
|
878
|
+
[
|
|
879
|
+
'update',
|
|
880
|
+
'posts',
|
|
881
|
+
randomUUID(),
|
|
882
|
+
{ title: "Bob's Post", creatorEmail: 'bob@test.com' },
|
|
883
|
+
],
|
|
884
|
+
]);
|
|
885
|
+
|
|
886
|
+
// Admin sees all posts
|
|
887
|
+
const adminResult = await runCli(
|
|
888
|
+
['query', '--admin', JSON.stringify({ posts: {} })],
|
|
889
|
+
{
|
|
890
|
+
cwd: project.dir,
|
|
891
|
+
env: {
|
|
892
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
893
|
+
INSTANT_APP_ID: appId,
|
|
894
|
+
},
|
|
895
|
+
},
|
|
896
|
+
);
|
|
897
|
+
expect(adminResult.exitCode).toBe(0);
|
|
898
|
+
const adminData = JSON.parse(adminResult.stdout);
|
|
899
|
+
expect(adminData.posts).toHaveLength(2);
|
|
900
|
+
|
|
901
|
+
// Alice only sees her post
|
|
902
|
+
const aliceResult = await runCli(
|
|
903
|
+
[
|
|
904
|
+
'query',
|
|
905
|
+
'--as-email',
|
|
906
|
+
'alice@test.com',
|
|
907
|
+
JSON.stringify({ posts: {} }),
|
|
908
|
+
],
|
|
909
|
+
{
|
|
910
|
+
cwd: project.dir,
|
|
911
|
+
env: {
|
|
912
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
913
|
+
INSTANT_APP_ID: appId,
|
|
914
|
+
},
|
|
915
|
+
},
|
|
916
|
+
);
|
|
917
|
+
expect(aliceResult.exitCode).toBe(0);
|
|
918
|
+
const aliceData = JSON.parse(aliceResult.stdout);
|
|
919
|
+
expect(aliceData.posts).toHaveLength(1);
|
|
920
|
+
expect(aliceData.posts[0].title).toBe("Alice's Post");
|
|
921
|
+
|
|
922
|
+
// Bob only sees his post
|
|
923
|
+
const bobResult = await runCli(
|
|
924
|
+
[
|
|
925
|
+
'query',
|
|
926
|
+
'--as-email',
|
|
927
|
+
'bob@test.com',
|
|
928
|
+
JSON.stringify({ posts: {} }),
|
|
929
|
+
],
|
|
930
|
+
{
|
|
931
|
+
cwd: project.dir,
|
|
932
|
+
env: {
|
|
933
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
934
|
+
INSTANT_APP_ID: appId,
|
|
935
|
+
},
|
|
936
|
+
},
|
|
937
|
+
);
|
|
938
|
+
expect(bobResult.exitCode).toBe(0);
|
|
939
|
+
const bobData = JSON.parse(bobResult.stdout);
|
|
940
|
+
expect(bobData.posts).toHaveLength(1);
|
|
941
|
+
expect(bobData.posts[0].title).toBe("Bob's Post");
|
|
942
|
+
} finally {
|
|
943
|
+
await project.cleanup();
|
|
944
|
+
}
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
it('--as-guest runs query as unauthenticated user', async () => {
|
|
948
|
+
const { appId, adminToken } = await createTempApp();
|
|
949
|
+
|
|
950
|
+
// Guests can only see posts marked as public
|
|
951
|
+
const schemaWithVisibility = `
|
|
952
|
+
import { i } from "@instantdb/core";
|
|
953
|
+
const _schema = i.schema({
|
|
954
|
+
entities: {
|
|
955
|
+
posts: i.entity({
|
|
956
|
+
title: i.string(),
|
|
957
|
+
isPublic: i.boolean(),
|
|
958
|
+
}),
|
|
959
|
+
},
|
|
960
|
+
});
|
|
961
|
+
export default _schema;
|
|
962
|
+
`;
|
|
963
|
+
|
|
964
|
+
const guestPerms = `export default {
|
|
965
|
+
posts: {
|
|
966
|
+
allow: {
|
|
967
|
+
view: "data.isPublic == true",
|
|
968
|
+
},
|
|
969
|
+
},
|
|
970
|
+
};
|
|
971
|
+
`;
|
|
972
|
+
|
|
973
|
+
const project = await createTestProject({
|
|
974
|
+
appId,
|
|
975
|
+
schemaFile: schemaWithVisibility,
|
|
976
|
+
permsFile: guestPerms,
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
try {
|
|
980
|
+
const pushResult = await runCli(['push', '--yes'], {
|
|
981
|
+
cwd: project.dir,
|
|
982
|
+
env: {
|
|
983
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
984
|
+
INSTANT_APP_ID: appId,
|
|
985
|
+
},
|
|
986
|
+
});
|
|
987
|
+
expect(pushResult.exitCode).toBe(0);
|
|
988
|
+
|
|
989
|
+
await adminTransact(appId, adminToken, [
|
|
990
|
+
[
|
|
991
|
+
'update',
|
|
992
|
+
'posts',
|
|
993
|
+
randomUUID(),
|
|
994
|
+
{ title: 'Public Post', isPublic: true },
|
|
995
|
+
],
|
|
996
|
+
[
|
|
997
|
+
'update',
|
|
998
|
+
'posts',
|
|
999
|
+
randomUUID(),
|
|
1000
|
+
{ title: 'Private Post', isPublic: false },
|
|
1001
|
+
],
|
|
1002
|
+
]);
|
|
1003
|
+
|
|
1004
|
+
// Admin sees both
|
|
1005
|
+
const adminResult = await runCli(
|
|
1006
|
+
['query', '--admin', JSON.stringify({ posts: {} })],
|
|
1007
|
+
{
|
|
1008
|
+
cwd: project.dir,
|
|
1009
|
+
env: {
|
|
1010
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
1011
|
+
INSTANT_APP_ID: appId,
|
|
1012
|
+
},
|
|
1013
|
+
},
|
|
1014
|
+
);
|
|
1015
|
+
expect(adminResult.exitCode).toBe(0);
|
|
1016
|
+
const adminData = JSON.parse(adminResult.stdout);
|
|
1017
|
+
expect(adminData.posts).toHaveLength(2);
|
|
1018
|
+
|
|
1019
|
+
// Guest only sees public post
|
|
1020
|
+
const guestResult = await runCli(
|
|
1021
|
+
['query', '--as-guest', JSON.stringify({ posts: {} })],
|
|
1022
|
+
{
|
|
1023
|
+
cwd: project.dir,
|
|
1024
|
+
env: {
|
|
1025
|
+
INSTANT_CLI_AUTH_TOKEN: adminToken,
|
|
1026
|
+
INSTANT_APP_ID: appId,
|
|
1027
|
+
},
|
|
1028
|
+
},
|
|
1029
|
+
);
|
|
1030
|
+
expect(guestResult.exitCode).toBe(0);
|
|
1031
|
+
const guestData = JSON.parse(guestResult.stdout);
|
|
1032
|
+
expect(guestData.posts).toHaveLength(1);
|
|
1033
|
+
expect(guestData.posts[0].title).toBe('Public Post');
|
|
1034
|
+
} finally {
|
|
1035
|
+
await project.cleanup();
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
|
|
497
1040
|
describe('info', () => {
|
|
498
1041
|
it('shows version', async () => {
|
|
499
1042
|
const result = await runCli(['info']);
|
package/__tests__/e2e/helpers.ts
CHANGED
|
@@ -114,6 +114,50 @@ export async function createTestProject(
|
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
export async function adminTransact(
|
|
118
|
+
appId: string,
|
|
119
|
+
adminToken: string,
|
|
120
|
+
steps: any[],
|
|
121
|
+
): Promise<void> {
|
|
122
|
+
const response = await fetch(`${apiUrl}/admin/transact`, {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
headers: {
|
|
125
|
+
'Content-Type': 'application/json',
|
|
126
|
+
Authorization: `Bearer ${adminToken}`,
|
|
127
|
+
'app-id': appId,
|
|
128
|
+
},
|
|
129
|
+
body: JSON.stringify({ steps }),
|
|
130
|
+
});
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`Failed to transact: ${response.status} ${await response.text()}`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function createAppUser(
|
|
139
|
+
appId: string,
|
|
140
|
+
adminToken: string,
|
|
141
|
+
email: string,
|
|
142
|
+
): Promise<{ userId: string; refreshToken: string }> {
|
|
143
|
+
const response = await fetch(`${apiUrl}/admin/refresh_tokens`, {
|
|
144
|
+
method: 'POST',
|
|
145
|
+
headers: {
|
|
146
|
+
'Content-Type': 'application/json',
|
|
147
|
+
Authorization: `Bearer ${adminToken}`,
|
|
148
|
+
'app-id': appId,
|
|
149
|
+
},
|
|
150
|
+
body: JSON.stringify({ email }),
|
|
151
|
+
});
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Failed to create user: ${response.status} ${await response.text()}`,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
const data = await response.json();
|
|
158
|
+
return { userId: data.user.id, refreshToken: data.user.refresh_token };
|
|
159
|
+
}
|
|
160
|
+
|
|
117
161
|
export async function createTempApp(title = 'cli-e2e-test'): Promise<{
|
|
118
162
|
appId: string;
|
|
119
163
|
adminToken: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAgnEA,8EAQC;AA+ED;;;;;EAKE"}
|