@project-ajax/sdk 0.0.35 → 0.0.37

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.
Files changed (47) hide show
  1. package/dist/builder.d.ts +13 -1
  2. package/dist/builder.d.ts.map +1 -1
  3. package/dist/builder.js +15 -0
  4. package/dist/capabilities/sync.d.ts +6 -1
  5. package/dist/capabilities/sync.d.ts.map +1 -1
  6. package/dist/cli/api/client.d.ts +27 -1
  7. package/dist/cli/api/client.d.ts.map +1 -1
  8. package/dist/cli/api/client.js +33 -2
  9. package/dist/cli/commands/auth.impl.d.ts.map +1 -1
  10. package/dist/cli/commands/auth.impl.js +2 -27
  11. package/dist/cli/commands/connect.d.ts +2 -0
  12. package/dist/cli/commands/connect.d.ts.map +1 -0
  13. package/dist/cli/commands/connect.impl.d.ts +6 -0
  14. package/dist/cli/commands/connect.impl.d.ts.map +1 -0
  15. package/dist/cli/commands/connect.impl.js +116 -0
  16. package/dist/cli/commands/connect.js +78 -0
  17. package/dist/cli/commands/secrets.impl.d.ts.map +1 -1
  18. package/dist/cli/commands/secrets.impl.js +6 -0
  19. package/dist/cli/routes.d.ts.map +1 -1
  20. package/dist/cli/routes.js +2 -0
  21. package/dist/cli/utils/openNotionUrl.d.ts +3 -0
  22. package/dist/cli/utils/openNotionUrl.d.ts.map +1 -0
  23. package/dist/cli/utils/openNotionUrl.js +33 -0
  24. package/dist/icon-names.d.ts +6 -0
  25. package/dist/icon-names.d.ts.map +1 -0
  26. package/dist/icon-names.js +0 -0
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +3 -0
  30. package/dist/schema.d.ts +7 -1
  31. package/dist/schema.d.ts.map +1 -1
  32. package/dist/types.d.ts +31 -1
  33. package/dist/types.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/src/builder.ts +29 -1
  36. package/src/capabilities/sync.ts +6 -1
  37. package/src/cli/api/client.ts +60 -1
  38. package/src/cli/commands/auth.impl.ts +2 -38
  39. package/src/cli/commands/connect.impl.ts +149 -0
  40. package/src/cli/commands/connect.ts +80 -0
  41. package/src/cli/commands/secrets.impl.ts +6 -0
  42. package/src/cli/routes.ts +2 -0
  43. package/src/cli/utils/openNotionUrl.ts +40 -0
  44. package/src/icon-names.ts +890 -0
  45. package/src/index.ts +2 -0
  46. package/src/schema.ts +7 -0
  47. package/src/types.ts +47 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,10 @@
1
+ import { emojiIcon, notionIcon } from "./builder.js";
1
2
  import { slashCommand } from "./capabilities/slashCommand.js";
2
3
  import { sync } from "./capabilities/sync.js";
3
4
  import { tool } from "./capabilities/tool.js";
