fimo 0.3.1 → 0.3.2
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/cli/bundle.json +2 -2
- package/dist/cli/index.js +223 -94
- package/dist/scripts/validate-schemas.d.ts +13 -0
- package/dist/scripts/validate-schemas.js +113 -0
- package/dist/scripts/validate-schemas.test.d.ts +1 -0
- package/dist/scripts/validate-schemas.test.js +132 -0
- package/package.json +1 -1
- package/templates/react-router/package.json +1 -1
package/dist/cli/bundle.json
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -17313,20 +17313,20 @@ var require_parse_async = __commonJS({
|
|
|
17313
17313
|
const index2 = 0;
|
|
17314
17314
|
const blocksize = opts.blocksize || 40960;
|
|
17315
17315
|
const parser = new TOMLParser();
|
|
17316
|
-
return new Promise((
|
|
17317
|
-
setImmediate(parseAsyncNext, index2, blocksize,
|
|
17316
|
+
return new Promise((resolve8, reject) => {
|
|
17317
|
+
setImmediate(parseAsyncNext, index2, blocksize, resolve8, reject);
|
|
17318
17318
|
});
|
|
17319
|
-
function parseAsyncNext(index3, blocksize2,
|
|
17319
|
+
function parseAsyncNext(index3, blocksize2, resolve8, reject) {
|
|
17320
17320
|
if (index3 >= str.length) {
|
|
17321
17321
|
try {
|
|
17322
|
-
return
|
|
17322
|
+
return resolve8(parser.finish());
|
|
17323
17323
|
} catch (err) {
|
|
17324
17324
|
return reject(prettyError(err, str));
|
|
17325
17325
|
}
|
|
17326
17326
|
}
|
|
17327
17327
|
try {
|
|
17328
17328
|
parser.parse(str.slice(index3, index3 + blocksize2));
|
|
17329
|
-
setImmediate(parseAsyncNext, index3 + blocksize2, blocksize2,
|
|
17329
|
+
setImmediate(parseAsyncNext, index3 + blocksize2, blocksize2, resolve8, reject);
|
|
17330
17330
|
} catch (err) {
|
|
17331
17331
|
reject(prettyError(err, str));
|
|
17332
17332
|
}
|
|
@@ -17355,7 +17355,7 @@ var require_parse_stream = __commonJS({
|
|
|
17355
17355
|
function parseReadable(stm) {
|
|
17356
17356
|
const parser = new TOMLParser();
|
|
17357
17357
|
stm.setEncoding("utf8");
|
|
17358
|
-
return new Promise((
|
|
17358
|
+
return new Promise((resolve8, reject) => {
|
|
17359
17359
|
let readable;
|
|
17360
17360
|
let ended = false;
|
|
17361
17361
|
let errored = false;
|
|
@@ -17363,7 +17363,7 @@ var require_parse_stream = __commonJS({
|
|
|
17363
17363
|
ended = true;
|
|
17364
17364
|
if (readable) return;
|
|
17365
17365
|
try {
|
|
17366
|
-
|
|
17366
|
+
resolve8(parser.finish());
|
|
17367
17367
|
} catch (err) {
|
|
17368
17368
|
reject(err);
|
|
17369
17369
|
}
|
|
@@ -41851,7 +41851,7 @@ var init_pagination = __esm({
|
|
|
41851
41851
|
});
|
|
41852
41852
|
|
|
41853
41853
|
// ../../packages/api-contracts/dist/esm/types/common.js
|
|
41854
|
-
var CommonSchemas, BaseEntitySchema, ProjectRoleKeySchema, ProjectRoleKeyWithSystemSchema, ProjectPrincipalTypeSchema, ProjectVisibilitySchema, ProjectStatusSchema, ProjectInviteStatusSchema, PublicationStatusSchema, OrganizationRoleSchema, AssetTypeSchema, TemplateCodeSchema, FieldTypeSchema;
|
|
41854
|
+
var CommonSchemas, BaseEntitySchema, ProjectRoleKeySchema, ProjectRoleKeyWithSystemSchema, ProjectPrincipalTypeSchema, ProjectVisibilitySchema, ProjectStatusSchema, ProjectInviteStatusSchema, PublicationStatusSchema, OrganizationRoleSchema, AssetTypeSchema, TemplateCodeSchema, FieldTypeSchema, RESERVED_CONTENT_FIELD_NAMES;
|
|
41855
41855
|
var init_common = __esm({
|
|
41856
41856
|
"../../packages/api-contracts/dist/esm/types/common.js"() {
|
|
41857
41857
|
"use strict";
|
|
@@ -41932,6 +41932,15 @@ var init_common = __esm({
|
|
|
41932
41932
|
"date",
|
|
41933
41933
|
"json"
|
|
41934
41934
|
]);
|
|
41935
|
+
RESERVED_CONTENT_FIELD_NAMES = [
|
|
41936
|
+
"id",
|
|
41937
|
+
"documentId",
|
|
41938
|
+
"slug",
|
|
41939
|
+
"locale",
|
|
41940
|
+
"createdAt",
|
|
41941
|
+
"updatedAt",
|
|
41942
|
+
"__fimo"
|
|
41943
|
+
];
|
|
41935
41944
|
}
|
|
41936
41945
|
});
|
|
41937
41946
|
|
|
@@ -69995,9 +70004,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
69995
70004
|
}
|
|
69996
70005
|
close(callback) {
|
|
69997
70006
|
if (callback === void 0) {
|
|
69998
|
-
return new Promise((
|
|
70007
|
+
return new Promise((resolve8, reject) => {
|
|
69999
70008
|
this.close((err, data2) => {
|
|
70000
|
-
return err ? reject(err) :
|
|
70009
|
+
return err ? reject(err) : resolve8(data2);
|
|
70001
70010
|
});
|
|
70002
70011
|
});
|
|
70003
70012
|
}
|
|
@@ -70035,9 +70044,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
70035
70044
|
err = null;
|
|
70036
70045
|
}
|
|
70037
70046
|
if (callback === void 0) {
|
|
70038
|
-
return new Promise((
|
|
70047
|
+
return new Promise((resolve8, reject) => {
|
|
70039
70048
|
this.destroy(err, (err2, data2) => {
|
|
70040
|
-
return err2 ? reject(err2) :
|
|
70049
|
+
return err2 ? reject(err2) : resolve8(data2);
|
|
70041
70050
|
});
|
|
70042
70051
|
});
|
|
70043
70052
|
}
|
|
@@ -73627,8 +73636,8 @@ var require_promise = __commonJS({
|
|
|
73627
73636
|
function createDeferredPromise() {
|
|
73628
73637
|
let res;
|
|
73629
73638
|
let rej;
|
|
73630
|
-
const promise2 = new Promise((
|
|
73631
|
-
res =
|
|
73639
|
+
const promise2 = new Promise((resolve8, reject) => {
|
|
73640
|
+
res = resolve8;
|
|
73632
73641
|
rej = reject;
|
|
73633
73642
|
});
|
|
73634
73643
|
return { promise: promise2, resolve: res, reject: rej };
|
|
@@ -74957,12 +74966,12 @@ upgrade: ${upgrade}\r
|
|
|
74957
74966
|
}
|
|
74958
74967
|
}
|
|
74959
74968
|
__name(onDrain, "onDrain");
|
|
74960
|
-
const waitForDrain = /* @__PURE__ */ __name(() => new Promise((
|
|
74969
|
+
const waitForDrain = /* @__PURE__ */ __name(() => new Promise((resolve8, reject) => {
|
|
74961
74970
|
assert2(callback === null);
|
|
74962
74971
|
if (socket[kError]) {
|
|
74963
74972
|
reject(socket[kError]);
|
|
74964
74973
|
} else {
|
|
74965
|
-
callback =
|
|
74974
|
+
callback = resolve8;
|
|
74966
74975
|
}
|
|
74967
74976
|
}), "waitForDrain");
|
|
74968
74977
|
socket.on("close", onDrain).on("drain", onDrain);
|
|
@@ -75835,12 +75844,12 @@ var require_client_h2 = __commonJS({
|
|
|
75835
75844
|
}
|
|
75836
75845
|
}
|
|
75837
75846
|
__name(onDrain, "onDrain");
|
|
75838
|
-
const waitForDrain = /* @__PURE__ */ __name(() => new Promise((
|
|
75847
|
+
const waitForDrain = /* @__PURE__ */ __name(() => new Promise((resolve8, reject) => {
|
|
75839
75848
|
assert2(callback === null);
|
|
75840
75849
|
if (socket[kError]) {
|
|
75841
75850
|
reject(socket[kError]);
|
|
75842
75851
|
} else {
|
|
75843
|
-
callback =
|
|
75852
|
+
callback = resolve8;
|
|
75844
75853
|
}
|
|
75845
75854
|
}), "waitForDrain");
|
|
75846
75855
|
h2stream.on("close", onDrain).on("drain", onDrain);
|
|
@@ -76156,16 +76165,16 @@ var require_client = __commonJS({
|
|
|
76156
76165
|
return this[kNeedDrain] < 2;
|
|
76157
76166
|
}
|
|
76158
76167
|
[kClose]() {
|
|
76159
|
-
return new Promise((
|
|
76168
|
+
return new Promise((resolve8) => {
|
|
76160
76169
|
if (this[kSize]) {
|
|
76161
|
-
this[kClosedResolve] =
|
|
76170
|
+
this[kClosedResolve] = resolve8;
|
|
76162
76171
|
} else {
|
|
76163
|
-
|
|
76172
|
+
resolve8(null);
|
|
76164
76173
|
}
|
|
76165
76174
|
});
|
|
76166
76175
|
}
|
|
76167
76176
|
[kDestroy](err) {
|
|
76168
|
-
return new Promise((
|
|
76177
|
+
return new Promise((resolve8) => {
|
|
76169
76178
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
76170
76179
|
for (let i = 0; i < requests.length; i++) {
|
|
76171
76180
|
const request = requests[i];
|
|
@@ -76176,7 +76185,7 @@ var require_client = __commonJS({
|
|
|
76176
76185
|
this[kClosedResolve]();
|
|
76177
76186
|
this[kClosedResolve] = null;
|
|
76178
76187
|
}
|
|
76179
|
-
|
|
76188
|
+
resolve8(null);
|
|
76180
76189
|
}, "callback");
|
|
76181
76190
|
if (this[kHTTPContext]) {
|
|
76182
76191
|
this[kHTTPContext].destroy(err, callback);
|
|
@@ -76596,8 +76605,8 @@ var require_pool_base = __commonJS({
|
|
|
76596
76605
|
}
|
|
76597
76606
|
return Promise.all(closeAll);
|
|
76598
76607
|
} else {
|
|
76599
|
-
return new Promise((
|
|
76600
|
-
this[kClosedResolve] =
|
|
76608
|
+
return new Promise((resolve8) => {
|
|
76609
|
+
this[kClosedResolve] = resolve8;
|
|
76601
76610
|
});
|
|
76602
76611
|
}
|
|
76603
76612
|
}
|
|
@@ -77717,10 +77726,10 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
77717
77726
|
const proxyHost = this[kProxyUrl].hostname;
|
|
77718
77727
|
const proxyPort = parseInt(this[kProxyUrl].port) || 1080;
|
|
77719
77728
|
debug("creating SOCKS5 connection to", proxyHost, proxyPort);
|
|
77720
|
-
const socket = await new Promise((
|
|
77729
|
+
const socket = await new Promise((resolve8, reject) => {
|
|
77721
77730
|
const onConnect = /* @__PURE__ */ __name(() => {
|
|
77722
77731
|
socket2.removeListener("error", onError);
|
|
77723
|
-
|
|
77732
|
+
resolve8(socket2);
|
|
77724
77733
|
}, "onConnect");
|
|
77725
77734
|
const onError = /* @__PURE__ */ __name((err) => {
|
|
77726
77735
|
socket2.removeListener("connect", onConnect);
|
|
@@ -77739,14 +77748,14 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
77739
77748
|
socket.destroy();
|
|
77740
77749
|
});
|
|
77741
77750
|
await socks5Client.handshake();
|
|
77742
|
-
await new Promise((
|
|
77751
|
+
await new Promise((resolve8, reject) => {
|
|
77743
77752
|
const timeout = setTimeout(() => {
|
|
77744
77753
|
reject(new Error("SOCKS5 authentication timeout"));
|
|
77745
77754
|
}, 5e3);
|
|
77746
77755
|
const onAuthenticated = /* @__PURE__ */ __name(() => {
|
|
77747
77756
|
clearTimeout(timeout);
|
|
77748
77757
|
socks5Client.removeListener("error", onError);
|
|
77749
|
-
|
|
77758
|
+
resolve8();
|
|
77750
77759
|
}, "onAuthenticated");
|
|
77751
77760
|
const onError = /* @__PURE__ */ __name((err) => {
|
|
77752
77761
|
clearTimeout(timeout);
|
|
@@ -77755,14 +77764,14 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
77755
77764
|
}, "onError");
|
|
77756
77765
|
if (socks5Client.state === "authenticated") {
|
|
77757
77766
|
clearTimeout(timeout);
|
|
77758
|
-
|
|
77767
|
+
resolve8();
|
|
77759
77768
|
} else {
|
|
77760
77769
|
socks5Client.once("authenticated", onAuthenticated);
|
|
77761
77770
|
socks5Client.once("error", onError);
|
|
77762
77771
|
}
|
|
77763
77772
|
});
|
|
77764
77773
|
await socks5Client.connect(targetHost, targetPort);
|
|
77765
|
-
await new Promise((
|
|
77774
|
+
await new Promise((resolve8, reject) => {
|
|
77766
77775
|
const timeout = setTimeout(() => {
|
|
77767
77776
|
reject(new Error("SOCKS5 connection timeout"));
|
|
77768
77777
|
}, 5e3);
|
|
@@ -77770,7 +77779,7 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
77770
77779
|
debug("SOCKS5 tunnel established to", targetHost, targetPort, "via", info);
|
|
77771
77780
|
clearTimeout(timeout);
|
|
77772
77781
|
socks5Client.removeListener("error", onError);
|
|
77773
|
-
|
|
77782
|
+
resolve8();
|
|
77774
77783
|
}, "onConnected");
|
|
77775
77784
|
const onError = /* @__PURE__ */ __name((err) => {
|
|
77776
77785
|
clearTimeout(timeout);
|
|
@@ -77811,8 +77820,8 @@ var require_socks5_proxy_agent = __commonJS({
|
|
|
77811
77820
|
servername: targetHost,
|
|
77812
77821
|
...connectOpts.tls || {}
|
|
77813
77822
|
});
|
|
77814
|
-
await new Promise((
|
|
77815
|
-
finalSocket.once("secureConnect",
|
|
77823
|
+
await new Promise((resolve8, reject) => {
|
|
77824
|
+
finalSocket.once("secureConnect", resolve8);
|
|
77816
77825
|
finalSocket.once("error", reject);
|
|
77817
77826
|
});
|
|
77818
77827
|
}
|
|
@@ -78866,7 +78875,7 @@ var require_readable = __commonJS({
|
|
|
78866
78875
|
if (this._readableState.closeEmitted) {
|
|
78867
78876
|
return Promise.resolve(null);
|
|
78868
78877
|
}
|
|
78869
|
-
return new Promise((
|
|
78878
|
+
return new Promise((resolve8, reject) => {
|
|
78870
78879
|
if (this[kContentLength] && this[kContentLength] > limit || this[kBytesRead] > limit) {
|
|
78871
78880
|
this.destroy(new AbortError());
|
|
78872
78881
|
}
|
|
@@ -78880,11 +78889,11 @@ var require_readable = __commonJS({
|
|
|
78880
78889
|
if (signal.aborted) {
|
|
78881
78890
|
reject(signal.reason ?? new AbortError());
|
|
78882
78891
|
} else {
|
|
78883
|
-
|
|
78892
|
+
resolve8(null);
|
|
78884
78893
|
}
|
|
78885
78894
|
});
|
|
78886
78895
|
} else {
|
|
78887
|
-
this.on("close",
|
|
78896
|
+
this.on("close", resolve8);
|
|
78888
78897
|
}
|
|
78889
78898
|
this.on("error", noop).on("data", () => {
|
|
78890
78899
|
if (this[kBytesRead] > limit) {
|
|
@@ -78914,7 +78923,7 @@ var require_readable = __commonJS({
|
|
|
78914
78923
|
__name(isUnusable, "isUnusable");
|
|
78915
78924
|
function consume(stream, type) {
|
|
78916
78925
|
assert2(!stream[kConsume]);
|
|
78917
|
-
return new Promise((
|
|
78926
|
+
return new Promise((resolve8, reject) => {
|
|
78918
78927
|
if (isUnusable(stream)) {
|
|
78919
78928
|
const rState = stream._readableState;
|
|
78920
78929
|
if (rState.destroyed && rState.closeEmitted === false) {
|
|
@@ -78929,7 +78938,7 @@ var require_readable = __commonJS({
|
|
|
78929
78938
|
stream[kConsume] = {
|
|
78930
78939
|
type,
|
|
78931
78940
|
stream,
|
|
78932
|
-
resolve:
|
|
78941
|
+
resolve: resolve8,
|
|
78933
78942
|
reject,
|
|
78934
78943
|
length: 0,
|
|
78935
78944
|
body: []
|
|
@@ -79007,18 +79016,18 @@ var require_readable = __commonJS({
|
|
|
79007
79016
|
}
|
|
79008
79017
|
__name(chunksConcat, "chunksConcat");
|
|
79009
79018
|
function consumeEnd(consume2, encoding) {
|
|
79010
|
-
const { type, body, resolve:
|
|
79019
|
+
const { type, body, resolve: resolve8, stream, length } = consume2;
|
|
79011
79020
|
try {
|
|
79012
79021
|
if (type === "text") {
|
|
79013
|
-
|
|
79022
|
+
resolve8(chunksDecode(body, length, encoding));
|
|
79014
79023
|
} else if (type === "json") {
|
|
79015
|
-
|
|
79024
|
+
resolve8(JSON.parse(chunksDecode(body, length, encoding)));
|
|
79016
79025
|
} else if (type === "arrayBuffer") {
|
|
79017
|
-
|
|
79026
|
+
resolve8(chunksConcat(body, length).buffer);
|
|
79018
79027
|
} else if (type === "blob") {
|
|
79019
|
-
|
|
79028
|
+
resolve8(new Blob(body, { type: stream[kContentType] }));
|
|
79020
79029
|
} else if (type === "bytes") {
|
|
79021
|
-
|
|
79030
|
+
resolve8(chunksConcat(body, length));
|
|
79022
79031
|
}
|
|
79023
79032
|
consumeFinish(consume2);
|
|
79024
79033
|
} catch (err) {
|
|
@@ -79215,9 +79224,9 @@ var require_api_request = __commonJS({
|
|
|
79215
79224
|
};
|
|
79216
79225
|
function request(opts, callback) {
|
|
79217
79226
|
if (callback === void 0) {
|
|
79218
|
-
return new Promise((
|
|
79227
|
+
return new Promise((resolve8, reject) => {
|
|
79219
79228
|
request.call(this, opts, (err, data2) => {
|
|
79220
|
-
return err ? reject(err) :
|
|
79229
|
+
return err ? reject(err) : resolve8(data2);
|
|
79221
79230
|
});
|
|
79222
79231
|
});
|
|
79223
79232
|
}
|
|
@@ -79437,9 +79446,9 @@ var require_api_stream = __commonJS({
|
|
|
79437
79446
|
};
|
|
79438
79447
|
function stream(opts, factory, callback) {
|
|
79439
79448
|
if (callback === void 0) {
|
|
79440
|
-
return new Promise((
|
|
79449
|
+
return new Promise((resolve8, reject) => {
|
|
79441
79450
|
stream.call(this, opts, factory, (err, data2) => {
|
|
79442
|
-
return err ? reject(err) :
|
|
79451
|
+
return err ? reject(err) : resolve8(data2);
|
|
79443
79452
|
});
|
|
79444
79453
|
});
|
|
79445
79454
|
}
|
|
@@ -79742,9 +79751,9 @@ var require_api_upgrade = __commonJS({
|
|
|
79742
79751
|
};
|
|
79743
79752
|
function upgrade(opts, callback) {
|
|
79744
79753
|
if (callback === void 0) {
|
|
79745
|
-
return new Promise((
|
|
79754
|
+
return new Promise((resolve8, reject) => {
|
|
79746
79755
|
upgrade.call(this, opts, (err, data2) => {
|
|
79747
|
-
return err ? reject(err) :
|
|
79756
|
+
return err ? reject(err) : resolve8(data2);
|
|
79748
79757
|
});
|
|
79749
79758
|
});
|
|
79750
79759
|
}
|
|
@@ -79841,9 +79850,9 @@ var require_api_connect = __commonJS({
|
|
|
79841
79850
|
};
|
|
79842
79851
|
function connect(opts, callback) {
|
|
79843
79852
|
if (callback === void 0) {
|
|
79844
|
-
return new Promise((
|
|
79853
|
+
return new Promise((resolve8, reject) => {
|
|
79845
79854
|
connect.call(this, opts, (err, data2) => {
|
|
79846
|
-
return err ? reject(err) :
|
|
79855
|
+
return err ? reject(err) : resolve8(data2);
|
|
79847
79856
|
});
|
|
79848
79857
|
});
|
|
79849
79858
|
}
|
|
@@ -81179,7 +81188,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
81179
81188
|
"../../node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
|
|
81180
81189
|
"use strict";
|
|
81181
81190
|
var { writeFile: writeFile4, readFile: readFile4, mkdir: mkdir2 } = __require("node:fs/promises");
|
|
81182
|
-
var { dirname: dirname8, resolve:
|
|
81191
|
+
var { dirname: dirname8, resolve: resolve8 } = __require("node:path");
|
|
81183
81192
|
var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
|
|
81184
81193
|
var { InvalidArgumentError: InvalidArgumentError2, UndiciError } = require_errors3();
|
|
81185
81194
|
var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
|
|
@@ -81387,7 +81396,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
81387
81396
|
throw new InvalidArgumentError2("Snapshot path is required");
|
|
81388
81397
|
}
|
|
81389
81398
|
try {
|
|
81390
|
-
const data2 = await readFile4(
|
|
81399
|
+
const data2 = await readFile4(resolve8(path46), "utf8");
|
|
81391
81400
|
const parsed = JSON.parse(data2);
|
|
81392
81401
|
if (Array.isArray(parsed)) {
|
|
81393
81402
|
this.#snapshots.clear();
|
|
@@ -81416,7 +81425,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
81416
81425
|
if (!path46) {
|
|
81417
81426
|
throw new InvalidArgumentError2("Snapshot path is required");
|
|
81418
81427
|
}
|
|
81419
|
-
const resolvedPath =
|
|
81428
|
+
const resolvedPath = resolve8(path46);
|
|
81420
81429
|
await mkdir2(dirname8(resolvedPath), { recursive: true });
|
|
81421
81430
|
const data2 = Array.from(this.#snapshots.entries()).map(([hash2, snapshot]) => ({
|
|
81422
81431
|
hash: hash2,
|
|
@@ -88396,7 +88405,7 @@ var require_fetch = __commonJS({
|
|
|
88396
88405
|
const agent = fetchParams.controller.dispatcher;
|
|
88397
88406
|
const path46 = url2.pathname + url2.search;
|
|
88398
88407
|
const hasTrailingQuestionMark = url2.search.length === 0 && url2.href[url2.href.length - url2.hash.length - 1] === "?";
|
|
88399
|
-
return new Promise((
|
|
88408
|
+
return new Promise((resolve8, reject) => agent.dispatch(
|
|
88400
88409
|
{
|
|
88401
88410
|
path: hasTrailingQuestionMark ? `${path46}?` : path46,
|
|
88402
88411
|
origin: url2.origin,
|
|
@@ -88484,7 +88493,7 @@ var require_fetch = __commonJS({
|
|
|
88484
88493
|
}
|
|
88485
88494
|
}
|
|
88486
88495
|
const onError = this.onError.bind(this);
|
|
88487
|
-
|
|
88496
|
+
resolve8({
|
|
88488
88497
|
status,
|
|
88489
88498
|
statusText,
|
|
88490
88499
|
headersList,
|
|
@@ -88537,7 +88546,7 @@ var require_fetch = __commonJS({
|
|
|
88537
88546
|
headersList.append(headerName, String(value), true);
|
|
88538
88547
|
}
|
|
88539
88548
|
}
|
|
88540
|
-
|
|
88549
|
+
resolve8({
|
|
88541
88550
|
status,
|
|
88542
88551
|
statusText: STATUS_CODES[status],
|
|
88543
88552
|
headersList,
|
|
@@ -88561,7 +88570,7 @@ var require_fetch = __commonJS({
|
|
|
88561
88570
|
headersList.append(nameStr, value.toString("latin1"), true);
|
|
88562
88571
|
}
|
|
88563
88572
|
}
|
|
88564
|
-
|
|
88573
|
+
resolve8({
|
|
88565
88574
|
status,
|
|
88566
88575
|
statusText: STATUS_CODES[status],
|
|
88567
88576
|
headersList,
|
|
@@ -96276,16 +96285,16 @@ function pickSurfaces(opts) {
|
|
|
96276
96285
|
return selected.length > 0 ? selected : void 0;
|
|
96277
96286
|
}
|
|
96278
96287
|
function withSoftTimeout(p2, ms) {
|
|
96279
|
-
return new Promise((
|
|
96280
|
-
const t2 = setTimeout(() =>
|
|
96288
|
+
return new Promise((resolve8) => {
|
|
96289
|
+
const t2 = setTimeout(() => resolve8({ kind: "timeout" }), ms);
|
|
96281
96290
|
p2.then(
|
|
96282
96291
|
(value) => {
|
|
96283
96292
|
clearTimeout(t2);
|
|
96284
|
-
|
|
96293
|
+
resolve8({ kind: "ok", value });
|
|
96285
96294
|
},
|
|
96286
96295
|
(error45) => {
|
|
96287
96296
|
clearTimeout(t2);
|
|
96288
|
-
|
|
96297
|
+
resolve8({ kind: "error", error: error45 });
|
|
96289
96298
|
}
|
|
96290
96299
|
);
|
|
96291
96300
|
});
|
|
@@ -98169,11 +98178,11 @@ function defaultConsentIO() {
|
|
|
98169
98178
|
__name(defaultConsentIO, "defaultConsentIO");
|
|
98170
98179
|
async function readLine(prompt) {
|
|
98171
98180
|
const readline = await import("node:readline");
|
|
98172
|
-
return new Promise((
|
|
98181
|
+
return new Promise((resolve8) => {
|
|
98173
98182
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
98174
98183
|
rl.question(prompt, (answer) => {
|
|
98175
98184
|
rl.close();
|
|
98176
|
-
|
|
98185
|
+
resolve8(answer);
|
|
98177
98186
|
});
|
|
98178
98187
|
});
|
|
98179
98188
|
}
|
|
@@ -101170,6 +101179,112 @@ function normalizeFimoLocale(locale) {
|
|
|
101170
101179
|
}
|
|
101171
101180
|
__name(normalizeFimoLocale, "normalizeFimoLocale");
|
|
101172
101181
|
|
|
101182
|
+
// src/scripts/validate-schemas.ts
|
|
101183
|
+
init_esm();
|
|
101184
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as readdirSync4 } from "node:fs";
|
|
101185
|
+
import { basename as basename2, join as join9, resolve as resolve6 } from "node:path";
|
|
101186
|
+
var SCHEMAS_REL2 = "src/schemas";
|
|
101187
|
+
var FIELD_TYPES = new Set(FieldTypeSchema.options);
|
|
101188
|
+
var RESERVED_FIELD_NAMES = new Set(RESERVED_CONTENT_FIELD_NAMES);
|
|
101189
|
+
function validateSchemas(options = {}) {
|
|
101190
|
+
const cwd = resolve6(options.cwd ?? process.cwd());
|
|
101191
|
+
const schemasDir = join9(cwd, SCHEMAS_REL2);
|
|
101192
|
+
if (!existsSync7(schemasDir)) {
|
|
101193
|
+
return { errors: [], schemasChecked: 0 };
|
|
101194
|
+
}
|
|
101195
|
+
const files = readdirSync4(schemasDir).filter((f) => f.endsWith(".json")).sort();
|
|
101196
|
+
const errors2 = [];
|
|
101197
|
+
for (const fileName of files) {
|
|
101198
|
+
const file2 = join9(SCHEMAS_REL2, fileName);
|
|
101199
|
+
errors2.push(...validateSchemaFile(join9(schemasDir, fileName), file2));
|
|
101200
|
+
}
|
|
101201
|
+
return { errors: errors2, schemasChecked: files.length };
|
|
101202
|
+
}
|
|
101203
|
+
__name(validateSchemas, "validateSchemas");
|
|
101204
|
+
function validateSchemaFile(absolutePath, file2) {
|
|
101205
|
+
let schema;
|
|
101206
|
+
try {
|
|
101207
|
+
schema = JSON.parse(readFileSync7(absolutePath, "utf-8"));
|
|
101208
|
+
} catch (error45) {
|
|
101209
|
+
return [
|
|
101210
|
+
{
|
|
101211
|
+
rule: "schemas/parse",
|
|
101212
|
+
message: `Invalid JSON: ${error45 instanceof Error ? error45.message : String(error45)}`,
|
|
101213
|
+
file: file2
|
|
101214
|
+
}
|
|
101215
|
+
];
|
|
101216
|
+
}
|
|
101217
|
+
if (typeof schema !== "object" || schema === null || Array.isArray(schema)) {
|
|
101218
|
+
return [{ rule: "schemas/shape", message: "Schema must be a JSON object.", file: file2 }];
|
|
101219
|
+
}
|
|
101220
|
+
const errors2 = [];
|
|
101221
|
+
const { uid, name, fields } = schema;
|
|
101222
|
+
const expectedUid = basename2(file2, ".json");
|
|
101223
|
+
if (typeof uid !== "string" || uid.length === 0) {
|
|
101224
|
+
errors2.push({
|
|
101225
|
+
rule: "schemas/uid",
|
|
101226
|
+
message: `Missing "uid". Set it to the file name: "${expectedUid}".`,
|
|
101227
|
+
file: file2
|
|
101228
|
+
});
|
|
101229
|
+
} else if (uid !== expectedUid) {
|
|
101230
|
+
errors2.push({
|
|
101231
|
+
rule: "schemas/uid",
|
|
101232
|
+
message: `"uid" is "${uid}" but the file is ${expectedUid}.json \u2014 they must match.`,
|
|
101233
|
+
file: file2
|
|
101234
|
+
});
|
|
101235
|
+
}
|
|
101236
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
101237
|
+
errors2.push({
|
|
101238
|
+
rule: "schemas/name",
|
|
101239
|
+
message: 'Missing "name" (the human-readable label).',
|
|
101240
|
+
file: file2
|
|
101241
|
+
});
|
|
101242
|
+
}
|
|
101243
|
+
if (typeof fields !== "object" || fields === null || Array.isArray(fields)) {
|
|
101244
|
+
errors2.push({
|
|
101245
|
+
rule: "schemas/fields",
|
|
101246
|
+
message: 'Missing "fields" object.',
|
|
101247
|
+
file: file2
|
|
101248
|
+
});
|
|
101249
|
+
return errors2;
|
|
101250
|
+
}
|
|
101251
|
+
for (const [fieldName, definition] of Object.entries(fields)) {
|
|
101252
|
+
if (RESERVED_FIELD_NAMES.has(fieldName)) {
|
|
101253
|
+
errors2.push({
|
|
101254
|
+
rule: "schemas/reserved-field",
|
|
101255
|
+
message: `Field "${fieldName}" is reserved entry metadata \u2014 the platform manages it automatically. Remove it from the schema${fieldName === "slug" ? " (set slug inside entry data on create instead)" : ""}.`,
|
|
101256
|
+
file: file2
|
|
101257
|
+
});
|
|
101258
|
+
continue;
|
|
101259
|
+
}
|
|
101260
|
+
if (typeof definition !== "object" || definition === null || Array.isArray(definition)) {
|
|
101261
|
+
errors2.push({
|
|
101262
|
+
rule: "schemas/field-shape",
|
|
101263
|
+
message: `Field "${fieldName}" must be an object like { "type": "string" }.`,
|
|
101264
|
+
file: file2
|
|
101265
|
+
});
|
|
101266
|
+
continue;
|
|
101267
|
+
}
|
|
101268
|
+
const { type } = definition;
|
|
101269
|
+
if (typeof type !== "string" || !FIELD_TYPES.has(type)) {
|
|
101270
|
+
errors2.push({
|
|
101271
|
+
rule: "schemas/field-type",
|
|
101272
|
+
message: `Field "${fieldName}" has unsupported type "${String(type)}". Allowed: ${[...FIELD_TYPES].join(", ")}.`,
|
|
101273
|
+
file: file2
|
|
101274
|
+
});
|
|
101275
|
+
}
|
|
101276
|
+
if ("i18n" in definition) {
|
|
101277
|
+
errors2.push({
|
|
101278
|
+
rule: "schemas/field-i18n",
|
|
101279
|
+
message: `Field "${fieldName}": field-level locale settings ("i18n") are not supported.`,
|
|
101280
|
+
file: file2
|
|
101281
|
+
});
|
|
101282
|
+
}
|
|
101283
|
+
}
|
|
101284
|
+
return errors2;
|
|
101285
|
+
}
|
|
101286
|
+
__name(validateSchemaFile, "validateSchemaFile");
|
|
101287
|
+
|
|
101173
101288
|
// src/cli/commands/validate.ts
|
|
101174
101289
|
init_api();
|
|
101175
101290
|
init_config2();
|
|
@@ -101314,8 +101429,8 @@ init_project();
|
|
|
101314
101429
|
|
|
101315
101430
|
// src/cli/commands/scripts.ts
|
|
101316
101431
|
init_dist();
|
|
101317
|
-
import { existsSync as
|
|
101318
|
-
import { join as
|
|
101432
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9, readdirSync as readdirSync6, statSync as statSync3 } from "node:fs";
|
|
101433
|
+
import { join as join11, resolve as resolve7 } from "node:path";
|
|
101319
101434
|
|
|
101320
101435
|
// src/scripts/export-static.ts
|
|
101321
101436
|
import fs23 from "node:fs/promises";
|
|
@@ -101357,8 +101472,8 @@ async function exportStatic(options = {}) {
|
|
|
101357
101472
|
__name(exportStatic, "exportStatic");
|
|
101358
101473
|
|
|
101359
101474
|
// src/scripts/lint-translation-keys.ts
|
|
101360
|
-
import { existsSync as
|
|
101361
|
-
import { join as
|
|
101475
|
+
import { existsSync as existsSync8, readFileSync as readFileSync8, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
|
|
101476
|
+
import { join as join10 } from "path";
|
|
101362
101477
|
import { parseSync as parseSync2 } from "oxc-parser";
|
|
101363
101478
|
var SRC_DIR = "src";
|
|
101364
101479
|
function getLineAndColumn(code2, offset) {
|
|
@@ -101452,9 +101567,9 @@ function lintTranslationKeys(filePath, code2) {
|
|
|
101452
101567
|
__name(lintTranslationKeys, "lintTranslationKeys");
|
|
101453
101568
|
function findReactFiles2(dir) {
|
|
101454
101569
|
const files = [];
|
|
101455
|
-
if (!
|
|
101456
|
-
for (const entry of
|
|
101457
|
-
const fullPath =
|
|
101570
|
+
if (!existsSync8(dir)) return files;
|
|
101571
|
+
for (const entry of readdirSync5(dir)) {
|
|
101572
|
+
const fullPath = join10(dir, entry);
|
|
101458
101573
|
const stat2 = statSync2(fullPath);
|
|
101459
101574
|
if (stat2.isDirectory()) {
|
|
101460
101575
|
if (entry === "ui" || entry === "node_modules" || entry === "fimo") continue;
|
|
@@ -101468,10 +101583,10 @@ function findReactFiles2(dir) {
|
|
|
101468
101583
|
__name(findReactFiles2, "findReactFiles");
|
|
101469
101584
|
var isStandalone = process.argv[1]?.includes("lint-translation-keys");
|
|
101470
101585
|
if (isStandalone) {
|
|
101471
|
-
const reactFiles = [...findReactFiles2(
|
|
101586
|
+
const reactFiles = [...findReactFiles2(join10(SRC_DIR, "components")), ...findReactFiles2(join10(SRC_DIR, "pages"))];
|
|
101472
101587
|
const errors2 = [];
|
|
101473
101588
|
for (const file2 of reactFiles) {
|
|
101474
|
-
const code2 =
|
|
101589
|
+
const code2 = readFileSync8(file2, "utf-8");
|
|
101475
101590
|
errors2.push(...lintTranslationKeys(file2, code2));
|
|
101476
101591
|
}
|
|
101477
101592
|
if (errors2.length > 0) {
|
|
@@ -101696,7 +101811,7 @@ __name(resolveRoutes, "resolveRoutes");
|
|
|
101696
101811
|
init_sync_forms();
|
|
101697
101812
|
init_sync_schemas();
|
|
101698
101813
|
function resolveCwd(options) {
|
|
101699
|
-
return options.cwd ?
|
|
101814
|
+
return options.cwd ? resolve7(options.cwd) : process.cwd();
|
|
101700
101815
|
}
|
|
101701
101816
|
__name(resolveCwd, "resolveCwd");
|
|
101702
101817
|
function renderPrettyJson4(data2) {
|
|
@@ -101767,7 +101882,7 @@ function resolveRoutesCommand(changedFiles, options) {
|
|
|
101767
101882
|
}
|
|
101768
101883
|
__name(resolveRoutesCommand, "resolveRoutesCommand");
|
|
101769
101884
|
function lintProject(opts) {
|
|
101770
|
-
const files = opts.targetPath ? [
|
|
101885
|
+
const files = opts.targetPath ? [resolve7(opts.cwd, opts.targetPath)] : collectFiles2(resolve7(opts.cwd, "src"));
|
|
101771
101886
|
const errors2 = [];
|
|
101772
101887
|
let filesChecked = 0;
|
|
101773
101888
|
for (const file2 of files) {
|
|
@@ -101775,7 +101890,7 @@ function lintProject(opts) {
|
|
|
101775
101890
|
continue;
|
|
101776
101891
|
}
|
|
101777
101892
|
try {
|
|
101778
|
-
const code2 =
|
|
101893
|
+
const code2 = readFileSync9(file2, "utf-8");
|
|
101779
101894
|
errors2.push(...lintTranslationKeys(file2, code2));
|
|
101780
101895
|
filesChecked++;
|
|
101781
101896
|
} catch {
|
|
@@ -101794,15 +101909,15 @@ function lintCommand(targetPath, options) {
|
|
|
101794
101909
|
}
|
|
101795
101910
|
__name(lintCommand, "lintCommand");
|
|
101796
101911
|
function collectFiles2(root2) {
|
|
101797
|
-
if (!
|
|
101912
|
+
if (!existsSync9(root2)) {
|
|
101798
101913
|
return [];
|
|
101799
101914
|
}
|
|
101800
101915
|
const results = [];
|
|
101801
|
-
for (const name of
|
|
101916
|
+
for (const name of readdirSync6(root2)) {
|
|
101802
101917
|
if (name === "node_modules" || name === "dist" || name === ".git") {
|
|
101803
101918
|
continue;
|
|
101804
101919
|
}
|
|
101805
|
-
const full =
|
|
101920
|
+
const full = join11(root2, name);
|
|
101806
101921
|
if (statSync3(full).isDirectory()) {
|
|
101807
101922
|
results.push(...collectFiles2(full));
|
|
101808
101923
|
} else {
|
|
@@ -101855,10 +101970,11 @@ async function runValidate(opts) {
|
|
|
101855
101970
|
__name(runValidate, "runValidate");
|
|
101856
101971
|
async function runChecksPhase(opts) {
|
|
101857
101972
|
const { cwd } = opts;
|
|
101858
|
-
const [lintResult, routeResult, agentsResult] = await Promise.allSettled([
|
|
101973
|
+
const [lintResult, routeResult, agentsResult, schemasResult] = await Promise.allSettled([
|
|
101859
101974
|
Promise.resolve().then(() => lintProject({ cwd })),
|
|
101860
101975
|
Promise.resolve().then(() => runRouteMetadataCheck({ cwd })),
|
|
101861
|
-
Promise.resolve().then(() => runAgentsCheck({ cwd }))
|
|
101976
|
+
Promise.resolve().then(() => runAgentsCheck({ cwd })),
|
|
101977
|
+
Promise.resolve().then(() => validateSchemas({ cwd }))
|
|
101862
101978
|
]);
|
|
101863
101979
|
const errors2 = [];
|
|
101864
101980
|
const stats = {};
|
|
@@ -101894,6 +102010,14 @@ async function runChecksPhase(opts) {
|
|
|
101894
102010
|
} else {
|
|
101895
102011
|
errors2.push(infraErrorFromException("agents", agentsResult.reason));
|
|
101896
102012
|
}
|
|
102013
|
+
if (schemasResult.status === "fulfilled") {
|
|
102014
|
+
stats.schemasChecked = schemasResult.value.schemasChecked;
|
|
102015
|
+
for (const err of schemasResult.value.errors) {
|
|
102016
|
+
errors2.push(authorError({ rule: err.rule, message: err.message, file: err.file }));
|
|
102017
|
+
}
|
|
102018
|
+
} else {
|
|
102019
|
+
errors2.push(infraErrorFromException("schemas", schemasResult.reason));
|
|
102020
|
+
}
|
|
101897
102021
|
return {
|
|
101898
102022
|
name: "Checks",
|
|
101899
102023
|
ok: errors2.length === 0,
|
|
@@ -103886,14 +104010,14 @@ var baseOpen = /* @__PURE__ */ __name(async (options) => {
|
|
|
103886
104010
|
}
|
|
103887
104011
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
103888
104012
|
if (options.wait) {
|
|
103889
|
-
return new Promise((
|
|
104013
|
+
return new Promise((resolve8, reject) => {
|
|
103890
104014
|
subprocess.once("error", reject);
|
|
103891
104015
|
subprocess.once("close", (exitCode) => {
|
|
103892
104016
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
103893
104017
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
103894
104018
|
return;
|
|
103895
104019
|
}
|
|
103896
|
-
|
|
104020
|
+
resolve8(subprocess);
|
|
103897
104021
|
});
|
|
103898
104022
|
});
|
|
103899
104023
|
}
|
|
@@ -104110,7 +104234,7 @@ async function pollUntilVerified(api, projectId, initial, timeoutMs, organizatio
|
|
|
104110
104234
|
sp.fail(`SSL validation failed for ${current.hostname}.`);
|
|
104111
104235
|
return current;
|
|
104112
104236
|
}
|
|
104113
|
-
await new Promise((
|
|
104237
|
+
await new Promise((resolve8) => setTimeout(resolve8, 5e3));
|
|
104114
104238
|
try {
|
|
104115
104239
|
current = await api.refreshProjectDomain(projectId, initial.id);
|
|
104116
104240
|
sp.update(`Waiting for ${current.hostname} (SSL: ${current.ssl.status})`);
|
|
@@ -104715,7 +104839,7 @@ async function pollPurchasePayment(api, organizationId, initial, timeoutMs) {
|
|
|
104715
104839
|
sp.fail(`${current.status === "payment_failed" ? "Payment" : "Registration"} failed for ${current.domain}.`);
|
|
104716
104840
|
return current;
|
|
104717
104841
|
}
|
|
104718
|
-
await new Promise((
|
|
104842
|
+
await new Promise((resolve8) => setTimeout(resolve8, 5e3));
|
|
104719
104843
|
try {
|
|
104720
104844
|
current = await api.refreshRegisteredDomainPayment(organizationId, current.id);
|
|
104721
104845
|
sp.update(`Waiting (status: ${current.status})`);
|
|
@@ -106953,7 +107077,7 @@ async function loginCommand() {
|
|
|
106953
107077
|
}
|
|
106954
107078
|
__name(loginCommand, "loginCommand");
|
|
106955
107079
|
async function startCallbackServer() {
|
|
106956
|
-
return new Promise((
|
|
107080
|
+
return new Promise((resolve8, reject) => {
|
|
106957
107081
|
const server = createHttpServer();
|
|
106958
107082
|
server.on("error", reject);
|
|
106959
107083
|
server.listen(0, "127.0.0.1", () => {
|
|
@@ -106962,13 +107086,13 @@ async function startCallbackServer() {
|
|
|
106962
107086
|
reject(new Error("Failed to bind callback server"));
|
|
106963
107087
|
return;
|
|
106964
107088
|
}
|
|
106965
|
-
|
|
107089
|
+
resolve8({ server, port: address.port });
|
|
106966
107090
|
});
|
|
106967
107091
|
});
|
|
106968
107092
|
}
|
|
106969
107093
|
__name(startCallbackServer, "startCallbackServer");
|
|
106970
107094
|
function waitForCallback(server, timeoutMs) {
|
|
106971
|
-
return new Promise((
|
|
107095
|
+
return new Promise((resolve8, reject) => {
|
|
106972
107096
|
const timeout = setTimeout(() => {
|
|
106973
107097
|
cleanup();
|
|
106974
107098
|
reject(new Error("Timed out waiting for browser callback"));
|
|
@@ -106991,7 +107115,7 @@ function waitForCallback(server, timeoutMs) {
|
|
|
106991
107115
|
}
|
|
106992
107116
|
respond(res, 200, renderSignedInPage(), "text/html");
|
|
106993
107117
|
cleanup();
|
|
106994
|
-
|
|
107118
|
+
resolve8({ token, state });
|
|
106995
107119
|
}, "handler");
|
|
106996
107120
|
server.on("request", handler);
|
|
106997
107121
|
function cleanup() {
|
|
@@ -107149,7 +107273,7 @@ init_api();
|
|
|
107149
107273
|
init_auth_errors();
|
|
107150
107274
|
init_color();
|
|
107151
107275
|
import { execSync, spawnSync as spawnSync4 } from "node:child_process";
|
|
107152
|
-
import { mkdtempSync, readFileSync as
|
|
107276
|
+
import { mkdtempSync, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
|
|
107153
107277
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
107154
107278
|
import path37 from "node:path";
|
|
107155
107279
|
|
|
@@ -107554,7 +107678,7 @@ function openEditorForPick(conflict) {
|
|
|
107554
107678
|
const seed = conflict.childValue !== void 0 ? JSON.stringify(conflict.childValue, null, 2) : '// Replace this comment with the resolved value as JSON\n""';
|
|
107555
107679
|
writeFileSync6(file2, seed, "utf8");
|
|
107556
107680
|
spawnSync4(editor, [file2], { stdio: "inherit" });
|
|
107557
|
-
const raw =
|
|
107681
|
+
const raw = readFileSync10(file2, "utf8").trim();
|
|
107558
107682
|
if (raw === "" || raw === seed.trim()) {
|
|
107559
107683
|
return null;
|
|
107560
107684
|
}
|
|
@@ -108630,6 +108754,7 @@ __name(deleteCommand, "deleteCommand");
|
|
|
108630
108754
|
init_dist();
|
|
108631
108755
|
import fs41 from "node:fs";
|
|
108632
108756
|
import path44 from "node:path";
|
|
108757
|
+
init_api();
|
|
108633
108758
|
init_project_context();
|
|
108634
108759
|
init_project();
|
|
108635
108760
|
function toApiShape(schema) {
|
|
@@ -108671,13 +108796,17 @@ async function schemaPushCommand(typeName, options, cmd) {
|
|
|
108671
108796
|
if (!fs41.existsSync(filePath)) {
|
|
108672
108797
|
throw new Error(`Schema file not found: ${filePath}`);
|
|
108673
108798
|
}
|
|
108799
|
+
const issues = validateSchemaFile(filePath, path44.join("src/schemas", file2));
|
|
108800
|
+
if (issues.length > 0) {
|
|
108801
|
+
throw new Error(issues.map((issue2) => `${issue2.file}: ${issue2.message}`).join("\n"));
|
|
108802
|
+
}
|
|
108674
108803
|
const schema = JSON.parse(fs41.readFileSync(filePath, "utf-8"));
|
|
108675
108804
|
const contentType = toApiShape(schema);
|
|
108676
108805
|
try {
|
|
108677
108806
|
const result = await api.createSchema(ctx.projectId, contentType);
|
|
108678
108807
|
results.push(result);
|
|
108679
108808
|
} catch (error45) {
|
|
108680
|
-
if (error45 instanceof
|
|
108809
|
+
if (error45 instanceof ApiRequestError && error45.status === 400 && error45.detail === "Content type already exists") {
|
|
108681
108810
|
const result = await api.updateSchema(ctx.projectId, contentType.name, contentType);
|
|
108682
108811
|
results.push(result);
|
|
108683
108812
|
} else {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface SchemaFileError {
|
|
2
|
+
rule: string;
|
|
3
|
+
message: string;
|
|
4
|
+
file: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ValidateSchemasResult {
|
|
7
|
+
errors: SchemaFileError[];
|
|
8
|
+
schemasChecked: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function validateSchemas(options?: {
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}): ValidateSchemasResult;
|
|
13
|
+
export declare function validateSchemaFile(absolutePath: string, file: string): SchemaFileError[];
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { basename, join, resolve } from 'node:path';
|
|
3
|
+
import { FieldTypeSchema, RESERVED_CONTENT_FIELD_NAMES } from '@fimo/api-contracts';
|
|
4
|
+
/**
|
|
5
|
+
* Validate `src/schemas/*.json` locally against the same rules the API's
|
|
6
|
+
* schema validator enforces (field types, reserved field names, required
|
|
7
|
+
* uid/name). Catching these in `fimo validate` surfaces the real problem
|
|
8
|
+
* before a `schemas push` can fail with a less direct server error.
|
|
9
|
+
*/
|
|
10
|
+
const SCHEMAS_REL = 'src/schemas';
|
|
11
|
+
const FIELD_TYPES = new Set(FieldTypeSchema.options);
|
|
12
|
+
const RESERVED_FIELD_NAMES = new Set(RESERVED_CONTENT_FIELD_NAMES);
|
|
13
|
+
export function validateSchemas(options = {}) {
|
|
14
|
+
const cwd = resolve(options.cwd ?? process.cwd());
|
|
15
|
+
const schemasDir = join(cwd, SCHEMAS_REL);
|
|
16
|
+
if (!existsSync(schemasDir)) {
|
|
17
|
+
return { errors: [], schemasChecked: 0 };
|
|
18
|
+
}
|
|
19
|
+
const files = readdirSync(schemasDir)
|
|
20
|
+
.filter((f) => f.endsWith('.json'))
|
|
21
|
+
.sort();
|
|
22
|
+
const errors = [];
|
|
23
|
+
for (const fileName of files) {
|
|
24
|
+
const file = join(SCHEMAS_REL, fileName);
|
|
25
|
+
errors.push(...validateSchemaFile(join(schemasDir, fileName), file));
|
|
26
|
+
}
|
|
27
|
+
return { errors, schemasChecked: files.length };
|
|
28
|
+
}
|
|
29
|
+
export function validateSchemaFile(absolutePath, file) {
|
|
30
|
+
let schema;
|
|
31
|
+
try {
|
|
32
|
+
schema = JSON.parse(readFileSync(absolutePath, 'utf-8'));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
return [
|
|
36
|
+
{
|
|
37
|
+
rule: 'schemas/parse',
|
|
38
|
+
message: `Invalid JSON: ${error instanceof Error ? error.message : String(error)}`,
|
|
39
|
+
file,
|
|
40
|
+
},
|
|
41
|
+
];
|
|
42
|
+
}
|
|
43
|
+
if (typeof schema !== 'object' || schema === null || Array.isArray(schema)) {
|
|
44
|
+
return [{ rule: 'schemas/shape', message: 'Schema must be a JSON object.', file }];
|
|
45
|
+
}
|
|
46
|
+
const errors = [];
|
|
47
|
+
const { uid, name, fields } = schema;
|
|
48
|
+
const expectedUid = basename(file, '.json');
|
|
49
|
+
if (typeof uid !== 'string' || uid.length === 0) {
|
|
50
|
+
errors.push({
|
|
51
|
+
rule: 'schemas/uid',
|
|
52
|
+
message: `Missing "uid". Set it to the file name: "${expectedUid}".`,
|
|
53
|
+
file,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
else if (uid !== expectedUid) {
|
|
57
|
+
errors.push({
|
|
58
|
+
rule: 'schemas/uid',
|
|
59
|
+
message: `"uid" is "${uid}" but the file is ${expectedUid}.json — they must match.`,
|
|
60
|
+
file,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
64
|
+
errors.push({
|
|
65
|
+
rule: 'schemas/name',
|
|
66
|
+
message: 'Missing "name" (the human-readable label).',
|
|
67
|
+
file,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (typeof fields !== 'object' || fields === null || Array.isArray(fields)) {
|
|
71
|
+
errors.push({
|
|
72
|
+
rule: 'schemas/fields',
|
|
73
|
+
message: 'Missing "fields" object.',
|
|
74
|
+
file,
|
|
75
|
+
});
|
|
76
|
+
return errors;
|
|
77
|
+
}
|
|
78
|
+
for (const [fieldName, definition] of Object.entries(fields)) {
|
|
79
|
+
if (RESERVED_FIELD_NAMES.has(fieldName)) {
|
|
80
|
+
errors.push({
|
|
81
|
+
rule: 'schemas/reserved-field',
|
|
82
|
+
message: `Field "${fieldName}" is reserved entry metadata — the platform manages it automatically. ` +
|
|
83
|
+
`Remove it from the schema${fieldName === 'slug' ? ' (set slug inside entry data on create instead)' : ''}.`,
|
|
84
|
+
file,
|
|
85
|
+
});
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (typeof definition !== 'object' || definition === null || Array.isArray(definition)) {
|
|
89
|
+
errors.push({
|
|
90
|
+
rule: 'schemas/field-shape',
|
|
91
|
+
message: `Field "${fieldName}" must be an object like { "type": "string" }.`,
|
|
92
|
+
file,
|
|
93
|
+
});
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const { type } = definition;
|
|
97
|
+
if (typeof type !== 'string' || !FIELD_TYPES.has(type)) {
|
|
98
|
+
errors.push({
|
|
99
|
+
rule: 'schemas/field-type',
|
|
100
|
+
message: `Field "${fieldName}" has unsupported type "${String(type)}". Allowed: ${[...FIELD_TYPES].join(', ')}.`,
|
|
101
|
+
file,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if ('i18n' in definition) {
|
|
105
|
+
errors.push({
|
|
106
|
+
rule: 'schemas/field-i18n',
|
|
107
|
+
message: `Field "${fieldName}": field-level locale settings ("i18n") are not supported.`,
|
|
108
|
+
file,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return errors;
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
|
+
import { validateSchemas } from './validate-schemas';
|
|
6
|
+
describe('validateSchemas', () => {
|
|
7
|
+
let scratch = null;
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
if (scratch) {
|
|
10
|
+
rmSync(scratch, { recursive: true, force: true });
|
|
11
|
+
scratch = null;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
function writeProject(schemas) {
|
|
15
|
+
scratch = mkdtempSync(join(tmpdir(), 'validate-schemas-'));
|
|
16
|
+
mkdirSync(join(scratch, 'src/schemas'), { recursive: true });
|
|
17
|
+
for (const [fileName, schema] of Object.entries(schemas)) {
|
|
18
|
+
writeFileSync(join(scratch, 'src/schemas', fileName), typeof schema === 'string' ? schema : JSON.stringify(schema, null, 2));
|
|
19
|
+
}
|
|
20
|
+
return scratch;
|
|
21
|
+
}
|
|
22
|
+
it('accepts a valid schema', () => {
|
|
23
|
+
const cwd = writeProject({
|
|
24
|
+
'BlogPost.json': {
|
|
25
|
+
uid: 'BlogPost',
|
|
26
|
+
name: 'Blog Posts',
|
|
27
|
+
fields: {
|
|
28
|
+
title: { type: 'string' },
|
|
29
|
+
body: { type: 'richtext' },
|
|
30
|
+
coverImage: { type: 'media' },
|
|
31
|
+
featured: { type: 'boolean' },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
expect(validateSchemas({ cwd })).toEqual({ errors: [], schemasChecked: 1 });
|
|
36
|
+
});
|
|
37
|
+
it('returns no errors when the schemas directory does not exist', () => {
|
|
38
|
+
scratch = mkdtempSync(join(tmpdir(), 'validate-schemas-'));
|
|
39
|
+
expect(validateSchemas({ cwd: scratch })).toEqual({ errors: [], schemasChecked: 0 });
|
|
40
|
+
});
|
|
41
|
+
it('rejects reserved field names like slug', () => {
|
|
42
|
+
const cwd = writeProject({
|
|
43
|
+
'TeamMember.json': {
|
|
44
|
+
uid: 'TeamMember',
|
|
45
|
+
name: 'Team Members',
|
|
46
|
+
fields: {
|
|
47
|
+
name: { type: 'string' },
|
|
48
|
+
slug: { type: 'string' },
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
const { errors } = validateSchemas({ cwd });
|
|
53
|
+
expect(errors).toHaveLength(1);
|
|
54
|
+
expect(errors[0]).toMatchObject({ rule: 'schemas/reserved-field', file: 'src/schemas/TeamMember.json' });
|
|
55
|
+
expect(errors[0].message).toContain('"slug" is reserved');
|
|
56
|
+
expect(errors[0].message).toContain('entry data');
|
|
57
|
+
});
|
|
58
|
+
it('rejects every reserved metadata name', () => {
|
|
59
|
+
const cwd = writeProject({
|
|
60
|
+
'Bad.json': {
|
|
61
|
+
uid: 'Bad',
|
|
62
|
+
name: 'Bad',
|
|
63
|
+
fields: Object.fromEntries(['id', 'documentId', 'slug', 'locale', 'createdAt', 'updatedAt', '__fimo'].map((name) => [
|
|
64
|
+
name,
|
|
65
|
+
{ type: 'string' },
|
|
66
|
+
])),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
const { errors } = validateSchemas({ cwd });
|
|
70
|
+
expect(errors).toHaveLength(7);
|
|
71
|
+
expect(errors.every((err) => err.rule === 'schemas/reserved-field')).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
it('rejects unsupported field types', () => {
|
|
74
|
+
const cwd = writeProject({
|
|
75
|
+
'Product.json': {
|
|
76
|
+
uid: 'Product',
|
|
77
|
+
name: 'Products',
|
|
78
|
+
fields: { price: { type: 'decimal' } },
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
const { errors } = validateSchemas({ cwd });
|
|
82
|
+
expect(errors).toHaveLength(1);
|
|
83
|
+
expect(errors[0]).toMatchObject({ rule: 'schemas/field-type' });
|
|
84
|
+
expect(errors[0].message).toContain('"decimal"');
|
|
85
|
+
expect(errors[0].message).toContain('string, richtext, media');
|
|
86
|
+
});
|
|
87
|
+
it('rejects field-level i18n settings', () => {
|
|
88
|
+
const cwd = writeProject({
|
|
89
|
+
'Page.json': {
|
|
90
|
+
uid: 'Page',
|
|
91
|
+
name: 'Pages',
|
|
92
|
+
fields: { title: { type: 'string', i18n: true } },
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
const { errors } = validateSchemas({ cwd });
|
|
96
|
+
expect(errors).toHaveLength(1);
|
|
97
|
+
expect(errors[0]).toMatchObject({ rule: 'schemas/field-i18n' });
|
|
98
|
+
});
|
|
99
|
+
it('rejects a uid that does not match the file name', () => {
|
|
100
|
+
const cwd = writeProject({
|
|
101
|
+
'TeamMember.json': {
|
|
102
|
+
uid: 'Member',
|
|
103
|
+
name: 'Team Members',
|
|
104
|
+
fields: { name: { type: 'string' } },
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const { errors } = validateSchemas({ cwd });
|
|
108
|
+
expect(errors).toHaveLength(1);
|
|
109
|
+
expect(errors[0]).toMatchObject({ rule: 'schemas/uid' });
|
|
110
|
+
});
|
|
111
|
+
it('rejects missing uid, name, and fields', () => {
|
|
112
|
+
const cwd = writeProject({ 'Empty.json': {} });
|
|
113
|
+
const { errors } = validateSchemas({ cwd });
|
|
114
|
+
expect(errors.map((err) => err.rule)).toEqual(['schemas/uid', 'schemas/name', 'schemas/fields']);
|
|
115
|
+
});
|
|
116
|
+
it('reports invalid JSON', () => {
|
|
117
|
+
const cwd = writeProject({ 'Broken.json': '{ not json' });
|
|
118
|
+
const { errors } = validateSchemas({ cwd });
|
|
119
|
+
expect(errors).toHaveLength(1);
|
|
120
|
+
expect(errors[0]).toMatchObject({ rule: 'schemas/parse' });
|
|
121
|
+
});
|
|
122
|
+
it('validates multiple files and counts them', () => {
|
|
123
|
+
const cwd = writeProject({
|
|
124
|
+
'Good.json': { uid: 'Good', name: 'Good', fields: { title: { type: 'string' } } },
|
|
125
|
+
'Bad.json': { uid: 'Bad', name: 'Bad', fields: { slug: { type: 'string' } } },
|
|
126
|
+
});
|
|
127
|
+
const result = validateSchemas({ cwd });
|
|
128
|
+
expect(result.schemasChecked).toBe(2);
|
|
129
|
+
expect(result.errors).toHaveLength(1);
|
|
130
|
+
expect(result.errors[0].file).toBe('src/schemas/Bad.json');
|
|
131
|
+
});
|
|
132
|
+
});
|
package/package.json
CHANGED