@clidey/dory 0.1.0

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 (104) hide show
  1. package/.dockerignore +4 -0
  2. package/.github/ISSUE_TEMPLATE/anything-else.md +10 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. package/.github/dependabot.yml +11 -0
  6. package/.github/workflows/claude.yml +37 -0
  7. package/CODE_OF_CONDUCT.md +128 -0
  8. package/CONTRIBUTING.md +91 -0
  9. package/LICENSE +201 -0
  10. package/README.md +185 -0
  11. package/SECURITY.md +11 -0
  12. package/assets/dory_logo.png +0 -0
  13. package/bin/dory.js +131 -0
  14. package/docs/README.md +2 -0
  15. package/docs/configuration/app-settings/feature-flags.mdx +157 -0
  16. package/docs/configuration/app-settings/user-settings.mdx +201 -0
  17. package/docs/configuration/installation-setup/env-vars.mdx +198 -0
  18. package/docs/configuration/installation-setup/installation.mdx +127 -0
  19. package/docs/dory.json +162 -0
  20. package/docs/integrations/analytics-monitoring/error-tracking.mdx +199 -0
  21. package/docs/integrations/analytics-monitoring/notifications.mdx +189 -0
  22. package/docs/integrations/analytics-monitoring/user-analytics.mdx +182 -0
  23. package/docs/integrations/shopify-integration/shopify-setup.mdx +226 -0
  24. package/docs/integrations/shopify-integration/shopify-webhooks.mdx +207 -0
  25. package/docs/overview/developer-overview/dev-architecture.mdx +292 -0
  26. package/docs/overview/product-intro/app-overview.mdx +167 -0
  27. package/docs/overview/product-intro/architecture.mdx +203 -0
  28. package/docs/overview/product-intro/core-concepts.mdx +267 -0
  29. package/docs/platform-admin/billing-subscriptions/billing.mdx +176 -0
  30. package/docs/platform-admin/system-maintenance/db-migrations.mdx +184 -0
  31. package/docs/platform-admin/system-maintenance/health-monitoring.mdx +222 -0
  32. package/docs/platform-admin/system-maintenance/queue-management.mdx +234 -0
  33. package/docs/platform-admin/user-team-management/teams.mdx +170 -0
  34. package/docs/platform-admin/user-team-management/users.mdx +185 -0
  35. package/docs/support/legal/dependency-analysis.mdx +132 -0
  36. package/docs/support/legal/privacy-terms.mdx +73 -0
  37. package/docs/support/troubleshooting/common-issues.mdx +159 -0
  38. package/docs/usage/api-usage/api-inventory.mdx +213 -0
  39. package/docs/usage/api-usage/api-products.mdx +249 -0
  40. package/docs/usage/api-usage/api-purchase-orders.mdx +289 -0
  41. package/docs/usage/api-usage/api-reports.mdx +227 -0
  42. package/docs/usage/api-usage/api-suppliers.mdx +171 -0
  43. package/docs/usage/api-usage/api-user-management.mdx +171 -0
  44. package/docs/usage/ui-workflows/bundles.mdx +157 -0
  45. package/docs/usage/ui-workflows/demand-planning.mdx +210 -0
  46. package/docs/usage/ui-workflows/favorites.mdx +167 -0
  47. package/docs/usage/ui-workflows/inventory-management.mdx +179 -0
  48. package/docs/usage/ui-workflows/onboarding.mdx +215 -0
  49. package/docs/usage/ui-workflows/purchase-orders.mdx +200 -0
  50. package/docs/usage/ui-workflows/reports.mdx +257 -0
  51. package/index.html +54 -0
  52. package/k8s/Dockerfile +15 -0
  53. package/k8s/config/nginx-default.conf +22 -0
  54. package/k8s/dev.Dockerfile +16 -0
  55. package/package.json +71 -0
  56. package/src/app.css +3 -0
  57. package/src/app.tsx +13 -0
  58. package/src/components/dark-mode-toggle.tsx +25 -0
  59. package/src/components/dropdown.tsx +49 -0
  60. package/src/components/hooks.tsx +28 -0
  61. package/src/components/loading.tsx +23 -0
  62. package/src/components/mdx-provider.tsx +13 -0
  63. package/src/components/navigation.tsx +53 -0
  64. package/src/components/notification.tsx +97 -0
  65. package/src/components/routes.tsx +89 -0
  66. package/src/components/search-index.ts +43 -0
  67. package/src/components/search.tsx +508 -0
  68. package/src/components/store.ts +144 -0
  69. package/src/index.css +24 -0
  70. package/src/main.tsx +18 -0
  71. package/src/mdx/accordion.tsx +48 -0
  72. package/src/mdx/api-playground.tsx +674 -0
  73. package/src/mdx/api.tsx +354 -0
  74. package/src/mdx/callout.tsx +80 -0
  75. package/src/mdx/card.tsx +48 -0
  76. package/src/mdx/code.tsx +289 -0
  77. package/src/mdx/expandable.tsx +40 -0
  78. package/src/mdx/fence.tsx +73 -0
  79. package/src/mdx/icon.tsx +73 -0
  80. package/src/mdx/latex.tsx +26 -0
  81. package/src/mdx/list.tsx +7 -0
  82. package/src/mdx/mdx.tsx +43 -0
  83. package/src/mdx/mermaid.tsx +102 -0
  84. package/src/mdx/open-api.tsx +325 -0
  85. package/src/mdx/source.tsx +47 -0
  86. package/src/mdx/step.tsx +49 -0
  87. package/src/mdx/table.tsx +15 -0
  88. package/src/mdx/tag.tsx +66 -0
  89. package/src/mdx/text.tsx +98 -0
  90. package/src/plugins/sanitize.ts +15 -0
  91. package/src/theme.scss +124 -0
  92. package/src/ui/header.tsx +88 -0
  93. package/src/ui/layout.tsx +167 -0
  94. package/src/ui/mobile-navigation.tsx +91 -0
  95. package/src/ui/prev-next-link.tsx +74 -0
  96. package/src/ui/table-of-content.tsx +166 -0
  97. package/src/utils/fonts.ts +20 -0
  98. package/src/utils/functions.ts +12 -0
  99. package/src/utils/hooks.ts +46 -0
  100. package/src/vite-env.d.ts +1 -0
  101. package/tsconfig.app.json +32 -0
  102. package/tsconfig.json +7 -0
  103. package/tsconfig.node.json +25 -0
  104. package/vite.config.ts +27 -0
