@rebasepro/common 0.11.1-canary.gfadf355 → 0.12.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/index.es.js +247 -10
- package/dist/index.es.js.map +1 -1
- package/dist/util/index.d.ts +1 -0
- package/dist/util/pg-column-to-property.d.ts +25 -0
- package/package.json +3 -3
- package/src/util/auth-default-policies.ts +4 -4
- package/src/util/index.ts +1 -0
- package/src/util/junction-policies.ts +1 -1
- package/src/util/pg-column-to-property.ts +335 -0
- package/src/util/relations.ts +3 -3
package/dist/index.es.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ANONYMOUS_USER_ID, CANONICAL_TO_REST, DEFAULT_DATA_SOURCE_KEY, EntityReference, EntityRelation, NULL_OPS, REST_TO_CANONICAL, getDataSourceCapabilities, getDeclaredSubcollections, isManyToMany, isPostgresCollectionConfig, policy, toCanonicalOp } from "@rebasepro/types";
|
|
2
|
-
import { deepClone, generateForeignKeyName, getIn, getPolicyOperations, isDefaultFieldConfigId, mergeDeep, randomString, removeFunctions, toSnakeCase } from "@rebasepro/utils";
|
|
1
|
+
import { ANONYMOUS_USER_ID, CANONICAL_TO_REST, DEFAULT_DATA_SOURCE_KEY, EntityReference, EntityRelation, NULL_OPS, REST_TO_CANONICAL, getDataSourceCapabilities, getDeclaredSubcollections, isManyToMany, isPostgresCollectionConfig, isRelationalCollectionConfig, policy, toCanonicalOp } from "@rebasepro/types";
|
|
2
|
+
import { deepClone, generateForeignKeyName, getIn, getPolicyOperations, isDefaultFieldConfigId, mergeDeep, prettifyIdentifier, randomString, removeFunctions, toSnakeCase } from "@rebasepro/utils";
|
|
3
3
|
import jsonLogic from "json-logic-js";
|
|
4
4
|
import { deepEqual } from "fast-equals";
|
|
5
5
|
//#region src/util/common.ts
|
|
@@ -494,7 +494,7 @@ var _resolvedRelationsCache = /* @__PURE__ */ new WeakMap();
|
|
|
494
494
|
function resolveCollectionRelations(collection) {
|
|
495
495
|
const cached = _resolvedRelationsCache.get(collection);
|
|
496
496
|
if (cached) return cached;
|
|
497
|
-
if (!
|
|
497
|
+
if (!isRelationalCollectionConfig(collection)) return {};
|
|
498
498
|
const relations = {};
|
|
499
499
|
for (const relation of collection.relations ?? []) {
|
|
500
500
|
const resolved = resolveRelation(relation, collection);
|
|
@@ -510,7 +510,7 @@ function resolveCollectionRelations(collection) {
|
|
|
510
510
|
return relations;
|
|
511
511
|
}
|
|
512
512
|
function getTableName(collection) {
|
|
513
|
-
if (
|
|
513
|
+
if (isRelationalCollectionConfig(collection)) return collection.table ?? toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
514
514
|
return toSnakeCase(collection.slug) ?? toSnakeCase(collection.name);
|
|
515
515
|
}
|
|
516
516
|
function getTableVarName(tableName) {
|
|
@@ -1606,8 +1606,8 @@ function getIdPropertyName$1(collection) {
|
|
|
1606
1606
|
* Collections that opt out via `disableDefaultPolicies` are returned unchanged.
|
|
1607
1607
|
*/
|
|
1608
1608
|
function getEffectiveSecurityRules(collection) {
|
|
1609
|
-
const explicit = [...
|
|
1610
|
-
if (collection.disableDefaultPolicies) return explicit;
|
|
1609
|
+
const explicit = [...collection.securityRules ?? []];
|
|
1610
|
+
if (isPostgresCollectionConfig(collection) && collection.disableDefaultPolicies) return explicit;
|
|
1611
1611
|
const tableName = getTableName(collection);
|
|
1612
1612
|
const injected = [];
|
|
1613
1613
|
injected.push({
|
|
@@ -1649,8 +1649,8 @@ function getEffectiveSecurityRules(collection) {
|
|
|
1649
1649
|
* DDL, which policies are injected and how to take them off.
|
|
1650
1650
|
*/
|
|
1651
1651
|
function getInjectedSecurityRules(collection) {
|
|
1652
|
-
if (collection.disableDefaultPolicies) return [];
|
|
1653
|
-
const explicitCount = (
|
|
1652
|
+
if (isPostgresCollectionConfig(collection) && collection.disableDefaultPolicies) return [];
|
|
1653
|
+
const explicitCount = (collection.securityRules ?? []).length;
|
|
1654
1654
|
return getEffectiveSecurityRules(collection).slice(explicitCount);
|
|
1655
1655
|
}
|
|
1656
1656
|
//#endregion
|
|
@@ -1794,7 +1794,7 @@ function coversUpdate(rule) {
|
|
|
1794
1794
|
* stays locked (RLS is still enabled) until they write policies for it.
|
|
1795
1795
|
*/
|
|
1796
1796
|
function getJunctionSecurityRules(spec) {
|
|
1797
|
-
if (spec.declaringSides.every((side) => side.collection.disableDefaultPolicies)) return [];
|
|
1797
|
+
if (spec.declaringSides.every((side) => isPostgresCollectionConfig(side.collection) && side.collection.disableDefaultPolicies)) return [];
|
|
1798
1798
|
const rules = [];
|
|
1799
1799
|
rules.push({
|
|
1800
1800
|
name: `${spec.table}_default_admin_read`,
|
|
@@ -1947,6 +1947,243 @@ function buildConditionContext(params) {
|
|
|
1947
1947
|
* Apply PropertyConditions to a resolved property, evaluating all JSON Logic rules.
|
|
1948
1948
|
*/
|
|
1949
1949
|
//#endregion
|
|
1950
|
+
//#region src/util/pg-column-to-property.ts
|
|
1951
|
+
/**
|
|
1952
|
+
* Maps a PostgreSQL column data type to a Rebase property type.
|
|
1953
|
+
*/
|
|
1954
|
+
function pgTypeToRebaseProperty(column) {
|
|
1955
|
+
const { column_name, data_type, udt_name, is_nullable, column_default, enum_values } = column;
|
|
1956
|
+
const required = is_nullable === "NO";
|
|
1957
|
+
const prettifiedName = prettifyIdentifier(column_name);
|
|
1958
|
+
const isAutoId = column_default != null && (column_default.includes("nextval") || column_default.includes("gen_random_uuid") || column_default.includes("uuid_generate") || column_default.includes("identity"));
|
|
1959
|
+
if (data_type === "USER-DEFINED" && enum_values && enum_values.length > 0) return {
|
|
1960
|
+
type: "string",
|
|
1961
|
+
name: prettifiedName,
|
|
1962
|
+
enum: enum_values.map((v) => ({
|
|
1963
|
+
id: v,
|
|
1964
|
+
label: prettifyIdentifier(v)
|
|
1965
|
+
})),
|
|
1966
|
+
validation: required ? { required: true } : void 0
|
|
1967
|
+
};
|
|
1968
|
+
const dt = data_type.toLowerCase();
|
|
1969
|
+
switch (dt) {
|
|
1970
|
+
case "character varying":
|
|
1971
|
+
case "varchar":
|
|
1972
|
+
case "text":
|
|
1973
|
+
case "char":
|
|
1974
|
+
case "character":
|
|
1975
|
+
case "citext": {
|
|
1976
|
+
let colType = "varchar";
|
|
1977
|
+
if (dt === "text" || dt === "citext") colType = "text";
|
|
1978
|
+
if (dt === "char" || dt === "character") colType = "char";
|
|
1979
|
+
const prop = {
|
|
1980
|
+
type: "string",
|
|
1981
|
+
name: prettifiedName,
|
|
1982
|
+
columnType: colType,
|
|
1983
|
+
validation: required ? { required: true } : void 0
|
|
1984
|
+
};
|
|
1985
|
+
if (isAutoId) prop.isId = "manual";
|
|
1986
|
+
return prop;
|
|
1987
|
+
}
|
|
1988
|
+
case "uuid": {
|
|
1989
|
+
const prop = {
|
|
1990
|
+
type: "string",
|
|
1991
|
+
name: prettifiedName,
|
|
1992
|
+
validation: required ? { required: true } : void 0
|
|
1993
|
+
};
|
|
1994
|
+
if (isAutoId) prop.isId = "uuid";
|
|
1995
|
+
return prop;
|
|
1996
|
+
}
|
|
1997
|
+
case "integer":
|
|
1998
|
+
case "bigint":
|
|
1999
|
+
case "smallint": {
|
|
2000
|
+
const prop = {
|
|
2001
|
+
type: "number",
|
|
2002
|
+
name: prettifiedName,
|
|
2003
|
+
columnType: dt === "bigint" ? "bigint" : "integer",
|
|
2004
|
+
validation: {
|
|
2005
|
+
...required ? { required: true } : {},
|
|
2006
|
+
integer: true
|
|
2007
|
+
}
|
|
2008
|
+
};
|
|
2009
|
+
if (isAutoId) prop.isId = "increment";
|
|
2010
|
+
return prop;
|
|
2011
|
+
}
|
|
2012
|
+
case "serial":
|
|
2013
|
+
case "bigserial":
|
|
2014
|
+
case "smallserial": return {
|
|
2015
|
+
type: "number",
|
|
2016
|
+
name: prettifiedName,
|
|
2017
|
+
columnType: dt === "bigserial" ? "bigserial" : "serial",
|
|
2018
|
+
isId: "increment",
|
|
2019
|
+
validation: {
|
|
2020
|
+
...required ? { required: true } : {},
|
|
2021
|
+
integer: true
|
|
2022
|
+
}
|
|
2023
|
+
};
|
|
2024
|
+
case "numeric":
|
|
2025
|
+
case "decimal":
|
|
2026
|
+
case "real":
|
|
2027
|
+
case "double precision": {
|
|
2028
|
+
let colType = "numeric";
|
|
2029
|
+
if (dt === "real") colType = "real";
|
|
2030
|
+
if (dt === "double precision") colType = "double precision";
|
|
2031
|
+
return {
|
|
2032
|
+
type: "number",
|
|
2033
|
+
name: prettifiedName,
|
|
2034
|
+
columnType: colType,
|
|
2035
|
+
validation: required ? { required: true } : void 0
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
case "boolean": return {
|
|
2039
|
+
type: "boolean",
|
|
2040
|
+
name: prettifiedName,
|
|
2041
|
+
validation: required ? { required: true } : void 0
|
|
2042
|
+
};
|
|
2043
|
+
case "timestamp with time zone":
|
|
2044
|
+
case "timestamp without time zone":
|
|
2045
|
+
case "timestamp":
|
|
2046
|
+
case "timestamptz":
|
|
2047
|
+
case "date":
|
|
2048
|
+
case "time with time zone":
|
|
2049
|
+
case "time without time zone":
|
|
2050
|
+
case "time": {
|
|
2051
|
+
let colType = "timestamp";
|
|
2052
|
+
if (dt.startsWith("date")) colType = "date";
|
|
2053
|
+
if (dt.startsWith("time ") || dt === "time") colType = "time";
|
|
2054
|
+
return {
|
|
2055
|
+
type: "date",
|
|
2056
|
+
name: prettifiedName,
|
|
2057
|
+
columnType: colType,
|
|
2058
|
+
validation: required ? { required: true } : void 0
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
case "jsonb":
|
|
2062
|
+
case "json": return {
|
|
2063
|
+
type: "map",
|
|
2064
|
+
name: prettifiedName,
|
|
2065
|
+
columnType: dt === "jsonb" ? "jsonb" : "json",
|
|
2066
|
+
keyValue: true,
|
|
2067
|
+
properties: {}
|
|
2068
|
+
};
|
|
2069
|
+
case "array":
|
|
2070
|
+
case "ARRAY": {
|
|
2071
|
+
let innerType = "string";
|
|
2072
|
+
let colType = void 0;
|
|
2073
|
+
if (udt_name === "_text" || udt_name === "_varchar") {
|
|
2074
|
+
innerType = "string";
|
|
2075
|
+
colType = "text[]";
|
|
2076
|
+
} else if (udt_name === "_int4" || udt_name === "_int2" || udt_name === "_int8") {
|
|
2077
|
+
innerType = "number";
|
|
2078
|
+
colType = "integer[]";
|
|
2079
|
+
} else if (udt_name === "_bool") {
|
|
2080
|
+
innerType = "boolean";
|
|
2081
|
+
colType = "boolean[]";
|
|
2082
|
+
} else if (udt_name === "_numeric") {
|
|
2083
|
+
innerType = "number";
|
|
2084
|
+
colType = "numeric[]";
|
|
2085
|
+
}
|
|
2086
|
+
return {
|
|
2087
|
+
type: "array",
|
|
2088
|
+
name: prettifiedName,
|
|
2089
|
+
columnType: colType,
|
|
2090
|
+
of: { type: innerType }
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
default: return {
|
|
2094
|
+
type: "string",
|
|
2095
|
+
name: prettifiedName,
|
|
2096
|
+
validation: required ? { required: true } : void 0
|
|
2097
|
+
};
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
/**
|
|
2101
|
+
* Builds a collection description from PostgreSQL table metadata.
|
|
2102
|
+
* This is used when creating a new collection from an existing database table.
|
|
2103
|
+
*/
|
|
2104
|
+
function buildCollectionFromTableMetadata(tableName, metadata) {
|
|
2105
|
+
const properties = {};
|
|
2106
|
+
const propertiesOrder = [];
|
|
2107
|
+
const relations = [];
|
|
2108
|
+
const securityRules = [];
|
|
2109
|
+
for (const column of metadata.columns) {
|
|
2110
|
+
const property = pgTypeToRebaseProperty(column);
|
|
2111
|
+
if (property) {
|
|
2112
|
+
const propRecord = property;
|
|
2113
|
+
Object.keys(propRecord).forEach((key) => propRecord[key] === void 0 && delete propRecord[key]);
|
|
2114
|
+
properties[column.column_name] = property;
|
|
2115
|
+
propertiesOrder.push(column.column_name);
|
|
2116
|
+
}
|
|
2117
|
+
}
|
|
2118
|
+
if (metadata.foreignKeys) for (const fk of metadata.foreignKeys) {
|
|
2119
|
+
const relName = fk.column_name.endsWith("_id") ? fk.column_name.substring(0, fk.column_name.length - 3) : fk.column_name;
|
|
2120
|
+
relations.push({
|
|
2121
|
+
id: fk.column_name,
|
|
2122
|
+
relationName: relName,
|
|
2123
|
+
target: fk.foreign_table_name,
|
|
2124
|
+
kind: "belongsTo",
|
|
2125
|
+
localKey: fk.column_name
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
if (metadata.junctions) for (const junction of metadata.junctions) {
|
|
2129
|
+
const relName = junction.target_table_name;
|
|
2130
|
+
relations.push({
|
|
2131
|
+
id: junction.target_table_name + "_relation",
|
|
2132
|
+
relationName: relName,
|
|
2133
|
+
target: junction.target_table_name,
|
|
2134
|
+
kind: "manyToMany",
|
|
2135
|
+
through: {
|
|
2136
|
+
table: junction.junction_table_name,
|
|
2137
|
+
sourceColumn: junction.source_column_name,
|
|
2138
|
+
targetColumn: junction.target_column_name
|
|
2139
|
+
}
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
if (metadata.policies) for (const policy of metadata.policies) {
|
|
2143
|
+
let operations = [];
|
|
2144
|
+
switch (policy.cmd) {
|
|
2145
|
+
case "ALL":
|
|
2146
|
+
operations = ["all"];
|
|
2147
|
+
break;
|
|
2148
|
+
case "SELECT":
|
|
2149
|
+
operations = ["select"];
|
|
2150
|
+
break;
|
|
2151
|
+
case "INSERT":
|
|
2152
|
+
operations = ["insert"];
|
|
2153
|
+
break;
|
|
2154
|
+
case "UPDATE":
|
|
2155
|
+
operations = ["update"];
|
|
2156
|
+
break;
|
|
2157
|
+
case "DELETE":
|
|
2158
|
+
operations = ["delete"];
|
|
2159
|
+
break;
|
|
2160
|
+
}
|
|
2161
|
+
const qual = policy.qual ?? void 0;
|
|
2162
|
+
const withCheck = policy.with_check ?? void 0;
|
|
2163
|
+
if (qual) securityRules.push({
|
|
2164
|
+
name: policy.policy_name,
|
|
2165
|
+
operations,
|
|
2166
|
+
roles: policy.roles ?? [],
|
|
2167
|
+
using: qual,
|
|
2168
|
+
...withCheck ? { withCheck } : {}
|
|
2169
|
+
});
|
|
2170
|
+
else securityRules.push({
|
|
2171
|
+
name: policy.policy_name,
|
|
2172
|
+
operations,
|
|
2173
|
+
roles: policy.roles ?? []
|
|
2174
|
+
});
|
|
2175
|
+
}
|
|
2176
|
+
return {
|
|
2177
|
+
name: prettifyIdentifier(tableName),
|
|
2178
|
+
slug: tableName,
|
|
2179
|
+
table: tableName,
|
|
2180
|
+
properties,
|
|
2181
|
+
propertiesOrder,
|
|
2182
|
+
...relations.length > 0 ? { relations } : {},
|
|
2183
|
+
...securityRules.length > 0 ? { securityRules } : {}
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
//#endregion
|
|
1950
2187
|
//#region src/data/resolveDataSource.ts
|
|
1951
2188
|
/**
|
|
1952
2189
|
* Build a keyed registry from a list of {@link DataSourceDefinition}s.
|
|
@@ -3536,6 +3773,6 @@ async function detectJunctionTables(executeSql) {
|
|
|
3536
3773
|
return junctionTables;
|
|
3537
3774
|
}
|
|
3538
3775
|
//#endregion
|
|
3539
|
-
export { COLLECTION_PATH_SEPARATOR, COMPOSITE_ID_SEPARATOR, CollectionRegistry, DEFAULT_FIND_ALL_MAX_ROWS, DEFAULT_MAX_PAGES, DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE, DEFAULT_PAGE_SIZE, JUNCTION_TABLES_SQL, QueryBuilder, REBASE_INTERNAL_PREFIXES, REBASE_INTERNAL_SCHEMAS, RebasePaginationError, and, buildCollection, buildCompositeId, buildConditionContext, buildProperty, buildPropertyCallbacks, buildRebaseData, buildRoutedRebaseData, buildSdkData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, checkOperation, classifyTable, collectAllPages, cond, createDataSourceRegistry, createPaginationHelpers, createRelationRef, createRelationRefWithData, defaultUsersCollection, defineCollection, deserializeFilter, deserializeLogicalCondition, deserializeOrderBy, detectJunctionTables, embedParentExpression, enumToObjectEntries, evaluateCondition, evaluatePolicy, findAnonymousGrants, findRelation, fullPathToCollectionSegments, getArrayResolvedProperties, getColumnName, getDeclaredPrimaryKeys, getDefaultValueFor, getDefaultValueFortype, getDefaultValuesFor, getEffectiveSecurityRules, getEntityChildViews, getEnumVarName, getInjectedSecurityRules, getJunctionCollectionConfig, getJunctionSecurityRules, getLabelOrConfigFrom, getPrimaryKeys, getReferenceFrom, getRelationFrom, getSubcollections, getTableName, getTableVarName, isJunctionBackedRelation, isPropertyBuilder, isRebaseInternalTable, normalizeToEntityRelation, or, paginateFind, parseIdValues, policyToPostgres, registerConditionOperations, resolveArrayProperties, resolveCollectionRelations, resolveDataSource, resolveEnumValues, resolveJunctionSpecs, resolvePrimaryKeys, resolveProperties, resolveProperty, resolvePropertyEnum, resolveRelation, resolveRelationProperty, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, sanitizeData, securityRuleToConditions, segmentsToStrippedPath, serializeFilter, serializeLogicalCondition, serializeOrderBy, sortProperties, sqlToPolicy, stripCollectionPath, traverseValueProperty, traverseValuesProperties, updateDateAutoValues, wrapAsEntityData, wrapAsSdkData };
|
|
3776
|
+
export { COLLECTION_PATH_SEPARATOR, COMPOSITE_ID_SEPARATOR, CollectionRegistry, DEFAULT_FIND_ALL_MAX_ROWS, DEFAULT_MAX_PAGES, DEFAULT_ONE_OF_TYPE, DEFAULT_ONE_OF_VALUE, DEFAULT_PAGE_SIZE, JUNCTION_TABLES_SQL, QueryBuilder, REBASE_INTERNAL_PREFIXES, REBASE_INTERNAL_SCHEMAS, RebasePaginationError, and, buildCollection, buildCollectionFromTableMetadata, buildCompositeId, buildConditionContext, buildProperty, buildPropertyCallbacks, buildRebaseData, buildRoutedRebaseData, buildSdkData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, checkOperation, classifyTable, collectAllPages, cond, createDataSourceRegistry, createPaginationHelpers, createRelationRef, createRelationRefWithData, defaultUsersCollection, defineCollection, deserializeFilter, deserializeLogicalCondition, deserializeOrderBy, detectJunctionTables, embedParentExpression, enumToObjectEntries, evaluateCondition, evaluatePolicy, findAnonymousGrants, findRelation, fullPathToCollectionSegments, getArrayResolvedProperties, getColumnName, getDeclaredPrimaryKeys, getDefaultValueFor, getDefaultValueFortype, getDefaultValuesFor, getEffectiveSecurityRules, getEntityChildViews, getEnumVarName, getInjectedSecurityRules, getJunctionCollectionConfig, getJunctionSecurityRules, getLabelOrConfigFrom, getPrimaryKeys, getReferenceFrom, getRelationFrom, getSubcollections, getTableName, getTableVarName, isJunctionBackedRelation, isPropertyBuilder, isRebaseInternalTable, normalizeToEntityRelation, or, paginateFind, parseIdValues, policyToPostgres, registerConditionOperations, resolveArrayProperties, resolveCollectionRelations, resolveDataSource, resolveEnumValues, resolveJunctionSpecs, resolvePrimaryKeys, resolveProperties, resolveProperty, resolvePropertyEnum, resolveRelation, resolveRelationProperty, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, sanitizeData, securityRuleToConditions, segmentsToStrippedPath, serializeFilter, serializeLogicalCondition, serializeOrderBy, sortProperties, sqlToPolicy, stripCollectionPath, traverseValueProperty, traverseValuesProperties, updateDateAutoValues, wrapAsEntityData, wrapAsSdkData };
|
|
3540
3777
|
|
|
3541
3778
|
//# sourceMappingURL=index.es.js.map
|