@lobehub/edge-contract 0.0.0-stage → 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.
- package/LICENSE +21 -0
- package/README.md +15 -2
- package/dist/landing-locales.d.ts +4 -0
- package/dist/landing-locales.js +22 -0
- package/dist/seo-topics.d.ts +261 -0
- package/dist/seo-topics.js +269 -0
- package/fixtures/acquisition-context.json +257 -0
- package/fixtures/last-workspace-cookie.json +141 -0
- package/fixtures/request-locale.json +262 -0
- package/package.json +38 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LobeHub
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @lobehub/edge-contract
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Edge logic that more than one LobeHub repository has to agree on, kept in exactly one place.
|
|
4
|
+
|
|
5
|
+
- `fixtures/*.json` — golden cases (`{ cases: [{ name, input, expected }] }`) generated from the
|
|
6
|
+
authority implementation of each piece of logic. Every repository that still carries its own
|
|
7
|
+
copy runs that copy against these cases until it switches to importing from here.
|
|
8
|
+
- `src/*` — the shared implementations, one subpath export each.
|
|
9
|
+
|
|
10
|
+
Design: `lobehub-gateway/docs/ryugi/specs/2026-11-06-logic-dedupe-design.md`.
|
|
11
|
+
|
|
12
|
+
Regenerate fixtures from the authority repositories (checked out as siblings of this one):
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm generate:fixtures
|
|
16
|
+
```
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const landingLocales: readonly ["en", "zh", "zh-TW", "ja", "ko", "de", "es", "ar", "fr", "pt-BR", "ru", "tr", "pl", "nl", "it", "vi-VN", "bg"];
|
|
2
|
+
export type LandingLocale = (typeof landingLocales)[number];
|
|
3
|
+
export declare const DEFAULT_LANDING_LOCALE = "en";
|
|
4
|
+
export declare const isLandingLocale: (value: string | undefined) => value is LandingLocale;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// The URL path prefixes landing serves. `en` is the default and lives at the bare path.
|
|
2
|
+
export const landingLocales = [
|
|
3
|
+
'en',
|
|
4
|
+
'zh',
|
|
5
|
+
'zh-TW',
|
|
6
|
+
'ja',
|
|
7
|
+
'ko',
|
|
8
|
+
'de',
|
|
9
|
+
'es',
|
|
10
|
+
'ar',
|
|
11
|
+
'fr',
|
|
12
|
+
'pt-BR',
|
|
13
|
+
'ru',
|
|
14
|
+
'tr',
|
|
15
|
+
'pl',
|
|
16
|
+
'nl',
|
|
17
|
+
'it',
|
|
18
|
+
'vi-VN',
|
|
19
|
+
'bg',
|
|
20
|
+
];
|
|
21
|
+
export const DEFAULT_LANDING_LOCALE = 'en';
|
|
22
|
+
export const isLandingLocale = (value) => Boolean(value && landingLocales.includes(value));
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
export declare const SEO_TOPICS: {
|
|
2
|
+
readonly agent: {
|
|
3
|
+
readonly aliyun: "Aliyun";
|
|
4
|
+
readonly baichuan: "Baichuan";
|
|
5
|
+
readonly baidu: "Baidu";
|
|
6
|
+
readonly bilibili: "Bilibili";
|
|
7
|
+
readonly chatgpt: "ChatGPT";
|
|
8
|
+
readonly claude: "Claude";
|
|
9
|
+
readonly 'claude-code': "Claude Code";
|
|
10
|
+
readonly clawdbot: "ClawdBot";
|
|
11
|
+
readonly coding: "Coding";
|
|
12
|
+
readonly codx: "Codx";
|
|
13
|
+
readonly crewai: "CrewAI";
|
|
14
|
+
readonly cursor: "Cursor";
|
|
15
|
+
readonly deepseek: "DeepSeek";
|
|
16
|
+
readonly design: "Design";
|
|
17
|
+
readonly dingtalk: "DingTalk";
|
|
18
|
+
readonly discord: "Discord";
|
|
19
|
+
readonly doubao: "Doubao";
|
|
20
|
+
readonly douyin: "Douyin";
|
|
21
|
+
readonly education: "Education";
|
|
22
|
+
readonly excel: "Microsoft Excel";
|
|
23
|
+
readonly feishu: "Feishu";
|
|
24
|
+
readonly gemini: "Gemini";
|
|
25
|
+
readonly github: "GitHub";
|
|
26
|
+
readonly hunyuan: "Hunyuan";
|
|
27
|
+
readonly image: "Image";
|
|
28
|
+
readonly jd: "JD.com";
|
|
29
|
+
readonly kimi: "Kimi";
|
|
30
|
+
readonly kuaishou: "Kuaishou";
|
|
31
|
+
readonly langchain: "LangChain";
|
|
32
|
+
readonly line: "Line";
|
|
33
|
+
readonly manus: "Manus";
|
|
34
|
+
readonly marketing: "Marketing";
|
|
35
|
+
readonly memory: "Memory";
|
|
36
|
+
readonly moltbot: "MoltBot";
|
|
37
|
+
readonly notion: "Notion";
|
|
38
|
+
readonly office: "Office";
|
|
39
|
+
readonly ollama: "Ollama";
|
|
40
|
+
readonly openai: "OpenAI";
|
|
41
|
+
readonly openclaw: "OpenClaw";
|
|
42
|
+
readonly pdf: "PDF";
|
|
43
|
+
readonly pinduoduo: "Pinduoduo";
|
|
44
|
+
readonly programming: "Programming";
|
|
45
|
+
readonly qwen: "Qwen";
|
|
46
|
+
readonly rag: "RAG";
|
|
47
|
+
readonly reddit: "Reddit";
|
|
48
|
+
readonly research: "Research";
|
|
49
|
+
readonly slack: "Slack";
|
|
50
|
+
readonly taobao: "Taobao";
|
|
51
|
+
readonly telegram: "Telegram";
|
|
52
|
+
readonly tencent: "Tencent";
|
|
53
|
+
readonly tongyi: "Tongyi";
|
|
54
|
+
readonly toutiao: "Toutiao";
|
|
55
|
+
readonly translation: "Translation";
|
|
56
|
+
readonly vscode: "VS Code";
|
|
57
|
+
readonly wechat: "WeChat";
|
|
58
|
+
readonly wecom: "WeCom";
|
|
59
|
+
readonly weibo: "Weibo";
|
|
60
|
+
readonly wenxin: "Wenxin";
|
|
61
|
+
readonly writing: "Writing";
|
|
62
|
+
readonly xiaohongshu: "Xiaohongshu";
|
|
63
|
+
readonly youtube: "YouTube";
|
|
64
|
+
readonly zhipu: "Zhipu";
|
|
65
|
+
readonly 京东: "京东";
|
|
66
|
+
readonly 今日头条: "今日头条";
|
|
67
|
+
readonly 企业微信: "企业微信";
|
|
68
|
+
readonly 公众号: "公众号";
|
|
69
|
+
readonly 写作: "写作";
|
|
70
|
+
readonly 哔哩哔哩: "哔哩哔哩";
|
|
71
|
+
readonly 小红书: "小红书";
|
|
72
|
+
readonly 微信: "微信";
|
|
73
|
+
readonly 微博: "微博";
|
|
74
|
+
readonly 快手: "快手";
|
|
75
|
+
readonly 抖音: "抖音";
|
|
76
|
+
readonly 拼多多: "拼多多";
|
|
77
|
+
readonly 推特: "推特";
|
|
78
|
+
readonly 淘宝: "淘宝";
|
|
79
|
+
readonly 百度: "百度";
|
|
80
|
+
readonly 营销: "营销";
|
|
81
|
+
readonly 论文: "论文";
|
|
82
|
+
readonly 豆包: "豆包";
|
|
83
|
+
readonly 运营: "运营";
|
|
84
|
+
readonly 钉钉: "钉钉";
|
|
85
|
+
readonly 阿里云: "阿里云";
|
|
86
|
+
readonly 飞书: "飞书";
|
|
87
|
+
};
|
|
88
|
+
readonly mcp: {
|
|
89
|
+
readonly aliyun: "Aliyun";
|
|
90
|
+
readonly aws: "AWS";
|
|
91
|
+
readonly azure: "Azure";
|
|
92
|
+
readonly baidu: "Baidu";
|
|
93
|
+
readonly bilibili: "Bilibili";
|
|
94
|
+
readonly bitbucket: "Bitbucket";
|
|
95
|
+
readonly blender: "Blender";
|
|
96
|
+
readonly brave: "Brave";
|
|
97
|
+
readonly chrome: "Chrome";
|
|
98
|
+
readonly confluence: "Confluence";
|
|
99
|
+
readonly deepseek: "DeepSeek";
|
|
100
|
+
readonly dingtalk: "DingTalk";
|
|
101
|
+
readonly discord: "Discord";
|
|
102
|
+
readonly excel: "Microsoft Excel";
|
|
103
|
+
readonly feishu: "Feishu";
|
|
104
|
+
readonly fhir: "FHIR";
|
|
105
|
+
readonly figma: "Figma";
|
|
106
|
+
readonly firebase: "Firebase";
|
|
107
|
+
readonly firecrawl: "Firecrawl";
|
|
108
|
+
readonly gemini: "Gemini";
|
|
109
|
+
readonly git: "Git";
|
|
110
|
+
readonly github: "GitHub";
|
|
111
|
+
readonly gitlab: "GitLab";
|
|
112
|
+
readonly gmail: "Gmail";
|
|
113
|
+
readonly godot: "Godot";
|
|
114
|
+
readonly google: "Google";
|
|
115
|
+
readonly 'google-calendar': "Google Calendar";
|
|
116
|
+
readonly grafana: "Grafana";
|
|
117
|
+
readonly 'home-assistant': "Home Assistant";
|
|
118
|
+
readonly huawei: "Huawei";
|
|
119
|
+
readonly image: "Image";
|
|
120
|
+
readonly jd: "JD.com";
|
|
121
|
+
readonly jetbrains: "JetBrains";
|
|
122
|
+
readonly jira: "Jira";
|
|
123
|
+
readonly kuaishou: "Kuaishou";
|
|
124
|
+
readonly kubernetes: "Kubernetes";
|
|
125
|
+
readonly line: "Line";
|
|
126
|
+
readonly linkedin: "LinkedIn";
|
|
127
|
+
readonly memory: "Memory";
|
|
128
|
+
readonly mongo: "MongoDB";
|
|
129
|
+
readonly mysql: "MySQL";
|
|
130
|
+
readonly neo4j: "Neo4j";
|
|
131
|
+
readonly notion: "Notion";
|
|
132
|
+
readonly obsidian: "Obsidian";
|
|
133
|
+
readonly ollama: "Ollama";
|
|
134
|
+
readonly openapi: "OpenAPI";
|
|
135
|
+
readonly outlook: "Outlook";
|
|
136
|
+
readonly pdf: "PDF";
|
|
137
|
+
readonly perplexity: "Perplexity";
|
|
138
|
+
readonly playwright: "Playwright";
|
|
139
|
+
readonly postgres: "PostgreSQL";
|
|
140
|
+
readonly python: "Python";
|
|
141
|
+
readonly qdrant: "Qdrant";
|
|
142
|
+
readonly rag: "RAG";
|
|
143
|
+
readonly reddit: "Reddit";
|
|
144
|
+
readonly salesforce: "Salesforce";
|
|
145
|
+
readonly sheets: "Google Sheets";
|
|
146
|
+
readonly shopify: "Shopify";
|
|
147
|
+
readonly slack: "Slack";
|
|
148
|
+
readonly spotify: "Spotify";
|
|
149
|
+
readonly sql: "SQL";
|
|
150
|
+
readonly sqlite: "SQLite";
|
|
151
|
+
readonly steam: "Steam";
|
|
152
|
+
readonly stripe: "Stripe";
|
|
153
|
+
readonly supabase: "Supabase";
|
|
154
|
+
readonly taobao: "Taobao";
|
|
155
|
+
readonly tavily: "Tavily";
|
|
156
|
+
readonly telegram: "Telegram";
|
|
157
|
+
readonly tencent: "Tencent";
|
|
158
|
+
readonly unity: "Unity";
|
|
159
|
+
readonly 'unity-editor': "Unity Editor";
|
|
160
|
+
readonly vercel: "Vercel";
|
|
161
|
+
readonly wechat: "WeChat";
|
|
162
|
+
readonly wecom: "WeCom";
|
|
163
|
+
readonly whatsapp: "WhatsApp";
|
|
164
|
+
readonly word: "Microsoft Word";
|
|
165
|
+
readonly 'x-twitter': "X (Twitter)";
|
|
166
|
+
readonly youtube: "YouTube";
|
|
167
|
+
readonly zapier: "Zapier";
|
|
168
|
+
readonly zhihu: "Zhihu";
|
|
169
|
+
readonly 京东: "京东";
|
|
170
|
+
readonly 企业微信: "企业微信";
|
|
171
|
+
readonly 哔哩哔哩: "哔哩哔哩";
|
|
172
|
+
readonly 微信: "微信";
|
|
173
|
+
readonly 快手: "快手";
|
|
174
|
+
readonly 淘宝: "淘宝";
|
|
175
|
+
readonly 百度: "百度";
|
|
176
|
+
readonly 知乎: "知乎";
|
|
177
|
+
readonly 钉钉: "钉钉";
|
|
178
|
+
readonly 阿里云: "阿里云";
|
|
179
|
+
readonly 飞书: "飞书";
|
|
180
|
+
};
|
|
181
|
+
readonly skills: {
|
|
182
|
+
readonly aliyun: "Aliyun";
|
|
183
|
+
readonly aws: "AWS";
|
|
184
|
+
readonly baidu: "Baidu";
|
|
185
|
+
readonly bilibili: "Bilibili";
|
|
186
|
+
readonly chatgpt: "ChatGPT";
|
|
187
|
+
readonly claude: "Claude";
|
|
188
|
+
readonly 'claude-code': "Claude Code";
|
|
189
|
+
readonly clawdbot: "ClawdBot";
|
|
190
|
+
readonly cline: "Cline";
|
|
191
|
+
readonly codex: "Codex";
|
|
192
|
+
readonly codx: "Codx";
|
|
193
|
+
readonly copilot: "GitHub Copilot";
|
|
194
|
+
readonly cursor: "Cursor";
|
|
195
|
+
readonly database: "Database";
|
|
196
|
+
readonly dingtalk: "DingTalk";
|
|
197
|
+
readonly discord: "Discord";
|
|
198
|
+
readonly docker: "Docker";
|
|
199
|
+
readonly excel: "Microsoft Excel";
|
|
200
|
+
readonly feishu: "Feishu";
|
|
201
|
+
readonly figma: "Figma";
|
|
202
|
+
readonly firebase: "Firebase";
|
|
203
|
+
readonly git: "Git";
|
|
204
|
+
readonly github: "GitHub";
|
|
205
|
+
readonly huawei: "Huawei";
|
|
206
|
+
readonly image: "Image";
|
|
207
|
+
readonly jd: "JD.com";
|
|
208
|
+
readonly kuaishou: "Kuaishou";
|
|
209
|
+
readonly kubernetes: "Kubernetes";
|
|
210
|
+
readonly line: "Line";
|
|
211
|
+
readonly manus: "Manus";
|
|
212
|
+
readonly memory: "Memory";
|
|
213
|
+
readonly moltbot: "MoltBot";
|
|
214
|
+
readonly mysql: "MySQL";
|
|
215
|
+
readonly notion: "Notion";
|
|
216
|
+
readonly ollama: "Ollama";
|
|
217
|
+
readonly openclaw: "OpenClaw";
|
|
218
|
+
readonly pdf: "PDF";
|
|
219
|
+
readonly perplexity: "Perplexity";
|
|
220
|
+
readonly pinduoduo: "Pinduoduo";
|
|
221
|
+
readonly playwright: "Playwright";
|
|
222
|
+
readonly postgres: "PostgreSQL";
|
|
223
|
+
readonly python: "Python";
|
|
224
|
+
readonly rag: "RAG";
|
|
225
|
+
readonly reddit: "Reddit";
|
|
226
|
+
readonly redis: "Redis";
|
|
227
|
+
readonly search: "Search";
|
|
228
|
+
readonly slack: "Slack";
|
|
229
|
+
readonly sql: "SQL";
|
|
230
|
+
readonly supabase: "Supabase";
|
|
231
|
+
readonly taobao: "Taobao";
|
|
232
|
+
readonly tavily: "Tavily";
|
|
233
|
+
readonly telegram: "Telegram";
|
|
234
|
+
readonly tencent: "Tencent";
|
|
235
|
+
readonly vscode: "VS Code";
|
|
236
|
+
readonly wechat: "WeChat";
|
|
237
|
+
readonly wecom: "WeCom";
|
|
238
|
+
readonly windsurf: "Windsurf";
|
|
239
|
+
readonly youtube: "YouTube";
|
|
240
|
+
readonly zhihu: "Zhihu";
|
|
241
|
+
readonly 公众号: "公众号";
|
|
242
|
+
readonly 写作: "写作";
|
|
243
|
+
readonly 哔哩哔哩: "哔哩哔哩";
|
|
244
|
+
readonly 小红书: "小红书";
|
|
245
|
+
readonly 微信: "微信";
|
|
246
|
+
readonly 抖音: "抖音";
|
|
247
|
+
readonly 推特: "推特";
|
|
248
|
+
readonly 淘宝: "淘宝";
|
|
249
|
+
readonly 百度: "百度";
|
|
250
|
+
readonly 知乎: "知乎";
|
|
251
|
+
readonly 营销: "营销";
|
|
252
|
+
readonly 论文: "论文";
|
|
253
|
+
readonly 运营: "运营";
|
|
254
|
+
readonly 钉钉: "钉钉";
|
|
255
|
+
readonly 阿里云: "阿里云";
|
|
256
|
+
readonly 飞书: "飞书";
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
export type SeoTopicMarket = keyof typeof SEO_TOPICS;
|
|
260
|
+
export declare const hasSeoTopic: (market: SeoTopicMarket, topic: string) => boolean;
|
|
261
|
+
export declare const isClientOnlySearch: (market: SeoTopicMarket, q: unknown) => boolean;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// Key = topic slug (the `q` query param), value = display name for the SEO page and Hero.
|
|
2
|
+
// Landing server-renders `q` only for these topics; the gateway drops any other `q` from the
|
|
3
|
+
// cache key. A topic missing here loses its server-rendered page.
|
|
4
|
+
export const SEO_TOPICS = {
|
|
5
|
+
agent: {
|
|
6
|
+
'aliyun': 'Aliyun',
|
|
7
|
+
'baichuan': 'Baichuan',
|
|
8
|
+
'baidu': 'Baidu',
|
|
9
|
+
'bilibili': 'Bilibili',
|
|
10
|
+
'chatgpt': 'ChatGPT',
|
|
11
|
+
'claude': 'Claude',
|
|
12
|
+
'claude-code': 'Claude Code',
|
|
13
|
+
'clawdbot': 'ClawdBot',
|
|
14
|
+
'coding': 'Coding',
|
|
15
|
+
'codx': 'Codx',
|
|
16
|
+
'crewai': 'CrewAI',
|
|
17
|
+
'cursor': 'Cursor',
|
|
18
|
+
'deepseek': 'DeepSeek',
|
|
19
|
+
'design': 'Design',
|
|
20
|
+
'dingtalk': 'DingTalk',
|
|
21
|
+
'discord': 'Discord',
|
|
22
|
+
'doubao': 'Doubao',
|
|
23
|
+
'douyin': 'Douyin',
|
|
24
|
+
'education': 'Education',
|
|
25
|
+
'excel': 'Microsoft Excel',
|
|
26
|
+
'feishu': 'Feishu',
|
|
27
|
+
'gemini': 'Gemini',
|
|
28
|
+
'github': 'GitHub',
|
|
29
|
+
'hunyuan': 'Hunyuan',
|
|
30
|
+
'image': 'Image',
|
|
31
|
+
'jd': 'JD.com',
|
|
32
|
+
'kimi': 'Kimi',
|
|
33
|
+
'kuaishou': 'Kuaishou',
|
|
34
|
+
'langchain': 'LangChain',
|
|
35
|
+
'line': 'Line',
|
|
36
|
+
'manus': 'Manus',
|
|
37
|
+
'marketing': 'Marketing',
|
|
38
|
+
'memory': 'Memory',
|
|
39
|
+
'moltbot': 'MoltBot',
|
|
40
|
+
'notion': 'Notion',
|
|
41
|
+
'office': 'Office',
|
|
42
|
+
'ollama': 'Ollama',
|
|
43
|
+
'openai': 'OpenAI',
|
|
44
|
+
'openclaw': 'OpenClaw',
|
|
45
|
+
'pdf': 'PDF',
|
|
46
|
+
'pinduoduo': 'Pinduoduo',
|
|
47
|
+
'programming': 'Programming',
|
|
48
|
+
'qwen': 'Qwen',
|
|
49
|
+
'rag': 'RAG',
|
|
50
|
+
'reddit': 'Reddit',
|
|
51
|
+
'research': 'Research',
|
|
52
|
+
'slack': 'Slack',
|
|
53
|
+
'taobao': 'Taobao',
|
|
54
|
+
'telegram': 'Telegram',
|
|
55
|
+
'tencent': 'Tencent',
|
|
56
|
+
'tongyi': 'Tongyi',
|
|
57
|
+
'toutiao': 'Toutiao',
|
|
58
|
+
'translation': 'Translation',
|
|
59
|
+
'vscode': 'VS Code',
|
|
60
|
+
'wechat': 'WeChat',
|
|
61
|
+
'wecom': 'WeCom',
|
|
62
|
+
'weibo': 'Weibo',
|
|
63
|
+
'wenxin': 'Wenxin',
|
|
64
|
+
'writing': 'Writing',
|
|
65
|
+
'xiaohongshu': 'Xiaohongshu',
|
|
66
|
+
'youtube': 'YouTube',
|
|
67
|
+
'zhipu': 'Zhipu',
|
|
68
|
+
'京东': '京东',
|
|
69
|
+
'今日头条': '今日头条',
|
|
70
|
+
'企业微信': '企业微信',
|
|
71
|
+
'公众号': '公众号',
|
|
72
|
+
'写作': '写作',
|
|
73
|
+
'哔哩哔哩': '哔哩哔哩',
|
|
74
|
+
'小红书': '小红书',
|
|
75
|
+
'微信': '微信',
|
|
76
|
+
'微博': '微博',
|
|
77
|
+
'快手': '快手',
|
|
78
|
+
'抖音': '抖音',
|
|
79
|
+
'拼多多': '拼多多',
|
|
80
|
+
'推特': '推特',
|
|
81
|
+
'淘宝': '淘宝',
|
|
82
|
+
'百度': '百度',
|
|
83
|
+
'营销': '营销',
|
|
84
|
+
'论文': '论文',
|
|
85
|
+
'豆包': '豆包',
|
|
86
|
+
'运营': '运营',
|
|
87
|
+
'钉钉': '钉钉',
|
|
88
|
+
'阿里云': '阿里云',
|
|
89
|
+
'飞书': '飞书',
|
|
90
|
+
},
|
|
91
|
+
mcp: {
|
|
92
|
+
'aliyun': 'Aliyun',
|
|
93
|
+
'aws': 'AWS',
|
|
94
|
+
'azure': 'Azure',
|
|
95
|
+
'baidu': 'Baidu',
|
|
96
|
+
'bilibili': 'Bilibili',
|
|
97
|
+
'bitbucket': 'Bitbucket',
|
|
98
|
+
'blender': 'Blender',
|
|
99
|
+
'brave': 'Brave',
|
|
100
|
+
'chrome': 'Chrome',
|
|
101
|
+
'confluence': 'Confluence',
|
|
102
|
+
'deepseek': 'DeepSeek',
|
|
103
|
+
'dingtalk': 'DingTalk',
|
|
104
|
+
'discord': 'Discord',
|
|
105
|
+
'excel': 'Microsoft Excel',
|
|
106
|
+
'feishu': 'Feishu',
|
|
107
|
+
'fhir': 'FHIR',
|
|
108
|
+
'figma': 'Figma',
|
|
109
|
+
'firebase': 'Firebase',
|
|
110
|
+
'firecrawl': 'Firecrawl',
|
|
111
|
+
'gemini': 'Gemini',
|
|
112
|
+
'git': 'Git',
|
|
113
|
+
'github': 'GitHub',
|
|
114
|
+
'gitlab': 'GitLab',
|
|
115
|
+
'gmail': 'Gmail',
|
|
116
|
+
'godot': 'Godot',
|
|
117
|
+
'google': 'Google',
|
|
118
|
+
'google-calendar': 'Google Calendar',
|
|
119
|
+
'grafana': 'Grafana',
|
|
120
|
+
'home-assistant': 'Home Assistant',
|
|
121
|
+
'huawei': 'Huawei',
|
|
122
|
+
'image': 'Image',
|
|
123
|
+
'jd': 'JD.com',
|
|
124
|
+
'jetbrains': 'JetBrains',
|
|
125
|
+
'jira': 'Jira',
|
|
126
|
+
'kuaishou': 'Kuaishou',
|
|
127
|
+
'kubernetes': 'Kubernetes',
|
|
128
|
+
'line': 'Line',
|
|
129
|
+
'linkedin': 'LinkedIn',
|
|
130
|
+
'memory': 'Memory',
|
|
131
|
+
'mongo': 'MongoDB',
|
|
132
|
+
'mysql': 'MySQL',
|
|
133
|
+
'neo4j': 'Neo4j',
|
|
134
|
+
'notion': 'Notion',
|
|
135
|
+
'obsidian': 'Obsidian',
|
|
136
|
+
'ollama': 'Ollama',
|
|
137
|
+
'openapi': 'OpenAPI',
|
|
138
|
+
'outlook': 'Outlook',
|
|
139
|
+
'pdf': 'PDF',
|
|
140
|
+
'perplexity': 'Perplexity',
|
|
141
|
+
'playwright': 'Playwright',
|
|
142
|
+
'postgres': 'PostgreSQL',
|
|
143
|
+
'python': 'Python',
|
|
144
|
+
'qdrant': 'Qdrant',
|
|
145
|
+
'rag': 'RAG',
|
|
146
|
+
'reddit': 'Reddit',
|
|
147
|
+
'salesforce': 'Salesforce',
|
|
148
|
+
'sheets': 'Google Sheets',
|
|
149
|
+
'shopify': 'Shopify',
|
|
150
|
+
'slack': 'Slack',
|
|
151
|
+
'spotify': 'Spotify',
|
|
152
|
+
'sql': 'SQL',
|
|
153
|
+
'sqlite': 'SQLite',
|
|
154
|
+
'steam': 'Steam',
|
|
155
|
+
'stripe': 'Stripe',
|
|
156
|
+
'supabase': 'Supabase',
|
|
157
|
+
'taobao': 'Taobao',
|
|
158
|
+
'tavily': 'Tavily',
|
|
159
|
+
'telegram': 'Telegram',
|
|
160
|
+
'tencent': 'Tencent',
|
|
161
|
+
'unity': 'Unity',
|
|
162
|
+
'unity-editor': 'Unity Editor',
|
|
163
|
+
'vercel': 'Vercel',
|
|
164
|
+
'wechat': 'WeChat',
|
|
165
|
+
'wecom': 'WeCom',
|
|
166
|
+
'whatsapp': 'WhatsApp',
|
|
167
|
+
'word': 'Microsoft Word',
|
|
168
|
+
'x-twitter': 'X (Twitter)',
|
|
169
|
+
'youtube': 'YouTube',
|
|
170
|
+
'zapier': 'Zapier',
|
|
171
|
+
'zhihu': 'Zhihu',
|
|
172
|
+
'京东': '京东',
|
|
173
|
+
'企业微信': '企业微信',
|
|
174
|
+
'哔哩哔哩': '哔哩哔哩',
|
|
175
|
+
'微信': '微信',
|
|
176
|
+
'快手': '快手',
|
|
177
|
+
'淘宝': '淘宝',
|
|
178
|
+
'百度': '百度',
|
|
179
|
+
'知乎': '知乎',
|
|
180
|
+
'钉钉': '钉钉',
|
|
181
|
+
'阿里云': '阿里云',
|
|
182
|
+
'飞书': '飞书',
|
|
183
|
+
},
|
|
184
|
+
skills: {
|
|
185
|
+
'aliyun': 'Aliyun',
|
|
186
|
+
'aws': 'AWS',
|
|
187
|
+
'baidu': 'Baidu',
|
|
188
|
+
'bilibili': 'Bilibili',
|
|
189
|
+
'chatgpt': 'ChatGPT',
|
|
190
|
+
'claude': 'Claude',
|
|
191
|
+
'claude-code': 'Claude Code',
|
|
192
|
+
'clawdbot': 'ClawdBot',
|
|
193
|
+
'cline': 'Cline',
|
|
194
|
+
'codex': 'Codex',
|
|
195
|
+
'codx': 'Codx',
|
|
196
|
+
'copilot': 'GitHub Copilot',
|
|
197
|
+
'cursor': 'Cursor',
|
|
198
|
+
'database': 'Database',
|
|
199
|
+
'dingtalk': 'DingTalk',
|
|
200
|
+
'discord': 'Discord',
|
|
201
|
+
'docker': 'Docker',
|
|
202
|
+
'excel': 'Microsoft Excel',
|
|
203
|
+
'feishu': 'Feishu',
|
|
204
|
+
'figma': 'Figma',
|
|
205
|
+
'firebase': 'Firebase',
|
|
206
|
+
'git': 'Git',
|
|
207
|
+
'github': 'GitHub',
|
|
208
|
+
'huawei': 'Huawei',
|
|
209
|
+
'image': 'Image',
|
|
210
|
+
'jd': 'JD.com',
|
|
211
|
+
'kuaishou': 'Kuaishou',
|
|
212
|
+
'kubernetes': 'Kubernetes',
|
|
213
|
+
'line': 'Line',
|
|
214
|
+
'manus': 'Manus',
|
|
215
|
+
'memory': 'Memory',
|
|
216
|
+
'moltbot': 'MoltBot',
|
|
217
|
+
'mysql': 'MySQL',
|
|
218
|
+
'notion': 'Notion',
|
|
219
|
+
'ollama': 'Ollama',
|
|
220
|
+
'openclaw': 'OpenClaw',
|
|
221
|
+
'pdf': 'PDF',
|
|
222
|
+
'perplexity': 'Perplexity',
|
|
223
|
+
'pinduoduo': 'Pinduoduo',
|
|
224
|
+
'playwright': 'Playwright',
|
|
225
|
+
'postgres': 'PostgreSQL',
|
|
226
|
+
'python': 'Python',
|
|
227
|
+
'rag': 'RAG',
|
|
228
|
+
'reddit': 'Reddit',
|
|
229
|
+
'redis': 'Redis',
|
|
230
|
+
'search': 'Search',
|
|
231
|
+
'slack': 'Slack',
|
|
232
|
+
'sql': 'SQL',
|
|
233
|
+
'supabase': 'Supabase',
|
|
234
|
+
'taobao': 'Taobao',
|
|
235
|
+
'tavily': 'Tavily',
|
|
236
|
+
'telegram': 'Telegram',
|
|
237
|
+
'tencent': 'Tencent',
|
|
238
|
+
'vscode': 'VS Code',
|
|
239
|
+
'wechat': 'WeChat',
|
|
240
|
+
'wecom': 'WeCom',
|
|
241
|
+
'windsurf': 'Windsurf',
|
|
242
|
+
'youtube': 'YouTube',
|
|
243
|
+
'zhihu': 'Zhihu',
|
|
244
|
+
'公众号': '公众号',
|
|
245
|
+
'写作': '写作',
|
|
246
|
+
'哔哩哔哩': '哔哩哔哩',
|
|
247
|
+
'小红书': '小红书',
|
|
248
|
+
'微信': '微信',
|
|
249
|
+
'抖音': '抖音',
|
|
250
|
+
'推特': '推特',
|
|
251
|
+
'淘宝': '淘宝',
|
|
252
|
+
'百度': '百度',
|
|
253
|
+
'知乎': '知乎',
|
|
254
|
+
'营销': '营销',
|
|
255
|
+
'论文': '论文',
|
|
256
|
+
'运营': '运营',
|
|
257
|
+
'钉钉': '钉钉',
|
|
258
|
+
'阿里云': '阿里云',
|
|
259
|
+
'飞书': '飞书',
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
export const hasSeoTopic = (market, topic) => Object.hasOwn(SEO_TOPICS[market], topic);
|
|
263
|
+
// Free-text searches outside the sitemapped topics are never server-rendered:
|
|
264
|
+
// SSR renders the list without `q` and the browser fetches the results, so the
|
|
265
|
+
// HTML is identical to the URL without `q` and the CDN can share one cache entry
|
|
266
|
+
export const isClientOnlySearch = (market, q) => {
|
|
267
|
+
const topic = typeof q === 'string' ? q.trim() : '';
|
|
268
|
+
return Boolean(topic) && !hasSeoTopic(market, topic);
|
|
269
|
+
};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
{
|
|
2
|
+
"attributionParams": [
|
|
3
|
+
"gad_source",
|
|
4
|
+
"mc_cid",
|
|
5
|
+
"gclid",
|
|
6
|
+
"gclsrc",
|
|
7
|
+
"dclid",
|
|
8
|
+
"gbraid",
|
|
9
|
+
"wbraid",
|
|
10
|
+
"fbclid",
|
|
11
|
+
"msclkid",
|
|
12
|
+
"twclid",
|
|
13
|
+
"li_fat_id",
|
|
14
|
+
"igshid",
|
|
15
|
+
"ttclid",
|
|
16
|
+
"rdt_cid",
|
|
17
|
+
"epik",
|
|
18
|
+
"qclid",
|
|
19
|
+
"sccid",
|
|
20
|
+
"irclid",
|
|
21
|
+
"_kx"
|
|
22
|
+
],
|
|
23
|
+
"authority": "lobehub-cloud@19f89cf50 src/libs/analytics/acquisitionContext.ts and src/proxy.ts ATTRIBUTION_PARAMS",
|
|
24
|
+
"cases": [
|
|
25
|
+
{
|
|
26
|
+
"expected": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
27
|
+
"input": {
|
|
28
|
+
"context": {
|
|
29
|
+
"capturedAt": "2026-11-06T08:00:00.000Z",
|
|
30
|
+
"lhCid": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
31
|
+
},
|
|
32
|
+
"kind": "sign",
|
|
33
|
+
"secret": "fixture-secret-fixture-secret-00"
|
|
34
|
+
},
|
|
35
|
+
"name": "sign lower-case click id"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"expected": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
39
|
+
"input": {
|
|
40
|
+
"context": {
|
|
41
|
+
"capturedAt": "2026-11-06T08:00:00.000Z",
|
|
42
|
+
"lhCid": "3F2A9C1E-5B7D-4E8A-9C21-7D4E5F6A8B90"
|
|
43
|
+
},
|
|
44
|
+
"kind": "sign",
|
|
45
|
+
"secret": "fixture-secret-fixture-secret-00"
|
|
46
|
+
},
|
|
47
|
+
"name": "sign upper-case click id is lower-cased"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"expected": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
51
|
+
"input": {
|
|
52
|
+
"context": {
|
|
53
|
+
"capturedAt": "2026-11-06T08:00:00Z",
|
|
54
|
+
"lhCid": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
55
|
+
},
|
|
56
|
+
"kind": "sign",
|
|
57
|
+
"secret": "fixture-secret-fixture-secret-00"
|
|
58
|
+
},
|
|
59
|
+
"name": "sign normalizes the timestamp"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"expected": {
|
|
63
|
+
"capturedAt": "2026-11-06T08:00:00.000Z",
|
|
64
|
+
"lhCid": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
65
|
+
},
|
|
66
|
+
"input": {
|
|
67
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
68
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
69
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
70
|
+
"kind": "verify"
|
|
71
|
+
},
|
|
72
|
+
"name": "verify valid"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"expected": null,
|
|
76
|
+
"input": {
|
|
77
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
78
|
+
"secret": "another-secret",
|
|
79
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
80
|
+
"kind": "verify"
|
|
81
|
+
},
|
|
82
|
+
"name": "verify wrong secret"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"expected": null,
|
|
86
|
+
"input": {
|
|
87
|
+
"now": "2026-12-06T08:00:01.000Z",
|
|
88
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
89
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
90
|
+
"kind": "verify"
|
|
91
|
+
},
|
|
92
|
+
"name": "verify past 30 days"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"expected": {
|
|
96
|
+
"capturedAt": "2026-11-06T08:00:00.000Z",
|
|
97
|
+
"lhCid": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
98
|
+
},
|
|
99
|
+
"input": {
|
|
100
|
+
"now": "2026-12-06T08:00:00.000Z",
|
|
101
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
102
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
103
|
+
"kind": "verify"
|
|
104
|
+
},
|
|
105
|
+
"name": "verify at 30 days"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"expected": null,
|
|
109
|
+
"input": {
|
|
110
|
+
"now": "2026-11-06T07:54:59.000Z",
|
|
111
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
112
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
113
|
+
"kind": "verify"
|
|
114
|
+
},
|
|
115
|
+
"name": "verify captured in the future"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"expected": {
|
|
119
|
+
"capturedAt": "2026-11-06T08:00:00.000Z",
|
|
120
|
+
"lhCid": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
121
|
+
},
|
|
122
|
+
"input": {
|
|
123
|
+
"now": "2026-11-06T07:55:01.000Z",
|
|
124
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
125
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
126
|
+
"kind": "verify"
|
|
127
|
+
},
|
|
128
|
+
"name": "verify within future skew"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"expected": null,
|
|
132
|
+
"input": {
|
|
133
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
134
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
135
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxxx.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148",
|
|
136
|
+
"kind": "verify"
|
|
137
|
+
},
|
|
138
|
+
"name": "verify tampered payload"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"expected": null,
|
|
142
|
+
"input": {
|
|
143
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
144
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
145
|
+
"token": "eyJjYXB0dXJlZEF0IjoiMjAyNi0xMS0wNlQwODowMDowMC4wMDBaIiwibGhDaWQiOiIzZjJhOWMxZS01YjdkLTRlOGEtOWMyMS03ZDRlNWY2YThiOTAiLCJ2ZXJzaW9uIjoxfQ.8T7LWAoeGsHxFp2U7WWylIDGXI19NFdSPtEtkhlb148.x",
|
|
146
|
+
"kind": "verify"
|
|
147
|
+
},
|
|
148
|
+
"name": "verify three parts"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"expected": null,
|
|
152
|
+
"input": {
|
|
153
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
154
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
155
|
+
"token": "a+b.c/d",
|
|
156
|
+
"kind": "verify"
|
|
157
|
+
},
|
|
158
|
+
"name": "verify not base64url"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"expected": null,
|
|
162
|
+
"input": {
|
|
163
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
164
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
165
|
+
"token": "",
|
|
166
|
+
"kind": "verify"
|
|
167
|
+
},
|
|
168
|
+
"name": "verify empty"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"expected": null,
|
|
172
|
+
"input": {
|
|
173
|
+
"now": "2026-11-07T00:00:00.000Z",
|
|
174
|
+
"secret": "fixture-secret-fixture-secret-00",
|
|
175
|
+
"token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
176
|
+
"kind": "verify"
|
|
177
|
+
},
|
|
178
|
+
"name": "verify too long"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"expected": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90",
|
|
182
|
+
"input": {
|
|
183
|
+
"kind": "capture",
|
|
184
|
+
"url": "https://lobehub.com/tasks?lh_cid=3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
185
|
+
},
|
|
186
|
+
"name": "capture valid click id"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"expected": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90",
|
|
190
|
+
"input": {
|
|
191
|
+
"kind": "capture",
|
|
192
|
+
"url": "https://lobehub.com/tasks?lh_cid=3F2A9C1E-5B7D-4E8A-9C21-7D4E5F6A8B90"
|
|
193
|
+
},
|
|
194
|
+
"name": "capture upper-case click id"
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
"expected": null,
|
|
198
|
+
"input": {
|
|
199
|
+
"kind": "capture",
|
|
200
|
+
"url": "https://lobehub.com/tasks?lh_cid=3f2a9c1e-5b7d-1e8a-9c21-7d4e5f6a8b90"
|
|
201
|
+
},
|
|
202
|
+
"name": "capture not a v4 uuid"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"expected": null,
|
|
206
|
+
"input": {
|
|
207
|
+
"kind": "capture",
|
|
208
|
+
"url": "https://lobehub.com/tasks?lh_cid=user-private-value"
|
|
209
|
+
},
|
|
210
|
+
"name": "capture free text"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"expected": null,
|
|
214
|
+
"input": {
|
|
215
|
+
"kind": "capture",
|
|
216
|
+
"url": "https://lobehub.com/tasks"
|
|
217
|
+
},
|
|
218
|
+
"name": "capture missing"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"expected": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90",
|
|
222
|
+
"input": {
|
|
223
|
+
"kind": "capture",
|
|
224
|
+
"url": "https://lobehub.com/signin?callbackUrl=https%3A%2F%2Flobehub.com%2Ftasks%3Flh_cid%3D3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
225
|
+
},
|
|
226
|
+
"name": "capture from the sign-in callback"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"expected": "3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90",
|
|
230
|
+
"input": {
|
|
231
|
+
"kind": "capture",
|
|
232
|
+
"url": "https://lobehub.com/signup?callbackUrl=https%3A%2F%2Flobehub.com%2Ftasks%3Flh_cid%3D3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
233
|
+
},
|
|
234
|
+
"name": "capture from the sign-up callback"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"expected": null,
|
|
238
|
+
"input": {
|
|
239
|
+
"kind": "capture",
|
|
240
|
+
"url": "https://lobehub.com/signin?callbackUrl=https%3A%2F%2Fevil.example%2F%3Flh_cid%3D3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
241
|
+
},
|
|
242
|
+
"name": "capture ignores a cross-origin callback"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"expected": null,
|
|
246
|
+
"input": {
|
|
247
|
+
"kind": "capture",
|
|
248
|
+
"url": "https://lobehub.com/tasks?callbackUrl=https%3A%2F%2Flobehub.com%2Fx%3Flh_cid%3D3f2a9c1e-5b7d-4e8a-9c21-7d4e5f6a8b90"
|
|
249
|
+
},
|
|
250
|
+
"name": "capture ignores callbacks off the auth pages"
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
"cookie": {
|
|
254
|
+
"maxAgeSeconds": 2592000,
|
|
255
|
+
"name": "lh_acq"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
{
|
|
2
|
+
"authority": "lobehub-cloud@19f89cf50 packages/const/src/workspace.ts parseLastWorkspaceCookie",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"expected": "my-team",
|
|
6
|
+
"input": {
|
|
7
|
+
"raw": "user_1:my-team",
|
|
8
|
+
"userId": "user_1"
|
|
9
|
+
},
|
|
10
|
+
"name": "valid"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"expected": null,
|
|
14
|
+
"input": {
|
|
15
|
+
"raw": "user_1:my-team",
|
|
16
|
+
"userId": "user_2"
|
|
17
|
+
},
|
|
18
|
+
"name": "another user"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"expected": null,
|
|
22
|
+
"input": {
|
|
23
|
+
"raw": "my-team",
|
|
24
|
+
"userId": "user_1"
|
|
25
|
+
},
|
|
26
|
+
"name": "no separator"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"expected": null,
|
|
30
|
+
"input": {
|
|
31
|
+
"raw": ":my-team",
|
|
32
|
+
"userId": "user_1"
|
|
33
|
+
},
|
|
34
|
+
"name": "empty user part"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"expected": null,
|
|
38
|
+
"input": {
|
|
39
|
+
"raw": "user_1:",
|
|
40
|
+
"userId": "user_1"
|
|
41
|
+
},
|
|
42
|
+
"name": "empty slug"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"expected": null,
|
|
46
|
+
"input": {
|
|
47
|
+
"raw": "user_1:ab",
|
|
48
|
+
"userId": "user_1"
|
|
49
|
+
},
|
|
50
|
+
"name": "slug too short"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"expected": "abc",
|
|
54
|
+
"input": {
|
|
55
|
+
"raw": "user_1:abc",
|
|
56
|
+
"userId": "user_1"
|
|
57
|
+
},
|
|
58
|
+
"name": "slug at min length"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"expected": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
62
|
+
"input": {
|
|
63
|
+
"raw": "user_1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
64
|
+
"userId": "user_1"
|
|
65
|
+
},
|
|
66
|
+
"name": "slug at max length"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"expected": null,
|
|
70
|
+
"input": {
|
|
71
|
+
"raw": "user_1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
|
72
|
+
"userId": "user_1"
|
|
73
|
+
},
|
|
74
|
+
"name": "slug too long"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"expected": null,
|
|
78
|
+
"input": {
|
|
79
|
+
"raw": "user_1:My-Team",
|
|
80
|
+
"userId": "user_1"
|
|
81
|
+
},
|
|
82
|
+
"name": "upper-case slug"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"expected": null,
|
|
86
|
+
"input": {
|
|
87
|
+
"raw": "user_1:my-team-",
|
|
88
|
+
"userId": "user_1"
|
|
89
|
+
},
|
|
90
|
+
"name": "trailing dash"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"expected": null,
|
|
94
|
+
"input": {
|
|
95
|
+
"raw": "user_1:-my-team",
|
|
96
|
+
"userId": "user_1"
|
|
97
|
+
},
|
|
98
|
+
"name": "leading dash"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"expected": null,
|
|
102
|
+
"input": {
|
|
103
|
+
"raw": "user_1:../admin",
|
|
104
|
+
"userId": "user_1"
|
|
105
|
+
},
|
|
106
|
+
"name": "path traversal"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"expected": null,
|
|
110
|
+
"input": {
|
|
111
|
+
"raw": "user_1:my:team",
|
|
112
|
+
"userId": "user_1"
|
|
113
|
+
},
|
|
114
|
+
"name": "second colon"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"expected": null,
|
|
118
|
+
"input": {
|
|
119
|
+
"raw": "user_1:my-team\r\nx",
|
|
120
|
+
"userId": "user_1"
|
|
121
|
+
},
|
|
122
|
+
"name": "CRLF smuggling"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"expected": null,
|
|
126
|
+
"input": {
|
|
127
|
+
"raw": null,
|
|
128
|
+
"userId": "user_1"
|
|
129
|
+
},
|
|
130
|
+
"name": "missing cookie"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"expected": null,
|
|
134
|
+
"input": {
|
|
135
|
+
"raw": "user_1:my-team",
|
|
136
|
+
"userId": null
|
|
137
|
+
},
|
|
138
|
+
"name": "missing user"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
{
|
|
2
|
+
"authority": "lobe-chat@0f9d2f1e41 packages/locales/src/requestLocale.ts resolveRequestLocale",
|
|
3
|
+
"cases": [
|
|
4
|
+
{
|
|
5
|
+
"expected": "en-US",
|
|
6
|
+
"input": {
|
|
7
|
+
"url": "https://app.lobehub.com/"
|
|
8
|
+
},
|
|
9
|
+
"name": "nothing to go on"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"expected": "ja-JP",
|
|
13
|
+
"input": {
|
|
14
|
+
"url": "https://app.lobehub.com/?hl=ja-JP"
|
|
15
|
+
},
|
|
16
|
+
"name": "hl exact"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"expected": "zh-CN",
|
|
20
|
+
"input": {
|
|
21
|
+
"url": "https://app.lobehub.com/?hl=zh-cn"
|
|
22
|
+
},
|
|
23
|
+
"name": "hl lower-case"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"expected": "ja-JP",
|
|
27
|
+
"input": {
|
|
28
|
+
"url": "https://app.lobehub.com/?hl=ja"
|
|
29
|
+
},
|
|
30
|
+
"name": "hl language only"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"expected": "en-US",
|
|
34
|
+
"input": {
|
|
35
|
+
"url": "https://app.lobehub.com/?hl=xx-YY"
|
|
36
|
+
},
|
|
37
|
+
"name": "hl unsupported"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"expected": "zh-CN",
|
|
41
|
+
"input": {
|
|
42
|
+
"headers": {
|
|
43
|
+
"accept-language": "zh-CN"
|
|
44
|
+
},
|
|
45
|
+
"url": "https://app.lobehub.com/?hl=auto"
|
|
46
|
+
},
|
|
47
|
+
"name": "hl auto defers to the browser"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"expected": "ko-KR",
|
|
51
|
+
"input": {
|
|
52
|
+
"headers": {
|
|
53
|
+
"cookie": "LOBE_LOCALE=ko-KR"
|
|
54
|
+
},
|
|
55
|
+
"url": "https://app.lobehub.com/"
|
|
56
|
+
},
|
|
57
|
+
"name": "cookie"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"expected": "de-DE",
|
|
61
|
+
"input": {
|
|
62
|
+
"headers": {
|
|
63
|
+
"cookie": "a=1; LOBE_LOCALE=de-DE; b=2"
|
|
64
|
+
},
|
|
65
|
+
"url": "https://app.lobehub.com/"
|
|
66
|
+
},
|
|
67
|
+
"name": "cookie among others"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"expected": "en-US",
|
|
71
|
+
"input": {
|
|
72
|
+
"headers": {
|
|
73
|
+
"cookie": "LOBE_LOCALE=%E0%A4%A"
|
|
74
|
+
},
|
|
75
|
+
"url": "https://app.lobehub.com/"
|
|
76
|
+
},
|
|
77
|
+
"name": "cookie malformed escape"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"expected": "fr-FR",
|
|
81
|
+
"input": {
|
|
82
|
+
"headers": {
|
|
83
|
+
"accept-language": "fr",
|
|
84
|
+
"cookie": "LOBE_LOCALE=auto"
|
|
85
|
+
},
|
|
86
|
+
"url": "https://app.lobehub.com/"
|
|
87
|
+
},
|
|
88
|
+
"name": "cookie auto defers to the browser"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"expected": "ja-JP",
|
|
92
|
+
"input": {
|
|
93
|
+
"headers": {
|
|
94
|
+
"cookie": "LOBE_LOCALE=ko-KR"
|
|
95
|
+
},
|
|
96
|
+
"url": "https://app.lobehub.com/?hl=ja-JP"
|
|
97
|
+
},
|
|
98
|
+
"name": "hl beats cookie"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"expected": "zh-CN",
|
|
102
|
+
"input": {
|
|
103
|
+
"headers": {
|
|
104
|
+
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8"
|
|
105
|
+
},
|
|
106
|
+
"url": "https://app.lobehub.com/"
|
|
107
|
+
},
|
|
108
|
+
"name": "accept zh-CN first"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"expected": "de-DE",
|
|
112
|
+
"input": {
|
|
113
|
+
"headers": {
|
|
114
|
+
"accept-language": "fr;q=0.5, de;q=0.9"
|
|
115
|
+
},
|
|
116
|
+
"url": "https://app.lobehub.com/"
|
|
117
|
+
},
|
|
118
|
+
"name": "accept weighted"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"expected": "ja-JP",
|
|
122
|
+
"input": {
|
|
123
|
+
"headers": {
|
|
124
|
+
"accept-language": "ja"
|
|
125
|
+
},
|
|
126
|
+
"url": "https://app.lobehub.com/"
|
|
127
|
+
},
|
|
128
|
+
"name": "accept language only"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"expected": "zh-TW",
|
|
132
|
+
"input": {
|
|
133
|
+
"headers": {
|
|
134
|
+
"accept-language": "zh-Hant"
|
|
135
|
+
},
|
|
136
|
+
"url": "https://app.lobehub.com/"
|
|
137
|
+
},
|
|
138
|
+
"name": "accept zh-Hant"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"expected": "zh-CN",
|
|
142
|
+
"input": {
|
|
143
|
+
"headers": {
|
|
144
|
+
"accept-language": "zh-Hans-CN"
|
|
145
|
+
},
|
|
146
|
+
"url": "https://app.lobehub.com/"
|
|
147
|
+
},
|
|
148
|
+
"name": "accept zh-Hans"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"expected": "zh-TW",
|
|
152
|
+
"input": {
|
|
153
|
+
"headers": {
|
|
154
|
+
"accept-language": "zh-TW"
|
|
155
|
+
},
|
|
156
|
+
"url": "https://app.lobehub.com/"
|
|
157
|
+
},
|
|
158
|
+
"name": "accept zh-TW"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"expected": "pt-BR",
|
|
162
|
+
"input": {
|
|
163
|
+
"headers": {
|
|
164
|
+
"accept-language": "pt"
|
|
165
|
+
},
|
|
166
|
+
"url": "https://app.lobehub.com/"
|
|
167
|
+
},
|
|
168
|
+
"name": "accept pt"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"expected": "en-US",
|
|
172
|
+
"input": {
|
|
173
|
+
"headers": {
|
|
174
|
+
"accept-language": "es-419"
|
|
175
|
+
},
|
|
176
|
+
"url": "https://app.lobehub.com/"
|
|
177
|
+
},
|
|
178
|
+
"name": "accept es-419"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"expected": "ar",
|
|
182
|
+
"input": {
|
|
183
|
+
"headers": {
|
|
184
|
+
"accept-language": "ar-EG"
|
|
185
|
+
},
|
|
186
|
+
"url": "https://app.lobehub.com/"
|
|
187
|
+
},
|
|
188
|
+
"name": "accept ar-EG"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"expected": "fa-IR",
|
|
192
|
+
"input": {
|
|
193
|
+
"headers": {
|
|
194
|
+
"accept-language": "fa"
|
|
195
|
+
},
|
|
196
|
+
"url": "https://app.lobehub.com/"
|
|
197
|
+
},
|
|
198
|
+
"name": "accept fa"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"expected": "zh-CN",
|
|
202
|
+
"input": {
|
|
203
|
+
"headers": {
|
|
204
|
+
"accept-language": "cn"
|
|
205
|
+
},
|
|
206
|
+
"url": "https://app.lobehub.com/"
|
|
207
|
+
},
|
|
208
|
+
"name": "accept legacy cn"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"expected": "en-US",
|
|
212
|
+
"input": {
|
|
213
|
+
"headers": {
|
|
214
|
+
"accept-language": "*"
|
|
215
|
+
},
|
|
216
|
+
"url": "https://app.lobehub.com/"
|
|
217
|
+
},
|
|
218
|
+
"name": "accept wildcard"
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
"expected": "en-US",
|
|
222
|
+
"input": {
|
|
223
|
+
"headers": {
|
|
224
|
+
"accept-language": "xx, en-GB;q=0.8"
|
|
225
|
+
},
|
|
226
|
+
"url": "https://app.lobehub.com/"
|
|
227
|
+
},
|
|
228
|
+
"name": "accept unsupported then en"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"expected": "en-US",
|
|
232
|
+
"input": {
|
|
233
|
+
"headers": {
|
|
234
|
+
"accept-language": "en-us"
|
|
235
|
+
},
|
|
236
|
+
"url": "https://app.lobehub.com/"
|
|
237
|
+
},
|
|
238
|
+
"name": "accept lower-case region"
|
|
239
|
+
}
|
|
240
|
+
],
|
|
241
|
+
"defaultLocale": "en-US",
|
|
242
|
+
"tags": [
|
|
243
|
+
"ar",
|
|
244
|
+
"bg-BG",
|
|
245
|
+
"de-DE",
|
|
246
|
+
"en-US",
|
|
247
|
+
"es-ES",
|
|
248
|
+
"fr-FR",
|
|
249
|
+
"ja-JP",
|
|
250
|
+
"ko-KR",
|
|
251
|
+
"pt-BR",
|
|
252
|
+
"ru-RU",
|
|
253
|
+
"tr-TR",
|
|
254
|
+
"zh-CN",
|
|
255
|
+
"zh-TW",
|
|
256
|
+
"vi-VN",
|
|
257
|
+
"fa-IR",
|
|
258
|
+
"it-IT",
|
|
259
|
+
"pl-PL",
|
|
260
|
+
"nl-NL"
|
|
261
|
+
]
|
|
262
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/edge-contract",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One implementation of the edge logic shared by the LobeHub gateway, landing, cloud and lobe-chat, plus golden fixtures every copy is tested against.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/lobehub/edge-contract.git"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"exports": {
|
|
13
|
+
"./landing-locales": {
|
|
14
|
+
"types": "./dist/landing-locales.d.ts",
|
|
15
|
+
"default": "./dist/landing-locales.js"
|
|
16
|
+
},
|
|
17
|
+
"./seo-topics": {
|
|
18
|
+
"types": "./dist/seo-topics.d.ts",
|
|
19
|
+
"default": "./dist/seo-topics.js"
|
|
20
|
+
},
|
|
21
|
+
"./fixtures/*": "./fixtures/*"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"fixtures"
|
|
26
|
+
],
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^26.6.6",
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"vitest": "3.2.7"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"build": "tsc -p tsconfig.build.json",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"generate:fixtures": "bun scripts/generate-fixtures.ts"
|
|
40
|
+
}
|
|
6
41
|
}
|