@rebasepro/app 0.22.0 → 0.24.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/dist/auth/api.d.ts +2 -2
- package/dist/auth/session_caches.d.ts +26 -0
- package/dist/auth/types.d.ts +84 -1
- package/dist/collections/entity-display-cache.d.ts +1 -0
- package/dist/collections/filter-operator-resolution.d.ts +18 -0
- package/dist/collections/navigation_utils.d.ts +8 -2
- package/dist/collections/property_presentation.d.ts +12 -15
- package/dist/components/ConnectionLostBanner.d.ts +31 -0
- package/dist/components/LoginView/email-link.d.ts +37 -0
- package/dist/components/LoginView/index.d.ts +2 -0
- package/dist/components/LoginView/mfa-required.d.ts +33 -0
- package/dist/components/UserSelectPopover.d.ts +14 -1
- package/dist/components/common/useDataTableController.d.ts +1 -1
- package/dist/components/common/useScrollRestoration.d.ts +7 -0
- package/dist/components/email-change-message.d.ts +6 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/contexts/CollectionResolverContext.d.ts +11 -1
- package/dist/core/PluginLifecycleManager.d.ts +12 -4
- package/dist/debug.js +47 -40
- package/dist/hooks/data/collectionWindow.d.ts +133 -0
- package/dist/hooks/data/useStableFilterValues.d.ts +9 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/index.es.js +7008 -2951
- package/dist/index.es.js.map +1 -1
- package/dist/util/entity_cache.d.ts +11 -0
- package/dist/util/index.d.ts +1 -0
- package/dist/util/realtime.d.ts +18 -0
- package/dist/vitePlugin.d.ts +6 -0
- package/dist/vitePlugin.js +138 -15
- package/package.json +7 -7
|
@@ -20,6 +20,17 @@ export declare function removeEntityFromMemoryCache(path: string): void;
|
|
|
20
20
|
*/
|
|
21
21
|
export declare function saveEntityToMemoryCache(path: string, data: object): void;
|
|
22
22
|
export declare function getEntityFromMemoryCache(path: string): object | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Drops every edit in flight. They were parked by a user who is no longer
|
|
25
|
+
* signed in, so nobody is taking them over.
|
|
26
|
+
*/
|
|
27
|
+
export declare function clearEntityMemoryCache(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Drops the whole local-changes backup: every draft in `sessionStorage`, for
|
|
30
|
+
* every record. For when the drafts belong to somebody other than the user now
|
|
31
|
+
* signed in.
|
|
32
|
+
*/
|
|
33
|
+
export declare function clearEntityDrafts(): void;
|
|
23
34
|
/**
|
|
24
35
|
* Retrieves a entity from the local-changes backup in `sessionStorage`.
|
|
25
36
|
*
|
package/dist/util/index.d.ts
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether an error is the realtime client saying the connection is down —
|
|
3
|
+
* not that the data is gone.
|
|
4
|
+
*
|
|
5
|
+
* Once the socket has been down for longer than a blip, the SDK tells every
|
|
6
|
+
* live subscription `CONNECTION_LOST` through its `onError`, once, and keeps
|
|
7
|
+
* the subscription: when the socket is back it is re-subscribed and its next
|
|
8
|
+
* update carries what changed meanwhile. A view that already shows data should
|
|
9
|
+
* keep showing it (the admin's connection banner says it may be stale) rather
|
|
10
|
+
* than replace it with an error — for an open record that would unmount the
|
|
11
|
+
* form and everything typed into it.
|
|
12
|
+
*
|
|
13
|
+
* Read by `code` rather than `instanceof RebaseApiError`: two copies of
|
|
14
|
+
* `@rebasepro/types` in one tree disagree about the class, never about the code.
|
|
15
|
+
*
|
|
16
|
+
* @group Hooks and utilities
|
|
17
|
+
*/
|
|
18
|
+
export declare function isConnectionLostError(error: unknown): boolean;
|
package/dist/vitePlugin.d.ts
CHANGED
|
@@ -50,6 +50,12 @@ export declare function transformCollectionSource(code: string, id: string): {
|
|
|
50
50
|
* every call site.
|
|
51
51
|
*/
|
|
52
52
|
export declare function rebaseCollectionsPlugin(options: RebaseCollectionsPluginOptions): Plugin;
|
|
53
|
+
/**
|
|
54
|
+
* Whether a module id is a file inside `directory`, whichever separators
|
|
55
|
+
* either was written with. On a whole path segment, so `collections-old/` is
|
|
56
|
+
* not inside `collections`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isInsideDirectory(id: string, directory: string): boolean;
|
|
53
59
|
/**
|
|
54
60
|
* How the admin's dependencies are split into cached chunks.
|
|
55
61
|
*
|
package/dist/vitePlugin.js
CHANGED
|
@@ -2,12 +2,114 @@ import path from "path";
|
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import MagicString from "magic-string";
|
|
4
4
|
const LAZY_COMPONENT_KEYS = /* @__PURE__ */ new Set(["Field", "Preview", "Builder", "Filter", "Component"]);
|
|
5
|
-
function
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return
|
|
5
|
+
function unwrapObjectLiteral(expr) {
|
|
6
|
+
let current = expr;
|
|
7
|
+
while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isNonNullExpression(current)) {
|
|
8
|
+
current = current.expression;
|
|
9
|
+
}
|
|
10
|
+
return ts.isObjectLiteralExpression(current) ? current : void 0;
|
|
11
|
+
}
|
|
12
|
+
function callbackStripEdits(sourceFile) {
|
|
13
|
+
const edits = [];
|
|
14
|
+
const memberEdit = (member) => {
|
|
15
|
+
if (ts.isPropertyAssignment(member)) {
|
|
16
|
+
return { start: member.initializer.getStart(sourceFile), end: member.initializer.getEnd(), text: "undefined" };
|
|
17
|
+
}
|
|
18
|
+
if (ts.isSpreadAssignment(member)) {
|
|
19
|
+
return { start: member.getStart(sourceFile), end: member.getEnd(), text: "...undefined" };
|
|
20
|
+
}
|
|
21
|
+
const name = member.name;
|
|
22
|
+
return name ? { start: member.getStart(sourceFile), end: member.getEnd(), text: `${name.getText(sourceFile)}: undefined` } : void 0;
|
|
23
|
+
};
|
|
24
|
+
walkAST(sourceFile, (node) => {
|
|
25
|
+
if (ts.isShorthandPropertyAssignment(node) && node.name.text === "callbacks") {
|
|
26
|
+
edits.push({ start: node.getStart(sourceFile), end: node.getEnd(), text: "callbacks: undefined" });
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!ts.isPropertyAssignment(node) || getPropertyName(node) !== "callbacks") return;
|
|
30
|
+
const literal = unwrapObjectLiteral(node.initializer);
|
|
31
|
+
if (!literal) {
|
|
32
|
+
edits.push({ start: node.initializer.getStart(sourceFile), end: node.initializer.getEnd(), text: "undefined" });
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
for (const member of literal.properties) {
|
|
36
|
+
const edit = memberEdit(member);
|
|
37
|
+
if (edit) edits.push(edit);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return edits.filter((edit) => !edits.some((outer) => outer !== edit && outer.start <= edit.start && edit.end <= outer.end));
|
|
41
|
+
}
|
|
42
|
+
function isReference(id) {
|
|
43
|
+
const parent = id.parent;
|
|
44
|
+
if (!parent) return false;
|
|
45
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === id) return false;
|
|
46
|
+
if (ts.isQualifiedName(parent) && parent.right === id) return false;
|
|
47
|
+
if ((ts.isPropertyAssignment(parent) || ts.isMethodDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertySignature(parent) || ts.isMethodSignature(parent) || ts.isGetAccessorDeclaration(parent) || ts.isSetAccessorDeclaration(parent) || ts.isEnumMember(parent) || ts.isJsxAttribute(parent)) && parent.name === id) return false;
|
|
48
|
+
if ((ts.isVariableDeclaration(parent) || ts.isFunctionDeclaration(parent) || ts.isClassDeclaration(parent) || ts.isParameter(parent) || ts.isImportClause(parent) || ts.isNamespaceImport(parent) || ts.isBindingElement(parent) || ts.isFunctionExpression(parent) || ts.isClassExpression(parent) || ts.isTypeAliasDeclaration(parent) || ts.isInterfaceDeclaration(parent) || ts.isTypeParameterDeclaration(parent)) && parent.name === id) return false;
|
|
49
|
+
if (ts.isBindingElement(parent) && parent.propertyName === id) return false;
|
|
50
|
+
if (ts.isImportSpecifier(parent)) return false;
|
|
51
|
+
if (ts.isLabeledStatement(parent) || ts.isBreakOrContinueStatement(parent)) return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function deadTopLevelStatements(sourceFile, removed) {
|
|
55
|
+
const bindings = [];
|
|
56
|
+
for (const statement of sourceFile.statements) {
|
|
57
|
+
const exported = ts.canHaveModifiers(statement) && (ts.getModifiers(statement) ?? []).some((m) => m.kind === ts.SyntaxKind.ExportKeyword);
|
|
58
|
+
if (exported) continue;
|
|
59
|
+
if (ts.isImportDeclaration(statement)) {
|
|
60
|
+
const clause = statement.importClause;
|
|
61
|
+
if (!clause || clause.isTypeOnly) continue;
|
|
62
|
+
const names = [];
|
|
63
|
+
if (clause.name) names.push(clause.name.text);
|
|
64
|
+
const named = clause.namedBindings;
|
|
65
|
+
if (named && ts.isNamespaceImport(named)) names.push(named.name.text);
|
|
66
|
+
if (named && ts.isNamedImports(named)) {
|
|
67
|
+
for (const el of named.elements) if (!el.isTypeOnly) names.push(el.name.text);
|
|
68
|
+
}
|
|
69
|
+
if (names.length > 0) bindings.push({ statement, names });
|
|
70
|
+
} else if (ts.isVariableStatement(statement)) {
|
|
71
|
+
const names = [];
|
|
72
|
+
const collect = (name) => {
|
|
73
|
+
if (ts.isIdentifier(name)) names.push(name.text);
|
|
74
|
+
else for (const el of name.elements) if (!ts.isOmittedExpression(el)) collect(el.name);
|
|
75
|
+
};
|
|
76
|
+
for (const decl of statement.declarationList.declarations) collect(decl.name);
|
|
77
|
+
bindings.push({ statement, names });
|
|
78
|
+
} else if ((ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) && statement.name) {
|
|
79
|
+
bindings.push({ statement, names: [statement.name.text] });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (bindings.length === 0) return [];
|
|
83
|
+
const references = [];
|
|
84
|
+
walkAST(sourceFile, (node) => {
|
|
85
|
+
if (ts.isIdentifier(node) && isReference(node)) references.push(node);
|
|
86
|
+
});
|
|
87
|
+
const ranges = removed.map(({ start, end }) => ({ start, end }));
|
|
88
|
+
const within = (node) => {
|
|
89
|
+
const at = node.getStart(sourceFile);
|
|
90
|
+
return ranges.some((r) => r.start <= at && node.getEnd() <= r.end);
|
|
91
|
+
};
|
|
92
|
+
const dead = [];
|
|
93
|
+
for (let changed = true; changed; ) {
|
|
94
|
+
changed = false;
|
|
95
|
+
for (const binding of bindings) {
|
|
96
|
+
if (dead.includes(binding.statement)) continue;
|
|
97
|
+
let readByStripped = false;
|
|
98
|
+
let readLive = false;
|
|
99
|
+
for (const ref of references) {
|
|
100
|
+
if (!binding.names.includes(ref.text)) continue;
|
|
101
|
+
if (ref.getStart(sourceFile) >= binding.statement.getStart(sourceFile) && ref.getEnd() <= binding.statement.getEnd()) continue;
|
|
102
|
+
if (within(ref)) readByStripped = true;
|
|
103
|
+
else readLive = true;
|
|
104
|
+
}
|
|
105
|
+
if (readByStripped && !readLive) {
|
|
106
|
+
dead.push(binding.statement);
|
|
107
|
+
ranges.push({ start: binding.statement.getStart(sourceFile), end: binding.statement.getEnd() });
|
|
108
|
+
changed = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return dead;
|
|
11
113
|
}
|
|
12
114
|
function walkAST(node, visitor) {
|
|
13
115
|
visitor(node);
|
|
@@ -30,15 +132,22 @@ function transformCollectionSource(code, id) {
|
|
|
30
132
|
);
|
|
31
133
|
const ms = new MagicString(code);
|
|
32
134
|
let replaced = false;
|
|
135
|
+
const strips = callbackStripEdits(sourceFile);
|
|
136
|
+
for (const edit of strips) {
|
|
137
|
+
ms.overwrite(edit.start, edit.end, edit.text);
|
|
138
|
+
replaced = true;
|
|
139
|
+
}
|
|
140
|
+
const gone = [...strips];
|
|
141
|
+
for (const statement of deadTopLevelStatements(sourceFile, strips)) {
|
|
142
|
+
ms.remove(statement.getStart(sourceFile), statement.getEnd());
|
|
143
|
+
gone.push({ start: statement.getStart(sourceFile), end: statement.getEnd() });
|
|
144
|
+
replaced = true;
|
|
145
|
+
}
|
|
146
|
+
const stripped = (node) => gone.some((e) => e.start <= node.getStart(sourceFile) && node.getEnd() <= e.end);
|
|
33
147
|
walkAST(sourceFile, (node) => {
|
|
34
148
|
if (!ts.isPropertyAssignment(node)) return;
|
|
149
|
+
if (stripped(node)) return;
|
|
35
150
|
const name = getPropertyName(node);
|
|
36
|
-
if (name && isInsideCallbacksBlock(node)) {
|
|
37
|
-
const value = node.initializer;
|
|
38
|
-
ms.overwrite(value.getStart(sourceFile), value.getEnd(), "undefined");
|
|
39
|
-
replaced = true;
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
151
|
const propName = name;
|
|
43
152
|
if (!propName || !LAZY_COMPONENT_KEYS.has(propName)) return;
|
|
44
153
|
const init = node.initializer;
|
|
@@ -61,10 +170,13 @@ function rebaseCollectionsPlugin(options) {
|
|
|
61
170
|
const virtualModuleId = "virtual:rebase-collections";
|
|
62
171
|
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
63
172
|
let resolvedCollectionsDir;
|
|
173
|
+
let collectionsDirGlob;
|
|
64
174
|
return {
|
|
65
175
|
name: "rebase-collections-plugin",
|
|
66
176
|
configResolved(config) {
|
|
67
177
|
resolvedCollectionsDir = path.isAbsolute(options.collectionsDir) ? options.collectionsDir : path.resolve(config.root, options.collectionsDir);
|
|
178
|
+
const fromRoot = toModuleIdPath(path.relative(config.root, resolvedCollectionsDir));
|
|
179
|
+
collectionsDirGlob = fromRoot ? "/" + fromRoot : "";
|
|
68
180
|
},
|
|
69
181
|
/**
|
|
70
182
|
* Watch the collections directory itself, not just the files in it.
|
|
@@ -103,10 +215,13 @@ function rebaseCollectionsPlugin(options) {
|
|
|
103
215
|
},
|
|
104
216
|
load(id) {
|
|
105
217
|
if (id === resolvedVirtualModuleId) {
|
|
106
|
-
const
|
|
218
|
+
const globPatterns = [
|
|
219
|
+
`${collectionsDirGlob}/*.ts`,
|
|
220
|
+
`!${collectionsDirGlob}/*.test.*`
|
|
221
|
+
];
|
|
107
222
|
return `
|
|
108
223
|
// GENERATED BY @rebasepro/app Vite Plugin
|
|
109
|
-
const collectionModules = import.meta.glob(
|
|
224
|
+
const collectionModules = import.meta.glob(${JSON.stringify(globPatterns)}, { eager: true });
|
|
110
225
|
|
|
111
226
|
// index exports the directory's defaults, not a collection \u2014
|
|
112
227
|
// it has no default export, so it drops out of the list below.
|
|
@@ -159,12 +274,19 @@ function rebaseCollectionsPlugin(options) {
|
|
|
159
274
|
*/
|
|
160
275
|
transform(code, id) {
|
|
161
276
|
if (!resolvedCollectionsDir) return null;
|
|
162
|
-
if (!id
|
|
277
|
+
if (!isInsideDirectory(id, resolvedCollectionsDir)) return null;
|
|
163
278
|
if (!/\.tsx?$/.test(id)) return null;
|
|
164
279
|
return transformCollectionSource(code, id);
|
|
165
280
|
}
|
|
166
281
|
};
|
|
167
282
|
}
|
|
283
|
+
function toModuleIdPath(filePath) {
|
|
284
|
+
return filePath.replace(/\\/g, "/");
|
|
285
|
+
}
|
|
286
|
+
function isInsideDirectory(id, directory) {
|
|
287
|
+
const dir = toModuleIdPath(directory);
|
|
288
|
+
return toModuleIdPath(id).startsWith(dir.endsWith("/") ? dir : dir + "/");
|
|
289
|
+
}
|
|
168
290
|
function rebaseManualChunks(id) {
|
|
169
291
|
if (id.includes("commonjsHelpers") || id.includes("commonjs-dynamic-modules")) return "vendor-commonjs-helpers";
|
|
170
292
|
if (id.includes("exceljs")) return "vendor-exceljs";
|
|
@@ -190,6 +312,7 @@ function rebaseManualChunks(id) {
|
|
|
190
312
|
return void 0;
|
|
191
313
|
}
|
|
192
314
|
export {
|
|
315
|
+
isInsideDirectory,
|
|
193
316
|
rebaseCollectionsPlugin,
|
|
194
317
|
rebaseManualChunks,
|
|
195
318
|
transformCollectionSource
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/app",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Rebase core — framework-agnostic runtime for data-driven admin panels",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rebase",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
"magic-string": "^0.30.0",
|
|
64
64
|
"notistack": "^3.0.2",
|
|
65
65
|
"react-i18next": "^17.0.11",
|
|
66
|
-
"@rebasepro/cms-types": "0.
|
|
67
|
-
"@rebasepro/
|
|
68
|
-
"@rebasepro/
|
|
69
|
-
"@rebasepro/
|
|
70
|
-
"@rebasepro/
|
|
71
|
-
"@rebasepro/
|
|
66
|
+
"@rebasepro/cms-types": "0.24.0",
|
|
67
|
+
"@rebasepro/common": "0.24.0",
|
|
68
|
+
"@rebasepro/types": "0.24.0",
|
|
69
|
+
"@rebasepro/ui": "0.24.0",
|
|
70
|
+
"@rebasepro/utils": "0.24.0",
|
|
71
|
+
"@rebasepro/forms": "0.24.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"react": "^19.2.7",
|