@trypattern/sdk 0.1.20 → 0.1.22
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/cli/app.js +25 -1
- package/dist/cli/data.d.ts +5 -0
- package/dist/cli/data.js +273 -0
- package/dist/cli/publishing.d.ts +9 -2
- package/dist/cli/publishing.js +7 -7
- package/dist/components/Badge.d.ts +1 -1
- package/dist/components/Badge.js +18 -0
- package/dist/components/ButtonBody.d.ts +1 -1
- package/dist/components/ButtonBody.js +43 -0
- package/dist/patternAccess.d.ts +2 -0
- package/dist/patternAccess.js +2 -1
- package/dist/publishWire.d.ts +355 -1
- package/dist/publishWire.js +66 -1
- package/dist/server/authService.d.ts +1 -0
- package/dist/server/bookings.d.ts +2 -1
- package/dist/server/bookings.js +22 -7
- package/dist/server/changes.d.ts +18 -0
- package/dist/server/changes.js +113 -0
- package/dist/server/createServer.d.ts +38 -0
- package/dist/server/database.d.ts +38 -0
- package/dist/server/database.js +2 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/patternViewer.js +4 -1
- package/dist/server/session.d.ts +1 -0
- package/dist/server/session.js +3 -0
- package/package.json +1 -1
package/dist/publishWire.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { appTitle } from './appTitle.ts';
|
|
3
3
|
export { appTitle };
|
|
4
|
-
export { ASSERTION_SECONDS, MEDIA_WRITE, NEXT_PAGE_HEADER, TABLES_READ, assertionKey, signAssertion } from './patternAccess.ts';
|
|
4
|
+
export { ASSERTION_SECONDS, MEDIA_WRITE, NEXT_PAGE_HEADER, TABLES_READ, TABLES_WRITE, assertionKey, signAssertion } from './patternAccess.ts';
|
|
5
5
|
export type { AssertionKey, AssertionScope } from './patternAccess.ts';
|
|
6
6
|
export declare const DASHBOARD_URL = "https://onpattern.app";
|
|
7
7
|
export declare const APPS_DOMAIN = "onpattern.app";
|
|
@@ -320,6 +320,94 @@ export declare const databaseRows: z.ZodObject<{
|
|
|
320
320
|
next: z.ZodNullable<z.ZodString>;
|
|
321
321
|
}, z.core.$strip>;
|
|
322
322
|
export type DatabaseRows = z.output<typeof databaseRows>;
|
|
323
|
+
export declare const CHANGE_SET_ROWS = 300;
|
|
324
|
+
export declare const dataChange: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
325
|
+
op: z.ZodLiteral<"add">;
|
|
326
|
+
table: z.ZodString;
|
|
327
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
328
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
329
|
+
op: z.ZodLiteral<"update">;
|
|
330
|
+
table: z.ZodString;
|
|
331
|
+
id: z.ZodString;
|
|
332
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
333
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
334
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
335
|
+
op: z.ZodLiteral<"remove">;
|
|
336
|
+
table: z.ZodString;
|
|
337
|
+
id: z.ZodString;
|
|
338
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
339
|
+
}, z.core.$strip>], "op">;
|
|
340
|
+
export type DataChange = z.output<typeof dataChange>;
|
|
341
|
+
export declare const changeOutcome: z.ZodObject<{
|
|
342
|
+
status: z.ZodEnum<{
|
|
343
|
+
failed: "failed";
|
|
344
|
+
applied: "applied";
|
|
345
|
+
skipped: "skipped";
|
|
346
|
+
}>;
|
|
347
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
348
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
349
|
+
}, z.core.$strip>;
|
|
350
|
+
export type ChangeOutcome = z.output<typeof changeOutcome>;
|
|
351
|
+
export declare const changeReply: z.ZodObject<{
|
|
352
|
+
outcomes: z.ZodArray<z.ZodObject<{
|
|
353
|
+
status: z.ZodEnum<{
|
|
354
|
+
failed: "failed";
|
|
355
|
+
applied: "applied";
|
|
356
|
+
skipped: "skipped";
|
|
357
|
+
}>;
|
|
358
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
359
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
360
|
+
}, z.core.$strip>>;
|
|
361
|
+
}, z.core.$strip>;
|
|
362
|
+
export declare const changeSetStatus: z.ZodEnum<{
|
|
363
|
+
declined: "declined";
|
|
364
|
+
waiting: "waiting";
|
|
365
|
+
applied: "applied";
|
|
366
|
+
expired: "expired";
|
|
367
|
+
undone: "undone";
|
|
368
|
+
}>;
|
|
369
|
+
export declare const changeSet: z.ZodObject<{
|
|
370
|
+
id: z.ZodString;
|
|
371
|
+
status: z.ZodEnum<{
|
|
372
|
+
declined: "declined";
|
|
373
|
+
waiting: "waiting";
|
|
374
|
+
applied: "applied";
|
|
375
|
+
expired: "expired";
|
|
376
|
+
undone: "undone";
|
|
377
|
+
}>;
|
|
378
|
+
title: z.ZodString;
|
|
379
|
+
asked: z.ZodString;
|
|
380
|
+
device: z.ZodString;
|
|
381
|
+
createdAt: z.ZodString;
|
|
382
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
383
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
384
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
385
|
+
op: z.ZodLiteral<"add">;
|
|
386
|
+
table: z.ZodString;
|
|
387
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
388
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
389
|
+
op: z.ZodLiteral<"update">;
|
|
390
|
+
table: z.ZodString;
|
|
391
|
+
id: z.ZodString;
|
|
392
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
393
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
394
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
395
|
+
op: z.ZodLiteral<"remove">;
|
|
396
|
+
table: z.ZodString;
|
|
397
|
+
id: z.ZodString;
|
|
398
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
399
|
+
}, z.core.$strip>], "op">>;
|
|
400
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
401
|
+
status: z.ZodEnum<{
|
|
402
|
+
failed: "failed";
|
|
403
|
+
applied: "applied";
|
|
404
|
+
skipped: "skipped";
|
|
405
|
+
}>;
|
|
406
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
407
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
408
|
+
}, z.core.$strip>>>;
|
|
409
|
+
}, z.core.$strip>;
|
|
410
|
+
export type ChangeSet = z.output<typeof changeSet>;
|
|
323
411
|
export declare const publishServices: {
|
|
324
412
|
readonly apps: {
|
|
325
413
|
readonly list: NoInfer<import("./services.ts").ServiceCall<"/apps", {}, z.ZodArray<z.ZodObject<{
|
|
@@ -647,6 +735,272 @@ export declare const publishServices: {
|
|
|
647
735
|
next: z.ZodNullable<z.ZodString>;
|
|
648
736
|
}, z.core.$strip>>>;
|
|
649
737
|
};
|
|
738
|
+
readonly changes: {
|
|
739
|
+
readonly list: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes", {}, z.ZodArray<z.ZodObject<{
|
|
740
|
+
id: z.ZodString;
|
|
741
|
+
status: z.ZodEnum<{
|
|
742
|
+
declined: "declined";
|
|
743
|
+
waiting: "waiting";
|
|
744
|
+
applied: "applied";
|
|
745
|
+
expired: "expired";
|
|
746
|
+
undone: "undone";
|
|
747
|
+
}>;
|
|
748
|
+
title: z.ZodString;
|
|
749
|
+
asked: z.ZodString;
|
|
750
|
+
device: z.ZodString;
|
|
751
|
+
createdAt: z.ZodString;
|
|
752
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
753
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
754
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
755
|
+
op: z.ZodLiteral<"add">;
|
|
756
|
+
table: z.ZodString;
|
|
757
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
758
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
759
|
+
op: z.ZodLiteral<"update">;
|
|
760
|
+
table: z.ZodString;
|
|
761
|
+
id: z.ZodString;
|
|
762
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
763
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
764
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
765
|
+
op: z.ZodLiteral<"remove">;
|
|
766
|
+
table: z.ZodString;
|
|
767
|
+
id: z.ZodString;
|
|
768
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
769
|
+
}, z.core.$strip>], "op">>;
|
|
770
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
771
|
+
status: z.ZodEnum<{
|
|
772
|
+
failed: "failed";
|
|
773
|
+
applied: "applied";
|
|
774
|
+
skipped: "skipped";
|
|
775
|
+
}>;
|
|
776
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
777
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
778
|
+
}, z.core.$strip>>>;
|
|
779
|
+
}, z.core.$strip>>>>;
|
|
780
|
+
readonly read: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes/:id", {}, z.ZodObject<{
|
|
781
|
+
id: z.ZodString;
|
|
782
|
+
status: z.ZodEnum<{
|
|
783
|
+
declined: "declined";
|
|
784
|
+
waiting: "waiting";
|
|
785
|
+
applied: "applied";
|
|
786
|
+
expired: "expired";
|
|
787
|
+
undone: "undone";
|
|
788
|
+
}>;
|
|
789
|
+
title: z.ZodString;
|
|
790
|
+
asked: z.ZodString;
|
|
791
|
+
device: z.ZodString;
|
|
792
|
+
createdAt: z.ZodString;
|
|
793
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
794
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
795
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
796
|
+
op: z.ZodLiteral<"add">;
|
|
797
|
+
table: z.ZodString;
|
|
798
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
799
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
800
|
+
op: z.ZodLiteral<"update">;
|
|
801
|
+
table: z.ZodString;
|
|
802
|
+
id: z.ZodString;
|
|
803
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
804
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
805
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
806
|
+
op: z.ZodLiteral<"remove">;
|
|
807
|
+
table: z.ZodString;
|
|
808
|
+
id: z.ZodString;
|
|
809
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
810
|
+
}, z.core.$strip>], "op">>;
|
|
811
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
812
|
+
status: z.ZodEnum<{
|
|
813
|
+
failed: "failed";
|
|
814
|
+
applied: "applied";
|
|
815
|
+
skipped: "skipped";
|
|
816
|
+
}>;
|
|
817
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
818
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
819
|
+
}, z.core.$strip>>>;
|
|
820
|
+
}, z.core.$strip>>>;
|
|
821
|
+
readonly create: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes", {
|
|
822
|
+
asked: z.ZodString;
|
|
823
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
824
|
+
op: z.ZodLiteral<"add">;
|
|
825
|
+
table: z.ZodString;
|
|
826
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
827
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
828
|
+
op: z.ZodLiteral<"update">;
|
|
829
|
+
table: z.ZodString;
|
|
830
|
+
id: z.ZodString;
|
|
831
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
832
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
833
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
834
|
+
op: z.ZodLiteral<"remove">;
|
|
835
|
+
table: z.ZodString;
|
|
836
|
+
id: z.ZodString;
|
|
837
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
838
|
+
}, z.core.$strip>], "op">>;
|
|
839
|
+
}, z.ZodObject<{
|
|
840
|
+
id: z.ZodString;
|
|
841
|
+
status: z.ZodEnum<{
|
|
842
|
+
declined: "declined";
|
|
843
|
+
waiting: "waiting";
|
|
844
|
+
applied: "applied";
|
|
845
|
+
expired: "expired";
|
|
846
|
+
undone: "undone";
|
|
847
|
+
}>;
|
|
848
|
+
title: z.ZodString;
|
|
849
|
+
asked: z.ZodString;
|
|
850
|
+
device: z.ZodString;
|
|
851
|
+
createdAt: z.ZodString;
|
|
852
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
853
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
854
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
855
|
+
op: z.ZodLiteral<"add">;
|
|
856
|
+
table: z.ZodString;
|
|
857
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
858
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
859
|
+
op: z.ZodLiteral<"update">;
|
|
860
|
+
table: z.ZodString;
|
|
861
|
+
id: z.ZodString;
|
|
862
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
863
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
864
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
865
|
+
op: z.ZodLiteral<"remove">;
|
|
866
|
+
table: z.ZodString;
|
|
867
|
+
id: z.ZodString;
|
|
868
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
869
|
+
}, z.core.$strip>], "op">>;
|
|
870
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
871
|
+
status: z.ZodEnum<{
|
|
872
|
+
failed: "failed";
|
|
873
|
+
applied: "applied";
|
|
874
|
+
skipped: "skipped";
|
|
875
|
+
}>;
|
|
876
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
877
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
878
|
+
}, z.core.$strip>>>;
|
|
879
|
+
}, z.core.$strip>>>;
|
|
880
|
+
readonly approve: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes/:id/approve", {}, z.ZodObject<{
|
|
881
|
+
id: z.ZodString;
|
|
882
|
+
status: z.ZodEnum<{
|
|
883
|
+
declined: "declined";
|
|
884
|
+
waiting: "waiting";
|
|
885
|
+
applied: "applied";
|
|
886
|
+
expired: "expired";
|
|
887
|
+
undone: "undone";
|
|
888
|
+
}>;
|
|
889
|
+
title: z.ZodString;
|
|
890
|
+
asked: z.ZodString;
|
|
891
|
+
device: z.ZodString;
|
|
892
|
+
createdAt: z.ZodString;
|
|
893
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
894
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
895
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
896
|
+
op: z.ZodLiteral<"add">;
|
|
897
|
+
table: z.ZodString;
|
|
898
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
899
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
900
|
+
op: z.ZodLiteral<"update">;
|
|
901
|
+
table: z.ZodString;
|
|
902
|
+
id: z.ZodString;
|
|
903
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
904
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
905
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
906
|
+
op: z.ZodLiteral<"remove">;
|
|
907
|
+
table: z.ZodString;
|
|
908
|
+
id: z.ZodString;
|
|
909
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
910
|
+
}, z.core.$strip>], "op">>;
|
|
911
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
912
|
+
status: z.ZodEnum<{
|
|
913
|
+
failed: "failed";
|
|
914
|
+
applied: "applied";
|
|
915
|
+
skipped: "skipped";
|
|
916
|
+
}>;
|
|
917
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
918
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
919
|
+
}, z.core.$strip>>>;
|
|
920
|
+
}, z.core.$strip>>>;
|
|
921
|
+
readonly decline: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes/:id/decline", {}, z.ZodObject<{
|
|
922
|
+
id: z.ZodString;
|
|
923
|
+
status: z.ZodEnum<{
|
|
924
|
+
declined: "declined";
|
|
925
|
+
waiting: "waiting";
|
|
926
|
+
applied: "applied";
|
|
927
|
+
expired: "expired";
|
|
928
|
+
undone: "undone";
|
|
929
|
+
}>;
|
|
930
|
+
title: z.ZodString;
|
|
931
|
+
asked: z.ZodString;
|
|
932
|
+
device: z.ZodString;
|
|
933
|
+
createdAt: z.ZodString;
|
|
934
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
935
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
936
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
937
|
+
op: z.ZodLiteral<"add">;
|
|
938
|
+
table: z.ZodString;
|
|
939
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
940
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
941
|
+
op: z.ZodLiteral<"update">;
|
|
942
|
+
table: z.ZodString;
|
|
943
|
+
id: z.ZodString;
|
|
944
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
945
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
946
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
947
|
+
op: z.ZodLiteral<"remove">;
|
|
948
|
+
table: z.ZodString;
|
|
949
|
+
id: z.ZodString;
|
|
950
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
951
|
+
}, z.core.$strip>], "op">>;
|
|
952
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
953
|
+
status: z.ZodEnum<{
|
|
954
|
+
failed: "failed";
|
|
955
|
+
applied: "applied";
|
|
956
|
+
skipped: "skipped";
|
|
957
|
+
}>;
|
|
958
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
959
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
960
|
+
}, z.core.$strip>>>;
|
|
961
|
+
}, z.core.$strip>>>;
|
|
962
|
+
readonly undo: NoInfer<import("./services.ts").ServiceCall<"/apps/:name/changes/:id/undo", {}, z.ZodObject<{
|
|
963
|
+
id: z.ZodString;
|
|
964
|
+
status: z.ZodEnum<{
|
|
965
|
+
declined: "declined";
|
|
966
|
+
waiting: "waiting";
|
|
967
|
+
applied: "applied";
|
|
968
|
+
expired: "expired";
|
|
969
|
+
undone: "undone";
|
|
970
|
+
}>;
|
|
971
|
+
title: z.ZodString;
|
|
972
|
+
asked: z.ZodString;
|
|
973
|
+
device: z.ZodString;
|
|
974
|
+
createdAt: z.ZodString;
|
|
975
|
+
decidedAt: z.ZodNullable<z.ZodString>;
|
|
976
|
+
undoneAt: z.ZodNullable<z.ZodString>;
|
|
977
|
+
changes: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
978
|
+
op: z.ZodLiteral<"add">;
|
|
979
|
+
table: z.ZodString;
|
|
980
|
+
row: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
981
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
982
|
+
op: z.ZodLiteral<"update">;
|
|
983
|
+
table: z.ZodString;
|
|
984
|
+
id: z.ZodString;
|
|
985
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
986
|
+
after: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
987
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
988
|
+
op: z.ZodLiteral<"remove">;
|
|
989
|
+
table: z.ZodString;
|
|
990
|
+
id: z.ZodString;
|
|
991
|
+
before: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
992
|
+
}, z.core.$strip>], "op">>;
|
|
993
|
+
outcomes: z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
994
|
+
status: z.ZodEnum<{
|
|
995
|
+
failed: "failed";
|
|
996
|
+
applied: "applied";
|
|
997
|
+
skipped: "skipped";
|
|
998
|
+
}>;
|
|
999
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
1000
|
+
row: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
1001
|
+
}, z.core.$strip>>>;
|
|
1002
|
+
}, z.core.$strip>>>;
|
|
1003
|
+
};
|
|
650
1004
|
readonly logins: {
|
|
651
1005
|
readonly read: NoInfer<import("./services.ts").ServiceCall<"/cli/logins/:approval", {}, z.ZodObject<{
|
|
652
1006
|
code: z.ZodString;
|
package/dist/publishWire.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { appTitle } from "./appTitle.js";
|
|
3
3
|
export { appTitle };
|
|
4
|
-
export { ASSERTION_SECONDS, MEDIA_WRITE, NEXT_PAGE_HEADER, TABLES_READ, assertionKey, signAssertion } from "./patternAccess.js";
|
|
4
|
+
export { ASSERTION_SECONDS, MEDIA_WRITE, NEXT_PAGE_HEADER, TABLES_READ, TABLES_WRITE, assertionKey, signAssertion } from "./patternAccess.js";
|
|
5
5
|
import { call, defineServices } from "./services.js";
|
|
6
6
|
export const DASHBOARD_URL = 'https://onpattern.app';
|
|
7
7
|
export const APPS_DOMAIN = 'onpattern.app';
|
|
@@ -256,6 +256,50 @@ export const databaseRows = z.object({
|
|
|
256
256
|
rows: z.array(databaseRow),
|
|
257
257
|
next: z.string().nullable()
|
|
258
258
|
});
|
|
259
|
+
export const CHANGE_SET_ROWS = 300;
|
|
260
|
+
const tableName = z.string().regex(/^[a-zA-Z][a-zA-Z0-9]*$/);
|
|
261
|
+
const rowId = z.string().min(1).max(200);
|
|
262
|
+
export const dataChange = z.discriminatedUnion('op', [
|
|
263
|
+
z.object({ op: z.literal('add'), table: tableName, row: databaseRow }),
|
|
264
|
+
z.object({
|
|
265
|
+
op: z.literal('update'),
|
|
266
|
+
table: tableName,
|
|
267
|
+
id: rowId,
|
|
268
|
+
before: databaseRow,
|
|
269
|
+
after: databaseRow
|
|
270
|
+
}),
|
|
271
|
+
z.object({
|
|
272
|
+
op: z.literal('remove'),
|
|
273
|
+
table: tableName,
|
|
274
|
+
id: rowId,
|
|
275
|
+
before: databaseRow
|
|
276
|
+
})
|
|
277
|
+
]);
|
|
278
|
+
export const changeOutcome = z.object({
|
|
279
|
+
status: z.enum(['applied', 'skipped', 'failed']),
|
|
280
|
+
reason: z.string().nullable(),
|
|
281
|
+
row: databaseRow.nullable()
|
|
282
|
+
});
|
|
283
|
+
export const changeReply = z.object({ outcomes: z.array(changeOutcome) });
|
|
284
|
+
export const changeSetStatus = z.enum([
|
|
285
|
+
'waiting',
|
|
286
|
+
'applied',
|
|
287
|
+
'declined',
|
|
288
|
+
'expired',
|
|
289
|
+
'undone'
|
|
290
|
+
]);
|
|
291
|
+
export const changeSet = z.object({
|
|
292
|
+
id: z.string(),
|
|
293
|
+
status: changeSetStatus,
|
|
294
|
+
title: z.string(),
|
|
295
|
+
asked: z.string(),
|
|
296
|
+
device: z.string(),
|
|
297
|
+
createdAt: z.string(),
|
|
298
|
+
decidedAt: z.string().nullable(),
|
|
299
|
+
undoneAt: z.string().nullable(),
|
|
300
|
+
changes: z.array(dataChange),
|
|
301
|
+
outcomes: z.array(changeOutcome).nullable()
|
|
302
|
+
});
|
|
259
303
|
export const publishServices = defineServices({
|
|
260
304
|
apps: {
|
|
261
305
|
list: call({ get: '/apps', reply: z.array(appSummary) }),
|
|
@@ -332,6 +376,27 @@ export const publishServices = defineServices({
|
|
|
332
376
|
reply: databaseRows
|
|
333
377
|
})
|
|
334
378
|
},
|
|
379
|
+
changes: {
|
|
380
|
+
list: call({ get: '/apps/:name/changes', reply: z.array(changeSet) }),
|
|
381
|
+
read: call({ get: '/apps/:name/changes/:id', reply: changeSet }),
|
|
382
|
+
create: call({
|
|
383
|
+
post: '/apps/:name/changes',
|
|
384
|
+
input: {
|
|
385
|
+
asked: z.string().trim().min(1).max(1000),
|
|
386
|
+
changes: z.array(dataChange).min(1).max(CHANGE_SET_ROWS)
|
|
387
|
+
},
|
|
388
|
+
reply: changeSet
|
|
389
|
+
}),
|
|
390
|
+
approve: call({
|
|
391
|
+
post: '/apps/:name/changes/:id/approve',
|
|
392
|
+
reply: changeSet
|
|
393
|
+
}),
|
|
394
|
+
decline: call({
|
|
395
|
+
post: '/apps/:name/changes/:id/decline',
|
|
396
|
+
reply: changeSet
|
|
397
|
+
}),
|
|
398
|
+
undo: call({ post: '/apps/:name/changes/:id/undo', reply: changeSet })
|
|
399
|
+
},
|
|
335
400
|
logins: {
|
|
336
401
|
read: call({ get: '/cli/logins/:approval', reply: loginToApprove }),
|
|
337
402
|
approve: call({
|
|
@@ -10,6 +10,7 @@ export type AuthService = {
|
|
|
10
10
|
export type OwnerNote = {
|
|
11
11
|
subject: string;
|
|
12
12
|
text: string;
|
|
13
|
+
replyTo?: string;
|
|
13
14
|
};
|
|
14
15
|
export declare function authServiceFor(env: ServerBindings): AuthService | undefined;
|
|
15
16
|
export declare function notifyOwner(env: ServerBindings, note: OwnerNote): Promise<boolean>;
|
|
@@ -3,10 +3,11 @@ import type { BookingRequest } from '../bookings.ts';
|
|
|
3
3
|
import type { ServerBlock, ServerEnv } from './env.ts';
|
|
4
4
|
export type BookingsOptions = {
|
|
5
5
|
timezone: string;
|
|
6
|
+
managePath?: string;
|
|
6
7
|
};
|
|
7
8
|
export type BookingEmail = {
|
|
8
9
|
kind: 'requested' | 'accepted' | 'declined';
|
|
9
10
|
request: BookingRequest;
|
|
10
11
|
};
|
|
11
12
|
export declare function sendBookingEmail(c: Context<ServerEnv>, email: BookingEmail): Promise<void>;
|
|
12
|
-
export declare function bookings({ timezone }: BookingsOptions): ServerBlock;
|
|
13
|
+
export declare function bookings({ timezone, managePath }: BookingsOptions): ServerBlock;
|
package/dist/server/bookings.js
CHANGED
|
@@ -10,9 +10,22 @@ export async function sendBookingEmail(c, email) {
|
|
|
10
10
|
const to = email.kind === 'requested' ? 'the owner' : email.request.email;
|
|
11
11
|
console.log(`Booking email (${email.kind}) to ${to} from ${new URL(c.req.url).host}: ${email.request.name}, ${email.request.date} ${email.request.window}`);
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function clockOf(time) {
|
|
14
|
+
const [hours = 0, minutes = 0] = time.split(':').map(Number);
|
|
15
|
+
const hour = hours % 12 === 0 ? 12 : hours % 12;
|
|
16
|
+
const suffix = hours < 12 ? 'am' : 'pm';
|
|
17
|
+
return minutes === 0
|
|
18
|
+
? `${hour}${suffix}`
|
|
19
|
+
: `${hour}:${String(minutes).padStart(2, '0')}${suffix}`;
|
|
20
|
+
}
|
|
21
|
+
function whenOf(request, label) {
|
|
22
|
+
const day = new Date(`${request.date}T12:00:00Z`).toLocaleDateString('en-US', { weekday: 'short', month: 'short', day: 'numeric', timeZone: 'UTC' });
|
|
23
|
+
const [start = '', end = ''] = request.window.split('-');
|
|
24
|
+
return `${day}, ${label} (${clockOf(start)}–${clockOf(end)})`;
|
|
25
|
+
}
|
|
26
|
+
function ownerNoteOf(request, label, manage) {
|
|
14
27
|
const lines = [
|
|
15
|
-
`${request.name} asked to book ${request.offering} on ${request
|
|
28
|
+
`${request.name} asked to book ${request.offering} on ${whenOf(request, label)}.`,
|
|
16
29
|
'',
|
|
17
30
|
`Email: ${request.email}`,
|
|
18
31
|
...(request.phone === '' ? [] : [`Phone: ${request.phone}`]),
|
|
@@ -20,12 +33,14 @@ function ownerNoteOf(request) {
|
|
|
20
33
|
...(request.notes === '' ? [] : ['', request.notes]),
|
|
21
34
|
'',
|
|
22
35
|
request.status === 'accepted'
|
|
23
|
-
?
|
|
24
|
-
:
|
|
36
|
+
? `It is booked: your booking rules accept requests on their own. See it at ${manage}`
|
|
37
|
+
: `Accept or decline it at ${manage}`,
|
|
38
|
+
`Reply to this email to write to ${request.name}.`
|
|
25
39
|
];
|
|
26
40
|
return {
|
|
27
41
|
subject: `New booking request from ${request.name}`,
|
|
28
|
-
text: lines.join('\n')
|
|
42
|
+
text: lines.join('\n'),
|
|
43
|
+
replyTo: request.email
|
|
29
44
|
};
|
|
30
45
|
}
|
|
31
46
|
function requireAdmin(c) {
|
|
@@ -84,7 +99,7 @@ async function decide(c, id, status) {
|
|
|
84
99
|
function monthRange(month) {
|
|
85
100
|
return { first: `${month}-01`, last: `${month}-31` };
|
|
86
101
|
}
|
|
87
|
-
export function bookings({ timezone }) {
|
|
102
|
+
export function bookings({ timezone, managePath = '/' }) {
|
|
88
103
|
if (!isValidTimezone(timezone)) {
|
|
89
104
|
throw new Error(`bookings({ timezone: '${timezone}' }) is not a time zone: use an IANA name such as 'America/Toronto'`);
|
|
90
105
|
}
|
|
@@ -116,7 +131,7 @@ export function bookings({ timezone }) {
|
|
|
116
131
|
const saved = await readRequest(c.env.DB, id);
|
|
117
132
|
if (saved === undefined)
|
|
118
133
|
throw new Error('The request was not saved');
|
|
119
|
-
await notifyOwner(c.env, ownerNoteOf(saved));
|
|
134
|
+
await notifyOwner(c.env, ownerNoteOf(saved, slot.label, new URL(managePath, c.req.url).href));
|
|
120
135
|
await sendBookingEmail(c, {
|
|
121
136
|
kind: status === 'accepted' ? 'accepted' : 'requested',
|
|
122
137
|
request: saved
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { Tables } from '../table.ts';
|
|
3
|
+
import type { ServerEnv } from './env.ts';
|
|
4
|
+
export declare function applyChanges<Group extends Tables>(c: Context<ServerEnv>, tables: Group): Promise<(Response & import("hono").TypedResponse<{
|
|
5
|
+
error: string;
|
|
6
|
+
}, 401, "json">) | (Response & import("hono").TypedResponse<{
|
|
7
|
+
error: string;
|
|
8
|
+
}, 403, "json">) | (Response & import("hono").TypedResponse<{
|
|
9
|
+
error: string;
|
|
10
|
+
}, 400, "json">) | (Response & import("hono").TypedResponse<{
|
|
11
|
+
outcomes: {
|
|
12
|
+
status: "failed" | "applied" | "skipped";
|
|
13
|
+
reason: string | null;
|
|
14
|
+
row: {
|
|
15
|
+
[x: string]: import("hono/utils/types").JSONValue;
|
|
16
|
+
} | null;
|
|
17
|
+
}[];
|
|
18
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">)>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { eq } from 'drizzle-orm';
|
|
2
|
+
import { drizzle } from 'drizzle-orm/d1';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { dataChange } from "../publishWire.js";
|
|
5
|
+
import { column, readRow, sqlTable } from "./tables.js";
|
|
6
|
+
const changeRequest = z.object({ changes: z.array(dataChange).max(1000) });
|
|
7
|
+
const META_KEYS = new Set(['id', 'createdAt', 'ownerId']);
|
|
8
|
+
function sameValue(left, right) {
|
|
9
|
+
return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
|
|
10
|
+
}
|
|
11
|
+
function changedSince(current, before, keys) {
|
|
12
|
+
return keys.some((key) => !sameValue(current[key], before[key]));
|
|
13
|
+
}
|
|
14
|
+
function withoutMeta(row) {
|
|
15
|
+
return Object.fromEntries(Object.entries(row).filter(([key]) => !META_KEYS.has(key)));
|
|
16
|
+
}
|
|
17
|
+
function failed(reason) {
|
|
18
|
+
return { status: 'failed', reason, row: null };
|
|
19
|
+
}
|
|
20
|
+
function skipped(reason) {
|
|
21
|
+
return { status: 'skipped', reason, row: null };
|
|
22
|
+
}
|
|
23
|
+
function problemOf(failure) {
|
|
24
|
+
for (let error = failure; error instanceof Error; error = error.cause) {
|
|
25
|
+
if (error.message.includes('UNIQUE constraint failed')) {
|
|
26
|
+
return 'Another row already has that value';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return 'The site couldn’t save this row';
|
|
30
|
+
}
|
|
31
|
+
async function applyOne(c, table, change) {
|
|
32
|
+
const target = sqlTable(table);
|
|
33
|
+
const db = drizzle(c.env.DB);
|
|
34
|
+
if (change.op === 'add') {
|
|
35
|
+
if (table.owned)
|
|
36
|
+
return failed('Rows in this table belong to their makers');
|
|
37
|
+
const id = typeof change.row['id'] === 'string' && change.row['id'] !== ''
|
|
38
|
+
? change.row['id']
|
|
39
|
+
: crypto.randomUUID();
|
|
40
|
+
const parsed = table.incoming.safeParse({ ...withoutMeta(change.row), id });
|
|
41
|
+
if (!parsed.success)
|
|
42
|
+
return failed(z.prettifyError(parsed.error));
|
|
43
|
+
const saved = await db
|
|
44
|
+
.insert(target)
|
|
45
|
+
.values(parsed.data)
|
|
46
|
+
.returning()
|
|
47
|
+
.get()
|
|
48
|
+
.catch((failure) => problemOf(failure));
|
|
49
|
+
if (typeof saved === 'string')
|
|
50
|
+
return failed(saved);
|
|
51
|
+
return {
|
|
52
|
+
status: 'applied',
|
|
53
|
+
reason: null,
|
|
54
|
+
row: (await readRow(c.env.DB, table, id)) ?? null
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const current = await readRow(c.env.DB, table, change.id);
|
|
58
|
+
if (current === undefined)
|
|
59
|
+
return skipped('It was removed since');
|
|
60
|
+
if (change.op === 'remove') {
|
|
61
|
+
if (changedSince(current, change.before, Object.keys(change.before))) {
|
|
62
|
+
return skipped('It changed since');
|
|
63
|
+
}
|
|
64
|
+
await db.delete(target).where(eq(column(target, 'id'), change.id));
|
|
65
|
+
return { status: 'applied', reason: null, row: current };
|
|
66
|
+
}
|
|
67
|
+
const keys = Object.keys(withoutMeta(change.after));
|
|
68
|
+
if (changedSince(current, change.before, keys)) {
|
|
69
|
+
return skipped('It changed since');
|
|
70
|
+
}
|
|
71
|
+
const parsed = table.incoming.safeParse({
|
|
72
|
+
...withoutMeta(current),
|
|
73
|
+
...withoutMeta(change.after),
|
|
74
|
+
id: change.id
|
|
75
|
+
});
|
|
76
|
+
if (!parsed.success)
|
|
77
|
+
return failed(z.prettifyError(parsed.error));
|
|
78
|
+
const values = Object.fromEntries(keys.map((key) => [key, Reflect.get(parsed.data, key)]));
|
|
79
|
+
const saved = await db
|
|
80
|
+
.update(target)
|
|
81
|
+
.set(values)
|
|
82
|
+
.where(eq(column(target, 'id'), change.id))
|
|
83
|
+
.run()
|
|
84
|
+
.then(() => undefined)
|
|
85
|
+
.catch((failure) => problemOf(failure));
|
|
86
|
+
if (saved !== undefined)
|
|
87
|
+
return failed(saved);
|
|
88
|
+
return {
|
|
89
|
+
status: 'applied',
|
|
90
|
+
reason: null,
|
|
91
|
+
row: (await readRow(c.env.DB, table, change.id)) ?? null
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
export async function applyChanges(c, tables) {
|
|
95
|
+
const viewer = c.get('viewer');
|
|
96
|
+
if (viewer === null)
|
|
97
|
+
return c.json({ error: 'Signed out' }, 401);
|
|
98
|
+
if (!viewer.isAdmin)
|
|
99
|
+
return c.json({ error: 'forbidden' }, 403);
|
|
100
|
+
const body = changeRequest.safeParse(await c.req.json().catch(() => null));
|
|
101
|
+
if (!body.success) {
|
|
102
|
+
return c.json({ error: z.prettifyError(body.error) }, 400);
|
|
103
|
+
}
|
|
104
|
+
const known = new Map(Object.values(tables).map((table) => [table.name, table]));
|
|
105
|
+
const outcomes = [];
|
|
106
|
+
for (const change of body.data.changes) {
|
|
107
|
+
const table = known.get(change.table);
|
|
108
|
+
outcomes.push(table === undefined || table.access.read === 'server'
|
|
109
|
+
? failed('No such table')
|
|
110
|
+
: await applyOne(c, table, change));
|
|
111
|
+
}
|
|
112
|
+
return c.json({ outcomes });
|
|
113
|
+
}
|