@contractkit/plugin-typescript
Advanced tools
| > @contractkit/plugin-typescript@0.24.0 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > @contractkit/plugin-typescript@0.25.0 build:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > eslint --max-warnings=0 && pnpm run build | ||
| > @contractkit/plugin-typescript@0.24.0 build /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > @contractkit/plugin-typescript@0.25.0 build /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > tsup src/index.ts --format esm --sourcemap --dts && tsc --emitDeclarationOnly --declaration | ||
@@ -15,6 +15,6 @@ | ||
| [32mESM[39m [1mdist/index.js [22m[32m149.94 KB[39m | ||
| [32mESM[39m [1mdist/index.js.map [22m[32m327.56 KB[39m | ||
| [32mESM[39m ⚡️ Build success in 339ms | ||
| [32mESM[39m [1mdist/index.js.map [22m[32m327.66 KB[39m | ||
| [32mESM[39m ⚡️ Build success in 449ms | ||
| [34mDTS[39m Build start | ||
| [32mDTS[39m ⚡️ Build success in 4724ms | ||
| [32mDTS[39m ⚡️ Build success in 5889ms | ||
| [32mDTS[39m [1mdist/index.d.ts [22m[32m1.82 KB[39m |
| > @contractkit/plugin-typescript@0.24.0 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > @contractkit/plugin-typescript@0.25.0 test:ci /home/runner/work/ContractKit/ContractKit/packages/plugin-typescript | ||
| > vitest run --coverage | ||
@@ -9,13 +9,13 @@ | ||
| [32m✓[39m tests/codegen-operation.test.ts [2m([22m[2m88 tests[22m[2m)[22m[32m 104[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-contract.test.ts [2m([22m[2m127 tests[22m[2m)[22m[32m 116[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-sdk.test.ts [2m([22m[2m132 tests[22m[2m)[22m[32m 134[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-operation.test.ts [2m([22m[2m88 tests[22m[2m)[22m[32m 149[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-contract.test.ts [2m([22m[2m127 tests[22m[2m)[22m[32m 132[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-sdk.test.ts [2m([22m[2m132 tests[22m[2m)[22m[32m 175[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-plain-types.test.ts [2m([22m[2m61 tests[22m[2m)[22m[32m 34[2mms[22m[39m | ||
| [32m✓[39m tests/pipeline.test.ts [2m([22m[2m25 tests[22m[2m)[22m[32m 149[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-server.test.ts [2m([22m[2m19 tests[22m[2m)[22m[32m 31[2mms[22m[39m | ||
| [32m✓[39m tests/pipeline.test.ts [2m([22m[2m25 tests[22m[2m)[22m[32m 199[2mms[22m[39m | ||
| [32m✓[39m tests/codegen-server.test.ts [2m([22m[2m19 tests[22m[2m)[22m[32m 67[2mms[22m[39m | ||
| [2m Test Files [22m [1m[32m6 passed[39m[22m[90m (6)[39m | ||
| [2m Tests [22m [1m[32m452 passed[39m[22m[90m (452)[39m | ||
| [2m Start at [22m 15:00:19 | ||
| [2m Duration [22m 5.63s[2m (transform 3.00s, setup 0ms, import 10.57s, tests 567ms, environment 4ms)[22m | ||
| [2m Start at [22m 17:08:46 | ||
| [2m Duration [22m 6.33s[2m (transform 4.31s, setup 0ms, import 12.82s, tests 757ms, environment 9ms)[22m | ||
@@ -26,6 +26,6 @@ [34m % [39m[2mCoverage report from [22m[33mv8[39m | ||
| -------------------|---------|----------|---------|---------|------------------- | ||
| All files | 80 | 75.28 | 83.5 | 82.61 | | ||
| src | 79.79 | 74.96 | 83.06 | 82.37 | | ||
| All files | 80.01 | 75.28 | 83.5 | 82.62 | | ||
| src | 79.79 | 74.96 | 83.06 | 82.38 | | ||
| ...n-contract.ts | 87.92 | 82.7 | 90.08 | 89.06 | ...1085,1090-1091 | ||
| ...-operation.ts | 78.13 | 74.26 | 77.77 | 79.69 | ...69-680,685-686 | ||
| ...-operation.ts | 78.18 | 74.26 | 77.77 | 79.75 | ...75-686,691-692 | ||
| ...lain-types.ts | 89.08 | 78.37 | 96.66 | 92.3 | ...31,243,249,301 | ||
@@ -32,0 +32,0 @@ codegen-sdk.ts | 88.09 | 82.56 | 87.32 | 91.32 | ...1108-1109,1112 |
+42
-0
| # @contractkit/contractkit-plugin-typescript | ||
| ## 0.25.0 | ||
| ### Minor Changes | ||
| - dd8197b: **Breaking:** Replace the `requireMfa: boolean` field in `security: { ... }` blocks with `policy: <ident|none>`, and switch the generated Koa router middleware from `requireSecurity` to ServerKit's new `requirePolicy`. | ||
| The `security` declaration on operations, routes, and the file-level `options { security: { ... } }` block no longer accepts a `requireMfa:` line. The new field is `policy:` and takes a bare identifier (the named policy) or the keyword `none` to explicitly bypass policy enforcement. Existing `.ck` files that use `requireMfa:` will fail to parse. | ||
| ```ck | ||
| # Before | ||
| security: { | ||
| requireMfa: true | ||
| } | ||
| # After | ||
| security: { | ||
| policy: paymentsWrite | ||
| } | ||
| # Explicit bypass | ||
| security: { | ||
| policy: none | ||
| } | ||
| ``` | ||
| **`@contractkit/core`** — `SecurityFields` interface drops `requireMfa` / `requireMfaDescription` and adds `policy?: string | false` / `policyDescription?: string`. The grammar's `SecurityRequireMfaLine` is replaced by `SecurityPolicyLine` (`policyKw ":" (noneKw | identifier)`). `security: none` (the route-level public sentinel) is unchanged. | ||
| **`@contractkit/plugin-typescript`** — Generated Koa routers now import `requirePolicy` from `@maroonedsoftware/koa` (previously `requireSecurity`) and emit `requirePolicy({ policy: 'name' })`, `requirePolicy({ policy: false })`, or bare `requirePolicy()`. Consumers must upgrade ServerKit alongside. | ||
| **`@contractkit/prettier-plugin`** — Formats `policy: <name>` and `policy: none` lines inside security blocks. Files containing `requireMfa:` will no longer round-trip and will surface as parse errors. | ||
| **`@contractkit/plugin-markdown`** — The "Security: authenticated" admonition now shows `policy: <name|none>` instead of `requireMfa: <bool>`. | ||
| **`@contractkit/openapi-to-ck`** — Non-empty OpenAPI `security` requirements continue to collapse to an empty `security: {}` (authenticated, default policy); the serializer now emits `policy:` lines when the field is set. | ||
| **`contractkit-vscode-extension`** — TextMate grammar highlights `policy:` inside the security block; LSP completion offers `policy` instead of `requireMfa`. Re-run `pnpm run vscode:install` to pick up the change. | ||
| ### Patch Changes | ||
| - Updated dependencies [dd8197b] | ||
| - @contractkit/core@0.18.0 | ||
| ## 0.24.0 | ||
@@ -4,0 +46,0 @@ |
@@ -26,5 +26,5 @@ | ||
| <div class='fl pad1y space-right2'> | ||
| <span class="strong">80% </span> | ||
| <span class="strong">80.01% </span> | ||
| <span class="quiet">Statements</span> | ||
| <span class='fraction'>2033/2541</span> | ||
| <span class='fraction'>2034/2542</span> | ||
| </div> | ||
@@ -48,5 +48,5 @@ | ||
| <div class='fl pad1y space-right2'> | ||
| <span class="strong">82.61% </span> | ||
| <span class="strong">82.62% </span> | ||
| <span class="quiet">Lines</span> | ||
| <span class='fraction'>1782/2157</span> | ||
| <span class='fraction'>1783/2158</span> | ||
| </div> | ||
@@ -89,3 +89,3 @@ | ||
| <td data-value="79.79" class="pct medium">79.79%</td> | ||
| <td data-value="2489" class="abs medium">1986/2489</td> | ||
| <td data-value="2490" class="abs medium">1987/2490</td> | ||
| <td data-value="74.96" class="pct medium">74.96%</td> | ||
@@ -95,4 +95,4 @@ <td data-value="1606" class="abs medium">1204/1606</td> | ||
| <td data-value="372" class="abs high">309/372</td> | ||
| <td data-value="82.37" class="pct high">82.37%</td> | ||
| <td data-value="2111" class="abs high">1739/2111</td> | ||
| <td data-value="82.38" class="pct high">82.38%</td> | ||
| <td data-value="2112" class="abs high">1740/2112</td> | ||
| </tr> | ||
@@ -123,3 +123,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -126,0 +126,0 @@ <script src="prettify.js"></script> |
@@ -985,3 +985,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -988,0 +988,0 @@ <script src="../prettify.js"></script> |
@@ -28,3 +28,3 @@ | ||
| <span class="quiet">Statements</span> | ||
| <span class='fraction'>1986/2489</span> | ||
| <span class='fraction'>1987/2490</span> | ||
| </div> | ||
@@ -48,5 +48,5 @@ | ||
| <div class='fl pad1y space-right2'> | ||
| <span class="strong">82.37% </span> | ||
| <span class="strong">82.38% </span> | ||
| <span class="quiet">Lines</span> | ||
| <span class='fraction'>1739/2111</span> | ||
| <span class='fraction'>1740/2112</span> | ||
| </div> | ||
@@ -100,7 +100,7 @@ | ||
| <td class="file medium" data-value="codegen-operation.ts"><a href="codegen-operation.ts.html">codegen-operation.ts</a></td> | ||
| <td data-value="78.13" class="pic medium"> | ||
| <td data-value="78.18" class="pic medium"> | ||
| <div class="chart"><div class="cover-fill" style="width: 78%"></div><div class="cover-empty" style="width: 22%"></div></div> | ||
| </td> | ||
| <td data-value="78.13" class="pct medium">78.13%</td> | ||
| <td data-value="462" class="abs medium">361/462</td> | ||
| <td data-value="78.18" class="pct medium">78.18%</td> | ||
| <td data-value="463" class="abs medium">362/463</td> | ||
| <td data-value="74.26" class="pct medium">74.26%</td> | ||
@@ -110,4 +110,4 @@ <td data-value="338" class="abs medium">251/338</td> | ||
| <td data-value="72" class="abs medium">56/72</td> | ||
| <td data-value="79.69" class="pct medium">79.69%</td> | ||
| <td data-value="399" class="abs medium">318/399</td> | ||
| <td data-value="79.75" class="pct medium">79.75%</td> | ||
| <td data-value="400" class="abs medium">319/400</td> | ||
| </tr> | ||
@@ -198,3 +198,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -201,0 +201,0 @@ <script src="../prettify.js"></script> |
@@ -733,3 +733,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -736,0 +736,0 @@ <script src="../prettify.js"></script> |
@@ -580,3 +580,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -583,0 +583,0 @@ <script src="../prettify.js"></script> |
@@ -814,3 +814,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -817,0 +817,0 @@ <script src="../prettify.js"></script> |
@@ -104,3 +104,3 @@ | ||
| <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a> | ||
| at 2026-05-12T15:00:24.685Z | ||
| at 2026-05-13T17:08:53.091Z | ||
| </div> | ||
@@ -107,0 +107,0 @@ <script src="../prettify.js"></script> |
+2
-2
| { | ||
| "name": "@contractkit/plugin-typescript", | ||
| "version": "0.24.0", | ||
| "version": "0.25.0", | ||
| "description": "ContractKit built-in plugin: TypeScript codegen (SDK clients, Koa routers, Zod schemas, plain types)", | ||
@@ -29,3 +29,3 @@ "author": { | ||
| "dependencies": { | ||
| "@contractkit/core": "0.17.0" | ||
| "@contractkit/core": "0.18.0" | ||
| }, | ||
@@ -32,0 +32,0 @@ "devDependencies": { |
@@ -140,5 +140,5 @@ import type { OpRootNode, OpRouteNode, OpOperationNode, ContractTypeNode, ParamSource, ObjectMode } from '@contractkit/core'; | ||
| const needsSignature = fileNeedsSignature(root); | ||
| const needsSecurity = fileNeedsSecurity(root); | ||
| const needsPolicy = fileNeedsPolicy(root); | ||
| const koaImports = ['ServerKitRouter', 'bodyParserMiddleware']; | ||
| if (needsSecurity) koaImports.push('requireSecurity'); | ||
| if (needsPolicy) koaImports.push('requirePolicy'); | ||
| if (needsSignature) koaImports.push('requireSignature'); | ||
@@ -245,4 +245,10 @@ body.push(`import { ${koaImports.join(', ')} } from '@maroonedsoftware/koa';`); | ||
| if (effectiveSecurity !== SECURITY_NONE) { | ||
| const args = effectiveSecurity && effectiveSecurity.requireMfa !== undefined ? `{ requireMfa: ${effectiveSecurity.requireMfa} }` : ''; | ||
| middlewares.push(`requireSecurity(${args})`); | ||
| const policy = effectiveSecurity?.policy; | ||
| const args = | ||
| policy === undefined | ||
| ? '' | ||
| : policy === false | ||
| ? '{ policy: false }' | ||
| : `{ policy: '${policy}' }`; | ||
| middlewares.push(`requirePolicy(${args})`); | ||
| } | ||
@@ -766,3 +772,3 @@ if (hasBody) { | ||
| function fileNeedsSecurity(root: OpRootNode): boolean { | ||
| function fileNeedsPolicy(root: OpRootNode): boolean { | ||
| return root.routes.some(route => route.operations.some(op => resolveSecurity(route, op, root) !== SECURITY_NONE)); | ||
@@ -769,0 +775,0 @@ } |
@@ -810,5 +810,5 @@ import { describe, it, expect } from 'vitest'; | ||
| it('emits no annotation for security with requireMfa', () => { | ||
| it('emits no annotation for security with policy', () => { | ||
| const op = opOperation('get', { | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| }); | ||
@@ -849,3 +849,3 @@ const root = opRoot([opRoute('/users', [op])]); | ||
| const out = generateOp(root); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requireSecurity, requireSignature }`); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requirePolicy, requireSignature }`); | ||
| expect(out).toContain(`requireSignature('MODERN_TREASURY_WEBHOOK')`); | ||
@@ -872,3 +872,3 @@ }); | ||
| const op = opOperation('get', { | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| }); | ||
@@ -878,29 +878,29 @@ const root = opRoot([opRoute('/users', [op])]); | ||
| expect(out).not.toContain('requireSignature'); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requireSecurity }`); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requirePolicy }`); | ||
| }); | ||
| }); | ||
| // ─── Security (requireMfa) middleware ─────────────────────────── | ||
| // ─── Policy middleware ────────────────────────────────────────── | ||
| describe('security middleware', () => { | ||
| it('injects requireSecurity() with no args for unannotated routes', () => { | ||
| describe('policy middleware', () => { | ||
| it('injects requirePolicy() with no args for unannotated routes', () => { | ||
| const op = opOperation('get'); | ||
| const root = opRoot([opRoute('/users', [op])]); | ||
| const out = generateOp(root); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requireSecurity }`); | ||
| expect(out).toContain(`requireSecurity()`); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requirePolicy }`); | ||
| expect(out).toContain(`requirePolicy()`); | ||
| }); | ||
| it('injects requireSecurity with requireMfa: true when set', () => { | ||
| it('injects requirePolicy with a named policy when set', () => { | ||
| const op = opOperation('get', { | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| }); | ||
| const root = opRoot([opRoute('/users', [op])]); | ||
| const out = generateOp(root); | ||
| expect(out).toContain(`requireSecurity({ requireMfa: true })`); | ||
| expect(out).toContain(`requirePolicy({ policy: 'paymentsWrite' })`); | ||
| }); | ||
| it('injects requireSecurity with requireMfa: false when set', () => { | ||
| it('injects requirePolicy with policy: false when explicitly bypassed', () => { | ||
| const op = opOperation('get', { | ||
| security: { requireMfa: false, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: false, loc: { file: 'test.op', line: 1 } }, | ||
| }); | ||
@@ -910,13 +910,13 @@ const routeLine = generateOp(opRoot([opRoute('/users', [op])])) | ||
| .find(l => l.includes('.get(')); | ||
| expect(routeLine).toContain(`requireSecurity({ requireMfa: false })`); | ||
| expect(routeLine).toContain(`requirePolicy({ policy: false })`); | ||
| }); | ||
| it('does not inject requireSecurity for public (security: none) routes', () => { | ||
| it('does not inject requirePolicy for public (security: none) routes', () => { | ||
| const op = opOperation('get', { security: SECURITY_NONE }); | ||
| const root = opRoot([opRoute('/health', [op])]); | ||
| const out = generateOp(root); | ||
| expect(out).not.toContain('requireSecurity'); | ||
| expect(out).not.toContain('requirePolicy'); | ||
| }); | ||
| it('does not import requireSecurity when all routes are public', () => { | ||
| it('does not import requirePolicy when all routes are public', () => { | ||
| const op = opOperation('get', { security: SECURITY_NONE }); | ||
@@ -926,8 +926,8 @@ const root = opRoot([opRoute('/health', [op])]); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware }`); | ||
| expect(out).not.toContain('requireSecurity'); | ||
| expect(out).not.toContain('requirePolicy'); | ||
| }); | ||
| it('places requireSecurity before bodyParserMiddleware in the route line', () => { | ||
| it('places requirePolicy before bodyParserMiddleware in the route line', () => { | ||
| const op = opOperation('post', { | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| request: opRequest('Payload'), | ||
@@ -940,12 +940,12 @@ }); | ||
| expect(routeLine).toBeDefined(); | ||
| const secIdx = routeLine!.indexOf(`requireSecurity`); | ||
| const polIdx = routeLine!.indexOf(`requirePolicy`); | ||
| const bodyIdx = routeLine!.indexOf(`bodyParserMiddleware`); | ||
| expect(secIdx).toBeGreaterThan(-1); | ||
| expect(bodyIdx).toBeGreaterThan(secIdx); | ||
| expect(polIdx).toBeGreaterThan(-1); | ||
| expect(bodyIdx).toBeGreaterThan(polIdx); | ||
| }); | ||
| it('places requireSecurity before requireSignature when both are set', () => { | ||
| it('places requirePolicy before requireSignature when both are set', () => { | ||
| const op = opOperation('post', { | ||
| signature: 'MY_KEY', | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| request: opRequest('Payload'), | ||
@@ -958,12 +958,12 @@ }); | ||
| expect(routeLine).toBeDefined(); | ||
| const secIdx = routeLine!.indexOf(`requireSecurity`); | ||
| const polIdx = routeLine!.indexOf(`requirePolicy`); | ||
| const sigIdx = routeLine!.indexOf(`requireSignature`); | ||
| expect(secIdx).toBeGreaterThan(-1); | ||
| expect(sigIdx).toBeGreaterThan(secIdx); | ||
| expect(polIdx).toBeGreaterThan(-1); | ||
| expect(sigIdx).toBeGreaterThan(polIdx); | ||
| }); | ||
| it('imports both requireSecurity and requireSignature when both are set', () => { | ||
| it('imports both requirePolicy and requireSignature when both are set', () => { | ||
| const op = opOperation('post', { | ||
| signature: 'MY_KEY', | ||
| security: { requireMfa: true, loc: { file: 'test.op', line: 1 } }, | ||
| security: { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }, | ||
| request: opRequest('Payload'), | ||
@@ -973,14 +973,14 @@ }); | ||
| const out = generateOp(root); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requireSecurity, requireSignature }`); | ||
| expect(out).toContain(`import { ServerKitRouter, bodyParserMiddleware, requirePolicy, requireSignature }`); | ||
| }); | ||
| it('works with route-level requireMfa security', () => { | ||
| it('works with route-level policy security', () => { | ||
| const op = opOperation('get'); | ||
| const route = opRoute('/users', [op]); | ||
| route.security = { requireMfa: true, loc: { file: 'test.op', line: 1 } }; | ||
| route.security = { policy: 'paymentsWrite', loc: { file: 'test.op', line: 1 } }; | ||
| const root = opRoot([route]); | ||
| const out = generateOp(root); | ||
| expect(out).toContain(`requireSecurity({ requireMfa: true })`); | ||
| expect(out).toContain(`requirePolicy({ policy: 'paymentsWrite' })`); | ||
| }); | ||
| }); | ||
| }); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
2545704
0.13%16292
0.04%+ Added
- Removed
Updated