@ucptools/validator 1.0.0 → 1.0.1

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 (236) hide show
  1. package/.claude/settings.local.json +60 -0
  2. package/.vercel/README.txt +11 -0
  3. package/.vercel/project.json +1 -0
  4. package/dist/cli/index.d.ts +6 -0
  5. package/dist/cli/index.d.ts.map +1 -0
  6. package/dist/cli/index.js +279 -0
  7. package/dist/cli/index.js.map +1 -0
  8. package/dist/compliance/compliance-generator.d.ts +34 -0
  9. package/dist/compliance/compliance-generator.d.ts.map +1 -0
  10. package/dist/compliance/compliance-generator.js +320 -0
  11. package/dist/compliance/compliance-generator.js.map +1 -0
  12. package/dist/compliance/index.d.ts +8 -0
  13. package/dist/compliance/index.d.ts.map +1 -0
  14. package/dist/compliance/index.js +17 -0
  15. package/dist/compliance/index.js.map +1 -0
  16. package/dist/compliance/templates.d.ts +34 -0
  17. package/dist/compliance/templates.d.ts.map +1 -0
  18. package/{src/compliance/templates.ts → dist/compliance/templates.js} +117 -155
  19. package/dist/compliance/templates.js.map +1 -0
  20. package/dist/compliance/types.d.ts +64 -0
  21. package/dist/compliance/types.d.ts.map +1 -0
  22. package/dist/compliance/types.js +64 -0
  23. package/dist/compliance/types.js.map +1 -0
  24. package/dist/db/index.d.ts +11 -0
  25. package/dist/db/index.d.ts.map +1 -0
  26. package/dist/db/index.js +63 -0
  27. package/dist/db/index.js.map +1 -0
  28. package/dist/db/schema.d.ts +444 -0
  29. package/dist/db/schema.d.ts.map +1 -0
  30. package/dist/db/schema.js +65 -0
  31. package/dist/db/schema.js.map +1 -0
  32. package/dist/feed-analyzer/feed-analyzer.d.ts +26 -0
  33. package/dist/feed-analyzer/feed-analyzer.d.ts.map +1 -0
  34. package/{src/feed-analyzer/feed-analyzer.ts → dist/feed-analyzer/feed-analyzer.js} +642 -726
  35. package/dist/feed-analyzer/feed-analyzer.js.map +1 -0
  36. package/dist/feed-analyzer/index.d.ts +8 -0
  37. package/dist/feed-analyzer/index.d.ts.map +1 -0
  38. package/dist/feed-analyzer/index.js +19 -0
  39. package/dist/feed-analyzer/index.js.map +1 -0
  40. package/dist/feed-analyzer/types.d.ts +204 -0
  41. package/dist/feed-analyzer/types.d.ts.map +1 -0
  42. package/dist/feed-analyzer/types.js +162 -0
  43. package/dist/feed-analyzer/types.js.map +1 -0
  44. package/{src/generator/index.ts → dist/generator/index.d.ts} +1 -1
  45. package/dist/generator/index.d.ts.map +1 -0
  46. package/dist/generator/index.js +13 -0
  47. package/dist/generator/index.js.map +1 -0
  48. package/dist/generator/key-generator.d.ts +24 -0
  49. package/dist/generator/key-generator.d.ts.map +1 -0
  50. package/dist/generator/key-generator.js +144 -0
  51. package/dist/generator/key-generator.js.map +1 -0
  52. package/dist/generator/profile-builder.d.ts +15 -0
  53. package/dist/generator/profile-builder.d.ts.map +1 -0
  54. package/dist/generator/profile-builder.js +338 -0
  55. package/dist/generator/profile-builder.js.map +1 -0
  56. package/dist/hosting/artifacts-generator.d.ts +10 -0
  57. package/dist/hosting/artifacts-generator.d.ts.map +1 -0
  58. package/{src/hosting/artifacts-generator.ts → dist/hosting/artifacts-generator.js} +191 -241
  59. package/dist/hosting/artifacts-generator.js.map +1 -0
  60. package/{src/hosting/index.ts → dist/hosting/index.d.ts} +1 -1
  61. package/dist/hosting/index.d.ts.map +1 -0
  62. package/dist/hosting/index.js +10 -0
  63. package/dist/hosting/index.js.map +1 -0
  64. package/dist/index.d.ts +18 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +78 -0
  67. package/dist/index.js.map +1 -0
  68. package/{src/security/index.ts → dist/security/index.d.ts} +8 -15
  69. package/dist/security/index.d.ts.map +1 -0
  70. package/dist/security/index.js +12 -0
  71. package/dist/security/index.js.map +1 -0
  72. package/dist/security/security-scanner.d.ts +10 -0
  73. package/dist/security/security-scanner.d.ts.map +1 -0
  74. package/dist/security/security-scanner.js +541 -0
  75. package/dist/security/security-scanner.js.map +1 -0
  76. package/dist/security/types.d.ts +48 -0
  77. package/dist/security/types.d.ts.map +1 -0
  78. package/dist/security/types.js +21 -0
  79. package/dist/security/types.js.map +1 -0
  80. package/dist/services/directory.d.ts +104 -0
  81. package/dist/services/directory.d.ts.map +1 -0
  82. package/dist/services/directory.js +333 -0
  83. package/dist/services/directory.js.map +1 -0
  84. package/dist/simulator/agent-simulator.d.ts +69 -0
  85. package/dist/simulator/agent-simulator.d.ts.map +1 -0
  86. package/{src/simulator/agent-simulator.ts → dist/simulator/agent-simulator.js} +650 -941
  87. package/dist/simulator/agent-simulator.js.map +1 -0
  88. package/{src/simulator/index.ts → dist/simulator/index.d.ts} +7 -7
  89. package/dist/simulator/index.d.ts.map +1 -0
  90. package/dist/simulator/index.js +23 -0
  91. package/dist/simulator/index.js.map +1 -0
  92. package/{src/simulator/types.ts → dist/simulator/types.d.ts} +145 -170
  93. package/dist/simulator/types.d.ts.map +1 -0
  94. package/dist/simulator/types.js +18 -0
  95. package/dist/simulator/types.js.map +1 -0
  96. package/dist/types/generator.d.ts +106 -0
  97. package/dist/types/generator.d.ts.map +1 -0
  98. package/dist/types/generator.js +6 -0
  99. package/dist/types/generator.js.map +1 -0
  100. package/{src/types/index.ts → dist/types/index.d.ts} +1 -1
  101. package/dist/types/index.d.ts.map +1 -0
  102. package/dist/types/index.js +23 -0
  103. package/dist/types/index.js.map +1 -0
  104. package/dist/types/ucp-profile.d.ts +103 -0
  105. package/dist/types/ucp-profile.d.ts.map +1 -0
  106. package/dist/types/ucp-profile.js +45 -0
  107. package/dist/types/ucp-profile.js.map +1 -0
  108. package/dist/types/validation.d.ts +68 -0
  109. package/dist/types/validation.d.ts.map +1 -0
  110. package/dist/types/validation.js +32 -0
  111. package/dist/types/validation.js.map +1 -0
  112. package/dist/validator/index.d.ts +26 -0
  113. package/dist/validator/index.d.ts.map +1 -0
  114. package/dist/validator/index.js +161 -0
  115. package/dist/validator/index.js.map +1 -0
  116. package/dist/validator/network-validator.d.ts +28 -0
  117. package/dist/validator/network-validator.d.ts.map +1 -0
  118. package/dist/validator/network-validator.js +319 -0
  119. package/dist/validator/network-validator.js.map +1 -0
  120. package/dist/validator/rules-validator.d.ts +11 -0
  121. package/dist/validator/rules-validator.d.ts.map +1 -0
  122. package/dist/validator/rules-validator.js +257 -0
  123. package/dist/validator/rules-validator.js.map +1 -0
  124. package/dist/validator/sdk-validator.d.ts +58 -0
  125. package/dist/validator/sdk-validator.d.ts.map +1 -0
  126. package/{src/validator/sdk-validator.ts → dist/validator/sdk-validator.js} +273 -330
  127. package/dist/validator/sdk-validator.js.map +1 -0
  128. package/dist/validator/structural-validator.d.ts +11 -0
  129. package/dist/validator/structural-validator.d.ts.map +1 -0
  130. package/dist/validator/structural-validator.js +415 -0
  131. package/dist/validator/structural-validator.js.map +1 -0
  132. package/package.json +1 -1
  133. package/publish-output.txt +0 -0
  134. package/CLAUDE.md +0 -109
  135. package/api/analyze-feed.js +0 -140
  136. package/api/badge.js +0 -185
  137. package/api/benchmark.js +0 -177
  138. package/api/directory-stats.ts +0 -29
  139. package/api/directory.ts +0 -73
  140. package/api/generate-compliance.js +0 -143
  141. package/api/generate-schema.js +0 -457
  142. package/api/generate.js +0 -132
  143. package/api/security-scan.js +0 -133
  144. package/api/simulate.js +0 -187
  145. package/api/tsconfig.json +0 -10
  146. package/api/validate.js +0 -1351
  147. package/apify-actor/.actor/actor.json +0 -68
  148. package/apify-actor/.actor/input_schema.json +0 -32
  149. package/apify-actor/APIFY-STORE-LISTING.md +0 -412
  150. package/apify-actor/Dockerfile +0 -8
  151. package/apify-actor/README.md +0 -166
  152. package/apify-actor/main.ts +0 -111
  153. package/apify-actor/package.json +0 -17
  154. package/apify-actor/src/main.js +0 -199
  155. package/docs/BRAND-IDENTITY.md +0 -238
  156. package/docs/BRAND-STYLE-GUIDE.md +0 -356
  157. package/drizzle/0000_black_king_cobra.sql +0 -39
  158. package/drizzle/meta/0000_snapshot.json +0 -309
  159. package/drizzle/meta/_journal.json +0 -13
  160. package/drizzle.config.ts +0 -10
  161. package/public/.well-known/ucp +0 -25
  162. package/public/android-chrome-192x192.png +0 -0
  163. package/public/android-chrome-512x512.png +0 -0
  164. package/public/apple-touch-icon.png +0 -0
  165. package/public/brand.css +0 -321
  166. package/public/directory.html +0 -701
  167. package/public/favicon-16x16.png +0 -0
  168. package/public/favicon-32x32.png +0 -0
  169. package/public/favicon.ico +0 -0
  170. package/public/guides/bigcommerce.html +0 -743
  171. package/public/guides/fastucp.html +0 -838
  172. package/public/guides/magento.html +0 -779
  173. package/public/guides/shopify.html +0 -726
  174. package/public/guides/squarespace.html +0 -749
  175. package/public/guides/wix.html +0 -747
  176. package/public/guides/woocommerce.html +0 -733
  177. package/public/index.html +0 -3835
  178. package/public/learn.html +0 -396
  179. package/public/logo.jpeg +0 -0
  180. package/public/og-image-icon.png +0 -0
  181. package/public/og-image.png +0 -0
  182. package/public/robots.txt +0 -6
  183. package/public/site.webmanifest +0 -31
  184. package/public/sitemap.xml +0 -69
  185. package/public/social/linkedin-banner-1128x191.png +0 -0
  186. package/public/social/temp.PNG +0 -0
  187. package/public/social/x-header-1500x500.png +0 -0
  188. package/public/verify.html +0 -410
  189. package/scripts/generate-favicons.js +0 -44
  190. package/scripts/generate-ico.js +0 -23
  191. package/scripts/generate-og-image.js +0 -45
  192. package/scripts/reset-db.ts +0 -77
  193. package/scripts/seed-db.ts +0 -71
  194. package/scripts/setup-benchmark-db.js +0 -70
  195. package/src/api/server.ts +0 -266
  196. package/src/cli/index.ts +0 -302
  197. package/src/compliance/compliance-generator.ts +0 -452
  198. package/src/compliance/index.ts +0 -28
  199. package/src/compliance/types.ts +0 -170
  200. package/src/db/index.ts +0 -28
  201. package/src/db/schema.ts +0 -84
  202. package/src/feed-analyzer/index.ts +0 -34
  203. package/src/feed-analyzer/types.ts +0 -354
  204. package/src/generator/key-generator.ts +0 -124
  205. package/src/generator/profile-builder.ts +0 -402
  206. package/src/index.ts +0 -105
  207. package/src/security/security-scanner.ts +0 -604
  208. package/src/security/types.ts +0 -55
  209. package/src/services/directory.ts +0 -434
  210. package/src/types/generator.ts +0 -140
  211. package/src/types/ucp-profile.ts +0 -140
  212. package/src/types/validation.ts +0 -89
  213. package/src/validator/index.ts +0 -194
  214. package/src/validator/network-validator.ts +0 -417
  215. package/src/validator/rules-validator.ts +0 -297
  216. package/src/validator/structural-validator.ts +0 -476
  217. package/tests/fixtures/non-compliant-profile.json +0 -25
  218. package/tests/fixtures/official-sample-profile.json +0 -75
  219. package/tests/integration/benchmark.test.ts +0 -207
  220. package/tests/integration/database.test.ts +0 -163
  221. package/tests/integration/directory-api.test.ts +0 -268
  222. package/tests/integration/simulate-api.test.ts +0 -230
  223. package/tests/integration/validate-api.test.ts +0 -269
  224. package/tests/setup.ts +0 -15
  225. package/tests/unit/agent-simulator.test.ts +0 -575
  226. package/tests/unit/compliance-generator.test.ts +0 -374
  227. package/tests/unit/directory-service.test.ts +0 -272
  228. package/tests/unit/feed-analyzer.test.ts +0 -517
  229. package/tests/unit/lint-suggestions.test.ts +0 -423
  230. package/tests/unit/official-samples.test.ts +0 -211
  231. package/tests/unit/pdf-report.test.ts +0 -390
  232. package/tests/unit/sdk-validator.test.ts +0 -531
  233. package/tests/unit/security-scanner.test.ts +0 -410
  234. package/tests/unit/validation.test.ts +0 -390
  235. package/vercel.json +0 -34
  236. package/vitest.config.ts +0 -22