4
5
  export {
6
+ emojiIcon,
7
+ notionIcon,
5
8
  slashCommand,
6
9
  sync,
7
10
  tool
package/dist/schema.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { DateFormat, NumberFormat, SelectOption, StatusGroup } from "./types.js";
1
+ import type { DateFormat, Icon, NumberFormat, SelectOption, StatusGroup } from "./types.js";
2
2
  /**
3
3
  * Supported property types for sync schemas.
4
4
  */
@@ -44,6 +44,12 @@ export type PropertyConfiguration = {
44
44
  };
45
45
  export type Schema<PK extends string> = {
46
46
  dataSourceTitle: string;
47
+ /**
48
+ * Optional icon to use as the icon for the database page.
49
+ * If not provided, defaults to 📋.
50
+ * Use the `icon()` builder to create an icon value.
51
+ */
52
+ databaseIcon?: Icon;
47
53
  properties: PropertySchema<PK>;
48
54
  };
49
55
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,YAAY,GACrB,OAAO,GACP,WAAW,GACX,KAAK,GACL,OAAO,GACP,cAAc,GACd,UAAU,GACV,MAAM,GACN,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,cAAc,GACd,QAAQ,CAAC;AAEZ;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,CAAC;CACrB,GACD;IACA,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,UAAU,CAAC;CACxB,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;CACvB,GACD;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;CACvB,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;CACrB,CAAC;AAEL,MAAM,MAAM,MAAM,CAAC,EAAE,SAAS,MAAM,IAAI;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,MAAM,IAAI;KAC9C,UAAU,IAAI,EAAE,GAAG,qBAAqB;CACzC,GAAG;IACH,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,IAAI,qBAAqB,CAE7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,qBAAqB,CAEhD;AAED;;GAEG;AACH,wBAAgB,GAAG,IAAI,qBAAqB,CAE3C;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,qBAAqB,CAE7C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,qBAAqB,CAEnD;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,qBAAqB,CAEhD;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,qBAAqB,CAE5C;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,qBAAqB,CAEnE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,qBAAqB,CAEpE;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAErE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAE1E;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;CACtB,GAAG,qBAAqB,CAExB"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,YAAY,GACrB,OAAO,GACP,WAAW,GACX,KAAK,GACL,OAAO,GACP,cAAc,GACd,UAAU,GACV,MAAM,GACN,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,cAAc,GACd,QAAQ,CAAC;AAEZ;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC9B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,GACf;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,CAAC,EAAE,YAAY,CAAC;CACrB,GACD;IACA,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,UAAU,CAAC;CACxB,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,YAAY,EAAE,CAAC;CACvB,GACD;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,YAAY,EAAE,CAAC;CACvB,GACD;IACA,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,WAAW,EAAE,CAAC;CACrB,CAAC;AAEL,MAAM,MAAM,MAAM,CAAC,EAAE,SAAS,MAAM,IAAI;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,YAAY,CAAC,EAAE,IAAI,CAAC;IACpB,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,EAAE,SAAS,MAAM,IAAI;KAC9C,UAAU,IAAI,EAAE,GAAG,qBAAqB;CACzC,GAAG;IACH,CAAC,YAAY,EAAE,MAAM,GAAG,qBAAqB,CAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,IAAI,qBAAqB,CAE7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,qBAAqB,CAEhD;AAED;;GAEG;AACH,wBAAgB,GAAG,IAAI,qBAAqB,CAE3C;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,qBAAqB,CAE7C;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,qBAAqB,CAEnD;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,qBAAqB,CAEhD;AAED;;GAEG;AACH,wBAAgB,IAAI,IAAI,qBAAqB,CAE5C;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,qBAAqB,CAEnE;AAED;;GAEG;AACH,wBAAgB,IAAI,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,qBAAqB,CAEpE;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAErE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,qBAAqB,CAE1E;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE;IAC9B,MAAM,EAAE,WAAW,EAAE,CAAC;CACtB,GAAG,qBAAqB,CAExB"}
package/dist/types.d.ts CHANGED
@@ -76,5 +76,35 @@ export type NumberFormat = "number" | "number_with_commas" | "percent" | "dollar
76
76
  * Date format types
77
77
  */
78
78
  export type DateFormat = "relative" | "MM/DD/YYYY" | "DD/MM/YYYY" | "YYYY/MM/DD" | "ll" | "MMM d";
