@fias/create-fias-plugin 1.0.5 → 1.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/index.js +55 -14
- package/package.json +1 -6
- package/templates/default/AGENTS.md +22 -6
- package/templates/default/CLAUDE.md +22 -6
package/index.js
CHANGED
|
@@ -7,7 +7,7 @@ var path = require('path');
|
|
|
7
7
|
|
|
8
8
|
var TEMPLATE_DIR = path.resolve(__dirname, 'templates/default');
|
|
9
9
|
|
|
10
|
-
function copyDir(src, dest, replacements) {
|
|
10
|
+
function copyDir(src, dest, replacements, opts) {
|
|
11
11
|
fs.mkdirSync(dest, { recursive: true });
|
|
12
12
|
|
|
13
13
|
var entries = fs.readdirSync(src, { withFileTypes: true });
|
|
@@ -17,8 +17,17 @@ function copyDir(src, dest, replacements) {
|
|
|
17
17
|
var destPath = path.join(dest, entry.name);
|
|
18
18
|
|
|
19
19
|
if (entry.isDirectory()) {
|
|
20
|
-
copyDir(srcPath, destPath, replacements);
|
|
20
|
+
copyDir(srcPath, destPath, replacements, opts);
|
|
21
21
|
} else {
|
|
22
|
+
if (opts.inPlace && fs.existsSync(destPath)) {
|
|
23
|
+
console.error(
|
|
24
|
+
'Error: refusing to overwrite existing file: ' + path.relative(opts.rootDest, destPath),
|
|
25
|
+
);
|
|
26
|
+
console.error(
|
|
27
|
+
'In --in-place mode, the target directory must not already contain plugin files.',
|
|
28
|
+
);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
22
31
|
var content = fs.readFileSync(srcPath, 'utf-8');
|
|
23
32
|
var keys = Object.keys(replacements);
|
|
24
33
|
for (var k = 0; k < keys.length; k++) {
|
|
@@ -29,27 +38,59 @@ function copyDir(src, dest, replacements) {
|
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!projectName) {
|
|
41
|
+
function printUsage() {
|
|
35
42
|
console.error('Usage: npm create @fias/fias-plugin <project-name>');
|
|
36
|
-
|
|
43
|
+
console.error(' or: npm create @fias/fias-plugin -- --in-place (scaffold into current directory)');
|
|
44
|
+
console.error(' or: npm create @fias/fias-plugin . (alias for --in-place)');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
var args = process.argv.slice(2);
|
|
48
|
+
var inPlace = false;
|
|
49
|
+
var positional = [];
|
|
50
|
+
for (var a = 0; a < args.length; a++) {
|
|
51
|
+
if (args[a] === '--in-place' || args[a] === '.') {
|
|
52
|
+
inPlace = true;
|
|
53
|
+
} else if (args[a].indexOf('--') === 0) {
|
|
54
|
+
console.error('Unknown option: ' + args[a]);
|
|
55
|
+
printUsage();
|
|
56
|
+
process.exit(1);
|
|
57
|
+
} else {
|
|
58
|
+
positional.push(args[a]);
|
|
59
|
+
}
|
|
37
60
|
}
|
|
38
61
|
|
|
39
|
-
var
|
|
62
|
+
var projectName;
|
|
63
|
+
var targetDir;
|
|
40
64
|
|
|
41
|
-
if (
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
if (inPlace) {
|
|
66
|
+
targetDir = process.cwd();
|
|
67
|
+
projectName = positional[0] || path.basename(targetDir);
|
|
68
|
+
} else {
|
|
69
|
+
projectName = positional[0];
|
|
70
|
+
if (!projectName) {
|
|
71
|
+
printUsage();
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
targetDir = path.resolve(process.cwd(), projectName);
|
|
75
|
+
if (fs.existsSync(targetDir)) {
|
|
76
|
+
console.error('Error: Directory "' + projectName + '" already exists.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
44
79
|
}
|
|
45
80
|
|
|
46
|
-
console.log(
|
|
81
|
+
console.log(
|
|
82
|
+
inPlace
|
|
83
|
+
? 'Scaffolding FIAS plugin into current directory (' + projectName + ')'
|
|
84
|
+
: 'Creating FIAS plugin project: ' + projectName,
|
|
85
|
+
);
|
|
47
86
|
|
|
48
|
-
copyDir(TEMPLATE_DIR, targetDir, { name: projectName });
|
|
87
|
+
copyDir(TEMPLATE_DIR, targetDir, { name: projectName }, { inPlace: inPlace, rootDest: targetDir });
|
|
49
88
|
|
|
50
|
-
console.log('\nPlugin
|
|
89
|
+
console.log('\nPlugin scaffolded.\n');
|
|
51
90
|
console.log('Next steps:');
|
|
52
|
-
|
|
91
|
+
if (!inPlace) {
|
|
92
|
+
console.log(' cd ' + projectName);
|
|
93
|
+
}
|
|
53
94
|
console.log(' npm install');
|
|
54
95
|
console.log(' npx fias-dev login # Authenticate with FIAS platform (opens browser)');
|
|
55
96
|
console.log(' npm start # Start dev server + real AI harness (uses credits)');
|
package/package.json
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fias/create-fias-plugin",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
7
|
"description": "Scaffold a new FIAS plugin arche project",
|
|
8
|
-
"scripts": {
|
|
9
|
-
"build": "pnpm build:ai-docs",
|
|
10
|
-
"build:ai-docs": "node scripts/build-ai-docs.mjs",
|
|
11
|
-
"check:ai-docs": "node scripts/build-ai-docs.mjs --check"
|
|
12
|
-
},
|
|
13
8
|
"bin": {
|
|
14
9
|
"create-fias-plugin": "index.js"
|
|
15
10
|
},
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
This project is a FIAS platform plugin — a React application that runs in a sandboxed iframe within the FIAS marketplace. This file provides the context AI coding assistants need to build, test, and submit plugins effectively.
|
|
4
4
|
|
|
5
|
+
For other AI tool instruction files, see `CLAUDE.md` (identical content).
|
|
6
|
+
|
|
5
7
|
## Project Structure
|
|
6
8
|
|
|
7
9
|
```
|
|
@@ -266,6 +268,8 @@ const [count, setCount] = usePersistentState<number>('counter', 0);
|
|
|
266
268
|
// Automatically persists to storage on change
|
|
267
269
|
```
|
|
268
270
|
|
|
271
|
+
**Writes are debounced (SDK ≥ 1.8.0).** The in-memory value updates synchronously, but the underlying `storage_write` is coalesced (250 ms trailing-edge debounce, 1 s max-wait, flushed on unmount). Safe to call from `requestAnimationFrame` and other high-frequency handlers. For state that updates every frame (game positions, drag coordinates), still prefer plain `useState` — persisting transient state is wasteful and not useful on reload.
|
|
272
|
+
|
|
269
273
|
### `fias` — Imperative utilities
|
|
270
274
|
|
|
271
275
|
```tsx
|
|
@@ -315,9 +319,15 @@ fias.showToast('Saved!', 'success'); // Toast: 'info' | 'success' | 'warning' |
|
|
|
315
319
|
|
|
316
320
|
These are hard limits enforced by the platform. Code that violates these will fail review or be blocked at runtime.
|
|
317
321
|
|
|
322
|
+
### Hitting a limit? Tell the user about Entity requests
|
|
323
|
+
|
|
324
|
+
Don't just say "can't do that" when the user asks for something blocked by these rules — most often a direct external API call, a third-party service, or a capability the platform hasn't surfaced yet. The Fias team adds new **Entities** on request: platform-managed wrappers that hold credentials, handle auth, and expose the capability to plugins through `useEntityInvocation()` (or `useImageGeneration()` for image models). The plugin never bypasses the sandbox — it invokes the new Entity like any other model.
|
|
325
|
+
|
|
326
|
+
When you hit a constraint, say so AND tell the user: file an Entity request on the Customer Support arche at `https://platform.fias.io/a/arche_customer_support`. Describe the service, endpoints, and auth method needed; once the Entity ships, the plugin can call it via `useEntityInvocation` with no sandbox change. Then propose a fallback that works inside the current sandbox (mock data, a simpler path, deferring the call) so the build keeps moving while the request is in flight.
|
|
327
|
+
|
|
318
328
|
### Sandboxing
|
|
319
329
|
|
|
320
|
-
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin"`
|
|
330
|
+
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin allow-downloads"`
|
|
321
331
|
- **No `fetch()` or `XMLHttpRequest`** — all network access is blocked
|
|
322
332
|
- **No access** to parent DOM, cookies, or localStorage
|
|
323
333
|
- **No external scripts or stylesheets** — everything must be bundled
|
|
@@ -336,6 +346,8 @@ These are hard limits enforced by the platform. Code that violates these will fa
|
|
|
336
346
|
- `storage_read`: 300/minute
|
|
337
347
|
- `storage_list`, `storage_delete`: 60/minute
|
|
338
348
|
|
|
349
|
+
A separate **runaway-loop detector** fires if any method is called >50 times in 5 s and blocks that method for 10 s. Errors include the target, e.g. `Runaway loop detected: "storage_write" (path: __state/gameState) …` — the path tells you where to debounce at the source.
|
|
350
|
+
|
|
339
351
|
### Security Rules (enforced during review)
|
|
340
352
|
|
|
341
353
|
- No `eval()`, `Function()`, `innerHTML`, or dynamic code execution
|
|
@@ -413,9 +425,17 @@ npx fias-dev validate
|
|
|
413
425
|
```bash
|
|
414
426
|
npm run submit
|
|
415
427
|
# Builds, validates, packages, uploads, submits for AI review
|
|
416
|
-
# First listing: 5000 credits ($50). Re-submissions: 100 credits ($1).
|
|
417
428
|
```
|
|
418
429
|
|
|
430
|
+
The first time you list a plugin in the marketplace there is a one-time
|
|
431
|
+
listing fee; subsequent submissions of the same plugin only pay a small
|
|
432
|
+
per-review fee. The harness fetches the exact amount from the server and
|
|
433
|
+
shows it before you confirm — never assume a hardcoded price.
|
|
434
|
+
|
|
435
|
+
If the AI review rejects your submission, the listing-fee portion is
|
|
436
|
+
refunded automatically (the per-review portion is not, since review work
|
|
437
|
+
happened either way).
|
|
438
|
+
|
|
419
439
|
## Common Patterns
|
|
420
440
|
|
|
421
441
|
### Theme-Aware Card Component
|
|
@@ -491,7 +511,3 @@ function Settings() {
|
|
|
491
511
|
);
|
|
492
512
|
}
|
|
493
513
|
```
|
|
494
|
-
|
|
495
|
-
## See also
|
|
496
|
-
|
|
497
|
-
`CLAUDE.md` — equivalent guide with Claude-specific additions.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
This project is a FIAS platform plugin — a React application that runs in a sandboxed iframe within the FIAS marketplace. This file provides the context AI coding assistants need to build, test, and submit plugins effectively.
|
|
4
4
|
|
|
5
|
+
For other AI tool instruction files, see `AGENTS.md` (identical content).
|
|
6
|
+
|
|
5
7
|
## Project Structure
|
|
6
8
|
|
|
7
9
|
```
|
|
@@ -266,6 +268,8 @@ const [count, setCount] = usePersistentState<number>('counter', 0);
|
|
|
266
268
|
// Automatically persists to storage on change
|
|
267
269
|
```
|
|
268
270
|
|
|
271
|
+
**Writes are debounced (SDK ≥ 1.8.0).** The in-memory value updates synchronously, but the underlying `storage_write` is coalesced (250 ms trailing-edge debounce, 1 s max-wait, flushed on unmount). Safe to call from `requestAnimationFrame` and other high-frequency handlers. For state that updates every frame (game positions, drag coordinates), still prefer plain `useState` — persisting transient state is wasteful and not useful on reload.
|
|
272
|
+
|
|
269
273
|
### `fias` — Imperative utilities
|
|
270
274
|
|
|
271
275
|
```tsx
|
|
@@ -315,9 +319,15 @@ fias.showToast('Saved!', 'success'); // Toast: 'info' | 'success' | 'warning' |
|
|
|
315
319
|
|
|
316
320
|
These are hard limits enforced by the platform. Code that violates these will fail review or be blocked at runtime.
|
|
317
321
|
|
|
322
|
+
### Hitting a limit? Tell the user about Entity requests
|
|
323
|
+
|
|
324
|
+
Don't just say "can't do that" when the user asks for something blocked by these rules — most often a direct external API call, a third-party service, or a capability the platform hasn't surfaced yet. The Fias team adds new **Entities** on request: platform-managed wrappers that hold credentials, handle auth, and expose the capability to plugins through `useEntityInvocation()` (or `useImageGeneration()` for image models). The plugin never bypasses the sandbox — it invokes the new Entity like any other model.
|
|
325
|
+
|
|
326
|
+
When you hit a constraint, say so AND tell the user: file an Entity request on the Customer Support arche at `https://platform.fias.io/a/arche_customer_support`. Describe the service, endpoints, and auth method needed; once the Entity ships, the plugin can call it via `useEntityInvocation` with no sandbox change. Then propose a fallback that works inside the current sandbox (mock data, a simpler path, deferring the call) so the build keeps moving while the request is in flight.
|
|
327
|
+
|
|
318
328
|
### Sandboxing
|
|
319
329
|
|
|
320
|
-
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin"`
|
|
330
|
+
- Plugins run in an iframe with `sandbox="allow-scripts allow-forms allow-same-origin allow-downloads"`
|
|
321
331
|
- **No `fetch()` or `XMLHttpRequest`** — all network access is blocked
|
|
322
332
|
- **No access** to parent DOM, cookies, or localStorage
|
|
323
333
|
- **No external scripts or stylesheets** — everything must be bundled
|
|
@@ -336,6 +346,8 @@ These are hard limits enforced by the platform. Code that violates these will fa
|
|
|
336
346
|
- `storage_read`: 300/minute
|
|
337
347
|
- `storage_list`, `storage_delete`: 60/minute
|
|
338
348
|
|
|
349
|
+
A separate **runaway-loop detector** fires if any method is called >50 times in 5 s and blocks that method for 10 s. Errors include the target, e.g. `Runaway loop detected: "storage_write" (path: __state/gameState) …` — the path tells you where to debounce at the source.
|
|
350
|
+
|
|
339
351
|
### Security Rules (enforced during review)
|
|
340
352
|
|
|
341
353
|
- No `eval()`, `Function()`, `innerHTML`, or dynamic code execution
|
|
@@ -413,9 +425,17 @@ npx fias-dev validate
|
|
|
413
425
|
```bash
|
|
414
426
|
npm run submit
|
|
415
427
|
# Builds, validates, packages, uploads, submits for AI review
|
|
416
|
-
# First listing: 5000 credits ($50). Re-submissions: 100 credits ($1).
|
|
417
428
|
```
|
|
418
429
|
|
|
430
|
+
The first time you list a plugin in the marketplace there is a one-time
|
|
431
|
+
listing fee; subsequent submissions of the same plugin only pay a small
|
|
432
|
+
per-review fee. The harness fetches the exact amount from the server and
|
|
433
|
+
shows it before you confirm — never assume a hardcoded price.
|
|
434
|
+
|
|
435
|
+
If the AI review rejects your submission, the listing-fee portion is
|
|
436
|
+
refunded automatically (the per-review portion is not, since review work
|
|
437
|
+
happened either way).
|
|
438
|
+
|
|
419
439
|
## Common Patterns
|
|
420
440
|
|
|
421
441
|
### Theme-Aware Card Component
|
|
@@ -491,7 +511,3 @@ function Settings() {
|
|
|
491
511
|
);
|
|
492
512
|
}
|
|
493
513
|
```
|
|
494
|
-
|
|
495
|
-
## See also
|
|
496
|
-
|
|
497
|
-
`AGENTS.md` — equivalent guide for non-Claude AI tools in this project.
|