@@ -0,0 +1,166 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+ import classNames from 'classnames'
3
+
4
+ export type Section = {
5
+ id: string
6
+ title: string
7
+ children: Array<Subsection>
8
+ }
9
+
10
+ export type Subsection = {
11
+ id: string
12
+ title: string
13
+ }
14
+
15
+ export function TableOfContents() {
16
+ const [currentSection, setCurrentSection] = useState<string>('')
17
+ const [sections, setSections] = useState<Section[]>([])
18
+ const [isContentLoaded, setIsContentLoaded] = useState(false)
19
+
20
+ const collectHeadings = useCallback(() => {
21
+ const article = document.querySelector('article')
22
+ if (!article) return
23
+
24
+ // Wait for content to be loaded
25
+ const observer = new MutationObserver(() => {
26
+ const headings = article.querySelectorAll('h2:not([style*="display: none"]), h3:not([style*="display: none"])')
27
+ const sections: Section[] = []
28
+ let currentSection: Section | null = null
29
+
30
+ headings.forEach((heading) => {
31
+ // Check if heading is visible
32
+ const style = window.getComputedStyle(heading)
33
+ if (style.display === 'none' || style.visibility === 'hidden') return
34
+
35
+ const id = heading.id || heading.textContent?.toLowerCase().replace(/\s+/g, '-') || ''
36
+ heading.id = id
37
+
38
+ if (heading.tagName === 'H2') {
39
+ currentSection = {
40
+ id,
41
+ title: heading.textContent || '',
42
+ children: []
43
+ }
44
+ sections.push(currentSection)
45
+ } else if (heading.tagName === 'H3' && currentSection) {
46
+ currentSection.children.push({
47
+ id,
48
+ title: heading.textContent || ''
49
+ })
50
+ }
51
+ })
52
+
53
+ setSections(sections)
54
+ setIsContentLoaded(true)
55
+ })
56
+
57
+ observer.observe(article, {
58
+ childList: true,
59
+ subtree: true,
60
+ attributes: true,
61
+ attributeFilter: ['style', 'class']
62
+ })
63
+
64
+ return () => observer.disconnect()
65
+ }, [])
66
+
67
+ useEffect(() => {
68
+ const cleanup = collectHeadings()
69
+ return () => cleanup?.()
70
+ }, [collectHeadings])
71
+
72
+ const getHeadings = useCallback(() => {
73
+ return sections
74
+ .flatMap((section) => [section.id, ...section.children.map((child) => child.id)])
75
+ .map((id) => {
76
+ const el = document.getElementById(id)
77
+ if (!el) return null
78
+ const top = window.scrollY + el.getBoundingClientRect().top
79
+ return { id, top }
80
+ })
81
+ .filter((x): x is { id: string; top: number } => x !== null)
82
+ }, [sections])
83
+
84
+ useEffect(() => {
85
+ if (!isContentLoaded || sections.length === 0) return
86
+ const headings = getHeadings()
87
+
88
+ function onScroll() {
89
+ const top = window.scrollY
90
+ let current = headings[0].id
91
+ for (const heading of headings) {
92
+ if (top >= heading.top - 10) {
93
+ current = heading.id
94
+ } else {
95
+ break
96
+ }
97
+ }
98
+ setCurrentSection(current)
99
+ }
100
+
101
+ window.addEventListener('scroll', onScroll, { passive: true })
102
+ onScroll()
103
+ return () => {
104
+ window.removeEventListener('scroll', onScroll)
105
+ }
106
+ }, [getHeadings, sections, isContentLoaded])
107
+
108
+ function isActive(section: Section | Subsection) {
109
+ return section.id === currentSection
110
+ }
111
+
112
+ if (!isContentLoaded) {
113
+ return null
114
+ }
115
+
116
+ return (
117
+ <div className="hidden xl:sticky xl:top-[4.75rem] xl:-mr-6 xl:block xl:h-[calc(100vh-4.75rem)] xl:flex-none xl:overflow-y-auto xl:py-16 xl:pr-6">
118
+ <nav aria-labelledby="on-this-page-title" className="w-56">
119
+ {sections.length > 0 && (
120
+ <>
121
+ <h2
122
+ id="on-this-page-title"
123
+ className="font-display text-sm font-medium text-slate-900 dark:text-white"
124
+ >
125
+ On this page
126
+ </h2>
127
+ <ol role="list" className="mt-4 space-y-3 text-sm">
128
+ {sections.map((section) => (
129
+ <li key={section.id}>
130
+ <h3>
131
+ <a
132
+ href={`#${section.id}`}
133
+ className={classNames({
134
+ "text-sky-500": isActive(section),
135
+ "font-normal text-slate-500 hover:text-slate-700 dark:text-slate-400 dark:hover:text-slate-300": !isActive(section),
136
+ })}>
137
+ {section.title}
138
+ </a>
139
+ </h3>
140
+ {section.children.length > 0 && (
141
+ <ol role="list" className="mt-2 space-y-3 pl-5 text-slate-500 dark:text-slate-400">
142
+ {section.children.map((subSection) => (
143
+ <li key={subSection.id}>
144
+ <a
145
+ href={`#${subSection.id}`}
146
+ className={
147
+ isActive(subSection)
148
+ ? 'text-sky-500'
149
+ : 'hover:text-slate-600 dark:hover:text-slate-300'
150
+ }
151
+ >
152
+ {subSection.title}
153
+ </a>
154
+ </li>
155
+ ))}
156
+ </ol>
157
+ )}
158
+ </li>
159
+ ))}
160
+ </ol>
161
+ </>
162
+ )}
163
+ </nav>
164
+ </div>
165
+ )
166
+ }
@@ -0,0 +1,20 @@
1
+ import docsConfig from '../../docs/dory.json';
2
+
3
+ export function loadFonts() {
4
+ const { fonts } = docsConfig;
5
+ if (!fonts) return;
6
+
7
+ // Create a style element for the font face
8
+ const style = document.createElement('style');
9
+ style.textContent = `
10
+ @font-face {
11
+ font-family: '${fonts.family}';
12
+ src: url('${fonts.source}') format('${fonts.format}');
13
+ font-display: swap;
14
+ }
15
+ `;
16
+ document.head.appendChild(style);
17
+
18
+ // Apply the font family to the root element
19
+ document.documentElement.style.fontFamily = fonts.family;
20
+ }
@@ -0,0 +1,12 @@
1
+ export function slugifyWithCounter() {
2
+ const counter = new Map<string, number>();
3
+ return (text: string) => {
4
+ const count = counter.get(text) ?? 0;
5
+ counter.set(text, count + 1);
6
+ return count === 0 ? text : `${text}-${count}`;
7
+ }
8
+ }
9
+
10
+ export function toTitleCase(text: string) {
11
+ return text.replace(/_/g, ' ').replace(/\b\w/g, char => char.toUpperCase());
12
+ }
@@ -0,0 +1,46 @@
1
+ import { useEffect, useState } from 'preact/hooks';
2
+
3
+ export function useDarkMode() {
4
+ // Check localStorage and system preference on initial load
5
+ const [isDark, setIsDark] = useState(() => {
6
+ if (typeof window === 'undefined') return false;
7
+
8
+ const stored = localStorage.getItem('darkMode');
9
+ if (stored !== null) {
10
+ return JSON.parse(stored);
11
+ }
12
+
13
+ return window.matchMedia('(prefers-color-scheme: dark)').matches;
14
+ });
15
+
16
+ // Update the HTML class and localStorage when isDark changes
17
+ useEffect(() => {
18
+ const body = document.querySelector('body');
19
+ if (!body) return;
20
+ if (isDark) {
21
+ body.classList.add('dark');
22
+ } else {
23
+ body.classList.remove('dark');
24
+ }
25
+ localStorage.setItem('darkMode', JSON.stringify(isDark));
26
+ }, [isDark]);
27
+
28
+ // Listen for system theme changes
29
+ useEffect(() => {
30
+ const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
31
+ const handleChange = (e: MediaQueryListEvent) => {
32
+ // Only update if user hasn't manually set a preference
33
+ const stored = localStorage.getItem('darkMode');
34
+ if (stored === null) {
35
+ setIsDark(e.matches);
36
+ }
37
+ };
38
+
39
+ mediaQuery.addEventListener('change', handleChange);
40
+ return () => mediaQuery.removeEventListener('change', handleChange);
41
+ }, []);
42
+
43
+ const toggleDarkMode = () => setIsDark(!isDark);
44
+
45
+ return { isDark, toggleDarkMode };
46
+ }
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
4
+ "target": "ES2020",
5
+ "useDefineForClassFields": true,
6
+ "module": "ESNext",
7
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
8
+ "skipLibCheck": true,
9
+ "paths": {
10
+ "react": ["./node_modules/preact/compat/"],
11
+ "react-dom": ["./node_modules/preact/compat/"]
12
+ },
13
+
14
+ /* Bundler mode */
15
+ "moduleResolution": "bundler",
16
+ "allowImportingTsExtensions": true,
17
+ "verbatimModuleSyntax": true,
18
+ "moduleDetection": "force",
19
+ "noEmit": true,
20
+ "jsx": "react-jsx",
21
+ "jsxImportSource": "preact",
22
+
23
+ /* Linting */
24
+ "strict": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "erasableSyntaxOnly": true,
28
+ "noFallthroughCasesInSwitch": true,
29
+ "noUncheckedSideEffectImports": true
30
+ },
31
+ "include": ["src"]
32
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" },
5
+ { "path": "./tsconfig.node.json" }
6
+ ]
7
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2022",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+
16
+ /* Linting */
17
+ "strict": true,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "erasableSyntaxOnly": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "noUncheckedSideEffectImports": true
23
+ },
24
+ "include": ["vite.config.ts"]
25
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { defineConfig } from 'vite';
2
+ import preact from '@preact/preset-vite';
3
+ import mdx from '@mdx-js/rollup';
4
+ import tailwindcss from '@tailwindcss/vite'
5
+ import remarkGfm from 'remark-gfm';
6
+ import { remarkSafeVars } from './src/plugins/sanitize';
7
+
8
+ export default defineConfig({
9
+ plugins: [
10
+ preact(),
11
+ mdx({
12
+ providerImportSource: '@mdx-js/preact',
13
+ remarkPlugins: [remarkGfm, remarkSafeVars],
14
+ }),
15
+ tailwindcss(),
16
+ ],
17
+ resolve: {
18
+ alias: {
19
+ react: 'preact/compat',
20
+ 'react-dom': 'preact/compat'
21
+ }
22
+ },
23
+ publicDir: "docs",
24
+ server: {
25
+ allowedHosts: true,
26
+ },
27
+ });