79
- export {};
79
+ import type { NoticonName } from "./icon-names.js";
80
+ /**
81
+ * Icon representing an emoji
82
+ */
83
+ export interface EmojiIcon {
84
+ type: "emoji";
85
+ value: string;
86
+ }
87
+ /**
88
+ * Valid colors for Notion icons
89
+ */
90
+ export type NoticonColor = "gray" | "lightgray" | "brown" | "yellow" | "orange" | "green" | "blue" | "purple" | "pink" | "red";
91
+ /**
92
+ * Icon representing a Notion built-in icon
93
+ */
94
+ export interface NoticonIcon {
95
+ type: "notion";
96
+ /**
97
+ * The name of the Notion icon (e.g., "checkmark", "pizza", "rocket")
98
+ */
99
+ icon: NoticonName;
100
+ /**
101
+ * The color variant of the icon
102
+ */
103
+ color: NoticonColor;
104
+ }
105
+ /**
106
+ * All possible icon types
107
+ */
108
+ export type Icon = EmojiIcon | NoticonIcon;
109
+ export type { NoticonName } from "./icon-names.js";
80
110
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,KAAK,SAAS,GAAG,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,WAAW,GACpB,SAAS,GACT,MAAM,GACN,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,MAAM,GACN,QAAQ,GACR,MAAM,GACN,KAAK,CAAC;AAET;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,GAAG,aAAa,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,YAAY,GACrB,QAAQ,GACR,oBAAoB,GACpB,SAAS,GACT,QAAQ,GACR,MAAM,GACN,OAAO,GACP,KAAK,GACL,OAAO,GACP,KAAK,GACL,MAAM,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,UAAU,GACnB,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,IAAI,GACJ,OAAO,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,KAAK,SAAS,GAAG,CAAC,MAAM,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;AAExC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;AAEzC;;GAEG;AACH,MAAM,MAAM,WAAW,GACpB,SAAS,GACT,MAAM,GACN,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,MAAM,GACN,QAAQ,GACR,MAAM,GACN,KAAK,CAAC;AAET;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,aAAa,GAAG,UAAU,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,YAAY,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,UAAU,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,IAAI,EAAE,eAAe,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,GAAG,aAAa,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,YAAY,GACrB,QAAQ,GACR,oBAAoB,GACpB,SAAS,GACT,QAAQ,GACR,MAAM,GACN,OAAO,GACP,KAAK,GACL,OAAO,GACP,KAAK,GACL,MAAM,CAAC;AAEV;;GAEG;AACH,MAAM,MAAM,UAAU,GACnB,UAAU,GACV,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,IAAI,GACJ,OAAO,CAAC;AAEX,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GACrB,MAAM,GACN,WAAW,GACX,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,MAAM,GACN,QAAQ,GACR,MAAM,GACN,KAAK,CAAC;AAET;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;IAClB;;OAEG;IACH,KAAK,EAAE,YAAY,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,MAAM,IAAI,GAAG,SAAS,GAAG,WAAW,CAAC;AAE3C,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@project-ajax/sdk",
3
- "version": "0.0.35",
3
+ "version": "0.0.37",
4
4
  "description": "An SDK for building workers for the Project Ajax platform",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/src/builder.ts CHANGED
@@ -1,4 +1,5 @@
1
- import type { DateValue, TextValue } from "./types.js";
1
+ import type { NoticonName } from "./icon-names.js";
2
+ import type { DateValue, Icon, NoticonColor, TextValue } from "./types.js";
2
3
 
