@fias/plugin-dev-harness 1.8.1 → 1.9.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/dist/bridge/live-handler.d.ts.map +1 -1
- package/dist/bridge/live-handler.js +10 -0
- package/dist/bridge/live-handler.js.map +1 -1
- package/dist/bridge/mock-handler.d.ts +1 -0
- package/dist/bridge/mock-handler.d.ts.map +1 -1
- package/dist/bridge/mock-handler.js +127 -0
- package/dist/bridge/mock-handler.js.map +1 -1
- package/dist/cli/preflight-client.d.ts +50 -0
- package/dist/cli/preflight-client.d.ts.map +1 -0
- package/dist/cli/preflight-client.js +80 -0
- package/dist/cli/preflight-client.js.map +1 -0
- package/dist/cli/submit.d.ts.map +1 -1
- package/dist/cli/submit.js +63 -6
- package/dist/cli/submit.js.map +1 -1
- package/dist/cli/submit.test.js +9 -0
- package/dist/cli/submit.test.js.map +1 -1
- package/dist/cli/version.d.ts +47 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +143 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/version.test.d.ts +2 -0
- package/dist/cli/version.test.d.ts.map +1 -0
- package/dist/cli/version.test.js +164 -0
- package/dist/cli/version.test.js.map +1 -0
- package/dist/server/harness-server.d.ts.map +1 -1
- package/dist/server/harness-server.js +122 -6
- package/dist/server/harness-server.js.map +1 -1
- package/dist/server/harness-server.test.js +17 -4
- package/dist/server/harness-server.test.js.map +1 -1
- package/dist/server/static/harness.css +28 -0
- package/dist/server/static/harness.html +1 -0
- package/dist/server/static/harness.js +147 -48
- package/package.json +11 -9
|
@@ -607,23 +607,23 @@
|
|
|
607
607
|
document.getElementById('pub-description').value = m.description || '';
|
|
608
608
|
document.getElementById('pub-expanded-desc').value = m.expandedDescription || '';
|
|
609
609
|
|
|
610
|
-
// Display options
|
|
610
|
+
// Display options. Full-screen is an independent display choice —
|
|
611
|
+
// it doesn't dictate pricing. A full-screen plugin can still be paid
|
|
612
|
+
// (e.g., a premium immersive experience), so the pricing controls
|
|
613
|
+
// stay visible regardless of this checkbox.
|
|
611
614
|
var isFullScreen = m.isFullScreen || m.archeType === 'site';
|
|
612
615
|
document.getElementById('pub-listed').checked = m.isListed !== false; // default true
|
|
613
616
|
document.getElementById('pub-public').checked = m.isPublic || false;
|
|
614
617
|
document.getElementById('pub-fullscreen').checked = isFullScreen;
|
|
615
618
|
|
|
616
|
-
// Pricing —
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
document.getElementById('pub-price').value = m.pricing?.priceCents || '';
|
|
625
|
-
document.getElementById('pub-price-row').style.display = pModel === 'free' ? 'none' : 'block';
|
|
626
|
-
}
|
|
619
|
+
// Pricing — always editable. Normalize legacy 'free'/'per_use' to
|
|
620
|
+
// the two supported manifest values.
|
|
621
|
+
var pModel = m.pricing?.model || 'free';
|
|
622
|
+
if (pModel === 'free' || pModel === 'included' || pModel === 'no_base_cost') pModel = 'free';
|
|
623
|
+
else pModel = 'fixed';
|
|
624
|
+
document.getElementById('pub-pricing-model').value = pModel;
|
|
625
|
+
document.getElementById('pub-price').value = m.pricing?.priceCents || '';
|
|
626
|
+
document.getElementById('pub-price-row').style.display = pModel === 'free' ? 'none' : 'block';
|
|
627
627
|
updatePublicAccessAvailability();
|
|
628
628
|
|
|
629
629
|
// Permissions (read-only, derived from fias-plugin.json)
|
|
@@ -634,21 +634,6 @@
|
|
|
634
634
|
: '<span style="color:#6b7280;font-size:12px">None declared in fias-plugin.json</span>';
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
function updatePricingVisibility(isFullScreen) {
|
|
638
|
-
var pricingLabel = document.getElementById('pub-pricing-model').previousElementSibling;
|
|
639
|
-
var pricingSelect = document.getElementById('pub-pricing-model');
|
|
640
|
-
var priceRow = document.getElementById('pub-price-row');
|
|
641
|
-
if (isFullScreen) {
|
|
642
|
-
pricingLabel.style.display = 'none';
|
|
643
|
-
pricingSelect.style.display = 'none';
|
|
644
|
-
priceRow.style.display = 'none';
|
|
645
|
-
} else {
|
|
646
|
-
pricingLabel.style.display = '';
|
|
647
|
-
pricingSelect.style.display = '';
|
|
648
|
-
priceRow.style.display = pricingSelect.value === 'free' ? 'none' : 'block';
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
|
|
652
637
|
/** Disable Public Access when the plugin is paid or uses AI entities */
|
|
653
638
|
function updatePublicAccessAvailability() {
|
|
654
639
|
var pubPublic = document.getElementById('pub-public');
|
|
@@ -669,9 +654,10 @@
|
|
|
669
654
|
}
|
|
670
655
|
}
|
|
671
656
|
|
|
672
|
-
// Full Screen Mode
|
|
657
|
+
// Full Screen Mode is purely a display choice — it doesn't affect
|
|
658
|
+
// pricing. Only re-check Public Access availability, which still
|
|
659
|
+
// depends on pricing + AI declarations (not on full-screen).
|
|
673
660
|
document.getElementById('pub-fullscreen').addEventListener('change', function () {
|
|
674
|
-
updatePricingVisibility(this.checked);
|
|
675
661
|
updatePublicAccessAvailability();
|
|
676
662
|
});
|
|
677
663
|
|
|
@@ -693,17 +679,15 @@
|
|
|
693
679
|
// Infer arche type: public → site (display-only), otherwise → tool
|
|
694
680
|
var archeType = isPublic ? 'site' : 'tool';
|
|
695
681
|
|
|
696
|
-
// Pricing: user picks "free" or "fixed" — these are the valid
|
|
682
|
+
// Pricing: user picks "free" or "fixed" — these are the valid
|
|
683
|
+
// manifest values. Full-screen does not override this; paid
|
|
684
|
+
// full-screen plugins are a valid shape.
|
|
697
685
|
var pricing;
|
|
698
|
-
|
|
699
|
-
|
|
686
|
+
var pricingChoice = document.getElementById('pub-pricing-model').value;
|
|
687
|
+
if (pricingChoice === 'fixed') {
|
|
688
|
+
pricing = { model: 'fixed', currency: 'usd', priceCents: parseInt(document.getElementById('pub-price').value, 10) || 0 };
|
|
700
689
|
} else {
|
|
701
|
-
|
|
702
|
-
if (pricingChoice === 'fixed') {
|
|
703
|
-
pricing = { model: 'fixed', currency: 'usd', priceCents: parseInt(document.getElementById('pub-price').value, 10) || 0 };
|
|
704
|
-
} else {
|
|
705
|
-
pricing = { model: 'free', currency: 'usd' };
|
|
706
|
-
}
|
|
690
|
+
pricing = { model: 'free', currency: 'usd' };
|
|
707
691
|
}
|
|
708
692
|
|
|
709
693
|
return {
|
|
@@ -810,26 +794,141 @@
|
|
|
810
794
|
document.getElementById('pub-build-output').textContent = '';
|
|
811
795
|
document.getElementById('pub-submit-progress').innerHTML = '';
|
|
812
796
|
|
|
813
|
-
//
|
|
797
|
+
// The server is the single source of truth for the publish fee. We ask
|
|
798
|
+
// the preflight endpoint (which knows whether this plugin's arche has
|
|
799
|
+
// ever been listed before) and render whatever it tells us. Never
|
|
800
|
+
// hardcode dollar amounts here — they will drift.
|
|
814
801
|
Promise.all([
|
|
815
|
-
fetch('/api/publish/
|
|
802
|
+
fetch('/api/publish/preflight-version', {
|
|
803
|
+
method: 'POST',
|
|
804
|
+
headers: { 'Content-Type': 'application/json' },
|
|
805
|
+
body: JSON.stringify({ bumpKind: 'patch' }),
|
|
806
|
+
}).then(function (r) { return r.ok ? r.json() : null; }),
|
|
816
807
|
fetch('/api/credits').then(function (r) { return r.json(); }),
|
|
817
808
|
]).then(function (results) {
|
|
818
|
-
var
|
|
809
|
+
var preflight = results[0];
|
|
819
810
|
var creditsData = results[1];
|
|
820
|
-
var existingCount = (subsData.submissions || []).length;
|
|
821
|
-
var isUpdate = existingCount > 0;
|
|
822
|
-
var cost = isUpdate ? '100 credits ($1.00)' : '5,000 credits ($50.00)';
|
|
823
|
-
var costType = isUpdate ? 'Update' : 'First listing';
|
|
824
811
|
|
|
825
|
-
|
|
812
|
+
var html;
|
|
813
|
+
if (preflight && preflight.feeCents != null) {
|
|
814
|
+
var feeCents = preflight.feeCents;
|
|
815
|
+
var costLabel =
|
|
816
|
+
(feeCents).toLocaleString() + ' credits ($' + (feeCents / 100).toFixed(2) + ')';
|
|
817
|
+
var costType = preflight.isFirstListing ? 'First listing' : 'Update';
|
|
818
|
+
html = '<p>' + costType + ' cost: <strong>' + costLabel + '</strong></p>';
|
|
819
|
+
if (preflight.refundableCents) {
|
|
820
|
+
html +=
|
|
821
|
+
'<p style="font-size:12px;color:#a1a1aa;margin-top:4px">' +
|
|
822
|
+
'$' + (preflight.refundableCents / 100).toFixed(2) +
|
|
823
|
+
' refunded automatically if the review rejects your submission.</p>';
|
|
824
|
+
}
|
|
825
|
+
} else {
|
|
826
|
+
// Older API or preflight unavailable — describe the model in words
|
|
827
|
+
// rather than guessing a number that might be wrong.
|
|
828
|
+
html = '<p>Submission cost will be confirmed by the server when you submit.</p>';
|
|
829
|
+
}
|
|
826
830
|
|
|
827
831
|
if (creditsData.balance != null && isFinite(creditsData.balance)) {
|
|
828
|
-
|
|
832
|
+
html +=
|
|
833
|
+
'<p style="margin-top:8px">Your balance: <strong>' +
|
|
834
|
+
creditsData.balance.toFixed(2) + ' credits</strong></p>';
|
|
829
835
|
}
|
|
836
|
+
costEl.innerHTML = html;
|
|
830
837
|
}).catch(function () {
|
|
831
|
-
costEl.innerHTML = '<p>Submission cost
|
|
838
|
+
costEl.innerHTML = '<p>Submission cost will be confirmed by the server when you submit.</p>';
|
|
832
839
|
});
|
|
840
|
+
|
|
841
|
+
showVersionInfo();
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
// Asks the server "what version will I publish as?" and shows a banner so
|
|
845
|
+
// the user is never surprised by an auto-bump. The actual write to disk
|
|
846
|
+
// happens server-side during /api/publish/package — this preview is read-
|
|
847
|
+
// only. The override link routes back to step 1 where they can edit
|
|
848
|
+
// pricing/about and the version field via the form.
|
|
849
|
+
function showVersionInfo() {
|
|
850
|
+
var versionEl = document.getElementById('pub-version-info');
|
|
851
|
+
versionEl.style.display = 'none';
|
|
852
|
+
versionEl.innerHTML = '';
|
|
853
|
+
|
|
854
|
+
fetch('/api/publish/preflight-version', {
|
|
855
|
+
method: 'POST',
|
|
856
|
+
headers: { 'Content-Type': 'application/json' },
|
|
857
|
+
body: JSON.stringify({ bumpKind: 'patch' }),
|
|
858
|
+
})
|
|
859
|
+
.then(function (r) { return r.ok ? r.json() : null; })
|
|
860
|
+
.then(function (data) {
|
|
861
|
+
if (!data || data.available === false) return;
|
|
862
|
+
versionEl.style.display = 'block';
|
|
863
|
+
var html;
|
|
864
|
+
if (data.wasAutoBumped) {
|
|
865
|
+
html =
|
|
866
|
+
'<p>Will publish as <strong>v' + escapeHtml(data.submittedVersion) + '</strong>' +
|
|
867
|
+
' (latest published: <strong>v' + escapeHtml(data.latestPublishedVersion || '—') + '</strong>).</p>' +
|
|
868
|
+
'<p style="font-size:12px;color:#a1a1aa;margin-top:4px">' +
|
|
869
|
+
'Auto-bumped from v' + escapeHtml(data.previousVersion) +
|
|
870
|
+
'. <a href="#" id="pub-version-override-link">Override</a></p>';
|
|
871
|
+
} else if (data.action === 'explicit' || data.previousVersion === data.submittedVersion) {
|
|
872
|
+
html =
|
|
873
|
+
'<p>Submitting as <strong>v' + escapeHtml(data.submittedVersion) + '</strong>' +
|
|
874
|
+
(data.latestPublishedVersion
|
|
875
|
+
? ' (latest published: <strong>v' + escapeHtml(data.latestPublishedVersion) + '</strong>)'
|
|
876
|
+
: '') + '.</p>' +
|
|
877
|
+
'<p style="font-size:12px;color:#a1a1aa;margin-top:4px">' +
|
|
878
|
+
'Manifest version respected. <a href="#" id="pub-version-override-link">Override</a></p>';
|
|
879
|
+
} else {
|
|
880
|
+
html =
|
|
881
|
+
'<p>Will publish as <strong>v' + escapeHtml(data.submittedVersion) + '</strong>.</p>' +
|
|
882
|
+
'<p style="font-size:12px;color:#a1a1aa;margin-top:4px">' +
|
|
883
|
+
'<a href="#" id="pub-version-override-link">Override</a></p>';
|
|
884
|
+
}
|
|
885
|
+
versionEl.innerHTML = html;
|
|
886
|
+
var override = document.getElementById('pub-version-override-link');
|
|
887
|
+
if (override) {
|
|
888
|
+
override.addEventListener('click', function (e) {
|
|
889
|
+
e.preventDefault();
|
|
890
|
+
promptVersionOverride(data);
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
})
|
|
894
|
+
.catch(function () { /* preflight is best-effort; silently skip */ });
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
function promptVersionOverride(data) {
|
|
898
|
+
var current = data.submittedVersion;
|
|
899
|
+
var input = window.prompt(
|
|
900
|
+
'Enter the version to publish as (e.g., 1.2.3 or 1.2.3-beta.1):',
|
|
901
|
+
current,
|
|
902
|
+
);
|
|
903
|
+
if (!input || input === current) return;
|
|
904
|
+
fetch('/api/publish/preflight-version', {
|
|
905
|
+
method: 'POST',
|
|
906
|
+
headers: { 'Content-Type': 'application/json' },
|
|
907
|
+
body: JSON.stringify({ explicitVersion: input.trim() }),
|
|
908
|
+
})
|
|
909
|
+
.then(function (r) { return r.json().then(function (b) { return { ok: r.ok, body: b }; }); })
|
|
910
|
+
.then(function (resp) {
|
|
911
|
+
if (!resp.ok) {
|
|
912
|
+
window.alert(resp.body.error || 'Invalid version.');
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
// Persist the override to fias-plugin.json so /api/publish/package
|
|
916
|
+
// sees it as the manifest version. The decideNextVersion logic on
|
|
917
|
+
// the server will then "respect" it (manifest > latest, or pre-
|
|
918
|
+
// release) and not re-bump.
|
|
919
|
+
fetch('/api/manifest', { method: 'GET' })
|
|
920
|
+
.then(function (r) { return r.json(); })
|
|
921
|
+
.then(function (manifest) {
|
|
922
|
+
manifest.version = input.trim();
|
|
923
|
+
return fetch('/api/manifest', {
|
|
924
|
+
method: 'PUT',
|
|
925
|
+
headers: { 'Content-Type': 'application/json' },
|
|
926
|
+
body: JSON.stringify(manifest),
|
|
927
|
+
});
|
|
928
|
+
})
|
|
929
|
+
.then(function () { showVersionInfo(); });
|
|
930
|
+
})
|
|
931
|
+
.catch(function () { window.alert('Could not validate version.'); });
|
|
833
932
|
}
|
|
834
933
|
|
|
835
934
|
function startBuildAndSubmit() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fias/plugin-dev-harness",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Development harness for building and testing FIAS plugin arches locally",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,12 +15,6 @@
|
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
18
|
-
"scripts": {
|
|
19
|
-
"build": "rm -rf dist && tsc && cp -r src/server/static dist/server/static && chmod +x dist/index.js",
|
|
20
|
-
"clean": "rm -rf dist",
|
|
21
|
-
"watch": "tsc -w",
|
|
22
|
-
"typecheck": "tsc --noEmit"
|
|
23
|
-
},
|
|
24
18
|
"keywords": [
|
|
25
19
|
"fias",
|
|
26
20
|
"plugin",
|
|
@@ -33,11 +27,19 @@
|
|
|
33
27
|
"@fias/arche-sdk": "^1.0.0",
|
|
34
28
|
"chalk": "^4.1.2",
|
|
35
29
|
"commander": "^12.0.0",
|
|
36
|
-
"express": "^4.21.0"
|
|
30
|
+
"express": "^4.21.0",
|
|
31
|
+
"semver": "^7.7.3"
|
|
37
32
|
},
|
|
38
33
|
"devDependencies": {
|
|
39
34
|
"@types/express": "^5.0.0",
|
|
40
35
|
"@types/node": "^25.5.0",
|
|
36
|
+
"@types/semver": "^7.7.0",
|
|
41
37
|
"typescript": "^5.3.3"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "rm -rf dist && tsc && cp -r src/server/static dist/server/static && chmod +x dist/index.js",
|
|
41
|
+
"clean": "rm -rf dist",
|
|
42
|
+
"watch": "tsc -w",
|
|
43
|
+
"typecheck": "tsc --noEmit"
|
|
42
44
|
}
|
|
43
|
-
}
|
|
45
|
+
}
|