@antlur/backstage 1.0.9 → 1.0.10

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 (86) hide show
  1. package/dist/cjs/components/json-ld.js +8 -0
  2. package/dist/cjs/config.js +2 -3
  3. package/dist/cjs/endpoints/alerts.js +1 -2
  4. package/dist/cjs/endpoints/events.js +3 -4
  5. package/dist/cjs/endpoints/locations.js +2 -3
  6. package/dist/cjs/endpoints/menus.js +3 -4
  7. package/dist/cjs/endpoints/navigation.js +3 -4
  8. package/dist/cjs/endpoints/pages.js +4 -5
  9. package/dist/cjs/endpoints/press.js +1 -2
  10. package/dist/cjs/endpoints/website.js +1 -2
  11. package/dist/cjs/util/event.js +70 -0
  12. package/dist/cjs/util/gtag.js +14 -0
  13. package/dist/cjs/util/imgproxy-loader.js +14 -0
  14. package/dist/cjs/util/publishing.js +6 -0
  15. package/dist/cjs/util/special-hours.js +23 -0
  16. package/dist/esm/components/json-ld.d.ts +7 -0
  17. package/dist/esm/components/json-ld.d.ts.map +1 -0
  18. package/dist/esm/components/json-ld.js +5 -0
  19. package/dist/esm/types/location.d.ts +2 -0
  20. package/dist/esm/types/location.d.ts.map +1 -1
  21. package/dist/esm/types/website.d.ts +1 -0
  22. package/dist/esm/types/website.d.ts.map +1 -1
  23. package/dist/esm/util/event.d.ts +8 -0
  24. package/dist/esm/util/event.d.ts.map +1 -0
  25. package/dist/esm/util/event.js +63 -0
  26. package/dist/esm/util/gtag.d.ts +23 -0
  27. package/dist/esm/util/gtag.d.ts.map +1 -0
  28. package/dist/esm/util/gtag.js +10 -0
  29. package/dist/esm/util/imgproxy-loader.d.ts +9 -0
  30. package/dist/esm/util/imgproxy-loader.d.ts.map +1 -0
  31. package/dist/esm/util/imgproxy-loader.js +11 -0
  32. package/dist/esm/util/publishing.d.ts +2 -0
  33. package/dist/esm/util/publishing.d.ts.map +1 -0
  34. package/dist/esm/util/publishing.js +3 -0
  35. package/dist/esm/util/special-hours.d.ts +3 -0
  36. package/dist/esm/util/special-hours.d.ts.map +1 -0
  37. package/dist/esm/util/special-hours.js +20 -0
  38. package/dist/types/components/json-ld.d.ts +7 -0
  39. package/dist/types/components/json-ld.d.ts.map +1 -0
  40. package/dist/types/types/location.d.ts +2 -0
  41. package/dist/types/types/location.d.ts.map +1 -1
  42. package/dist/types/types/website.d.ts +1 -0
  43. package/dist/types/types/website.d.ts.map +1 -1
  44. package/dist/types/util/event.d.ts +8 -0
  45. package/dist/types/util/event.d.ts.map +1 -0
  46. package/dist/types/util/gtag.d.ts +23 -0
  47. package/dist/types/util/gtag.d.ts.map +1 -0
  48. package/dist/types/util/imgproxy-loader.d.ts +9 -0
  49. package/dist/types/util/imgproxy-loader.d.ts.map +1 -0
  50. package/dist/types/util/publishing.d.ts +2 -0
  51. package/dist/types/util/publishing.d.ts.map +1 -0
  52. package/dist/types/util/special-hours.d.ts +3 -0
  53. package/dist/types/util/special-hours.d.ts.map +1 -0
  54. package/package.json +31 -4
  55. package/src/client.ts +97 -0
  56. package/src/components/json-ld.tsx +9 -0
  57. package/src/config.ts +31 -0
  58. package/src/constants/google-events.ts +13 -0
  59. package/src/endpoints/alerts.ts +7 -0
  60. package/src/endpoints/events.ts +20 -0
  61. package/src/endpoints/locations.ts +25 -0
  62. package/src/endpoints/menus.ts +30 -0
  63. package/src/endpoints/navigation.ts +34 -0
  64. package/src/endpoints/pages.ts +23 -0
  65. package/src/endpoints/press.ts +7 -0
  66. package/src/endpoints/website.ts +7 -0
  67. package/src/index.ts +18 -0
  68. package/src/types/alert.ts +11 -0
  69. package/src/types/api.ts +12 -0
  70. package/src/types/event.ts +14 -0
  71. package/src/types/index.ts +13 -0
  72. package/src/types/location.ts +69 -0
  73. package/src/types/media-item.ts +10 -0
  74. package/src/types/menu-category-item.ts +18 -0
  75. package/src/types/menu-category.ts +15 -0
  76. package/src/types/menu-item.ts +15 -0
  77. package/src/types/menu.ts +12 -0
  78. package/src/types/navigation.ts +17 -0
  79. package/src/types/page.ts +24 -0
  80. package/src/types/press.ts +13 -0
  81. package/src/types/website.ts +76 -0
  82. package/src/util/event.ts +77 -0
  83. package/src/util/gtag.ts +40 -0
  84. package/src/util/imgproxy-loader.ts +22 -0
  85. package/src/util/publishing.ts +3 -0
  86. package/src/util/special-hours.ts +24 -0
