@brika/plugin 0.3.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.
- package/package.json +26 -0
- package/src/__tests__/plugin.test.ts +64 -0
- package/src/index.ts +159 -0
- package/src/manifests.ts +87 -0
- package/src/preferences.ts +79 -0
- package/src/store.ts +96 -0
- package/tsconfig.json +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brika/plugin",
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Core plugin runtime types and port compatibility for BRIKA",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/brikalabs/brika.git",
|
|
10
|
+
"directory": "packages/plugin"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["brika", "plugin", "types"],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": "./src/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"typecheck": "tsgo --noEmit",
|
|
18
|
+
"test": "bun test"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@brika/type-system": "0.1.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/bun": "^1.3.9"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { arePortTypesCompatible } from '..';
|
|
3
|
+
|
|
4
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
// arePortTypesCompatible
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
describe('arePortTypesCompatible', () => {
|
|
9
|
+
test('generic/undefined types are always compatible', () => {
|
|
10
|
+
expect(arePortTypesCompatible(undefined, 'string')).toBe(true);
|
|
11
|
+
expect(arePortTypesCompatible('string', undefined)).toBe(true);
|
|
12
|
+
expect(arePortTypesCompatible(undefined, undefined)).toBe(true);
|
|
13
|
+
expect(arePortTypesCompatible('any', 'number')).toBe(true);
|
|
14
|
+
expect(arePortTypesCompatible('unknown', 'boolean')).toBe(true);
|
|
15
|
+
expect(arePortTypesCompatible('generic', 'string')).toBe(true);
|
|
16
|
+
expect(arePortTypesCompatible('generic-foo', 'number')).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('exact type matches', () => {
|
|
20
|
+
expect(arePortTypesCompatible('string', 'string')).toBe(true);
|
|
21
|
+
expect(arePortTypesCompatible('number', 'number')).toBe(true);
|
|
22
|
+
expect(arePortTypesCompatible('boolean', 'boolean')).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('case-insensitive matching', () => {
|
|
26
|
+
expect(arePortTypesCompatible('String', 'string')).toBe(true);
|
|
27
|
+
expect(arePortTypesCompatible('NUMBER', 'number')).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('number family compatibility', () => {
|
|
31
|
+
expect(arePortTypesCompatible('number', 'integer')).toBe(true);
|
|
32
|
+
expect(arePortTypesCompatible('integer', 'float')).toBe(true);
|
|
33
|
+
expect(arePortTypesCompatible('float', 'double')).toBe(true);
|
|
34
|
+
expect(arePortTypesCompatible('double', 'number')).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('string accepts primitives', () => {
|
|
38
|
+
expect(arePortTypesCompatible('number', 'string')).toBe(true);
|
|
39
|
+
expect(arePortTypesCompatible('integer', 'string')).toBe(true);
|
|
40
|
+
expect(arePortTypesCompatible('boolean', 'string')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('string does not accept non-primitives', () => {
|
|
44
|
+
expect(arePortTypesCompatible('object', 'string')).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('object/json family compatibility', () => {
|
|
48
|
+
expect(arePortTypesCompatible('object', 'json')).toBe(true);
|
|
49
|
+
expect(arePortTypesCompatible('json', 'record')).toBe(true);
|
|
50
|
+
expect(arePortTypesCompatible('record', 'object')).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('array compatibility checks base types', () => {
|
|
54
|
+
expect(arePortTypesCompatible('number[]', 'number[]')).toBe(true);
|
|
55
|
+
expect(arePortTypesCompatible('number[]', 'integer[]')).toBe(true);
|
|
56
|
+
expect(arePortTypesCompatible('string[]', 'number[]')).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('incompatible types are rejected', () => {
|
|
60
|
+
expect(arePortTypesCompatible('string', 'number')).toBe(false);
|
|
61
|
+
expect(arePortTypesCompatible('boolean', 'number')).toBe(false);
|
|
62
|
+
expect(arePortTypesCompatible('string', 'boolean')).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brika/plugin — core plugin types, manifests, preferences, and port compatibility.
|
|
3
|
+
*
|
|
4
|
+
* Defines the plugin system types:
|
|
5
|
+
* - Runtime Plugin representation (hub ↔ UI API contract)
|
|
6
|
+
* - Capability manifests (blocks, sparks, bricks, pages)
|
|
7
|
+
* - Preference/configuration system
|
|
8
|
+
* - Port type compatibility checking for workflow connections
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export * from './manifests';
|
|
12
|
+
export * from './preferences';
|
|
13
|
+
export * from './store';
|
|
14
|
+
|
|
15
|
+
import { type TypeDescriptor, T, isCompatible } from '@brika/type-system';
|
|
16
|
+
import type { BlockManifest, BrickManifest, PageManifest, SparkManifest } from './manifests';
|
|
17
|
+
|
|
18
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
// Plugin Health & Runtime Representation
|
|
20
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
|
|
22
|
+
export type PluginHealth =
|
|
23
|
+
| 'running'
|
|
24
|
+
| 'stopped'
|
|
25
|
+
| 'crashed'
|
|
26
|
+
| 'degraded'
|
|
27
|
+
| 'installing'
|
|
28
|
+
| 'updating'
|
|
29
|
+
| 'restarting'
|
|
30
|
+
| 'crash-loop'
|
|
31
|
+
| 'incompatible';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Structured error with i18n support.
|
|
35
|
+
*
|
|
36
|
+
* - `key`: i18n translation key (e.g. `"plugins:errors.incompatibleVersion"`)
|
|
37
|
+
* - `params`: interpolation parameters for the key
|
|
38
|
+
* - `message`: pre-built English fallback (used in logs and when translations are unavailable)
|
|
39
|
+
*/
|
|
40
|
+
export interface PluginError {
|
|
41
|
+
key: string;
|
|
42
|
+
params?: Record<string, string>;
|
|
43
|
+
message: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Plugin representation - flattened for easy consumption */
|
|
47
|
+
export interface Plugin {
|
|
48
|
+
// ─── Identity ──────────────────────────────────────────────────────────────
|
|
49
|
+
/** Short unique ID - primary identifier */
|
|
50
|
+
uid: string;
|
|
51
|
+
/** Plugin name from package.json (e.g. "@brika/blocks-builtin") */
|
|
52
|
+
name: string;
|
|
53
|
+
/** Plugin version */
|
|
54
|
+
version: string;
|
|
55
|
+
|
|
56
|
+
// ─── Metadata (inlined from package.json) ──────────────────────────────────
|
|
57
|
+
/** Human-readable display name */
|
|
58
|
+
displayName: string | null;
|
|
59
|
+
/** Human-readable description */
|
|
60
|
+
description: string | null;
|
|
61
|
+
/** Author name or object */
|
|
62
|
+
author:
|
|
63
|
+
| string
|
|
64
|
+
| {
|
|
65
|
+
name: string;
|
|
66
|
+
email?: string;
|
|
67
|
+
url?: string;
|
|
68
|
+
}
|
|
69
|
+
| null;
|
|
70
|
+
/** Homepage URL */
|
|
71
|
+
homepage: string | null;
|
|
72
|
+
/** Repository URL or object */
|
|
73
|
+
repository:
|
|
74
|
+
| string
|
|
75
|
+
| {
|
|
76
|
+
type?: string;
|
|
77
|
+
url: string;
|
|
78
|
+
directory?: string;
|
|
79
|
+
}
|
|
80
|
+
| null;
|
|
81
|
+
/** Path to icon file */
|
|
82
|
+
icon: string | null;
|
|
83
|
+
/** Keywords for search/categorization */
|
|
84
|
+
keywords: string[];
|
|
85
|
+
/** License identifier */
|
|
86
|
+
license: string | null;
|
|
87
|
+
/** Engine compatibility requirements */
|
|
88
|
+
engines: {
|
|
89
|
+
brika: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// ─── Installation ──────────────────────────────────────────────────────────
|
|
93
|
+
/** Plugin root directory where package.json lives */
|
|
94
|
+
rootDirectory: string;
|
|
95
|
+
/** Entry point file path (absolute) */
|
|
96
|
+
entryPoint: string;
|
|
97
|
+
|
|
98
|
+
// ─── Runtime ───────────────────────────────────────────────────────────────
|
|
99
|
+
/** Current status */
|
|
100
|
+
status: PluginHealth;
|
|
101
|
+
/** Process ID (null when stopped) */
|
|
102
|
+
pid: number | null;
|
|
103
|
+
/** Timestamp when plugin was started (null when stopped) */
|
|
104
|
+
startedAt: number | null;
|
|
105
|
+
/** Last error (structured with i18n key, params, and English fallback) */
|
|
106
|
+
lastError: PluginError | null;
|
|
107
|
+
|
|
108
|
+
// ─── Capabilities ──────────────────────────────────────────────────────────
|
|
109
|
+
/** Available blocks */
|
|
110
|
+
blocks: BlockManifest[];
|
|
111
|
+
/** Available sparks (typed events) */
|
|
112
|
+
sparks: SparkManifest[];
|
|
113
|
+
/** Available bricks (board UI) */
|
|
114
|
+
bricks: BrickManifest[];
|
|
115
|
+
/** Custom pages provided by this plugin */
|
|
116
|
+
pages: PageManifest[];
|
|
117
|
+
|
|
118
|
+
// ─── Permissions ──────────────────────────────────────────────────────────
|
|
119
|
+
/** Permissions declared by this plugin (from package.json) */
|
|
120
|
+
permissions: string[];
|
|
121
|
+
/** Permissions currently granted by the user */
|
|
122
|
+
grantedPermissions: string[];
|
|
123
|
+
|
|
124
|
+
// ─── i18n ───────────────────────────────────────────────────────────────────
|
|
125
|
+
/** Available translation locales (e.g., ["en", "fr", "fr-CH"]) */
|
|
126
|
+
locales: string[];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
130
|
+
// Port Type Compatibility
|
|
131
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Check if two port types are compatible for connection.
|
|
135
|
+
* Returns true if source type can flow into target type.
|
|
136
|
+
*
|
|
137
|
+
* @deprecated Use `isCompatible()` from `@brika/type-system` instead.
|
|
138
|
+
* This function delegates to the structural type checker.
|
|
139
|
+
*/
|
|
140
|
+
export function arePortTypesCompatible(sourceType?: string, targetType?: string): boolean {
|
|
141
|
+
return isCompatible(parseTypeName(sourceType), parseTypeName(targetType));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Re-export for consumers migrating to @brika/type-system
|
|
145
|
+
export { isCompatible } from '@brika/type-system';
|
|
146
|
+
|
|
147
|
+
/** Parse a typeName string to a TypeDescriptor for backward compatibility */
|
|
148
|
+
function parseTypeName(typeName?: string): TypeDescriptor {
|
|
149
|
+
if (!typeName) return T.generic();
|
|
150
|
+
if (typeName.startsWith('generic') || typeName === 'unknown' || typeName === 'any') return T.generic();
|
|
151
|
+
const lower = typeName.toLowerCase().trim();
|
|
152
|
+
if (lower === 'string') return T.string;
|
|
153
|
+
if (['number', 'integer', 'float', 'double'].includes(lower)) return T.number;
|
|
154
|
+
if (lower === 'boolean') return T.boolean;
|
|
155
|
+
if (lower === 'null') return T.null;
|
|
156
|
+
if (['object', 'json', 'record'].includes(lower)) return T.record(T.unknown);
|
|
157
|
+
if (lower.endsWith('[]')) return T.array(parseTypeName(lower.slice(0, -2)));
|
|
158
|
+
return T.unknown;
|
|
159
|
+
}
|
package/src/manifests.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin manifest and capability type definitions.
|
|
3
|
+
*
|
|
4
|
+
* These types mirror the Zod schemas in @brika/schema and describe
|
|
5
|
+
* the structure of plugin capabilities in package.json.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { PreferenceDefinition } from './preferences';
|
|
9
|
+
|
|
10
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// Capability Manifests (from package.json)
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
/** Block manifest from package.json */
|
|
15
|
+
export interface BlockManifest {
|
|
16
|
+
id: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
category?: 'trigger' | 'flow' | 'action' | 'transform';
|
|
20
|
+
icon?: string;
|
|
21
|
+
color?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Spark (typed event) manifest from package.json */
|
|
25
|
+
export interface SparkManifest {
|
|
26
|
+
id: string;
|
|
27
|
+
name?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Brick size family */
|
|
32
|
+
export type BrickFamily = 'sm' | 'md' | 'lg';
|
|
33
|
+
|
|
34
|
+
/** Brick (board UI) manifest from package.json */
|
|
35
|
+
export interface BrickManifest {
|
|
36
|
+
id: string;
|
|
37
|
+
name?: string;
|
|
38
|
+
description?: string;
|
|
39
|
+
category?: string;
|
|
40
|
+
icon?: string;
|
|
41
|
+
color?: string;
|
|
42
|
+
families?: BrickFamily[];
|
|
43
|
+
config?: PreferenceDefinition[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Plugin page manifest from package.json */
|
|
47
|
+
export interface PageManifest {
|
|
48
|
+
id: string;
|
|
49
|
+
icon?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
53
|
+
// Plugin Manifest (from package.json)
|
|
54
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
export interface PluginManifest {
|
|
57
|
+
name: string;
|
|
58
|
+
version: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
author?:
|
|
61
|
+
| string
|
|
62
|
+
| {
|
|
63
|
+
name: string;
|
|
64
|
+
email?: string;
|
|
65
|
+
url?: string;
|
|
66
|
+
};
|
|
67
|
+
homepage?: string;
|
|
68
|
+
repository?:
|
|
69
|
+
| string
|
|
70
|
+
| {
|
|
71
|
+
type?: string;
|
|
72
|
+
url: string;
|
|
73
|
+
directory?: string;
|
|
74
|
+
};
|
|
75
|
+
icon?: string;
|
|
76
|
+
keywords?: string[];
|
|
77
|
+
license?: string;
|
|
78
|
+
engines?: {
|
|
79
|
+
brika?: string;
|
|
80
|
+
};
|
|
81
|
+
main?: string;
|
|
82
|
+
blocks?: BlockManifest[];
|
|
83
|
+
sparks?: SparkManifest[];
|
|
84
|
+
bricks?: BrickManifest[];
|
|
85
|
+
pages?: PageManifest[];
|
|
86
|
+
preferences?: PreferenceDefinition[];
|
|
87
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin preference type definitions.
|
|
3
|
+
*
|
|
4
|
+
* Raycast-style configuration system for plugins.
|
|
5
|
+
* Mirrors the Zod PreferenceSchema for runtime validation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type PreferenceType =
|
|
9
|
+
| 'text'
|
|
10
|
+
| 'password'
|
|
11
|
+
| 'checkbox'
|
|
12
|
+
| 'dropdown'
|
|
13
|
+
| 'dynamic-dropdown'
|
|
14
|
+
| 'number'
|
|
15
|
+
| 'link';
|
|
16
|
+
|
|
17
|
+
export interface BasePreference {
|
|
18
|
+
name: string;
|
|
19
|
+
type: PreferenceType;
|
|
20
|
+
label?: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TextPreference extends BasePreference {
|
|
26
|
+
type: 'text';
|
|
27
|
+
default?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PasswordPreference extends BasePreference {
|
|
31
|
+
type: 'password';
|
|
32
|
+
default?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface NumberPreference extends BasePreference {
|
|
36
|
+
type: 'number';
|
|
37
|
+
default?: number;
|
|
38
|
+
min?: number;
|
|
39
|
+
max?: number;
|
|
40
|
+
step?: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface CheckboxPreference extends BasePreference {
|
|
44
|
+
type: 'checkbox';
|
|
45
|
+
default?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface DropdownPreference extends BasePreference {
|
|
49
|
+
type: 'dropdown';
|
|
50
|
+
default?: string;
|
|
51
|
+
options: Array<{
|
|
52
|
+
value: string;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface DynamicDropdownPreference extends BasePreference {
|
|
57
|
+
type: 'dynamic-dropdown';
|
|
58
|
+
default?: string;
|
|
59
|
+
/** Options resolved server-side via plugin route GET /preferences/{name}. */
|
|
60
|
+
options?: Array<{
|
|
61
|
+
value: string;
|
|
62
|
+
label: string;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface LinkPreference extends BasePreference {
|
|
67
|
+
type: 'link';
|
|
68
|
+
/** URL to open. Relative paths (starting with /) resolve to plugin routes. */
|
|
69
|
+
url: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export type PreferenceDefinition =
|
|
73
|
+
| TextPreference
|
|
74
|
+
| PasswordPreference
|
|
75
|
+
| NumberPreference
|
|
76
|
+
| CheckboxPreference
|
|
77
|
+
| DropdownPreference
|
|
78
|
+
| DynamicDropdownPreference
|
|
79
|
+
| LinkPreference;
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Plugin Store Types — shared between hub and UI
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
/** Plugin data from the store (combines npm + verified status + compatibility) */
|
|
6
|
+
export interface StorePlugin {
|
|
7
|
+
name: string;
|
|
8
|
+
displayName?: string;
|
|
9
|
+
version: string;
|
|
10
|
+
/** Version string to pass to the installer (e.g. 'workspace:*' for local plugins) */
|
|
11
|
+
installVersion: string;
|
|
12
|
+
description: string;
|
|
13
|
+
author:
|
|
14
|
+
| string
|
|
15
|
+
| {
|
|
16
|
+
name: string;
|
|
17
|
+
email?: string;
|
|
18
|
+
};
|
|
19
|
+
keywords: string[];
|
|
20
|
+
repository?:
|
|
21
|
+
| string
|
|
22
|
+
| {
|
|
23
|
+
url: string;
|
|
24
|
+
};
|
|
25
|
+
homepage?: string;
|
|
26
|
+
license?: string;
|
|
27
|
+
engines?: {
|
|
28
|
+
brika?: string;
|
|
29
|
+
};
|
|
30
|
+
verified: boolean;
|
|
31
|
+
verifiedAt?: string;
|
|
32
|
+
featured: boolean;
|
|
33
|
+
compatible: boolean;
|
|
34
|
+
compatibilityReason?: string;
|
|
35
|
+
installed: boolean;
|
|
36
|
+
installedVersion?: string;
|
|
37
|
+
source: string;
|
|
38
|
+
npm: {
|
|
39
|
+
downloads: number;
|
|
40
|
+
publishedAt: string;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** npm package data from registry API */
|
|
45
|
+
export interface PluginPackageData {
|
|
46
|
+
name: string;
|
|
47
|
+
version: string;
|
|
48
|
+
displayName?: string;
|
|
49
|
+
description?: string;
|
|
50
|
+
author?:
|
|
51
|
+
| string
|
|
52
|
+
| {
|
|
53
|
+
name: string;
|
|
54
|
+
email?: string;
|
|
55
|
+
};
|
|
56
|
+
keywords?: string[];
|
|
57
|
+
repository?:
|
|
58
|
+
| string
|
|
59
|
+
| {
|
|
60
|
+
type?: string;
|
|
61
|
+
url: string;
|
|
62
|
+
directory?: string;
|
|
63
|
+
};
|
|
64
|
+
homepage?: string;
|
|
65
|
+
license?: string;
|
|
66
|
+
engines?: {
|
|
67
|
+
brika?: string;
|
|
68
|
+
};
|
|
69
|
+
date?: string;
|
|
70
|
+
links?: {
|
|
71
|
+
npm?: string;
|
|
72
|
+
homepage?: string;
|
|
73
|
+
repository?: string;
|
|
74
|
+
bugs?: string;
|
|
75
|
+
};
|
|
76
|
+
score?: {
|
|
77
|
+
final: number;
|
|
78
|
+
detail: {
|
|
79
|
+
quality: number;
|
|
80
|
+
popularity: number;
|
|
81
|
+
maintenance: number;
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** npm search result from registry API */
|
|
87
|
+
export interface PluginSearchResult {
|
|
88
|
+
package: PluginPackageData;
|
|
89
|
+
source: string;
|
|
90
|
+
installVersion: string;
|
|
91
|
+
downloadCount: number;
|
|
92
|
+
installed: boolean;
|
|
93
|
+
installedVersion?: string;
|
|
94
|
+
compatible: boolean;
|
|
95
|
+
compatibilityReason?: string;
|
|
96
|
+
}
|
package/tsconfig.json
ADDED