snow-flow 3.4.13 → 3.4.15
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/.mcp.json.template +91 -31
- package/README.md +597 -96
- package/dist/cli.js +23 -51
- package/dist/mcp/servicenow-automation-mcp.js +65 -29
- package/dist/mcp/servicenow-change-virtualagent-pa-mcp.js +51 -21
- package/dist/mcp/servicenow-cmdb-event-hr-csm-devops-mcp.js +59 -25
- package/dist/mcp/servicenow-deployment-mcp.js +38 -16
- package/dist/mcp/servicenow-development-assistant-mcp.js +67 -31
- package/dist/mcp/servicenow-flow-workspace-mobile-mcp.js +53 -22
- package/dist/mcp/servicenow-integration-mcp.js +48 -12
- package/dist/mcp/servicenow-knowledge-catalog-mcp.js +42 -16
- package/dist/mcp/servicenow-machine-learning-mcp.js +44 -17
- package/dist/mcp/servicenow-operations-mcp.d.ts +1 -0
- package/dist/mcp/servicenow-operations-mcp.js +108 -79
- package/dist/mcp/servicenow-platform-development-mcp.js +42 -11
- package/dist/mcp/servicenow-reporting-analytics-mcp.js +36 -13
- package/dist/mcp/servicenow-security-compliance-mcp.js +35 -13
- package/dist/mcp/servicenow-system-properties-mcp.d.ts +1 -0
- package/dist/mcp/servicenow-system-properties-mcp.js +66 -42
- package/dist/mcp/servicenow-update-set-mcp.js +35 -11
- package/package.json +2 -2
- package/website/README.md +152 -0
- package/website/css/api-docs.css +366 -0
- package/website/css/style.css +809 -0
- package/website/index.html +750 -0
- package/website/js/main.js +323 -0
- package/website/netlify.toml +37 -0
- package/website/package.json +49 -0
- package/website/vercel.json +54 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
// Snow-Flow Website JavaScript
|
|
2
|
+
|
|
3
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
4
|
+
// Mobile Navigation Toggle
|
|
5
|
+
const hamburger = document.querySelector('.hamburger');
|
|
6
|
+
const navMenu = document.querySelector('.nav-menu');
|
|
7
|
+
|
|
8
|
+
if (hamburger) {
|
|
9
|
+
hamburger.addEventListener('click', function() {
|
|
10
|
+
navMenu.classList.toggle('active');
|
|
11
|
+
|
|
12
|
+
// Animate hamburger
|
|
13
|
+
const spans = hamburger.querySelectorAll('span');
|
|
14
|
+
if (navMenu.classList.contains('active')) {
|
|
15
|
+
spans[0].style.transform = 'rotate(45deg) translate(5px, 5px)';
|
|
16
|
+
spans[1].style.opacity = '0';
|
|
17
|
+
spans[2].style.transform = 'rotate(-45deg) translate(7px, -6px)';
|
|
18
|
+
} else {
|
|
19
|
+
spans[0].style.transform = 'none';
|
|
20
|
+
spans[1].style.opacity = '1';
|
|
21
|
+
spans[2].style.transform = 'none';
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Smooth Scrolling for Navigation Links
|
|
27
|
+
const navLinks = document.querySelectorAll('.nav-link');
|
|
28
|
+
navLinks.forEach(link => {
|
|
29
|
+
link.addEventListener('click', function(e) {
|
|
30
|
+
const href = this.getAttribute('href');
|
|
31
|
+
if (href.startsWith('#')) {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
const target = document.querySelector(href);
|
|
34
|
+
if (target) {
|
|
35
|
+
const offset = 80; // Height of navbar
|
|
36
|
+
const targetPosition = target.offsetTop - offset;
|
|
37
|
+
window.scrollTo({
|
|
38
|
+
top: targetPosition,
|
|
39
|
+
behavior: 'smooth'
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Close mobile menu if open
|
|
43
|
+
navMenu.classList.remove('active');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Tab Functionality for Installation Section
|
|
50
|
+
const tabBtns = document.querySelectorAll('.tab-btn');
|
|
51
|
+
const tabContents = document.querySelectorAll('.tab-content');
|
|
52
|
+
|
|
53
|
+
tabBtns.forEach(btn => {
|
|
54
|
+
btn.addEventListener('click', function() {
|
|
55
|
+
const tabName = this.getAttribute('data-tab');
|
|
56
|
+
|
|
57
|
+
// Remove active class from all tabs and contents
|
|
58
|
+
tabBtns.forEach(b => b.classList.remove('active'));
|
|
59
|
+
tabContents.forEach(c => c.classList.remove('active'));
|
|
60
|
+
|
|
61
|
+
// Add active class to clicked tab and corresponding content
|
|
62
|
+
this.classList.add('active');
|
|
63
|
+
const activeContent = document.getElementById(tabName);
|
|
64
|
+
if (activeContent) {
|
|
65
|
+
activeContent.classList.add('active');
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Navbar Background on Scroll
|
|
71
|
+
const navbar = document.querySelector('.navbar');
|
|
72
|
+
let lastScroll = 0;
|
|
73
|
+
|
|
74
|
+
window.addEventListener('scroll', function() {
|
|
75
|
+
const currentScroll = window.pageYOffset;
|
|
76
|
+
|
|
77
|
+
if (currentScroll > 100) {
|
|
78
|
+
navbar.style.background = 'rgba(255, 255, 255, 0.98)';
|
|
79
|
+
navbar.style.backdropFilter = 'blur(10px)';
|
|
80
|
+
navbar.style.boxShadow = '0 4px 20px rgba(0,0,0,0.1)';
|
|
81
|
+
} else {
|
|
82
|
+
navbar.style.background = 'white';
|
|
83
|
+
navbar.style.backdropFilter = 'none';
|
|
84
|
+
navbar.style.boxShadow = '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Hide/Show navbar on scroll
|
|
88
|
+
if (currentScroll > lastScroll && currentScroll > 500) {
|
|
89
|
+
navbar.style.transform = 'translateY(-100%)';
|
|
90
|
+
} else {
|
|
91
|
+
navbar.style.transform = 'translateY(0)';
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
lastScroll = currentScroll;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Animate Elements on Scroll
|
|
98
|
+
const observerOptions = {
|
|
99
|
+
threshold: 0.1,
|
|
100
|
+
rootMargin: '0px 0px -100px 0px'
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const observer = new IntersectionObserver(function(entries) {
|
|
104
|
+
entries.forEach(entry => {
|
|
105
|
+
if (entry.isIntersecting) {
|
|
106
|
+
entry.target.style.opacity = '1';
|
|
107
|
+
entry.target.style.transform = 'translateY(0)';
|
|
108
|
+
|
|
109
|
+
// Add stagger effect for grid items
|
|
110
|
+
if (entry.target.classList.contains('feature') ||
|
|
111
|
+
entry.target.classList.contains('mcp-card') ||
|
|
112
|
+
entry.target.classList.contains('what-is-card')) {
|
|
113
|
+
const siblings = entry.target.parentElement.children;
|
|
114
|
+
Array.from(siblings).forEach((sibling, index) => {
|
|
115
|
+
setTimeout(() => {
|
|
116
|
+
sibling.style.opacity = '1';
|
|
117
|
+
sibling.style.transform = 'translateY(0)';
|
|
118
|
+
}, index * 100);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}, observerOptions);
|
|
124
|
+
|
|
125
|
+
// Observe elements for animation
|
|
126
|
+
const animateElements = document.querySelectorAll('.feature, .mcp-card, .what-is-card, .workflow-step, .example-card, .practice');
|
|
127
|
+
animateElements.forEach(el => {
|
|
128
|
+
el.style.opacity = '0';
|
|
129
|
+
el.style.transform = 'translateY(20px)';
|
|
130
|
+
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
|
|
131
|
+
observer.observe(el);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Copy Code Functionality
|
|
135
|
+
const codeBlocks = document.querySelectorAll('pre code');
|
|
136
|
+
codeBlocks.forEach(block => {
|
|
137
|
+
const wrapper = block.parentElement;
|
|
138
|
+
|
|
139
|
+
// Create copy button
|
|
140
|
+
const copyBtn = document.createElement('button');
|
|
141
|
+
copyBtn.className = 'copy-btn';
|
|
142
|
+
copyBtn.textContent = 'Copy';
|
|
143
|
+
copyBtn.style.cssText = `
|
|
144
|
+
position: absolute;
|
|
145
|
+
top: 10px;
|
|
146
|
+
right: 10px;
|
|
147
|
+
background: rgba(255,255,255,0.1);
|
|
148
|
+
color: white;
|
|
149
|
+
border: 1px solid rgba(255,255,255,0.2);
|
|
150
|
+
padding: 5px 15px;
|
|
151
|
+
border-radius: 5px;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
font-size: 0.9rem;
|
|
154
|
+
transition: all 0.3s ease;
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
wrapper.style.position = 'relative';
|
|
158
|
+
wrapper.appendChild(copyBtn);
|
|
159
|
+
|
|
160
|
+
copyBtn.addEventListener('click', function() {
|
|
161
|
+
const text = block.textContent;
|
|
162
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
163
|
+
copyBtn.textContent = 'Copied!';
|
|
164
|
+
copyBtn.style.background = '#48bb78';
|
|
165
|
+
copyBtn.style.borderColor = '#48bb78';
|
|
166
|
+
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
copyBtn.textContent = 'Copy';
|
|
169
|
+
copyBtn.style.background = 'rgba(255,255,255,0.1)';
|
|
170
|
+
copyBtn.style.borderColor = 'rgba(255,255,255,0.2)';
|
|
171
|
+
}, 2000);
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Show copy button on hover
|
|
176
|
+
wrapper.addEventListener('mouseenter', () => {
|
|
177
|
+
copyBtn.style.opacity = '1';
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
wrapper.addEventListener('mouseleave', () => {
|
|
181
|
+
if (copyBtn.textContent === 'Copy') {
|
|
182
|
+
copyBtn.style.opacity = '0.7';
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Active Section Highlighting in Navigation
|
|
188
|
+
const sections = document.querySelectorAll('section[id]');
|
|
189
|
+
|
|
190
|
+
function highlightNavigation() {
|
|
191
|
+
const scrollPosition = window.scrollY + 100;
|
|
192
|
+
|
|
193
|
+
sections.forEach(section => {
|
|
194
|
+
const sectionTop = section.offsetTop;
|
|
195
|
+
const sectionHeight = section.offsetHeight;
|
|
196
|
+
const sectionId = section.getAttribute('id');
|
|
197
|
+
|
|
198
|
+
if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) {
|
|
199
|
+
navLinks.forEach(link => {
|
|
200
|
+
link.classList.remove('active');
|
|
201
|
+
if (link.getAttribute('href') === `#${sectionId}`) {
|
|
202
|
+
link.classList.add('active');
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
window.addEventListener('scroll', highlightNavigation);
|
|
210
|
+
|
|
211
|
+
// Typing Effect for Hero Title
|
|
212
|
+
const heroTitle = document.querySelector('.hero-title');
|
|
213
|
+
if (heroTitle) {
|
|
214
|
+
const text = heroTitle.textContent;
|
|
215
|
+
heroTitle.textContent = '';
|
|
216
|
+
let index = 0;
|
|
217
|
+
|
|
218
|
+
function typeText() {
|
|
219
|
+
if (index < text.length) {
|
|
220
|
+
heroTitle.textContent += text.charAt(index);
|
|
221
|
+
index++;
|
|
222
|
+
setTimeout(typeText, 100);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Start typing after a short delay
|
|
227
|
+
setTimeout(typeText, 500);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Counter Animation for Stats
|
|
231
|
+
const stats = document.querySelectorAll('.stat-number');
|
|
232
|
+
const statsObserver = new IntersectionObserver(function(entries) {
|
|
233
|
+
entries.forEach(entry => {
|
|
234
|
+
if (entry.isIntersecting && !entry.target.classList.contains('counted')) {
|
|
235
|
+
entry.target.classList.add('counted');
|
|
236
|
+
const target = entry.target;
|
|
237
|
+
const value = target.textContent;
|
|
238
|
+
|
|
239
|
+
// Extract number from string (e.g., "16+" -> 16)
|
|
240
|
+
const number = parseInt(value.replace(/\D/g, ''));
|
|
241
|
+
const suffix = value.replace(/\d/g, '');
|
|
242
|
+
const duration = 2000; // 2 seconds
|
|
243
|
+
const increment = number / (duration / 16); // 60fps
|
|
244
|
+
let current = 0;
|
|
245
|
+
|
|
246
|
+
const counter = setInterval(() => {
|
|
247
|
+
current += increment;
|
|
248
|
+
if (current >= number) {
|
|
249
|
+
target.textContent = number + suffix;
|
|
250
|
+
clearInterval(counter);
|
|
251
|
+
} else {
|
|
252
|
+
target.textContent = Math.floor(current) + suffix;
|
|
253
|
+
}
|
|
254
|
+
}, 16);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}, { threshold: 0.5 });
|
|
258
|
+
|
|
259
|
+
stats.forEach(stat => {
|
|
260
|
+
statsObserver.observe(stat);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Search Functionality for MCP Tools
|
|
264
|
+
const searchInput = document.createElement('input');
|
|
265
|
+
searchInput.type = 'text';
|
|
266
|
+
searchInput.placeholder = 'Search MCP tools...';
|
|
267
|
+
searchInput.className = 'mcp-search';
|
|
268
|
+
searchInput.style.cssText = `
|
|
269
|
+
width: 100%;
|
|
270
|
+
max-width: 400px;
|
|
271
|
+
margin: 0 auto 2rem;
|
|
272
|
+
display: block;
|
|
273
|
+
padding: 12px 20px;
|
|
274
|
+
border: 2px solid #e2e8f0;
|
|
275
|
+
border-radius: 25px;
|
|
276
|
+
font-size: 1rem;
|
|
277
|
+
transition: all 0.3s ease;
|
|
278
|
+
`;
|
|
279
|
+
|
|
280
|
+
const mcpSection = document.querySelector('#mcp-servers .container');
|
|
281
|
+
if (mcpSection) {
|
|
282
|
+
const subtitle = mcpSection.querySelector('.section-subtitle');
|
|
283
|
+
if (subtitle) {
|
|
284
|
+
subtitle.insertAdjacentElement('afterend', searchInput);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
searchInput.addEventListener('input', function(e) {
|
|
288
|
+
const searchTerm = e.target.value.toLowerCase();
|
|
289
|
+
const mcpCards = document.querySelectorAll('.mcp-card');
|
|
290
|
+
|
|
291
|
+
mcpCards.forEach(card => {
|
|
292
|
+
const text = card.textContent.toLowerCase();
|
|
293
|
+
if (text.includes(searchTerm)) {
|
|
294
|
+
card.style.display = 'block';
|
|
295
|
+
card.style.animation = 'fadeIn 0.3s ease';
|
|
296
|
+
} else {
|
|
297
|
+
card.style.display = 'none';
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
searchInput.addEventListener('focus', function() {
|
|
303
|
+
this.style.borderColor = '#0066cc';
|
|
304
|
+
this.style.boxShadow = '0 0 0 3px rgba(0,102,204,0.1)';
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
searchInput.addEventListener('blur', function() {
|
|
308
|
+
this.style.borderColor = '#e2e8f0';
|
|
309
|
+
this.style.boxShadow = 'none';
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Add Loading Animation
|
|
314
|
+
window.addEventListener('load', function() {
|
|
315
|
+
document.body.classList.add('loaded');
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Console Easter Egg
|
|
319
|
+
console.log('%c🏔️❄️ Snow-Flow', 'font-size: 30px; font-weight: bold; background: linear-gradient(135deg, #0066cc 0%, #00d4ff 100%); color: white; padding: 10px 20px; border-radius: 10px;');
|
|
320
|
+
console.log('%cAdvanced ServiceNow Development Framework', 'font-size: 14px; color: #666;');
|
|
321
|
+
console.log('%cVersion 3.4.14 | MIT License', 'font-size: 12px; color: #999;');
|
|
322
|
+
console.log('%cInterested in contributing? Visit: https://github.com/groeimetai/snow-flow', 'font-size: 12px; color: #0066cc;');
|
|
323
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Netlify deployment configuration for Snow-Flow website
|
|
2
|
+
|
|
3
|
+
[build]
|
|
4
|
+
publish = "."
|
|
5
|
+
|
|
6
|
+
[[headers]]
|
|
7
|
+
for = "/*"
|
|
8
|
+
[headers.values]
|
|
9
|
+
X-Frame-Options = "DENY"
|
|
10
|
+
X-XSS-Protection = "1; mode=block"
|
|
11
|
+
X-Content-Type-Options = "nosniff"
|
|
12
|
+
Referrer-Policy = "strict-origin-when-cross-origin"
|
|
13
|
+
|
|
14
|
+
[[headers]]
|
|
15
|
+
for = "/*.js"
|
|
16
|
+
[headers.values]
|
|
17
|
+
Cache-Control = "public, max-age=604800"
|
|
18
|
+
|
|
19
|
+
[[headers]]
|
|
20
|
+
for = "/*.css"
|
|
21
|
+
[headers.values]
|
|
22
|
+
Cache-Control = "public, max-age=604800"
|
|
23
|
+
|
|
24
|
+
[[headers]]
|
|
25
|
+
for = "/images/*"
|
|
26
|
+
[headers.values]
|
|
27
|
+
Cache-Control = "public, max-age=2592000"
|
|
28
|
+
|
|
29
|
+
[[redirects]]
|
|
30
|
+
from = "/api"
|
|
31
|
+
to = "/docs/api-full.html"
|
|
32
|
+
status = 301
|
|
33
|
+
|
|
34
|
+
[[redirects]]
|
|
35
|
+
from = "/docs"
|
|
36
|
+
to = "/docs/api-full.html"
|
|
37
|
+
status = 301
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snow-flow-website",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official documentation website for Snow-Flow - Advanced ServiceNow Development Framework",
|
|
5
|
+
"main": "index.html",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"serve": "npx http-server -p 8080",
|
|
8
|
+
"serve:python": "python -m http.server 8080",
|
|
9
|
+
"deploy:netlify": "netlify deploy --prod",
|
|
10
|
+
"deploy:vercel": "vercel --prod",
|
|
11
|
+
"deploy:surge": "surge . snow-flow.surge.sh",
|
|
12
|
+
"lint:html": "npx htmlhint '**/*.html'",
|
|
13
|
+
"lint:css": "npx stylelint 'css/*.css'",
|
|
14
|
+
"optimize:images": "npx imagemin images/* --out-dir=images",
|
|
15
|
+
"minify:css": "npx cleancss -o css/style.min.css css/style.css && npx cleancss -o css/api-docs.min.css css/api-docs.css",
|
|
16
|
+
"minify:js": "npx terser js/main.js -o js/main.min.js",
|
|
17
|
+
"build": "npm run minify:css && npm run minify:js",
|
|
18
|
+
"test": "npx live-server"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"snow-flow",
|
|
22
|
+
"servicenow",
|
|
23
|
+
"documentation",
|
|
24
|
+
"mcp",
|
|
25
|
+
"api",
|
|
26
|
+
"developer-tools"
|
|
27
|
+
],
|
|
28
|
+
"author": "Snow-Flow Team",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/groeimetai/snow-flow.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://snow-flow.dev",
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"http-server": "^14.1.1",
|
|
37
|
+
"live-server": "^1.2.2",
|
|
38
|
+
"htmlhint": "^1.1.4",
|
|
39
|
+
"stylelint": "^15.11.0",
|
|
40
|
+
"clean-css-cli": "^5.6.2",
|
|
41
|
+
"terser": "^5.24.0",
|
|
42
|
+
"imagemin-cli": "^7.0.0"
|
|
43
|
+
},
|
|
44
|
+
"browserslist": [
|
|
45
|
+
"> 1%",
|
|
46
|
+
"last 2 versions",
|
|
47
|
+
"not dead"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snow-flow-docs",
|
|
3
|
+
"version": 2,
|
|
4
|
+
"public": true,
|
|
5
|
+
"headers": [
|
|
6
|
+
{
|
|
7
|
+
"source": "/(.*)",
|
|
8
|
+
"headers": [
|
|
9
|
+
{
|
|
10
|
+
"key": "X-Frame-Options",
|
|
11
|
+
"value": "DENY"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"key": "X-Content-Type-Options",
|
|
15
|
+
"value": "nosniff"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"key": "X-XSS-Protection",
|
|
19
|
+
"value": "1; mode=block"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"source": "/(.*)\\.(js|css)",
|
|
25
|
+
"headers": [
|
|
26
|
+
{
|
|
27
|
+
"key": "Cache-Control",
|
|
28
|
+
"value": "public, max-age=604800"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"source": "/images/(.*)",
|
|
34
|
+
"headers": [
|
|
35
|
+
{
|
|
36
|
+
"key": "Cache-Control",
|
|
37
|
+
"value": "public, max-age=2592000"
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"redirects": [
|
|
43
|
+
{
|
|
44
|
+
"source": "/api",
|
|
45
|
+
"destination": "/docs/api-full.html",
|
|
46
|
+
"permanent": true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"source": "/docs",
|
|
50
|
+
"destination": "/docs/api-full.html",
|
|
51
|
+
"permanent": true
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|