@@ -1 +1 @@
1
- {"version":3,"file":"website.d.ts","sourceRoot":"","sources":["../../../src/types/website.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACnC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B"}
1
+ {"version":3,"file":"website.d.ts","sourceRoot":"","sources":["../../../src/types/website.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,UAAU,EAAE,SAAS,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;IACb,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IACnC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wBAAwB,EAAE,OAAO,CAAC;CACnC"}
@@ -0,0 +1,8 @@
1
+ import type { Event, Location, Website } from "../types";
2
+ import { Event as SchemaEvent, WithContext } from "schema-dts";
3
+ export declare function isMultipleDays(start: Date, end: Date): boolean;
4
+ export declare function dateString(event: Event): string;
5
+ export declare function timeString(event: Event): string;
6
+ export declare function shortDescription(event: Event): string;
7
+ export declare function makeEventSchema(website: Website, event: Event, locations: Location[]): WithContext<SchemaEvent>;
8
+ //# sourceMappingURL=event.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../../../src/util/event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE/D,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,WAEpD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,UAkBtC;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,UAQtC;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,UAQ5C;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,WAAW,CAAC,CA6B/G"}
@@ -0,0 +1,23 @@
1
+ import { GAEvents } from "../constants/google-events";
2
+ declare global {
3
+ interface Window {
4
+ gtag?: (...args: any[]) => void;
5
+ }
6
+ }
7
+ export declare function gtag(...args: any[]): void;
8
+ interface GtagEventParams {
9
+ category?: string;
10
+ label?: string;
11
+ value?: number;
12
+ page_url?: string;
13
+ location?: string;
14
+ store?: string | null | undefined;
15
+ /** @deprecated Use category instead */
16
+ event_category?: string;
17
+ /** @deprecated Use label instead */
18
+ event_label?: string;
19
+ }
20
+ type GtagEventName = keyof typeof GAEvents | (string & {});
21
+ export declare function gtagEvent(name: GtagEventName, params?: GtagEventParams): void;
22
+ export {};
23
+ //# sourceMappingURL=gtag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gtag.d.ts","sourceRoot":"","sources":["../../../src/util/gtag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAe,MAAM,4BAA4B,CAAC;AAGnE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC;KACjC;CACF;AAED,wBAAgB,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,QAIlC;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAElC,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,aAAa,GAAG,MAAM,OAAO,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAE3D,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,GAAE,eAAoB,QAI1E"}
@@ -0,0 +1,9 @@
1
+ interface ImgproxyLoaderProps {
2
+ src: string;
3
+ width?: number;
4
+ height?: number;
5
+ quality?: number;
6
+ }
7
+ export default function imgproxyLoader({ src, width, height, quality }: ImgproxyLoaderProps): string;
8
+ export {};
9
+ //# sourceMappingURL=imgproxy-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imgproxy-loader.d.ts","sourceRoot":"","sources":["../../../src/util/imgproxy-loader.ts"],"names":[],"mappings":"AAAA,UAAU,mBAAmB;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,mBAAmB,UAc1F"}
@@ -0,0 +1,2 @@
1
+ export declare function filterPublishedItems(items: any[]): any[];
2
+ //# sourceMappingURL=publishing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publishing.d.ts","sourceRoot":"","sources":["../../../src/util/publishing.ts"],"names":[],"mappings":"AAAA,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,SAEhD"}
@@ -0,0 +1,3 @@
1
+ import type { Location } from "../types";
2
+ export declare function getSpecialHoursFromLocation(location: Location): any[];
3
+ //# sourceMappingURL=special-hours.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"special-hours.d.ts","sourceRoot":"","sources":["../../../src/util/special-hours.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAGzC,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,GAAG,GAAG,EAAE,CAoBrE"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@antlur/backstage",
3
3
  "author": "Anthony Holmes",
4
- "version": "1.0.9",
4
+ "version": "1.0.10",
5
5
  "description": "A simple client for Backstage CMS",
6
6
  "main": "./dist/cjs/index.js",
7
7
  "module": "./dist/esm/index.js",
@@ -11,6 +11,16 @@
11
11
  "require": "./dist/cjs/index.js",
12
12
  "import": "./dist/esm/index.js",
13
13
  "types": "./dist/types/index.d.ts"
14
+ },
15
+ "./types": {
16
+ "require": "./dist/cjs/types/index.js",
17
+ "import": "./dist/esm/types/index.js",
18
+ "types": "./dist/types/types/*.d.ts"
19
+ },
20
+ "./*": {
21
+ "require": "./dist/cjs/*.js",
22
+ "import": "./dist/esm/*.js",
23
+ "types": "./dist/types/*.d.ts"
14
24
  }
15
25
  },
