@rebasepro/server 0.10.1-canary.d8d45b2 → 0.10.1-canary.ff9ccd6
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/api/ast-schema-editor.d.ts +10 -0
- package/dist/index.es.js +63 -67
- package/dist/index.es.js.map +1 -1
- package/dist/{openapi-generator-DqSIwNLV.js → openapi-generator-C3_pTcsb.js} +2 -3
- package/dist/{openapi-generator-DqSIwNLV.js.map → openapi-generator-C3_pTcsb.js.map} +1 -1
- package/dist/{schema-editor-routes-D3ef8zu1.js → schema-editor-routes-CF-g0gVN.js} +30 -2
- package/dist/schema-editor-routes-CF-g0gVN.js.map +1 -0
- package/dist/{src-BITicbgD.js → src-DRUswG_w.js} +107 -3
- package/dist/src-DRUswG_w.js.map +1 -0
- package/dist/utils/dev-port.d.ts +5 -2
- package/package.json +8 -11
- package/dist/schema-editor-routes-D3ef8zu1.js.map +0 -1
- package/dist/src-BITicbgD.js.map +0 -1
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move presentation keys into the `admin` block.
|
|
3
|
+
*
|
|
4
|
+
* `ADMIN_COLLECTION_KEYS` comes from `@rebasepro/types` rather than being spelled
|
|
5
|
+
* out here, so adding a field to `AdminCollectionOptions` cannot leave this writer
|
|
6
|
+
* behind. Any such key already inside `admin` wins over a top-level copy: the
|
|
7
|
+
* nested one is what the file said, and a flat duplicate is the view model's
|
|
8
|
+
* flattening leaking back.
|
|
9
|
+
*/
|
|
10
|
+
export declare function nestAdminKeys(collectionData: Record<string, unknown>): Record<string, unknown>;
|
|
1
11
|
export declare class AstSchemaEditor {
|
|
2
12
|
private project;
|
|
3
13
|
private collectionsDir;
|
package/dist/index.es.js
CHANGED
|
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
|
|
|
2
2
|
import process from "process";
|
|
3
3
|
__createRequire(import.meta.url);
|
|
4
4
|
import { _ as __toESM, a as generateRefreshToken, c as getRefreshTokenTtlMs, d as verifyAccessToken, f as verifyDownloadToken, g as __require, h as __exportAll, i as generateDownloadToken, l as hashRefreshToken, m as __commonJSMin, n as configureJwt, o as getAccessTokenExpiry, p as require_jsonwebtoken, r as generateAccessToken, s as getRefreshTokenExpiry, t as MAX_COOKIE_AGE_MS } from "./jwt-Dj7r7QX7.js";
|
|
5
|
-
import { _ as
|
|
5
|
+
import { S as RebaseClientError, _ as EntityReference, a as DEFAULT_DATA_SOURCE_KEY, b as Vector, c as policy, d as isPostgresCollectionConfig, g as toCanonicalOp, h as REST_TO_CANONICAL, i as DEFAULT_STORAGE_SOURCE_KEY, l as getCollectionDataPath, m as NULL_OPS, n as serializeCollections, o as getDataSourceCapabilities, p as CANONICAL_TO_REST, r as SCHEMA_VERSION_HEADER, s as isSQLAdmin, t as computeSchemaVersion, u as getDeclaredSubcollections, v as EntityRelation, x as RebaseApiError, y as GeoPoint } from "./src-DRUswG_w.js";
|
|
6
6
|
import { t as logger } from "./logger-BYU66ENZ.js";
|
|
7
7
|
import { t as nativeDynamicImport } from "./dynamic-import-Dvh-K5fl.js";
|
|
8
8
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
@@ -1689,39 +1689,9 @@ policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
|
|
|
1689
1689
|
return jsonLogic;
|
|
1690
1690
|
});
|
|
1691
1691
|
})))();
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
* Default operators offered per property type, before engine capabilities and
|
|
1696
|
-
* per-property narrowing are applied. These mirror what the built-in filter
|
|
1697
|
-
* fields can render.
|
|
1698
|
-
*/
|
|
1699
|
-
var COMPARISON_OPS = [
|
|
1700
|
-
"==",
|
|
1701
|
-
"!=",
|
|
1702
|
-
">",
|
|
1703
|
-
">=",
|
|
1704
|
-
"<",
|
|
1705
|
-
"<="
|
|
1706
|
-
];
|
|
1707
|
-
var NULL_CHECK_OPS = ["is-null", "is-not-null"];
|
|
1708
|
-
var MEMBERSHIP_OPS = ["in", "not-in"];
|
|
1709
|
-
var PATTERN_OPS = [
|
|
1710
|
-
"like",
|
|
1711
|
-
"ilike",
|
|
1712
|
-
"not-like",
|
|
1713
|
-
"not-ilike"
|
|
1714
|
-
];
|
|
1715
|
-
[
|
|
1716
|
-
...COMPARISON_OPS,
|
|
1717
|
-
...MEMBERSHIP_OPS,
|
|
1718
|
-
...PATTERN_OPS,
|
|
1719
|
-
...NULL_CHECK_OPS
|
|
1720
|
-
], [
|
|
1721
|
-
...COMPARISON_OPS,
|
|
1722
|
-
...MEMBERSHIP_OPS,
|
|
1723
|
-
...NULL_CHECK_OPS
|
|
1724
|
-
], [...COMPARISON_OPS, ...NULL_CHECK_OPS], [...NULL_CHECK_OPS], [...MEMBERSHIP_OPS, ...NULL_CHECK_OPS], [...MEMBERSHIP_OPS, ...NULL_CHECK_OPS];
|
|
1692
|
+
/**
|
|
1693
|
+
* Apply PropertyConditions to a resolved property, evaluating all JSON Logic rules.
|
|
1694
|
+
*/
|
|
1725
1695
|
//#endregion
|
|
1726
1696
|
//#region ../../node_modules/.pnpm/fast-equals@6.0.0/node_modules/fast-equals/dist/es/index.mjs
|
|
1727
1697
|
var { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
@@ -12888,6 +12858,7 @@ async function verifyGoogleAccessToken(accessToken, expectedClientId) {
|
|
|
12888
12858
|
function createGoogleProvider(config) {
|
|
12889
12859
|
const clientId = typeof config === "string" ? config : config.clientId;
|
|
12890
12860
|
const clientSecret = typeof config === "string" ? void 0 : config.clientSecret;
|
|
12861
|
+
if (!clientSecret) console.warn("[Rebase] Google provider configured without a client secret. ID-token and access-token sign-in still work, but the authorization-code flow used by the admin login button will fail. Set GOOGLE_CLIENT_SECRET to enable it.");
|
|
12891
12862
|
let googleClient;
|
|
12892
12863
|
async function getClient() {
|
|
12893
12864
|
if (!googleClient) {
|
|
@@ -15044,7 +15015,7 @@ function assertStorageAccessControlConfigured(state, isProduction) {
|
|
|
15044
15015
|
//#region src/init/docs.ts
|
|
15045
15016
|
async function mountOpenApiDocs(app, basePath, enableSwagger, activeCollections, requireAuth) {
|
|
15046
15017
|
if (enableSwagger === false || activeCollections.length === 0) return;
|
|
15047
|
-
const { generateOpenApiSpec } = await import("./openapi-generator-
|
|
15018
|
+
const { generateOpenApiSpec } = await import("./openapi-generator-C3_pTcsb.js");
|
|
15048
15019
|
app.get(`${basePath}/docs`, (c) => {
|
|
15049
15020
|
const spec = generateOpenApiSpec(activeCollections, {
|
|
15050
15021
|
basePath,
|
|
@@ -15546,6 +15517,34 @@ function createAuth(transport, options) {
|
|
|
15546
15517
|
transport.setToken(null);
|
|
15547
15518
|
emit("SIGNED_OUT", null);
|
|
15548
15519
|
}
|
|
15520
|
+
/**
|
|
15521
|
+
* Recover from a 401 on an ordinary API request.
|
|
15522
|
+
*
|
|
15523
|
+
* Returns `true` when the caller should retry — we minted a fresh access
|
|
15524
|
+
* token. When the refresh is rejected *fatally* (the refresh token itself
|
|
15525
|
+
* is invalid, expired or revoked) this client can no longer act as the
|
|
15526
|
+
* user at all, so we drop the session and emit `SIGNED_OUT`. UIs gate on
|
|
15527
|
+
* that event, so they show their login screen instead of leaving the user
|
|
15528
|
+
* staring at "Invalid or expired token" on every view.
|
|
15529
|
+
*
|
|
15530
|
+
* Transient failures (offline, 5xx, backend restarting) keep the session:
|
|
15531
|
+
* the scheduled refresh backs off and retries, and the token is very
|
|
15532
|
+
* likely still good once the backend answers again.
|
|
15533
|
+
*/
|
|
15534
|
+
async function handleUnauthorized() {
|
|
15535
|
+
if (!currentSession) return false;
|
|
15536
|
+
if (authFlowMode !== "cookie" && !currentSession.refreshToken) {
|
|
15537
|
+
abandonSessionLocally();
|
|
15538
|
+
return false;
|
|
15539
|
+
}
|
|
15540
|
+
try {
|
|
15541
|
+
await refreshSession();
|
|
15542
|
+
return true;
|
|
15543
|
+
} catch (err) {
|
|
15544
|
+
if (isFatalRefreshError(err)) abandonSessionLocally();
|
|
15545
|
+
return false;
|
|
15546
|
+
}
|
|
15547
|
+
}
|
|
15549
15548
|
async function attemptScheduledRefresh(attempt) {
|
|
15550
15549
|
try {
|
|
15551
15550
|
await refreshSession();
|
|
@@ -16047,6 +16046,7 @@ function createAuth(transport, options) {
|
|
|
16047
16046
|
signInWithSpotify,
|
|
16048
16047
|
signOut,
|
|
16049
16048
|
refreshSession,
|
|
16049
|
+
handleUnauthorized,
|
|
16050
16050
|
getUser,
|
|
16051
16051
|
findUserByEmail,
|
|
16052
16052
|
updateUser,
|
|
@@ -20190,14 +20190,7 @@ function createRebaseClient(options) {
|
|
|
20190
20190
|
} catch (e) {}
|
|
20191
20191
|
return session?.accessToken || options.token || "";
|
|
20192
20192
|
},
|
|
20193
|
-
onUnauthorized: options.onUnauthorized || (
|
|
20194
|
-
try {
|
|
20195
|
-
await auth.refreshSession();
|
|
20196
|
-
return true;
|
|
20197
|
-
} catch (e) {
|
|
20198
|
-
return false;
|
|
20199
|
-
}
|
|
20200
|
-
})
|
|
20193
|
+
onUnauthorized: options.onUnauthorized || (() => auth.handleUnauthorized())
|
|
20201
20194
|
});
|
|
20202
20195
|
auth.onAuthStateChange((event, session) => {
|
|
20203
20196
|
if (!ws) return;
|
|
@@ -20207,14 +20200,7 @@ function createRebaseClient(options) {
|
|
|
20207
20200
|
}
|
|
20208
20201
|
});
|
|
20209
20202
|
}
|
|
20210
|
-
if (!options.onUnauthorized) transport.setOnUnauthorized(
|
|
20211
|
-
try {
|
|
20212
|
-
await auth.refreshSession();
|
|
20213
|
-
return true;
|
|
20214
|
-
} catch (e) {
|
|
20215
|
-
return false;
|
|
20216
|
-
}
|
|
20217
|
-
});
|
|
20203
|
+
if (!options.onUnauthorized) transport.setOnUnauthorized(() => auth.handleUnauthorized());
|
|
20218
20204
|
/**
|
|
20219
20205
|
* Suggest the closest known collection key for a mistyped accessor.
|
|
20220
20206
|
* Uses edit-distance-1 and prefix matching — no external dependency.
|
|
@@ -20952,7 +20938,7 @@ async function _initializeRebaseBackend(config) {
|
|
|
20952
20938
|
if (schemaEditorEnabled && config.collectionsDir) {
|
|
20953
20939
|
let editorModule;
|
|
20954
20940
|
try {
|
|
20955
|
-
editorModule = await import("./schema-editor-routes-
|
|
20941
|
+
editorModule = await import("./schema-editor-routes-CF-g0gVN.js");
|
|
20956
20942
|
} catch (err) {
|
|
20957
20943
|
if (err?.code === "ERR_MODULE_NOT_FOUND") logger.warn("Schema Editor disabled: its dependency ts-morph is not installed. Run `npm install ts-morph@28.0.0` to enable it.");
|
|
20958
20944
|
else throw err;
|
|
@@ -22461,8 +22447,11 @@ var DEV_PORT_FILENAME = ".rebase-dev-port";
|
|
|
22461
22447
|
* Try to `listen` on `startPort`. If the port is busy (`EADDRINUSE`), increment
|
|
22462
22448
|
* and retry up to `maxAttempts` times.
|
|
22463
22449
|
*
|
|
22464
|
-
* When a port file
|
|
22465
|
-
*
|
|
22450
|
+
* When a port file written by a previous run exists *and that run asked for the
|
|
22451
|
+
* same `startPort`*, the port it landed on is tried first, so tsx watch restarts
|
|
22452
|
+
* keep the address the frontend was configured with. A different `startPort` means
|
|
22453
|
+
* the configuration changed and the file is ignored — an explicitly requested port
|
|
22454
|
+
* is never overridden by a stale one.
|
|
22466
22455
|
*
|
|
22467
22456
|
* Resolves with the port that was actually bound.
|
|
22468
22457
|
*
|
|
@@ -22490,8 +22479,10 @@ function listenWithPortRetry(server, startPort, options) {
|
|
|
22490
22479
|
if (portFileDir) try {
|
|
22491
22480
|
const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
|
|
22492
22481
|
if (fs.existsSync(portFile)) {
|
|
22493
|
-
const
|
|
22494
|
-
|
|
22482
|
+
const [savedRaw, requestedRaw] = fs.readFileSync(portFile, "utf-8").trim().split(/\s+/);
|
|
22483
|
+
const saved = parseInt(savedRaw, 10);
|
|
22484
|
+
const requestedThen = requestedRaw === void 0 ? NaN : parseInt(requestedRaw, 10);
|
|
22485
|
+
if (saved > 0 && saved < 65536 && saved !== startPort && (Number.isNaN(requestedThen) || requestedThen === startPort)) affinityPort = saved;
|
|
22495
22486
|
}
|
|
22496
22487
|
} catch {}
|
|
22497
22488
|
return new Promise((resolve, reject) => {
|
|
@@ -22509,24 +22500,29 @@ function listenWithPortRetry(server, startPort, options) {
|
|
|
22509
22500
|
}
|
|
22510
22501
|
const port = portsToTry[index];
|
|
22511
22502
|
attempt++;
|
|
22512
|
-
const
|
|
22513
|
-
|
|
22514
|
-
server.removeListener("error", onError);
|
|
22515
|
-
tryNext(index + 1);
|
|
22516
|
-
} else reject(err);
|
|
22517
|
-
};
|
|
22518
|
-
server.once("error", onError);
|
|
22519
|
-
server.listen(port, host, () => {
|
|
22520
|
-
server.removeListener("error", onError);
|
|
22503
|
+
const onListening = () => {
|
|
22504
|
+
cleanup();
|
|
22521
22505
|
if (portFileDir) {
|
|
22522
22506
|
try {
|
|
22523
22507
|
const portFile = path.join(portFileDir, DEV_PORT_FILENAME);
|
|
22524
|
-
fs.writeFileSync(portFile,
|
|
22508
|
+
fs.writeFileSync(portFile, `${port} ${startPort}`, "utf-8");
|
|
22525
22509
|
} catch {}
|
|
22526
22510
|
writeStateFile(portFileDir, port, options?.serviceKey);
|
|
22527
22511
|
}
|
|
22528
22512
|
resolve(port);
|
|
22529
|
-
}
|
|
22513
|
+
};
|
|
22514
|
+
const onError = (err) => {
|
|
22515
|
+
cleanup();
|
|
22516
|
+
if (err.code === "EADDRINUSE") tryNext(index + 1);
|
|
22517
|
+
else reject(err);
|
|
22518
|
+
};
|
|
22519
|
+
function cleanup() {
|
|
22520
|
+
server.removeListener("listening", onListening);
|
|
22521
|
+
server.removeListener("error", onError);
|
|
22522
|
+
}
|
|
22523
|
+
server.once("error", onError);
|
|
22524
|
+
server.once("listening", onListening);
|
|
22525
|
+
server.listen(port, host);
|
|
22530
22526
|
}
|
|
22531
22527
|
tryNext(0);
|
|
22532
22528
|
});
|