3
4
  /**
4
5
  * Creates a rich text value.
@@ -213,3 +214,30 @@ function formatTime(date: Date): string {
213
214
  const minutes = String(date.getMinutes()).padStart(2, "0");
214
215
  return `${hours}:${minutes}`;
215
216
  }
217
+
218
+ /**
219
+ * Creates an emoji icon.
220
+ * @param emoji - An emoji string (e.g., "🎯", "✨", "🚀")
221
+ */
222
+ export function emojiIcon(emoji: string): Icon {
223
+ return {
224
+ type: "emoji",
225
+ value: emoji,
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Creates a Notion icon with a specific color.
231
+ * @param icon - The name of the Notion icon (e.g., "checkmark", "pizza", "rocket")
232
+ * @param color - The color variant (defaults to "gray")
233
+ */
234
+ export function notionIcon(
235
+ icon: NoticonName,
236
+ color: NoticonColor = "gray",
237
+ ): Icon {
238
+ return {
239
+ type: "notion",
240
+ icon,
241
+ color,
242
+ };
243
+ }
@@ -1,6 +1,6 @@
1
1
  import { ExecutionError } from "../error.js";
2
2
  import type { PropertySchema, Schema } from "../schema.js";
3
- import type { TextValue } from "../types.js";
3
+ import type { Icon, TextValue } from "../types.js";
4
4
 
5
5
  /**
6
6
  * An object representing a third-party record to be synced.
@@ -8,6 +8,11 @@ import type { TextValue } from "../types.js";
8
8
  export type SyncedObject<PK extends string, S extends PropertySchema<PK>> = {
9
9
  key: string;
10
10
  properties: { [Property in keyof S]: TextValue };
11
+ /**
12
+ * Optional icon to use as the icon for this row's page.
13
+ * Use the `icon()` builder to create an icon value.
14
+ */
15
+ icon?: Icon;
11
16
  };
12
17
 
13
18
  /**
@@ -330,7 +330,10 @@ export class ApiClient {
330
330
  /**
331
331
  * List all secrets for a worker (keys only, not values)
332
332
  */
333
- async listSecrets(workerId: string): Promise<
333
+ async listSecrets(
334
+ workerId: string,
335
+ options?: { secretKinds?: Array<"keyValue" | "oauth"> },
336
+ ): Promise<
334
337
  Result<
335
338
  {
336
339
  secrets: Array<{
@@ -338,6 +341,7 @@ export class ApiClient {
338
341
  workerId: string;
339
342
  key: string;
340
343
  createdAt: string;
344
+ kind: "keyValue" | "oauth";
341
345
  }>;
342
346
  },
343
347
  ApiError
@@ -347,6 +351,61 @@ export class ApiClient {
347
351
  method: "POST",
348
352
  body: {
349
353
  workerId,
354
+ secretKinds: options?.secretKinds,
355
+ },
356
+ });
357
+ }
358
+
359
+ async listOauthProviders(): Promise<
360
+ Result<
361
+ {
362
+ providers: Array<{
363
+ key: string;
364
+ displayName: string;
365
+ }>;
366
+ },
367
+ ApiError
368
+ >
369
+ > {
370
+ return this.fetch("/workersListOauthProviders", {
371
+ method: "POST",
372
+ body: {},
373
+ });
374
+ }
375
+
376
+ /**
377
+ * Start the OAuth flow for a provider
378
+ */
379
+ async startOauth(args: { workerId: string; provider: string }): Promise<
380
+ Result<
381
+ {
382
+ authorizationUrl: string;
383
+ state: string;
384
+ },
385
+ ApiError
386
+ >
387
+ > {
388
+ return this.fetch("/workersStartOauth", {
389
+ method: "POST",
390
+ body: {
391
+ workerId: args.workerId,
392
+ provider: args.provider,
393
+ },
394
+ });
395
+ }
396
+
397
+ /**
398
+ * Remove an OAuth connection for a worker
399
+ */
400
+ async deleteOauthConnection(args: {
401
+ workerId: string;
402
+ provider: string;
403
+ }): Promise<Result<Record<string, never>, ApiError>> {
404
+ return this.fetch("/workersDeleteOauthConnection", {
405
+ method: "POST",
406
+ body: {
407
+ workerId: args.workerId,
408
+ provider: args.provider,
350
409
  },
351
410
  });
352
411
  }
@@ -1,49 +1,13 @@
1
- import { exec } from "node:child_process";
2
- import { existsSync } from "node:fs";
3
1
  import { baseUrl } from "../api/client.js";
4
2
  import type { Environment } from "../config.js";
5
3
  import { buildHandler, type HandlerContext } from "../handler.js";
4
+ import { openNotionUrl } from "../utils/openNotionUrl.js";
6
5
 
7
6
  interface LoginFlags {
8
7
  env?: Environment;
9
8
  "base-url"?: string;
10
9
  }
11
10
 