16
26
  "scripts": {
@@ -19,16 +29,33 @@
19
29
  "build:cjs": "tsc --project tsconfig.cjs.json",
20
30
  "build:esm": "tsc --project tsconfig.esm.json",
21
31
  "prepublishOnly": "npm run build && npm test",
32
+ "watch": "npm run watch:cjs & npm run watch:esm",
33
+ "watch:cjs": "tsc --project tsconfig.cjs.json --watch",
34
+ "watch:esm": "tsc --project tsconfig.esm.json --watch",
22
35
  "test": "echo \"No tests yet\" && exit 0"
23
36
  },
37
+ "peerDependencies": {
38
+ "luxon": "^3.5.0",
39
+ "react": "^18.0.0 || ^19.0.0",
40
+ "react-dom": "^18.0.0 || ^19.0.0"
41
+ },
24
42
  "dependencies": {
25
- "axios": "^1.3.0"
43
+ "axios": "^1.7.9",
44
+ "schema-dts": "^1.1.2"
26
45
  },
27
46
  "devDependencies": {
47
+ "@types/luxon": "^3.4.2",
28
48
  "@types/node": "^22.10.5",
29
- "typescript": "^4.8.0"
49
+ "@types/react": "^19.0.2",
50
+ "@types/react-dom": "^19.0.2",
51
+ "luxon": "^3.5.0",
52
+ "react": "^19.0.0",
53
+ "react-dom": "^19.0.0",
54
+ "typescript": "^5.7.2"
30
55
  },
31
56
  "files": [
32
- "dist"
57
+ "dist",
58
+ "src",
59
+ "readme.md"
33
60
  ]
34
61
  }
