@leadertechie/personal-site-kit 0.1.0-alpha.7 → 0.1.0-alpha.9
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/api/content-utils.d.ts +27 -0
- package/dist/api/content-utils.d.ts.map +1 -0
- package/dist/api/handlers/about-me.d.ts.map +1 -1
- package/dist/api/handlers/content-api.d.ts +0 -1
- package/dist/api/handlers/content-api.d.ts.map +1 -1
- package/dist/api/website-api.d.ts.map +1 -1
- package/dist/api.js +2 -2
- package/dist/chunks/index-CGvOrVf8.js +213 -0
- package/dist/chunks/{index-Bq8WDk9L.js → index-CnSEOZse.js} +1285 -477
- package/dist/chunks/{template-Boh_MKY5.js → template-DWcsZW22.js} +8 -7
- package/dist/chunks/{website-api-XoeLwo_N.js → website-api-BEYGOsT3.js} +137 -156
- package/dist/index.js +19 -9
- package/dist/prerender/data-fetcher.d.ts +19 -0
- package/dist/prerender/data-fetcher.d.ts.map +1 -0
- package/dist/prerender/page-content.d.ts.map +1 -1
- package/dist/prerender/page-generators/about.d.ts +16 -0
- package/dist/prerender/page-generators/about.d.ts.map +1 -0
- package/dist/prerender/page-generators/base.d.ts +26 -0
- package/dist/prerender/page-generators/base.d.ts.map +1 -0
- package/dist/prerender/page-generators/blog-detail.d.ts +15 -0
- package/dist/prerender/page-generators/blog-detail.d.ts.map +1 -0
- package/dist/prerender/page-generators/blogs-list.d.ts +17 -0
- package/dist/prerender/page-generators/blogs-list.d.ts.map +1 -0
- package/dist/prerender/page-generators/home.d.ts +19 -0
- package/dist/prerender/page-generators/home.d.ts.map +1 -0
- package/dist/prerender/page-generators/index.d.ts +9 -0
- package/dist/prerender/page-generators/index.d.ts.map +1 -0
- package/dist/prerender/page-generators/not-found.d.ts +14 -0
- package/dist/prerender/page-generators/not-found.d.ts.map +1 -0
- package/dist/prerender/page-generators/stories-list.d.ts +17 -0
- package/dist/prerender/page-generators/stories-list.d.ts.map +1 -0
- package/dist/prerender/page-generators/story-detail.d.ts +15 -0
- package/dist/prerender/page-generators/story-detail.d.ts.map +1 -0
- package/dist/prerender.js +109 -102
- package/dist/shared.js +1 -1
- package/dist/ui/about-me/index.d.ts +2 -10
- package/dist/ui/about-me/index.d.ts.map +1 -1
- package/dist/ui/admin/api.d.ts +16 -0
- package/dist/ui/admin/api.d.ts.map +1 -0
- package/dist/ui/admin/components/AboutMeSection.d.ts +7 -0
- package/dist/ui/admin/components/AboutMeSection.d.ts.map +1 -0
- package/dist/ui/admin/components/AdminSection.d.ts +13 -0
- package/dist/ui/admin/components/AdminSection.d.ts.map +1 -0
- package/dist/ui/admin/components/BlogsSection.d.ts +7 -0
- package/dist/ui/admin/components/BlogsSection.d.ts.map +1 -0
- package/dist/ui/admin/components/HomeSection.d.ts +7 -0
- package/dist/ui/admin/components/HomeSection.d.ts.map +1 -0
- package/dist/ui/admin/components/ImagesSection.d.ts +7 -0
- package/dist/ui/admin/components/ImagesSection.d.ts.map +1 -0
- package/dist/ui/admin/components/LoginForm.d.ts +9 -0
- package/dist/ui/admin/components/LoginForm.d.ts.map +1 -0
- package/dist/ui/admin/components/LogoSection.d.ts +7 -0
- package/dist/ui/admin/components/LogoSection.d.ts.map +1 -0
- package/dist/ui/admin/components/ProfileSection.d.ts +7 -0
- package/dist/ui/admin/components/ProfileSection.d.ts.map +1 -0
- package/dist/ui/admin/components/StaticSection.d.ts +13 -0
- package/dist/ui/admin/components/StaticSection.d.ts.map +1 -0
- package/dist/ui/admin/components/StoriesSection.d.ts +7 -0
- package/dist/ui/admin/components/StoriesSection.d.ts.map +1 -0
- package/dist/ui/admin/components/index.d.ts +11 -0
- package/dist/ui/admin/components/index.d.ts.map +1 -0
- package/dist/ui/admin/index.d.ts +18 -26
- package/dist/ui/admin/index.d.ts.map +1 -1
- package/dist/ui/admin/types.d.ts +24 -0
- package/dist/ui/admin/types.d.ts.map +1 -0
- package/dist/ui/blog-viewer/index.d.ts.map +1 -1
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/story-viewer/index.d.ts.map +1 -1
- package/dist/ui.js +14 -4
- package/package.json +4 -4
- package/dist/ui/about-me/renderer.d.ts +0 -6
- package/dist/ui/about-me/renderer.d.ts.map +0 -1
- package/src/api/__tests__/info.test.ts +0 -44
- package/src/api/__tests__/utils.test.ts +0 -78
- package/src/api/handlers/about-me.ts +0 -99
- package/src/api/handlers/auth-handler.ts +0 -194
- package/src/api/handlers/auth.ts +0 -157
- package/src/api/handlers/content-api.ts +0 -268
- package/src/api/handlers/content.ts +0 -139
- package/src/api/handlers/home.ts +0 -79
- package/src/api/handlers/info.ts +0 -12
- package/src/api/handlers/logo.ts +0 -55
- package/src/api/handlers/static-details.ts +0 -48
- package/src/api/index.ts +0 -9
- package/src/api/utils.ts +0 -16
- package/src/api/website-api.ts +0 -138
- package/src/index.ts +0 -4
- package/src/prerender/__tests__/page-content.test.ts +0 -54
- package/src/prerender/__tests__/template.test.ts +0 -54
- package/src/prerender/index.ts +0 -7
- package/src/prerender/page-content.ts +0 -263
- package/src/prerender/prerender.ts +0 -25
- package/src/prerender/template.ts +0 -65
- package/src/prerender/website-prerender.ts +0 -152
- package/src/shared/config/api.ts +0 -16
- package/src/shared/config/index.ts +0 -43
- package/src/shared/config/types.ts +0 -16
- package/src/shared/core/__tests__/theme-toggle.test.ts +0 -204
- package/src/shared/core/site-store.ts +0 -38
- package/src/shared/core/theme-toggle.ts +0 -118
- package/src/shared/index.ts +0 -17
- package/src/shared/interfaces/ifooter-link.ts +0 -4
- package/src/shared/interfaces/iroute.ts +0 -4
- package/src/shared/models/theme-variables.css +0 -25
- package/src/shared/page-content.ts +0 -210
- package/src/shared/router.ts +0 -250
- package/src/shared/runtime.ts +0 -11
- package/src/shared/template.ts +0 -35
- package/src/shared/website-ui.ts +0 -92
- package/src/styles/markdown.css +0 -129
- package/src/ui/about-me/api.ts +0 -12
- package/src/ui/about-me/index.ts +0 -164
- package/src/ui/about-me/renderer.ts +0 -23
- package/src/ui/about-me/styles.ts +0 -85
- package/src/ui/admin/index.ts +0 -655
- package/src/ui/admin/styles.ts +0 -270
- package/src/ui/banner/index.ts +0 -38
- package/src/ui/banner/styles.ts +0 -95
- package/src/ui/blog-viewer/__tests__/blogviewer.test.ts +0 -7
- package/src/ui/blog-viewer/index.ts +0 -124
- package/src/ui/blog-viewer/styles.ts +0 -23
- package/src/ui/footer/index.ts +0 -37
- package/src/ui/footer/styles.ts +0 -50
- package/src/ui/index.ts +0 -6
- package/src/ui/story-viewer/__tests__/storyviewer.test.ts +0 -7
- package/src/ui/story-viewer/index.ts +0 -120
- package/src/ui/story-viewer/styles.ts +0 -54
- /package/{src/shared → dist}/styles/markdown.css +0 -0
- /package/{src → dist}/styles/theme.css +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAK5C,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EACnB,CAAC;AAEF,qBACa,WAAY,SAAQ,UAAU;IACzC,MAAM,CAAC,MAAM,0BAAe;IAG5B,QAAQ,CAAC,eAAe,UAAS;IAGjC,QAAQ,CAAC,OAAO,UAAS;IAGzB,QAAQ,CAAC,SAAS,UAAQ;IAG1B,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,CAAM;IAGzC,QAAQ,CAAC,aAAa,SAAM;IAG5B,QAAQ,CAAC,aAAa,SAAa;IAGnC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAM;IAG3C,QAAQ,CAAC,UAAU,SAAM;IAEzB,OAAO,CAAC,UAAU,CAAkB;;IAQpC,OAAO,CAAC,gBAAgB;IAIlB,iBAAiB;IAMjB,eAAe;IAcf,YAAY;IASZ,WAAW,CAAC,CAAC,EAAE,WAAW;IAkB1B,WAAW,CAAC,CAAC,EAAE,WAAW;IAkC1B,YAAY;IAQZ,YAAY;IAQZ,kBAAkB;IAMlB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI;IAWpC,gBAAgB;IAUhB,YAAY,CAAC,GAAG,EAAE,MAAM;IAS9B,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,mBAAmB;IAY3B,eAAe;IAUf,WAAW;IAUX,MAAM;CAyDP;AAED,eAAO,MAAM,WAAW,OAAO,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ContentItem {
|
|
2
|
+
key: string;
|
|
3
|
+
size: number;
|
|
4
|
+
uploaded?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface StaticDetails {
|
|
7
|
+
siteTitle?: string;
|
|
8
|
+
copyright?: string;
|
|
9
|
+
linkedin?: string;
|
|
10
|
+
github?: string;
|
|
11
|
+
email?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AuthStatus {
|
|
14
|
+
configured: boolean;
|
|
15
|
+
username: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface AdminSectionProps {
|
|
18
|
+
contentList: ContentItem[];
|
|
19
|
+
staticDetails: StaticDetails;
|
|
20
|
+
onUpload: (key: string, file: File) => Promise<void>;
|
|
21
|
+
onDelete: (key: string) => Promise<void>;
|
|
22
|
+
onStatusMessage: (message: string) => void;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/ui/admin/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/blog-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAe5C,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,UAAW,SAAQ,UAAU;IACxC,MAAM,CAAC,MAAM,0BAAoB;IAGjC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAG1C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/blog-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAe5C,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,UAAW,SAAQ,UAAU;IACxC,MAAM,CAAC,MAAM,0BAAoB;IAGjC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAQ;IAG1C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,GAKrB;IAED,iBAAiB;IAOjB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAM/C,QAAQ;IA2BR,MAAM;IAiCN,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAKxC"}
|
package/dist/ui/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAE/B,OAAO,YAAY,CAAC;AACpB,OAAO,SAAS,CAAC;AACjB,OAAO,UAAU,CAAC;AAClB,OAAO,UAAU,CAAC;AAClB,OAAO,eAAe,CAAC;AACvB,OAAO,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/story-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAe5C,UAAU,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,WAAY,SAAQ,UAAU;IACzC,MAAM,CAAC,MAAM,0BAAqB;IAGlC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAG5C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/story-viewer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAe5C,UAAU,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,qBACa,WAAY,SAAQ,UAAU;IACzC,MAAM,CAAC,MAAM,0BAAqB;IAGlC,QAAQ,CAAC,IAAI,SAAM;IAGnB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAAQ;IAG5C,QAAQ,CAAC,OAAO,UAAQ;IAGxB,QAAQ,CAAC,KAAK,SAAM;IAEpB,OAAO,KAAK,UAAU,GAKrB;IAEK,iBAAiB;IAOvB,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;IAMrC,SAAS;IAuBf,MAAM;IAiCN,OAAO,CAAC,cAAc;CAKvB"}
|
package/dist/ui.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import { A, B, F, M,
|
|
1
|
+
import { A, a, b, c, d, e, f, g, h, i, B, F, M, j, S, k } from "./chunks/index-CnSEOZse.js";
|
|
2
2
|
export {
|
|
3
|
-
A as
|
|
3
|
+
A as AdminAboutMeSection,
|
|
4
|
+
a as AdminBlogsSection,
|
|
5
|
+
b as AdminHomeSection,
|
|
6
|
+
c as AdminImagesSection,
|
|
7
|
+
d as AdminLoginForm,
|
|
8
|
+
e as AdminLogoSection,
|
|
9
|
+
f as AdminPortal,
|
|
10
|
+
g as AdminProfileSection,
|
|
11
|
+
h as AdminStaticSection,
|
|
12
|
+
i as AdminStoriesSection,
|
|
4
13
|
B as BlogViewer,
|
|
5
14
|
F as FooterComponent,
|
|
6
15
|
M as MyAboutme,
|
|
7
|
-
|
|
8
|
-
S as StoryViewer
|
|
16
|
+
j as MyBanner,
|
|
17
|
+
S as StoryViewer,
|
|
18
|
+
k as adminLoaded
|
|
9
19
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leadertechie/personal-site-kit",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A high-performance personal website engine for Cloudflare Workers and R2",
|
|
6
6
|
"repository": {
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"files": [
|
|
13
13
|
"dist",
|
|
14
|
-
"src",
|
|
15
14
|
"README.md",
|
|
16
15
|
"public"
|
|
17
16
|
],
|
|
@@ -36,10 +35,11 @@
|
|
|
36
35
|
"types": "./dist/prerender.d.ts",
|
|
37
36
|
"import": "./dist/prerender.js"
|
|
38
37
|
},
|
|
39
|
-
"./styles/*": "./
|
|
38
|
+
"./styles/*": "./dist/styles/*"
|
|
40
39
|
},
|
|
41
40
|
"scripts": {
|
|
42
|
-
"build": "vite build",
|
|
41
|
+
"build": "vite build && npm run postbuild",
|
|
42
|
+
"postbuild": "cp -r src/styles dist/",
|
|
43
43
|
"test": "vitest run"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/ui/about-me/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,qBAAa,eAAe;IAC1B,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,cAAc,EAAE;CAkBtD"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { handleInfo } from '../handlers/info';
|
|
4
|
-
|
|
5
|
-
describe('Info Handler', () => {
|
|
6
|
-
it('should return API information', async () => {
|
|
7
|
-
const response = await handleInfo();
|
|
8
|
-
|
|
9
|
-
expect(response.status).toBe(200);
|
|
10
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
11
|
-
|
|
12
|
-
const body = await response.text();
|
|
13
|
-
const data = JSON.parse(body);
|
|
14
|
-
|
|
15
|
-
expect(data.name).toBe('TechieLeader');
|
|
16
|
-
expect(data.version).toBe('1.0.0');
|
|
17
|
-
expect(data.description).toBe('TechieLeader API');
|
|
18
|
-
expect(data.endpoints).toBeInstanceOf(Array);
|
|
19
|
-
expect(data.endpoints.length).toBeGreaterThan(0);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should return valid endpoints array', async () => {
|
|
23
|
-
const response = await handleInfo();
|
|
24
|
-
const body = await response.text();
|
|
25
|
-
const data = JSON.parse(body);
|
|
26
|
-
|
|
27
|
-
expect(data.endpoints).toContainEqual({
|
|
28
|
-
path: '/info',
|
|
29
|
-
method: 'GET',
|
|
30
|
-
description: 'Get API information'
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should have correct response structure', async () => {
|
|
35
|
-
const response = await handleInfo();
|
|
36
|
-
const body = await response.text();
|
|
37
|
-
const data = JSON.parse(body);
|
|
38
|
-
|
|
39
|
-
expect(data).toHaveProperty('name');
|
|
40
|
-
expect(data).toHaveProperty('version');
|
|
41
|
-
expect(data).toHaveProperty('description');
|
|
42
|
-
expect(data).toHaveProperty('endpoints');
|
|
43
|
-
});
|
|
44
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
|
|
3
|
-
import { createErrorResponse, createJSONResponse } from '../utils';
|
|
4
|
-
|
|
5
|
-
describe('Utils', () => {
|
|
6
|
-
describe('createJSONResponse', () => {
|
|
7
|
-
it('should create JSON response with data', async () => {
|
|
8
|
-
const data = { message: 'Hello' };
|
|
9
|
-
const response = createJSONResponse(data);
|
|
10
|
-
|
|
11
|
-
expect(response.status).toBe(200);
|
|
12
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
13
|
-
|
|
14
|
-
const body = await response.text();
|
|
15
|
-
expect(JSON.parse(body)).toEqual(data);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should create JSON response with custom status', async () => {
|
|
19
|
-
const data = { message: 'Not Found' };
|
|
20
|
-
const response = createJSONResponse(data, 404);
|
|
21
|
-
|
|
22
|
-
expect(response.status).toBe(404);
|
|
23
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should handle empty data', async () => {
|
|
27
|
-
const response = createJSONResponse(null);
|
|
28
|
-
|
|
29
|
-
expect(response.status).toBe(200);
|
|
30
|
-
const body = await response.text();
|
|
31
|
-
expect(body).toBe('null');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should handle complex data structures', async () => {
|
|
35
|
-
const data = {
|
|
36
|
-
nested: {
|
|
37
|
-
array: [1, 2, 3],
|
|
38
|
-
string: 'test'
|
|
39
|
-
},
|
|
40
|
-
number: 42
|
|
41
|
-
};
|
|
42
|
-
const response = createJSONResponse(data);
|
|
43
|
-
|
|
44
|
-
const body = await response.text();
|
|
45
|
-
expect(JSON.parse(body)).toEqual(data);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('createErrorResponse', () => {
|
|
50
|
-
it('should create error response with message', async () => {
|
|
51
|
-
const response = createErrorResponse('Something went wrong');
|
|
52
|
-
|
|
53
|
-
expect(response.status).toBe(500);
|
|
54
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
55
|
-
|
|
56
|
-
const body = await response.text();
|
|
57
|
-
const parsed = JSON.parse(body);
|
|
58
|
-
expect(parsed.error).toBe('Something went wrong');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should create error response with custom status', async () => {
|
|
62
|
-
const response = createErrorResponse('Not found', 404);
|
|
63
|
-
|
|
64
|
-
expect(response.status).toBe(404);
|
|
65
|
-
expect(response.headers.get('Content-Type')).toBe('application/json');
|
|
66
|
-
|
|
67
|
-
const body = await response.text();
|
|
68
|
-
const parsed = JSON.parse(body);
|
|
69
|
-
expect(parsed.error).toBe('Not found');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should default to status 500 if not provided', () => {
|
|
73
|
-
const response = createErrorResponse('Error');
|
|
74
|
-
|
|
75
|
-
expect(response.status).toBe(500);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// Simple JSON response handler for Cloudflare Workers
|
|
2
|
-
|
|
3
|
-
import { R2ContentLoader, type ContentNode } from '@leadertechie/r2tohtml';
|
|
4
|
-
|
|
5
|
-
interface Profile {
|
|
6
|
-
name: string;
|
|
7
|
-
title: string;
|
|
8
|
-
experience: string;
|
|
9
|
-
profileImageUrl: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface AboutMeApiResponse {
|
|
13
|
-
profile: Profile;
|
|
14
|
-
contentNodes: ContentNode[];
|
|
15
|
-
processedMarkdown: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let loader: R2ContentLoader | null = null;
|
|
19
|
-
|
|
20
|
-
function getLoader(env: any): R2ContentLoader | null {
|
|
21
|
-
if (!env?.CONTENT_BUCKET) {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!loader) {
|
|
26
|
-
loader = new R2ContentLoader(
|
|
27
|
-
{
|
|
28
|
-
bucket: env.CONTENT_BUCKET,
|
|
29
|
-
cacheTTL: 5 * 60 * 1000,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
md2html: {
|
|
33
|
-
imagePathPrefix: 'images/',
|
|
34
|
-
styleOptions: {
|
|
35
|
-
classPrefix: 'md-',
|
|
36
|
-
addHeadingIds: true
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return loader;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function clearContentCache() {
|
|
46
|
-
loader?.clearCache();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function handleAboutMe(env?: any): Promise<Response> {
|
|
50
|
-
try {
|
|
51
|
-
console.log('handleAboutMe: env?.CONTENT_BUCKET =', !!env?.CONTENT_BUCKET);
|
|
52
|
-
|
|
53
|
-
if (!env?.CONTENT_BUCKET) {
|
|
54
|
-
return new Response(JSON.stringify({ error: 'Content bucket not configured', env: !!env }), {
|
|
55
|
-
status: 500,
|
|
56
|
-
headers: { 'Content-Type': 'application/json' },
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const r2 = getLoader(env);
|
|
61
|
-
if (!r2) {
|
|
62
|
-
return new Response(JSON.stringify({ error: 'Content bucket not configured' }), {
|
|
63
|
-
status: 500,
|
|
64
|
-
headers: { 'Content-Type': 'application/json' },
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
console.log('handleAboutMe: r2 created, fetching data');
|
|
68
|
-
|
|
69
|
-
const [profileObj, astResult] = await Promise.all([
|
|
70
|
-
r2.getObject('profile.json'),
|
|
71
|
-
r2.getWithAST('about-me.md')
|
|
72
|
-
]);
|
|
73
|
-
|
|
74
|
-
console.log('handleAboutMe: profileObj =', !!profileObj, 'astResult =', !!astResult);
|
|
75
|
-
|
|
76
|
-
if (!profileObj || !astResult) {
|
|
77
|
-
throw new Error('Content not found in R2');
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const profile = await profileObj.json() as Profile;
|
|
81
|
-
console.log('handleAboutMe: profile loaded:', profile.name);
|
|
82
|
-
|
|
83
|
-
const responseData: AboutMeApiResponse = {
|
|
84
|
-
profile,
|
|
85
|
-
contentNodes: astResult.contentNodes,
|
|
86
|
-
processedMarkdown: ''
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
return new Response(JSON.stringify(responseData), {
|
|
90
|
-
headers: { 'Content-Type': 'application/json' },
|
|
91
|
-
});
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error('Error serving aboutme content:', error);
|
|
94
|
-
return new Response(JSON.stringify({ error: 'Content not available', message: String(error) }), {
|
|
95
|
-
status: 500,
|
|
96
|
-
headers: { 'Content-Type': 'application/json' },
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import { createJSONResponse, createErrorResponse } from '../utils';
|
|
2
|
-
import {
|
|
3
|
-
setupAuth,
|
|
4
|
-
getAuthStore,
|
|
5
|
-
checkRateLimit,
|
|
6
|
-
recordFailedAttempt,
|
|
7
|
-
clearRateLimit,
|
|
8
|
-
verifyCredentials,
|
|
9
|
-
getClientIP,
|
|
10
|
-
MAX_ATTEMPTS
|
|
11
|
-
} from './auth';
|
|
12
|
-
|
|
13
|
-
function createSessionCookie(token: string, origin: string): string {
|
|
14
|
-
const expires = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toUTCString();
|
|
15
|
-
const isSecure = origin.startsWith('https://');
|
|
16
|
-
const hostname = new URL(origin).hostname;
|
|
17
|
-
const SameSite = isSecure ? 'Strict' : 'Lax';
|
|
18
|
-
|
|
19
|
-
let cookie = `session=${token}; HttpOnly; SameSite=${SameSite}; Path=/; Expires=${expires}`;
|
|
20
|
-
if (isSecure) {
|
|
21
|
-
cookie += '; Secure';
|
|
22
|
-
}
|
|
23
|
-
cookie += `; Domain=${hostname}`;
|
|
24
|
-
return cookie;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function handleAuth(request: Request, env: any, subpath: string): Promise<Response> {
|
|
28
|
-
const method = request.method;
|
|
29
|
-
const clientIP = getClientIP(request);
|
|
30
|
-
const path = subpath.replace(/^\//, '').split('/')[0];
|
|
31
|
-
const origin = request.headers.get('Origin') || new URL(request.url).origin;
|
|
32
|
-
|
|
33
|
-
// Check rate limit for login attempts
|
|
34
|
-
const rateCheck = await checkRateLimit(env, clientIP);
|
|
35
|
-
if (!rateCheck.allowed) {
|
|
36
|
-
return new Response(JSON.stringify({
|
|
37
|
-
error: 'Too many failed attempts. Please wait.',
|
|
38
|
-
retryAfter: Math.ceil(rateCheck.delayMs / 1000)
|
|
39
|
-
}), {
|
|
40
|
-
status: 429,
|
|
41
|
-
headers: {
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
'Retry-After': String(Math.ceil(rateCheck.delayMs / 1000))
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
switch (path) {
|
|
49
|
-
case 'setup':
|
|
50
|
-
return handleSetup(request, env, clientIP, origin);
|
|
51
|
-
case 'status':
|
|
52
|
-
return handleStatus(env);
|
|
53
|
-
case 'login':
|
|
54
|
-
return handleLogin(request, env, clientIP, origin);
|
|
55
|
-
case 'logout':
|
|
56
|
-
return handleLogout(request, env);
|
|
57
|
-
default:
|
|
58
|
-
return createErrorResponse('Not found', 404);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function handleSetup(request: Request, env: any, clientIP: string, origin: string): Promise<Response> {
|
|
63
|
-
if (request.method !== 'POST') {
|
|
64
|
-
return createErrorResponse('Method not allowed', 405);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const existing = await getAuthStore(env);
|
|
68
|
-
if (existing) {
|
|
69
|
-
return createErrorResponse('Admin already configured. Use /auth/login to login.', 400);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
const body = await request.json();
|
|
74
|
-
const { username, password } = body;
|
|
75
|
-
|
|
76
|
-
if (!username || !password) {
|
|
77
|
-
return createErrorResponse('Username and password required', 400);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (username.length < 3 || password.length < 8) {
|
|
81
|
-
return createErrorResponse('Username must be 3+ chars, password must be 8+ chars', 400);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
await setupAuth(env, username, password);
|
|
85
|
-
await clearRateLimit(env, clientIP);
|
|
86
|
-
|
|
87
|
-
const token = crypto.randomUUID();
|
|
88
|
-
await env.KV.put(`session:${token}`, JSON.stringify({
|
|
89
|
-
createdAt: Date.now(),
|
|
90
|
-
expiresAt: Date.now() + (7 * 24 * 60 * 60 * 1000)
|
|
91
|
-
}), { expirationTtl: 7 * 24 * 60 * 60 });
|
|
92
|
-
|
|
93
|
-
const headers: Record<string, string> = {
|
|
94
|
-
'Content-Type': 'application/json',
|
|
95
|
-
'Set-Cookie': createSessionCookie(token, origin)
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
return new Response(JSON.stringify({
|
|
99
|
-
success: true,
|
|
100
|
-
message: 'Admin configured successfully'
|
|
101
|
-
}), {
|
|
102
|
-
status: 201,
|
|
103
|
-
headers
|
|
104
|
-
});
|
|
105
|
-
} catch (e) {
|
|
106
|
-
return createErrorResponse('Invalid request body', 400);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
async function handleStatus(env: any): Promise<Response> {
|
|
111
|
-
const store = await getAuthStore(env);
|
|
112
|
-
|
|
113
|
-
return createJSONResponse({
|
|
114
|
-
configured: !!store,
|
|
115
|
-
username: store?.username || null
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async function handleLogin(request: Request, env: any, clientIP: string, origin: string): Promise<Response> {
|
|
120
|
-
if (request.method !== 'POST') {
|
|
121
|
-
return createErrorResponse('Method not allowed', 405);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const store = await getAuthStore(env);
|
|
125
|
-
if (!store) {
|
|
126
|
-
return createErrorResponse('Admin not configured. Use POST /auth/setup first.', 401);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
try {
|
|
130
|
-
const body = await request.json();
|
|
131
|
-
const { username, password } = body;
|
|
132
|
-
|
|
133
|
-
if (!username || !password) {
|
|
134
|
-
return createErrorResponse('Username and password required', 400);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (await verifyCredentials(env, username, password)) {
|
|
138
|
-
await clearRateLimit(env, clientIP);
|
|
139
|
-
|
|
140
|
-
const token = crypto.randomUUID();
|
|
141
|
-
await env.KV.put(`session:${token}`, JSON.stringify({
|
|
142
|
-
createdAt: Date.now(),
|
|
143
|
-
expiresAt: Date.now() + (7 * 24 * 60 * 60 * 1000)
|
|
144
|
-
}), { expirationTtl: 7 * 24 * 60 * 60 });
|
|
145
|
-
|
|
146
|
-
const headers: Record<string, string> = {
|
|
147
|
-
'Content-Type': 'application/json',
|
|
148
|
-
'Set-Cookie': createSessionCookie(token, origin)
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
return new Response(JSON.stringify({
|
|
152
|
-
success: true,
|
|
153
|
-
message: 'Login successful'
|
|
154
|
-
}), {
|
|
155
|
-
status: 200,
|
|
156
|
-
headers
|
|
157
|
-
});
|
|
158
|
-
} else {
|
|
159
|
-
await recordFailedAttempt(env, clientIP);
|
|
160
|
-
return createErrorResponse('Invalid credentials', 401);
|
|
161
|
-
}
|
|
162
|
-
} catch (e) {
|
|
163
|
-
return createErrorResponse('Invalid request body', 400);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
async function handleLogout(request: Request, env: any): Promise<Response> {
|
|
168
|
-
if (request.method !== 'POST') {
|
|
169
|
-
return createErrorResponse('Method not allowed', 405);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const origin = request.headers.get('Origin') || new URL(request.url).origin;
|
|
173
|
-
const cookieHeader = request.headers.get('Cookie');
|
|
174
|
-
const sessionToken = cookieHeader?.split(';')
|
|
175
|
-
.find(c => c.trim().startsWith('session='))
|
|
176
|
-
?.split('=')[1];
|
|
177
|
-
|
|
178
|
-
if (sessionToken) {
|
|
179
|
-
await env.KV.delete(`session:${sessionToken}`);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const hostname = new URL(origin).hostname;
|
|
183
|
-
const isSecure = origin.startsWith('https://');
|
|
184
|
-
const SameSite = isSecure ? 'Strict' : 'Lax';
|
|
185
|
-
const logoutCookie = `session=; HttpOnly; SameSite=${SameSite}; Path=/; Max-Age=0; Domain=${hostname}${isSecure ? '; Secure' : ''}`;
|
|
186
|
-
|
|
187
|
-
return new Response(JSON.stringify({ success: true, message: 'Logged out' }), {
|
|
188
|
-
status: 200,
|
|
189
|
-
headers: {
|
|
190
|
-
'Content-Type': 'application/json',
|
|
191
|
-
'Set-Cookie': logoutCookie
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|