12
- /**
13
- * Open a URL in the user's default browser or Notion app (if app available)
14
- */
15
- async function openUrl(env: Environment, url: string): Promise<void> {
16
- const platform = process.platform;
17
-
18
- try {
19
- if (platform === "darwin") {
20
- // Check if we should try to open Notion app on macOS
21
- let notionAppName: string | null = null;
22
-
23
- if (env === "prod" && existsSync("/Applications/Notion.app")) {
24
- notionAppName = "Notion";
25
- } else if (env === "dev" && existsSync("/Applications/Notion Dev.app")) {
26
- notionAppName = "Notion Dev";
27
- }
28
-
29
- if (notionAppName) {
30
- // Open the app first, then the URL (which will open in the app)
31
- exec(`open -a "${notionAppName}" "${url}"`);
32
- } else {
33
- // Fall back to opening in default browser
34
- exec(`open "${url}"`);
35
- }
36
- } else if (platform === "win32") {
37
- exec(`start "" "${url}"`);
38
- } else {
39
- // Linux and other Unix-like systems
40
- exec(`xdg-open "${url}"`);
41
- }
42
- } catch (error) {
43
- throw new Error(`Failed to open browser: ${error}`);
44
- }
45
- }
46
-
47
11
  export const login = buildHandler(async function (
48
12
  this: HandlerContext,
49
13
  flags: LoginFlags,
@@ -67,7 +31,7 @@ export const login = buildHandler(async function (
67
31
  this.writer.writeErr("\tnpx workers auth login <token>");
68
32
 
69
33
  try {
70
- await openUrl(environment, url);
34
+ await openNotionUrl(environment, url);
71
35
  } catch (_error) {
72
36
  this.writer.writeErr(
73
37
  `Failed to open browser automatically. Please visit:\n ${url}`,
@@ -0,0 +1,149 @@
1
+ import type { ApiError } from "../api/client.js";
2
+ import { Result } from "../api/result.js";
3
+ import type { FormatFlags, GlobalFlags } from "../flags.js";
4
+ import { type AuthedContext, buildAuthedHandler } from "../handler.js";
5
+ import { openNotionUrl } from "../utils/openNotionUrl.js";
6
+
7
+ export const listProviders = buildAuthedHandler(async function (
8
+ flags: FormatFlags,
9
+ ) {
10
+ this.process.stderr.write("Fetching providers...");
11
+ const providersResult = await this.apiClient.listOauthProviders();
12
+
13
+ if (Result.isFail(providersResult)) {
14
+ this.process.stderr.write("ERROR\n\n");
15
+ reportApiError(this, providersResult.error, "list providers");
16
+ } else {
17
+ this.process.stderr.write("OK\n\n");
18
+ const providers = providersResult.value.providers;
19
+ if (providers.length === 0) {
20
+ this.writer.writeErr("No OAuth providers are currently available.");
21
+ return;
22
+ }
23
+
24
+ this.writer.writeTableOut({
25
+ headers: ["Provider", "Description"],
26
+ rows: providers.map((provider) => [provider.key, provider.displayName]),
27
+ plain: flags.plain,
28
+ });
29
+ }
30
+ });
31
+
32
+ export const addConnection = buildAuthedHandler(async function (
33
+ _flags: GlobalFlags,
34
+ provider: string,
35
+ ) {
36
+ const workerId = requireWorkerId(this);
37
+
38
+ this.process.stderr.write(
39
+ `Starting OAuth flow with provider "${provider}"...`,
40
+ );
41
+ const startResult = await this.apiClient.startOauth({ workerId, provider });
42
+
43
+ if (Result.isFail(startResult)) {
44
+ this.process.stderr.write("ERROR\n\n");
45
+ reportApiError(this, startResult.error, "start OAuth flow");
46
+ return;
47
+ }
48
+
49
+ this.process.stderr.write("OK\n\n");
50
+
51
+ const { authorizationUrl } = startResult.value;
52
+
53
+ this.writer.writeErr("Opening your browser to continue the OAuth flow...");
54
+ try {
55
+ await openNotionUrl(this.config.environment ?? "prod", authorizationUrl);
56
+ } catch (error) {
57
+ this.writer.writeErr(
58
+ `Unable to open the browser automatically (${String(
59
+ error,
60
+ )}). Please open the link below manually.`,
61
+ );
62
+ }
63
+
64
+ this.writer.writeErr("");
65
+ this.writer.writeErr("If the browser did not open, visit:");
66
+ this.writer.writeErr(` ${authorizationUrl}`);
67
+ this.writer.writeErr("");
68
+ this.writer.writeErr(
69
+ "After completing the flow in your browser, return to the CLI.",
70
+ );
71
+ });
72
+
73
+ export const listConnections = buildAuthedHandler(async function (
74
+ flags: FormatFlags,
75
+ ) {
76
+ const workerId = requireWorkerId(this);
77
+
78
+ this.process.stderr.write("Fetching OAuth connections...");
79
+ const secretsResult = await this.apiClient.listSecrets(workerId, {
80
+ secretKinds: ["oauth"],
81
+ });
82
+
83
+ if (Result.isFail(secretsResult)) {
84
+ this.process.stderr.write("ERROR\n\n");
85
+ reportApiError(this, secretsResult.error, "list OAuth connections");
86
+ return;
87
+ }
88
+
89
+ this.process.stderr.write("OK\n\n");
90
+
91
+ const secrets = secretsResult.value.secrets;
92
+
93
+ if (secrets.length === 0) {
94
+ this.writer.writeErr("No OAuth connections found for this worker.");
95
+ return;
96
+ }
97
+
98
+ this.writer.writeTableOut({
99
+ headers: ["Env Var", "Created At"],
100
+ rows: secrets.map((secret) => [
101
+ `process.env.${secret.key}`,
102
+ secret.createdAt,
103
+ ]),
104
+ plain: flags.plain,
105
+ });
106
+ });
107
+
108
+ export const removeConnection = buildAuthedHandler(async function (
109
+ _flags: GlobalFlags,
110
+ provider: string,
111
+ ) {
112
+ const workerId = requireWorkerId(this);
113
+
114
+ this.process.stderr.write(
115
+ `Removing OAuth connection for provider "${provider}"...`,
116
+ );
117
+ const result = await this.apiClient.deleteOauthConnection({
118
+ workerId,
119
+ provider,
120
+ });
121
+
122
+ if (Result.isFail(result)) {
123
+ this.process.stderr.write("ERROR\n\n");
124
+ reportApiError(this, result.error, "remove connection");
125
+ return;
126
+ }
127
+
128
+ this.process.stderr.write("OK\n");
129
+ });
130
+
131
+ function requireWorkerId(context: AuthedContext): string {
132
+ const workerId = context.config.workerId;
133
+ if (!workerId) {
134
+ throw new Error(
135
+ "No worker configured. Run 'workers deploy' first to create a worker.",
136
+ );
137
+ }
138
+ return workerId;
139
+ }
140
+
141
+ function reportApiError(
142
+ context: AuthedContext,
143
+ error: ApiError,
144
+ action: string,
145
+ ): never {
146
+ context.writer.writeErr(`✗ Failed to ${action}`);
147
+ context.writer.writeErr(`✗ ${error.message}`);
148
+ throw new Error(error.message);
149
+ }
@@ -0,0 +1,80 @@
1
+ import { buildCommand, buildRouteMap } from "@stricli/core";
2
+
3
+ import { formatFlags, globalFlags } from "../flags.js";
4
+
5
+ export const connectCommands = buildRouteMap({
6
+ docs: {
7
+ brief: "Manage OAuth connections for your worker",
8
+ },
9
+ routes: {
10
+ providers: buildCommand({
11
+ docs: {
12
+ brief: "List available OAuth providers",
13
+ },
14
+ parameters: {
15
+ flags: {
16
+ ...globalFlags,
17
+ ...formatFlags,
18
+ },
19
+ },
20
+ loader: () => import("./connect.impl.js").then((m) => m.listProviders),
21
+ }),
22
+
23
+ add: buildCommand({
24
+ docs: {
25
+ brief: "Start an OAuth flow for a provider",
26
+ },
27
+ parameters: {
28
+ positional: {
29
+ kind: "tuple",
30
+ parameters: [
31
+ {
32
+ brief: "Provider name (see `providers` command)",
33
+ parse: String,
34
+ placeholder: "provider",
35
+ },
36
+ ],
37
+ },
38
+ flags: {
39
+ ...globalFlags,
40
+ },
41
+ },
42
+ loader: () => import("./connect.impl.js").then((m) => m.addConnection),
43
+ }),
44
+
45
+ list: buildCommand({
46
+ docs: {
47
+ brief: "List active OAuth connections",
48
+ },
49
+ parameters: {
50
+ flags: {
51
+ ...globalFlags,
52
+ ...formatFlags,
53
+ },
54
+ },
55
+ loader: () => import("./connect.impl.js").then((m) => m.listConnections),
56
+ }),
57
+
58
+ rm: buildCommand({
59
+ docs: {
60
+ brief: "Remove an OAuth connection",
61
+ },
62
+ parameters: {
63
+ positional: {
64
+ kind: "tuple",
65
+ parameters: [
66
+ {
67
+ brief: "Provider name to remove",
68
+ parse: String,
69
+ placeholder: "provider",
70
+ },
71
+ ],
72
+ },
73
+ flags: {
74
+ ...globalFlags,
75
+ },
76
+ },
77
+ loader: () => import("./connect.impl.js").then((m) => m.removeConnection),
78
+ }),
79
+ },
80
+ });
@@ -52,12 +52,18 @@ export const listSecrets = buildAuthedHandler(async function (
52
52
  const data = Result.unwrap(result);
53
53
  if (data.secrets.length === 0) {
54
54
  this.writer.writeErr("No secrets for this worker.");
55
+ this.writer.writeErr(
56
+ "To list OAuth connect secrets, use `npx workers connect list`",
57
+ );
55
58
  } else {
56
59
  this.writer.writeTableOut({
57
60
  headers: ["Key", "Created At"],
58
61
  rows: data.secrets.map((secret) => [secret.key, secret.createdAt]),
59
62
  plain: flags.plain,
60
63
  });
64
+ this.writer.writeErr(
65
+ "To list OAuth connect secrets, use `npx workers connect list`",
66
+ );
61
67
  }
62
68
  } else {
63
69
  this.process.stderr.write("ERROR\n\n");
package/src/cli/routes.ts CHANGED
@@ -3,6 +3,7 @@ import packageJson from "../../package.json" with { type: "json" };
3
3
  import { authCommands } from "./commands/auth.js";
4
4
  import { bundleCommands } from "./commands/bundle.js";
5
5
  import { capabilitiesCommands } from "./commands/capabilities.js";
6
+ import { connectCommands } from "./commands/connect.js";
6
7
  import deploy from "./commands/deploy.js";
7
8
  import exec from "./commands/exec.js";
8
9
  import { runsCommands } from "./commands/runs.js";
@@ -18,6 +19,7 @@ const routes = buildRouteMap({
18
19
  capabilities: capabilitiesCommands,
19
20
  deploy: deploy,
20
21
  exec: exec,
22
+ connect: connectCommands,
21
23
  runs: runsCommands,
22
24
  secrets: secretsCommands,
23
25
  bundle: bundleCommands,
@@ -0,0 +1,40 @@
1
+ import { exec } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+
4
+ import type { Environment } from "../config.js";
5
+
6
+ export async function openNotionUrl(
7
+ env: Environment,
8
+ url: string,
9
+ ): Promise<void> {
10
+ const platform = process.platform;
11
+
12
+ try {
13
+ if (platform === "darwin") {
14
+ const appName = preferredNotionApp(env);
15
+ if (appName) {
16
+ exec(`open -a "${appName}" "${url}"`);
17
+ } else {
18
+ exec(`open "${url}"`);
19
+ }
20
+ } else if (platform === "win32") {
21
+ exec(`start "" "${url}"`);
22
+ } else {
23
+ exec(`xdg-open "${url}"`);
24
+ }
25
+ } catch (error) {
26
+ throw new Error(`Failed to open browser: ${error}`);
27
+ }
28
+ }
29
+
30
+ function preferredNotionApp(env: Environment): string | null {
31
+ if (env === "prod" && existsSync("/Applications/Notion.app")) {
32
+ return "Notion";
33
+ }
34
+
35
+ if (env === "dev" && existsSync("/Applications/Notion Dev.app")) {
36
+ return "Notion Dev";
37
+ }
38
+
39
+ return null;
40
+ }