package/src/client.ts ADDED
@@ -0,0 +1,97 @@
1
+ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from "axios";
2
+ import { getGlobalConfig, BackstageUserConfig } from "./config";
3
+
4
+ export class BackstageClient {
5
+ private instance: AxiosInstance;
6
+
7
+ constructor(config?: BackstageUserConfig) {
8
+ // If no config is passed, try to get from the global config
9
+ const globalConfig = getGlobalConfig();
10
+ const finalConfig = config || globalConfig;
11
+
12
+ if (!finalConfig) {
13
+ throw new Error("No Backstage config found. Please call defineConfig() or pass config to BackstageClient.");
14
+ }
15
+
16
+ // check for token and accountId in the config
17
+ if (!finalConfig.token) {
18
+ throw new Error("No token found in the Backstage config. Please provide a token.");
19
+ }
20
+
21
+ if (!finalConfig.accountId) {
22
+ throw new Error("No accountId found in the Backstage config. Please provide an accountId.");
23
+ }
24
+
25
+ const { baseURL, token, onError } = finalConfig;
26
+
27
+ this.instance = axios.create({
28
+ baseURL,
29
+ headers: {
30
+ Authorization: `Bearer ${token}`,
31
+ "X-Account-ID": finalConfig.accountId,
32
+ Accept: "application/json",
33
+ "Content-Type": "application/json",
34
+ },
35
+ });
36
+
37
+ // Add request interceptor for debugging
38
+ this.instance.interceptors.request.use((requestConfig) => {
39
+ // console.log("Request:", {
40
+ // method: requestConfig.method,
41
+ // url: requestConfig.url,
42
+ // headers: requestConfig.headers,
43
+ // data: requestConfig.data,
44
+ // });
45
+ return requestConfig;
46
+ });
47
+
48
+ // Add response interceptor for debugging
49
+ this.instance.interceptors.response.use(
50
+ (response) => response,
51
+ (error) => {
52
+ // console.error("API Error:", {
53
+ // status: error.response?.status,
54
+ // method: error.config?.method,
55
+ // url: error.config?.url,
56
+ // headers: error.config?.headers,
57
+ // data: error.response?.data,
58
+ // });
59
+ if (onError) onError(error);
60
+ return Promise.reject(error);
61
+ }
62
+ );
63
+ }
64
+
65
+ public async get<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
66
+ const response = await this.instance.get<T>(url, config);
67
+ return response.data;
68
+ }
69
+
70
+ public async post<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
71
+ const response = await this.instance.post<T>(url, data, config);
72
+ return response.data;
73
+ }
74
+
75
+ public async put<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
76
+ const response = await this.instance.put<T>(url, data, config);
77
+ return response.data;
78
+ }
79
+
80
+ public async patch<T = unknown>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<T> {
81
+ const response = await this.instance.patch<T>(url, data, config);
82
+ return response.data;
83
+ }
84
+
85
+ public async delete<T = unknown>(url: string, config?: AxiosRequestConfig): Promise<T> {
86
+ const response = await this.instance.delete<T>(url, config);
87
+ return response.data;
88
+ }
89
+
90
+ public getAxiosInstance(): AxiosInstance {
91
+ return this.instance;
92
+ }
93
+ }
94
+
95
+ export const client = function (config?: BackstageUserConfig): BackstageClient {
96
+ return new BackstageClient(config);
97
+ };
@@ -0,0 +1,9 @@
1
+ interface JsonLdProps {
2
+ schema: any;
3
+ id: string;
4
+ }
5
+
6
+ export function JsonLd({ schema, id }: JsonLdProps) {
7
+ const schemaString = JSON.stringify(schema);
8
+ return <script id={id} type="application/ld+json" dangerouslySetInnerHTML={{ __html: schemaString }}></script>;
9
+ }
package/src/config.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { AxiosError } from "axios";
2
+
3
+ const ROOT = process.cwd();
4
+ const CONFIG_PATH = process.env.BACKSTAGE_CONFIG_PATH || "./backstage.config";
5
+ const DEFAULT_BASE_URL = "https://bckstg.app/api";
6
+
7
+ export interface BackstageUserConfig {
8
+ accountId?: string | undefined;
9
+ token?: string | undefined;
10
+ baseURL?: string;
11
+ onError?: (error: AxiosError) => void;
12
+ }
13
+
14
+ let globalConfig: BackstageUserConfig = {
15
+ baseURL: process.env.BACKSTAGE_API_URL ?? DEFAULT_BASE_URL,
16
+ token: process.env.BACKSTAGE_API_KEY ?? undefined,
17
+ accountId: process.env.BACKSTAGE_ACCOUNT_ID ?? undefined,
18
+ };
19
+
20
+ export function defineConfig(config: BackstageUserConfig): BackstageUserConfig {
21
+ globalConfig = {
22
+ ...globalConfig,
23
+ ...config,
24
+ };
25
+ return globalConfig;
26
+ }
27
+
28
+ export function getGlobalConfig(): BackstageUserConfig {
29
+ // read the config from the project root
30
+ return globalConfig;
31
+ }
@@ -0,0 +1,13 @@
1
+ export const GAEvents = {
2
+ CLICK_TO_MAP: "click_to_map",
3
+ CLICK_TO_CALL: "click_to_call",
4
+ CLICK_TO_SOCIAL: "click_to_social",
5
+ CLICK_TO_WAITLIST: "click_to_waitlist",
6
+ FIND_LOCATION: "find_location",
7
+ CLICK_TO_ORDER: "click_to_order",
8
+ };
9
+
10
+ export const GALocations = {
11
+ LOCATION_CARD: "location_card",
12
+ TOPBAR: "topbar",
13
+ };
@@ -0,0 +1,7 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Alert } from "../types";
3
+
4
+ export async function getAlerts() {
5
+ const { data } = await client().get<ApiCollectionResponse<Alert>>("/alerts");
6
+ return data;
7
+ }
@@ -0,0 +1,20 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Event } from "../types";
3
+
4
+ export async function getEvents(): Promise<Event[]> {
5
+ const res = await client().get<ApiCollectionResponse<Event>>("/events");
6
+ const pages = res.data;
7
+ return pages;
8
+ }
9
+
10
+ export async function getEvent(id: string): Promise<Event> {
11
+ const res = await client().get<ApiCollectionResponse<Event>>("/events" + "?filter[id]=" + id);
12
+ const pages = res.data?.[0];
13
+ return pages;
14
+ }
15
+
16
+ export async function getEventBySlug(slug: string): Promise<Event> {
17
+ const res = await client().get<ApiCollectionResponse<Event>>("/events" + "?filter[slug]=" + slug);
18
+ const pages = res.data?.[0];
19
+ return pages;
20
+ }
@@ -0,0 +1,25 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Location } from "../types";
3
+
4
+ export async function getLocations(): Promise<Location[]> {
5
+ const res = await client().get<ApiCollectionResponse<Location>>("/locations");
6
+ let locations = res.data;
7
+ locations = locations.sort((a: any, b: any) => {
8
+ if (a.name < b.name) {
9
+ return -1;
10
+ }
11
+ return 1;
12
+ });
13
+ return locations;
14
+ }
15
+
16
+ export async function getLocationBySlug(slug: string) {
17
+ const res = await client().get<ApiCollectionResponse<Location>>(`/locations?filter[slug]=${slug}`);
18
+ const data = res.data;
19
+
20
+ if (Array.isArray(data) && data.length > 0) {
21
+ return data[0];
22
+ }
23
+
24
+ return data;
25
+ }
@@ -0,0 +1,30 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Menu } from "../types";
3
+
4
+ export async function getMenus(): Promise<Menu[]> {
5
+ const res = await client().get<ApiCollectionResponse<Menu>>("/menus");
6
+ const menus = res.data;
7
+ return menus;
8
+ }
9
+
10
+ export async function getMenu(id: string) {
11
+ const res = await client().get<ApiCollectionResponse<Menu>>(`/menus?filter[id]=${id}&include=categories.items`);
12
+ const data = res.data;
13
+
14
+ if (Array.isArray(data) && data.length > 0) {
15
+ return data[0];
16
+ }
17
+
18
+ return data;
19
+ }
20
+
21
+ export async function getMenuBySlug(slug: string) {
22
+ const res = await client().get<ApiCollectionResponse<Menu>>(`/menus?filter[slug]=${slug}&include=categories.items`);
23
+ const data = res.data;
24
+
25
+ if (Array.isArray(data) && data.length > 0) {
26
+ return data[0];
27
+ }
28
+
29
+ return data;
30
+ }
@@ -0,0 +1,34 @@
1
+ import { client } from "../client";
2
+ import { ApiSingleResponse, ApiCollectionResponse, Navigation } from "../types";
3
+
4
+ export async function getDefaultNavigation(): Promise<Navigation> {
5
+ const navigations = await getNavigations();
6
+ return navigations[0];
7
+ }
8
+
9
+ export async function getNavigations(): Promise<Navigation[]> {
10
+ const res = await client().get<ApiCollectionResponse<Navigation>>("/navigations");
11
+ const navigations = res.data;
12
+
13
+ return Promise.all(
14
+ navigations.map(async (navigation: any) => {
15
+ const res = await client().get<ApiCollectionResponse<Navigation>>("/navigations/" + navigation.id);
16
+ return res.data[0];
17
+ })
18
+ );
19
+ }
20
+
21
+ export async function getNavigation(id: string): Promise<Navigation> {
22
+ const res = await client().get<ApiSingleResponse<Navigation>>(`/navigations/${id}`);
23
+ const navigation = res.data;
24
+
25
+ const topLevelItems = navigation.items.filter((item: any) => item.parent_id === null);
26
+
27
+ topLevelItems.forEach((item: any) => {
28
+ item.children = navigation.items.filter((child: any) => child.parent_id === item.id);
29
+ });
30
+
31
+ navigation.items = topLevelItems;
32
+
33
+ return navigation;
34
+ }
@@ -0,0 +1,23 @@
1
+ import { client } from "../client";
2
+ import { Page } from "../types/page";
3
+ import { ApiCollectionResponse } from "../types/api";
4
+
5
+ export async function getPage(slug: string): Promise<Page> {
6
+ const res = await client().get<ApiCollectionResponse<Page>>(`/pages/?filter[slug]=${slug}`);
7
+ return res.data[0];
8
+ }
9
+
10
+ export async function getPages() {
11
+ const { data } = await client().get<ApiCollectionResponse<Page>>("/pages");
12
+ return data;
13
+ }
14
+
15
+ export async function getHomePage() {
16
+ const res = await client().get<ApiCollectionResponse<Page>>("/pages?filter[slug]=/");
17
+ return res.data[0];
18
+ }
19
+
20
+ export async function getPageBySlug(slug: string) {
21
+ const res = await client().get<ApiCollectionResponse<Page>>("/pages?filter[slug]=" + slug);
22
+ return res.data[0];
23
+ }
@@ -0,0 +1,7 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Press } from "../types";
3
+
4
+ export async function getPress(): Promise<Press[]> {
5
+ const { data } = await client().get<ApiCollectionResponse<Press>>("/press");
6
+ return data;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { client } from "../client";
2
+ import { ApiCollectionResponse, Website } from "../types";
3
+
4
+ export async function getWebsite(): Promise<Website> {
5
+ const res = await client().get<ApiCollectionResponse<Website>>("/websites");
6
+ return res.data[0];
7
+ }
package/src/index.ts ADDED
@@ -0,0 +1,18 @@
1
+ // Re-export config
2
+ export { defineConfig, getGlobalConfig } from "./config";
3
+
4
+ // Re-export the client class
5
+ export { BackstageClient } from "./client";
6
+
7
+ // Re-export endpoints
8
+ export * from "./endpoints/alerts";
9
+ export * from "./endpoints/events";
10
+ export * from "./endpoints/locations";
11
+ export * from "./endpoints/menus";
12
+ export * from "./endpoints/navigation";
13
+ export * from "./endpoints/pages";
14
+ export * from "./endpoints/press";
15
+ export * from "./endpoints/website";
16
+
17
+ // Re-export domain types
18
+ export * from "./types";
@@ -0,0 +1,11 @@
1
+ export interface Alert {
2
+ id: string;
3
+ title: string;
4
+ type: string;
5
+ is_global: boolean;
6
+ published: boolean;
7
+ pages: {
8
+ id: string;
9
+ slug: string;
10
+ }[];
11
+ }
@@ -0,0 +1,12 @@
1
+ export interface ApiCollectionResponse<T> {
2
+ data: T[];
3
+ meta: {
4
+ current_page: number;
5
+ from: number;
6
+ last_page: number;
7
+ };
8
+ }
9
+
10
+ export interface ApiSingleResponse<T> {
11
+ data: T;
12
+ }
@@ -0,0 +1,14 @@
1
+ import { MediaItem } from "./media-item";
2
+
3
+ export interface Event {
4
+ id: number;
5
+ title: string;
6
+ short_description: string;
7
+ description: string;
8
+ start_time: string; // or Date if the date is being converted before being used in TypeScript
9
+ end_time: string; // or Date if the date is being converted before being used in TypeScript
10
+ timezone: string;
11
+ cover_media_id: number;
12
+ cover_media: MediaItem; // Replace 'any' with the actual type of the cover_media
13
+ account_id: number;
14
+ }
@@ -0,0 +1,13 @@
1
+ export * from "./alert";
2
+ export * from "./api";
3
+ export * from "./event";
4
+ export * from "./location";
5
+ export * from "./media-item";
6
+ export * from "./menu-category-item";
7
+ export * from "./menu-category";
8
+ export * from "./menu-item";
9
+ export * from "./menu";
10
+ export * from "./navigation";
11
+ export * from "./page";
12
+ export * from "./press";
13
+ export * from "./website";
@@ -0,0 +1,69 @@
1
+ export interface Location {
2
+ id: string;
3
+ account_id: string;
4
+ google_my_business_id: string | null;
5
+ name: string;
6
+ slug: string | null;
7
+ description: string | null;
8
+ featured_media_id: number;
9
+ address: string;
10
+ address2: string;
11
+ city: string;
12
+ state: string;
13
+ zip: string;
14
+ map_link: string | null;
15
+ map_embed: string | null;
16
+ latitude: number | null;
17
+ longitude: number | null;
18
+ phone: string;
19
+ email: string;
20
+ timezone: string | null;
21
+ hours: {
22
+ day: string;
23
+ openTime: string;
24
+ closeTime: string;
25
+ open24Hours: boolean;
26
+ closed24Hours: boolean;
27
+ notes: string;
28
+ }[];
29
+ special_hours: {
30
+ id: string;
31
+ date: string;
32
+ openTime: string;
33
+ closeTime: string;
34
+ open24Hours: boolean;
35
+ closed24Hours: boolean;
36
+ notes: string;
37
+ }[];
38
+ ordering_links: {
39
+ service: string;
40
+ url: string;
41
+ }[];
42
+ delivery_links: {
43
+ service: string;
44
+ url: string;
45
+ }[];
46
+ reservation_links: {
47
+ service: string;
48
+ url: string;
49
+ }[];
50
+ waitlist_links: {
51
+ service: string;
52
+ url: string;
53
+ }[];
54
+ loyalty_url: string | null;
55
+ created_at: string;
56
+ updated_at: string;
57
+ featured_media: {
58
+ id: number;
59
+ file_name: string;
60
+ url: string;
61
+ transform_url: string;
62
+ path: string;
63
+ width: number;
64
+ height: number;
65
+ alt: string;
66
+ };
67
+ status: string;
68
+ status_text: string;
69
+ }
@@ -0,0 +1,10 @@
1
+ export interface MediaItem {
2
+ id: string;
3
+ file_name: string;
4
+ url: string;
5
+ transform_url: string;
6
+ path: string;
7
+ width: number;
8
+ height: number;
9
+ alt: string;
10
+ }
@@ -0,0 +1,18 @@
1
+ import { MenuItem } from "./menu-item";
2
+
3
+ export interface MenuCategoryItem {
4
+ id: string;
5
+ menu_category_id: string;
6
+ menu_item_id: string;
7
+ title: string;
8
+ post_title: string | null;
9
+ subtitle: string | null;
10
+ description: string | null;
11
+ price: number | null;
12
+ order: number;
13
+ price2: number | null;
14
+ image_id: string | null;
15
+ created_at: string;
16
+ updated_at: string;
17
+ menu_item: MenuItem;
18
+ }
@@ -0,0 +1,15 @@
1
+ import { MenuCategoryItem } from "./menu-category-item";
2
+
3
+ export interface MenuCategory {
4
+ id: string;
5
+ title: string;
6
+ subtitle: string | null;
7
+ description: string | null;
8
+ after_description: string | null;
9
+ column_count: number | null;
10
+ menu_id: string;
11
+ order: number;
12
+ created_at: string;
13
+ updated_at: string;
14
+ items: MenuCategoryItem[];
15
+ }