@@ -1,297 +0,0 @@
1
- /**
2
- * UCP Rules Validator
3
- * Validates UCP-specific business rules (no network calls)
4
- */
5
-
6
- import type { UcpProfile, UcpCapability } from '../types/ucp-profile.js';
7
- import type { ValidationIssue } from '../types/validation.js';
8
- import { ValidationErrorCodes } from '../types/validation.js';
9
- import { CAPABILITY_NAMESPACES, KNOWN_CAPABILITIES } from '../types/ucp-profile.js';
10
-
11
- /**
12
- * Validate UCP business rules
13
- */
14
- export function validateRules(profile: UcpProfile): ValidationIssue[] {
15
- const issues: ValidationIssue[] = [];
16
-
17
- // Validate namespace/origin binding for capabilities
18
- issues.push(...validateNamespaceOrigins(profile));
19
-
20
- // Validate extension chains (no orphaned extends)
21
- issues.push(...validateExtensions(profile));
22
-
23
- // Validate endpoint rules
24
- issues.push(...validateEndpoints(profile));
25
-
26
- // Validate signing keys if Order capability is present
27
- issues.push(...validateSigningKeysRequirement(profile));
28
-
29
- return issues;
30
- }
31
-
32
- /**
33
- * Validate namespace and URL origin binding
34
- * - dev.ucp.* capabilities must have spec/schema from ucp.dev
35
- * - com.vendor.* capabilities must have spec/schema from vendor's domain
36
- */
37
- function validateNamespaceOrigins(profile: UcpProfile): ValidationIssue[] {
38
- const issues: ValidationIssue[] = [];
39
- const capabilities = profile.ucp.capabilities || [];
40
-
41
- for (let i = 0; i < capabilities.length; i++) {
42
- const cap = capabilities[i];
43
- const path = `$.ucp.capabilities[${i}]`;
44
-
45
- // Check dev.ucp.* namespace
46
- if (cap.name.startsWith(CAPABILITY_NAMESPACES.UCP_OFFICIAL)) {
47
- // Spec must be from ucp.dev
48
- if (cap.spec && !isUcpDevOrigin(cap.spec)) {
49
- issues.push({
50
- severity: 'error',
51
- code: ValidationErrorCodes.NS_ORIGIN_MISMATCH,
52
- path: `${path}.spec`,
53
- message: `dev.ucp.* capability spec must be hosted on ucp.dev`,
54
- hint: `Use https://ucp.dev/specification/... instead of "${cap.spec}"`,
55
- });
56
- }
57
-
58
- // Schema must be from ucp.dev
59
- if (cap.schema && !isUcpDevOrigin(cap.schema)) {
60
- issues.push({
61
- severity: 'error',
62
- code: ValidationErrorCodes.NS_ORIGIN_MISMATCH,
63
- path: `${path}.schema`,
64
- message: `dev.ucp.* capability schema must be hosted on ucp.dev`,
65
- hint: `Use https://ucp.dev/schemas/... instead of "${cap.schema}"`,
66
- });
67
- }
68
- }
69
-
70
- // Check vendor namespace (com.vendor.*)
71
- if (cap.name.startsWith(CAPABILITY_NAMESPACES.VENDOR_PREFIX)) {
72
- const vendorDomain = extractVendorDomain(cap.name);
73
- if (vendorDomain) {
74
- // Spec origin should match vendor domain
75
- if (cap.spec && !isOriginFromDomain(cap.spec, vendorDomain)) {
76
- issues.push({
77
- severity: 'warn',
78
- code: ValidationErrorCodes.NS_ORIGIN_MISMATCH,
79
- path: `${path}.spec`,
80
- message: `Vendor capability spec should be hosted on vendor's domain (${vendorDomain})`,
81
- hint: `Consider hosting spec at https://${vendorDomain}/...`,
82
- });
83
- }
84
-
85
- // Schema origin should match vendor domain
86
- if (cap.schema && !isOriginFromDomain(cap.schema, vendorDomain)) {
87
- issues.push({
88
- severity: 'warn',
89
- code: ValidationErrorCodes.NS_ORIGIN_MISMATCH,
90
- path: `${path}.schema`,
91
- message: `Vendor capability schema should be hosted on vendor's domain (${vendorDomain})`,
92
- hint: `Consider hosting schema at https://${vendorDomain}/...`,
93
- });
94
- }
95
- }
96
- }
97
- }
98
-
99
- return issues;
100
- }
101
-
102
- /**
103
- * Validate extension chains - ensure parent capabilities exist
104
- */
105
- function validateExtensions(profile: UcpProfile): ValidationIssue[] {
106
- const issues: ValidationIssue[] = [];
107
- const capabilities = profile.ucp.capabilities || [];
108
-
109
- // Build set of capability names
110
- const capabilityNames = new Set(capabilities.map(c => c.name));
111
-
112
- for (let i = 0; i < capabilities.length; i++) {
113
- const cap = capabilities[i];
114
-
115
- if (cap.extends) {
116
- // Check if parent capability exists in this profile
117
- if (!capabilityNames.has(cap.extends)) {
118
- issues.push({
119
- severity: 'error',
120
- code: ValidationErrorCodes.ORPHANED_EXTENSION,
121
- path: `$.ucp.capabilities[${i}].extends`,
122
- message: `Extension "${cap.name}" references non-existent parent capability "${cap.extends}"`,
123
- hint: `Add "${cap.extends}" to capabilities or remove the extends field`,
124
- });
125
- }
126
- }
127
- }
128
-
129
- return issues;
130
- }
131
-
132
- /**
133
- * Validate endpoint rules (https, no trailing slash)
134
- */
135
- function validateEndpoints(profile: UcpProfile): ValidationIssue[] {
136
- const issues: ValidationIssue[] = [];
137
- const services = profile.ucp.services || {};
138
-
139
- for (const [serviceName, service] of Object.entries(services)) {
140
- const basePath = `$.ucp.services["${serviceName}"]`;
141
-
142
- // Validate REST endpoint
143
- if (service.rest?.endpoint) {
144
- issues.push(...validateEndpoint(service.rest.endpoint, `${basePath}.rest.endpoint`));
145
- }
146
-
147
- // Validate MCP endpoint
148
- if (service.mcp?.endpoint) {
149
- issues.push(...validateEndpoint(service.mcp.endpoint, `${basePath}.mcp.endpoint`));
150
- }
151
-
152
- // Validate A2A agent card URL
153
- if (service.a2a?.agentCard) {
154
- issues.push(...validateEndpoint(service.a2a.agentCard, `${basePath}.a2a.agentCard`));
155
- }
156
- }
157
-
158
- return issues;
159
- }
160
-
161
- /**
162
- * Validate a single endpoint URL
163
- */
164
- function validateEndpoint(endpoint: string, path: string): ValidationIssue[] {
165
- const issues: ValidationIssue[] = [];
166
-
167
- // Must be HTTPS
168
- if (!endpoint.startsWith('https://')) {
169
- issues.push({
170
- severity: 'error',
171
- code: ValidationErrorCodes.ENDPOINT_NOT_HTTPS,
172
- path,
173
- message: `Endpoint must use HTTPS`,
174
- hint: `Change "${endpoint}" to use https://`,
175
- });
176
- }
177
-
178
- // Should not have trailing slash
179
- if (endpoint.endsWith('/')) {
180
- issues.push({
181
- severity: 'warn',
182
- code: ValidationErrorCodes.ENDPOINT_TRAILING_SLASH,
183
- path,
184
- message: `Endpoint should not have a trailing slash`,
185
- hint: `Remove trailing slash from "${endpoint}"`,
186
- });
187
- }
188
-
189
- // Check for private IP ranges (basic check)
190
- if (isPrivateIpEndpoint(endpoint)) {
191
- issues.push({
192
- severity: 'warn',
193
- code: ValidationErrorCodes.PRIVATE_IP_ENDPOINT,
194
- path,
195
- message: `Endpoint appears to use a private IP address`,
196
- hint: `Use a public domain name for production profiles`,
197
- });
198
- }
199
-
200
- return issues;
201
- }
202
-
203
- /**
204
- * Validate signing keys requirement for Order capability
205
- */
206
- function validateSigningKeysRequirement(profile: UcpProfile): ValidationIssue[] {
207
- const issues: ValidationIssue[] = [];
208
- const capabilities = profile.ucp.capabilities || [];
209
-
210
- // Check if Order capability is present
211
- const hasOrderCapability = capabilities.some(
212
- c => c.name === KNOWN_CAPABILITIES.ORDER
213
- );
214
-
215
- if (hasOrderCapability) {
216
- // Signing keys should be present for webhook signing
217
- if (!profile.signing_keys || profile.signing_keys.length === 0) {
218
- issues.push({
219
- severity: 'error',
220
- code: ValidationErrorCodes.MISSING_SIGNING_KEYS,
221
- path: '$.signing_keys',
222
- message: `Order capability requires signing_keys for webhook verification`,
223
- hint: `Add signing_keys array with at least one JWK public key`,
224
- });
225
- }
226
- }
227
-
228
- return issues;
229
- }
230
-
231
- /**
232
- * Check if URL is from ucp.dev origin
233
- */
234
- function isUcpDevOrigin(url: string): boolean {
235
- try {
236
- const parsed = new URL(url);
237
- return parsed.hostname === 'ucp.dev' || parsed.hostname.endsWith('.ucp.dev');
238
- } catch {
239
- return false;
240
- }
241
- }
242
-
243
- /**
244
- * Extract vendor domain from capability name
245
- * e.g., "com.example.feature" -> "example.com"
246
- */
247
- function extractVendorDomain(name: string): string | null {
248
- if (!name.startsWith('com.')) {
249
- return null;
250
- }
251
-
252
- const parts = name.split('.');
253
- if (parts.length < 3) {
254
- return null;
255
- }
256
-
257
- // "com.example.feature" -> "example.com"
258
- return `${parts[1]}.com`;
259
- }
260
-
261
- /**
262
- * Check if URL origin matches expected domain
263
- */
264
- function isOriginFromDomain(url: string, domain: string): boolean {
265
- try {
266
- const parsed = new URL(url);
267
- return parsed.hostname === domain || parsed.hostname.endsWith(`.${domain}`);
268
- } catch {
269
- return false;
270
- }
271
- }
272
-
273
- /**
274
- * Check if endpoint uses private IP address
275
- */
276
- function isPrivateIpEndpoint(endpoint: string): boolean {
277
- try {
278
- const parsed = new URL(endpoint);
279
- const hostname = parsed.hostname;
280
-
281
- // Check for localhost
282
- if (hostname === 'localhost' || hostname === '127.0.0.1') {
283
- return true;
284
- }
285
-
286
- // Check for private IP ranges (simplified)
287
- if (hostname.startsWith('10.') ||
288
- hostname.startsWith('192.168.') ||
289
- hostname.match(/^172\.(1[6-9]|2[0-9]|3[0-1])\./)) {
290
- return true;
291
- }
292
-
293
- return false;
294
- } catch {
295
- return false;
296
- }
297
- }