@01.software/sdk 0.38.0 → 0.39.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/README.md +117 -34
- package/dist/analytics/react.cjs.map +1 -1
- package/dist/analytics/react.js.map +1 -1
- package/dist/analytics.cjs.map +1 -1
- package/dist/analytics.js.map +1 -1
- package/dist/client.cjs +1219 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +5 -4
- package/dist/client.d.ts +5 -4
- package/dist/client.js +1219 -5
- package/dist/client.js.map +1 -1
- package/dist/{collection-client-BroIWHY1.d.ts → collection-client-CaMgs5KE.d.ts} +14 -8
- package/dist/{collection-client-B0J9wMNE.d.cts → collection-client-DVfB0Em1.d.cts} +14 -8
- package/dist/errors.cjs +4 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js +4 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.cjs +2787 -2612
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2787 -2612
- package/dist/index.js.map +1 -1
- package/dist/query.cjs +241 -58
- package/dist/query.cjs.map +1 -1
- package/dist/query.d.cts +148 -23
- package/dist/query.d.ts +148 -23
- package/dist/query.js +241 -58
- package/dist/query.js.map +1 -1
- package/dist/realtime.cjs +5 -1
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.js +5 -1
- package/dist/realtime.js.map +1 -1
- package/dist/server.cjs +1149 -1
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +1149 -1
- package/dist/server.js.map +1 -1
- package/dist/storefront-cache.cjs +144 -0
- package/dist/storefront-cache.cjs.map +1 -0
- package/dist/storefront-cache.d.cts +24 -0
- package/dist/storefront-cache.d.ts +24 -0
- package/dist/storefront-cache.js +121 -0
- package/dist/storefront-cache.js.map +1 -0
- package/dist/{types-CIGscmus.d.cts → types-BQo7UdI9.d.cts} +181 -35
- package/dist/{types-D2xYdz4P.d.ts → types-CVf8sCZ-.d.ts} +181 -35
- package/dist/ui/canvas/server.cjs +5 -1
- package/dist/ui/canvas/server.cjs.map +1 -1
- package/dist/ui/canvas/server.js +5 -1
- package/dist/ui/canvas/server.js.map +1 -1
- package/dist/ui/canvas.cjs +5 -1
- package/dist/ui/canvas.cjs.map +1 -1
- package/dist/ui/canvas.js +5 -1
- package/dist/ui/canvas.js.map +1 -1
- package/package.json +13 -3
|
@@ -1194,7 +1194,8 @@ type ProductListingSwatch = {
|
|
|
1194
1194
|
href: string;
|
|
1195
1195
|
availableForSale: boolean;
|
|
1196
1196
|
};
|
|
1197
|
-
type
|
|
1197
|
+
type ProductListingCardSourceItem = ProductListingGroupsCatalogItem | ProductListingGroupsItem;
|
|
1198
|
+
type ProductListingCardRepresentativeVariant = ProductListingCardSourceItem['groups'][number]['variants'][number];
|
|
1198
1199
|
type ProductListingCard = {
|
|
1199
1200
|
id: EntityID;
|
|
1200
1201
|
href: string;
|
|
@@ -1353,7 +1354,7 @@ type ProductListingCardOptions = {
|
|
|
1353
1354
|
};
|
|
1354
1355
|
declare function buildProductHref(product: ProductHrefProduct, group?: ProductHrefGroup | null, options?: ProductHrefOptions): string;
|
|
1355
1356
|
declare function buildProductListingProjection(product: ProductListingProductShape | null | undefined, variants: ProductVariantShape[]): ProductListingProjection;
|
|
1356
|
-
declare function buildProductListingCard(item:
|
|
1357
|
+
declare function buildProductListingCard(item: ProductListingCardSourceItem, options?: ProductListingCardOptions): ProductListingCard;
|
|
1357
1358
|
/** Shopify `priceRangeV2` naming for persisted listing projection fields. */
|
|
1358
1359
|
declare function toShopifyPriceRangeV2(listing: {
|
|
1359
1360
|
minPrice?: number | null;
|
|
@@ -1367,33 +1368,22 @@ declare function toShopifyPriceRangeV2(listing: {
|
|
|
1367
1368
|
};
|
|
1368
1369
|
};
|
|
1369
1370
|
/**
|
|
1370
|
-
*
|
|
1371
|
+
* Server-side PLP query preset for raw `products` collection reads.
|
|
1371
1372
|
*
|
|
1372
|
-
*
|
|
1373
|
-
* `
|
|
1374
|
-
*
|
|
1375
|
-
*
|
|
1376
|
-
* `buildProductListingGroupsByOption()` then drops primary-option values with
|
|
1377
|
-
* no matching variant in the response — a common cause of missing color swatches
|
|
1378
|
-
* even when the product has more variants than the default join cap.
|
|
1373
|
+
* Greenfield storefronts should prefer
|
|
1374
|
+
* `client.commerce.product.listingPage()` because it calls the shaped catalog
|
|
1375
|
+
* endpoint, preserves pagination metadata, returns card-ready `cards`, and
|
|
1376
|
+
* avoids exposing inventory quantities.
|
|
1379
1377
|
*
|
|
1380
|
-
*
|
|
1378
|
+
* This preset remains only for server-auth raw product query code
|
|
1379
|
+
* that deliberately understands Payload join behavior. It raises top-level
|
|
1380
|
+
* `products.options` and `products.variants` join limits, but it cannot fix
|
|
1381
|
+
* nested `options[].values.docs` joins because the Payload REST `joins` param
|
|
1382
|
+
* is flat.
|
|
1381
1383
|
*
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1384
|
-
*
|
|
1385
|
-
* where: { status: { equals: 'published' } },
|
|
1386
|
-
* limit: 24,
|
|
1387
|
-
* })
|
|
1388
|
-
* ```
|
|
1389
|
-
*
|
|
1390
|
-
* **Limitation:** This preset cures top-level `products.options` and
|
|
1391
|
-
* `products.variants` join truncation. It cannot cure the nested
|
|
1392
|
-
* `options[].values.docs` join — the Payload REST `joins` param is flat and
|
|
1393
|
-
* nested join limits require the listing-groups endpoint. Prefer
|
|
1394
|
-
* `commerce.product.listingGroupsCatalog()` + `buildProductListingCard()` as
|
|
1395
|
-
* the primary PLP path; they apply unlimited join fetches server-side and
|
|
1396
|
-
* return pre-grouped data ready for rendering.
|
|
1384
|
+
* It is not accepted by publishable
|
|
1385
|
+
* `createClient().collections.from('products').find()` because browser-public
|
|
1386
|
+
* raw reads are constrained to `depth: 0`, `joins: false`, and no `populate`.
|
|
1397
1387
|
*/
|
|
1398
1388
|
declare const PRODUCT_PLP_FIND_OPTIONS: ApiQueryOptions;
|
|
1399
1389
|
/**
|
|
@@ -1530,16 +1520,37 @@ type ProductListingGroupsProductVariants = NonNullable<PublicProduct['variants']
|
|
|
1530
1520
|
type ProductListingGroupsProductPrimaryMediaItemId = string | number | {
|
|
1531
1521
|
id?: string | number | null;
|
|
1532
1522
|
} | null;
|
|
1533
|
-
type ProductListingGroupsProduct = Omit<PublicProduct, 'variants'> & {
|
|
1523
|
+
type ProductListingGroupsProduct = Omit<PublicProduct, 'createdAt' | 'primaryMediaItemId' | 'updatedAt' | 'variants'> & {
|
|
1534
1524
|
id: string;
|
|
1535
1525
|
slug: string;
|
|
1536
1526
|
title: string;
|
|
1527
|
+
createdAt?: PublicProduct['createdAt'];
|
|
1528
|
+
updatedAt?: PublicProduct['updatedAt'];
|
|
1537
1529
|
primaryMediaItemId?: ProductListingGroupsProductPrimaryMediaItemId;
|
|
1538
1530
|
variants?: (Omit<ProductListingGroupsProductVariants, 'docs'> & {
|
|
1539
1531
|
docs: ProductListingGroupVariant[];
|
|
1540
1532
|
}) | null;
|
|
1541
1533
|
};
|
|
1542
|
-
type
|
|
1534
|
+
type ProductListingGroupsCatalogListing = {
|
|
1535
|
+
minPrice?: NonNullable<ProductListingGroupsProduct['listing']>['minPrice'];
|
|
1536
|
+
maxPrice?: NonNullable<ProductListingGroupsProduct['listing']>['maxPrice'];
|
|
1537
|
+
minCompareAtPrice?: NonNullable<ProductListingGroupsProduct['listing']>['minCompareAtPrice'];
|
|
1538
|
+
maxCompareAtPrice?: NonNullable<ProductListingGroupsProduct['listing']>['maxCompareAtPrice'];
|
|
1539
|
+
isPriceRange?: NonNullable<ProductListingGroupsProduct['listing']>['isPriceRange'];
|
|
1540
|
+
primaryImage?: NonNullable<ProductListingGroupsProduct['listing']>['primaryImage'];
|
|
1541
|
+
availableForSale?: NonNullable<ProductListingGroupsProduct['listing']>['availableForSale'];
|
|
1542
|
+
selectionHintVariant?: NonNullable<ProductListingGroupsProduct['listing']>['selectionHintVariant'];
|
|
1543
|
+
};
|
|
1544
|
+
type ProductListingGroupsCatalogProduct = {
|
|
1545
|
+
id: string;
|
|
1546
|
+
slug: string;
|
|
1547
|
+
handle?: string | null;
|
|
1548
|
+
title: string;
|
|
1549
|
+
subtitle?: ProductListingGroupsProduct['subtitle'];
|
|
1550
|
+
primaryMediaItemId?: ProductListingGroupsProductPrimaryMediaItemId;
|
|
1551
|
+
thumbnail?: ProductListingGroupsProduct['thumbnail'];
|
|
1552
|
+
images?: ProductListingGroupsProduct['images'];
|
|
1553
|
+
listing?: ProductListingGroupsCatalogListing | null;
|
|
1543
1554
|
variants?: (Omit<NonNullable<ProductListingGroupsProduct['variants']>, 'docs'> & {
|
|
1544
1555
|
docs: ProductListingGroupCatalogVariant[];
|
|
1545
1556
|
}) | null;
|
|
@@ -1565,6 +1576,36 @@ type ProductListingGroupsResponse = {
|
|
|
1565
1576
|
type ProductListingGroupsCatalogResponse = Omit<ProductListingGroupsResponse, 'docs'> & {
|
|
1566
1577
|
docs: ProductListingGroupsCatalogItem[];
|
|
1567
1578
|
};
|
|
1579
|
+
type ProductListingPageSort = 'id' | '-id' | 'slug' | '-slug' | 'handle' | '-handle' | 'createdAt' | '-createdAt' | 'updatedAt' | '-updatedAt' | 'title' | '-title' | 'listing.minPrice' | '-listing.minPrice' | 'listing.maxPrice' | '-listing.maxPrice' | 'listing.availableForSale' | '-listing.availableForSale';
|
|
1580
|
+
type ProductListingPageFilters = {
|
|
1581
|
+
ids?: string[];
|
|
1582
|
+
slugs?: string[];
|
|
1583
|
+
handles?: string[];
|
|
1584
|
+
categoryIds?: string[];
|
|
1585
|
+
tagIds?: string[];
|
|
1586
|
+
price?: {
|
|
1587
|
+
min?: number;
|
|
1588
|
+
max?: number;
|
|
1589
|
+
};
|
|
1590
|
+
availableForSale?: boolean;
|
|
1591
|
+
};
|
|
1592
|
+
type ProductListingPageBaseParams = {
|
|
1593
|
+
page?: number;
|
|
1594
|
+
limit?: number;
|
|
1595
|
+
search?: string;
|
|
1596
|
+
sort?: ProductListingPageSort | ProductListingPageSort[];
|
|
1597
|
+
filters?: ProductListingPageFilters;
|
|
1598
|
+
} & ProductListingCardOptions;
|
|
1599
|
+
type ProductListingPageCatalogParams = ProductListingPageBaseParams & {
|
|
1600
|
+
mode?: 'catalog';
|
|
1601
|
+
};
|
|
1602
|
+
type ProductListingPageFullParams = ProductListingPageBaseParams & {
|
|
1603
|
+
mode: 'full';
|
|
1604
|
+
};
|
|
1605
|
+
type ProductListingPageParams = ProductListingPageCatalogParams | ProductListingPageFullParams;
|
|
1606
|
+
type ProductListingPageResult<TItem> = PayloadFindResponse<TItem> & {
|
|
1607
|
+
cards: ProductListingCard[];
|
|
1608
|
+
};
|
|
1568
1609
|
type ProductDetailParams = {
|
|
1569
1610
|
slug: string;
|
|
1570
1611
|
} | {
|
|
@@ -1778,6 +1819,9 @@ declare class ProductApi extends BaseApi {
|
|
|
1778
1819
|
stockSnapshot(params: StockSnapshotParams): Promise<StockSnapshotResponse>;
|
|
1779
1820
|
listingGroups(params: ListingGroupsParams): Promise<ProductListingGroupsResponse>;
|
|
1780
1821
|
listingGroupsCatalog(params: ListingGroupsParams): Promise<ProductListingGroupsCatalogResponse>;
|
|
1822
|
+
listingPage(params?: ProductListingPageCatalogParams): Promise<ProductListingPageResult<ProductListingGroupsCatalogItem>>;
|
|
1823
|
+
listingPage(params: ProductListingPageFullParams): Promise<ProductListingPageResult<ProductListingGroupsItem>>;
|
|
1824
|
+
listingPage(params: ProductListingPageParams): Promise<ProductListingPageResult<ProductListingGroupsCatalogItem> | ProductListingPageResult<ProductListingGroupsItem>>;
|
|
1781
1825
|
/**
|
|
1782
1826
|
* Fetch full product detail by slug or id.
|
|
1783
1827
|
* Returns a discriminated result so storefronts can distinguish missing,
|
|
@@ -1849,8 +1893,11 @@ declare class CommerceClient {
|
|
|
1849
1893
|
readonly product: {
|
|
1850
1894
|
stockCheck: (params: StockCheckParams) => Promise<StockCheckResponse>;
|
|
1851
1895
|
stockSnapshot: (params: StockSnapshotParams) => Promise<StockSnapshotResponse>;
|
|
1852
|
-
listingGroups: (params: ListingGroupsParams) => Promise<
|
|
1896
|
+
listingGroups: (params: ListingGroupsParams) => Promise<ProductListingGroupsCatalogResponse>;
|
|
1853
1897
|
listingGroupsCatalog: (params: ListingGroupsParams) => Promise<ProductListingGroupsCatalogResponse>;
|
|
1898
|
+
listingPage: {
|
|
1899
|
+
(params?: ProductListingPageCatalogParams): Promise<ProductListingPageResult<ProductListingGroupsCatalogItem>>;
|
|
1900
|
+
};
|
|
1854
1901
|
detail: (params: ProductDetailParams) => Promise<ProductDetailResult>;
|
|
1855
1902
|
detailCatalog: (params: ProductDetailParams) => Promise<ProductDetailCatalogResult>;
|
|
1856
1903
|
};
|
|
@@ -1884,6 +1931,85 @@ declare class CommerceClient {
|
|
|
1884
1931
|
constructor(options: CommerceClientOptions);
|
|
1885
1932
|
}
|
|
1886
1933
|
|
|
1934
|
+
type StorefrontContentReference = {
|
|
1935
|
+
id?: string | number | null;
|
|
1936
|
+
title?: string | null;
|
|
1937
|
+
name?: string | null;
|
|
1938
|
+
slug?: string | null;
|
|
1939
|
+
displayName?: string | null;
|
|
1940
|
+
handle?: string | null;
|
|
1941
|
+
color?: string | null;
|
|
1942
|
+
image?: PublicMediaAsset | null;
|
|
1943
|
+
thumbnail?: PublicMediaAsset | null;
|
|
1944
|
+
avatar?: PublicMediaAsset | null;
|
|
1945
|
+
};
|
|
1946
|
+
type StorefrontLink = {
|
|
1947
|
+
id?: string | number | null;
|
|
1948
|
+
title?: string | null;
|
|
1949
|
+
subtitle?: string | null;
|
|
1950
|
+
url?: string | null;
|
|
1951
|
+
description?: string | null;
|
|
1952
|
+
slug?: string | null;
|
|
1953
|
+
type?: 'external' | 'social' | 'internal' | string | null;
|
|
1954
|
+
platform?: string | null;
|
|
1955
|
+
opensInNewTab?: boolean | null;
|
|
1956
|
+
noFollow?: boolean | null;
|
|
1957
|
+
expiresAt?: string | null;
|
|
1958
|
+
isFeatured?: boolean | null;
|
|
1959
|
+
publishedAt?: string | null;
|
|
1960
|
+
createdAt?: string | null;
|
|
1961
|
+
updatedAt?: string | null;
|
|
1962
|
+
categories?: StorefrontContentReference[] | StorefrontContentReference | null;
|
|
1963
|
+
tags?: StorefrontContentReference[] | StorefrontContentReference | null;
|
|
1964
|
+
thumbnail?: PublicMediaAsset | null;
|
|
1965
|
+
icon?: PublicMediaAsset | null;
|
|
1966
|
+
};
|
|
1967
|
+
type StorefrontGalleryItem = {
|
|
1968
|
+
id?: string | number | null;
|
|
1969
|
+
title?: string | null;
|
|
1970
|
+
description?: string | null;
|
|
1971
|
+
content?: unknown;
|
|
1972
|
+
createdAt?: string | null;
|
|
1973
|
+
updatedAt?: string | null;
|
|
1974
|
+
gallery?: StorefrontContentReference | string | null;
|
|
1975
|
+
image?: PublicMediaAsset | null;
|
|
1976
|
+
};
|
|
1977
|
+
type StorefrontLinksSort = 'createdAt' | '-createdAt' | 'updatedAt' | '-updatedAt' | 'publishedAt' | '-publishedAt' | 'title' | '-title' | 'isFeatured' | '-isFeatured';
|
|
1978
|
+
type StorefrontGalleryItemsSort = 'manual' | 'createdAt' | '-createdAt' | 'updatedAt' | '-updatedAt' | 'title' | '-title';
|
|
1979
|
+
type StorefrontContentListOptions<TSort extends string = string> = {
|
|
1980
|
+
page?: number;
|
|
1981
|
+
limit?: number;
|
|
1982
|
+
sort?: TSort;
|
|
1983
|
+
};
|
|
1984
|
+
type StorefrontLinksListOptions = StorefrontContentListOptions<StorefrontLinksSort> & {
|
|
1985
|
+
categoryId?: string;
|
|
1986
|
+
categorySlug?: string;
|
|
1987
|
+
tagId?: string;
|
|
1988
|
+
tagSlug?: string;
|
|
1989
|
+
featured?: boolean;
|
|
1990
|
+
};
|
|
1991
|
+
type StorefrontGalleryItemsListOptions = StorefrontContentListOptions<StorefrontGalleryItemsSort> & ({
|
|
1992
|
+
galleryId: string;
|
|
1993
|
+
gallerySlug?: string;
|
|
1994
|
+
} | {
|
|
1995
|
+
galleryId?: string;
|
|
1996
|
+
gallerySlug: string;
|
|
1997
|
+
});
|
|
1998
|
+
type ContentClientOptions = {
|
|
1999
|
+
publishableKey: string;
|
|
2000
|
+
apiUrl?: string;
|
|
2001
|
+
onRequestId?: (id: string | null) => void;
|
|
2002
|
+
};
|
|
2003
|
+
declare class ContentClient {
|
|
2004
|
+
readonly links: {
|
|
2005
|
+
list: (options?: StorefrontLinksListOptions) => Promise<PayloadFindResponse<StorefrontLink>>;
|
|
2006
|
+
};
|
|
2007
|
+
readonly galleryItems: {
|
|
2008
|
+
list: (options: StorefrontGalleryItemsListOptions) => Promise<PayloadFindResponse<StorefrontGalleryItem>>;
|
|
2009
|
+
};
|
|
2010
|
+
constructor(options: ContentClientOptions);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1887
2013
|
interface ServerCommerceClientOptions {
|
|
1888
2014
|
publishableKey?: string;
|
|
1889
2015
|
secretKey: string;
|
|
@@ -1894,6 +2020,11 @@ declare class ServerCommerceClient {
|
|
|
1894
2020
|
readonly product: {
|
|
1895
2021
|
stockCheck: (params: StockCheckParams) => Promise<StockCheckResponse>;
|
|
1896
2022
|
listingGroups: (params: ListingGroupsParams) => Promise<ProductListingGroupsResponse>;
|
|
2023
|
+
listingPage: {
|
|
2024
|
+
(params?: ProductListingPageCatalogParams): Promise<ProductListingPageResult<ProductListingGroupsCatalogItem>>;
|
|
2025
|
+
(params: ProductListingPageFullParams): Promise<ProductListingPageResult<ProductListingGroupsItem>>;
|
|
2026
|
+
(params: ProductListingPageParams): Promise<ProductListingPageResult<ProductListingGroupsCatalogItem> | ProductListingPageResult<ProductListingGroupsItem>>;
|
|
2027
|
+
};
|
|
1897
2028
|
detail: (params: ProductDetailParams) => Promise<ProductDetailResult>;
|
|
1898
2029
|
previewDetail: (params: ProductDetailPreviewParams, options: ProductDetailPreviewOptions) => Promise<ProductDetail | null>;
|
|
1899
2030
|
upsert: (params: ProductUpsertParams) => Promise<ProductUpsertResponse>;
|
|
@@ -2332,6 +2463,20 @@ interface ApiQueryOptions {
|
|
|
2332
2463
|
/** Include soft-deleted documents (requires `trash` enabled on the collection) */
|
|
2333
2464
|
trash?: boolean;
|
|
2334
2465
|
}
|
|
2466
|
+
type PublicReadQueryOptions = Omit<ApiQueryOptions, 'depth' | 'joins' | 'populate'> & {
|
|
2467
|
+
/**
|
|
2468
|
+
* Publishable collection reads stay unpopulated. Use shaped commerce/community
|
|
2469
|
+
* endpoints or a server client when populated relations are required.
|
|
2470
|
+
*/
|
|
2471
|
+
depth?: 0;
|
|
2472
|
+
/**
|
|
2473
|
+
* Publishable collection reads disable Payload join fields to avoid accidental
|
|
2474
|
+
* exposure and expensive generic list responses.
|
|
2475
|
+
*/
|
|
2476
|
+
joins?: false;
|
|
2477
|
+
/** Publishable collection reads do not support relationship populate maps. */
|
|
2478
|
+
populate?: never;
|
|
2479
|
+
};
|
|
2335
2480
|
interface DebugConfig {
|
|
2336
2481
|
logRequests?: boolean;
|
|
2337
2482
|
logResponses?: boolean;
|
|
@@ -2342,14 +2487,14 @@ interface RetryConfig {
|
|
|
2342
2487
|
retryableStatuses?: number[];
|
|
2343
2488
|
retryDelay?: (attempt: number) => number;
|
|
2344
2489
|
}
|
|
2345
|
-
interface RootQueryLookup<T extends string> {
|
|
2346
|
-
find(options?:
|
|
2347
|
-
findById(id: string | number, options?:
|
|
2348
|
-
count(options?:
|
|
2490
|
+
interface RootQueryLookup<T extends string, Options extends ApiQueryOptions = ApiQueryOptions> {
|
|
2491
|
+
find(options?: Options): Promise<PayloadFindResponse<CollectionType<T>>>;
|
|
2492
|
+
findById(id: string | number, options?: Options): Promise<CollectionType<T>>;
|
|
2493
|
+
count(options?: Options): Promise<{
|
|
2349
2494
|
totalDocs: number;
|
|
2350
2495
|
}>;
|
|
2351
2496
|
}
|
|
2352
|
-
type RootReadOnlyQueryBuilder<T extends PublicCollection> = RootQueryLookup<T>;
|
|
2497
|
+
type RootReadOnlyQueryBuilder<T extends PublicCollection> = RootQueryLookup<T, PublicReadQueryOptions>;
|
|
2353
2498
|
interface RootServerQueryBuilder<T extends ServerCollection> extends RootQueryLookup<T> {
|
|
2354
2499
|
create(data: Partial<CollectionType<T>>, options?: {
|
|
2355
2500
|
file?: File | Blob;
|
|
@@ -2372,6 +2517,7 @@ interface RootServerCollectionClient {
|
|
|
2372
2517
|
interface RootClient {
|
|
2373
2518
|
commerce: CommerceClient;
|
|
2374
2519
|
community: CommunityClient;
|
|
2520
|
+
content: ContentClient;
|
|
2375
2521
|
/** Set on {@link createClient} return values; optional for structural mocks. */
|
|
2376
2522
|
events?: EventsClient;
|
|
2377
2523
|
customer: CustomerNamespace;
|
|
@@ -2409,4 +2555,4 @@ type DeepPartial<T> = {
|
|
|
2409
2555
|
};
|
|
2410
2556
|
type ExtractArrayType<T> = T extends (infer U)[] ? U : never;
|
|
2411
2557
|
|
|
2412
|
-
export { type
|
|
2558
|
+
export { type CollectionFieldSchema as $, type AddItemParams as A, type RootReadOnlyQueryBuilder as B, CommerceClient as C, type DebugConfig as D, EventsClient as E, type StorefrontContentListOptions as F, type StorefrontContentReference as G, type StorefrontGalleryItem as H, type StorefrontGalleryItemsListOptions as I, type StorefrontGalleryItemsSort as J, type StorefrontLink as K, type StorefrontLinksListOptions as L, type StorefrontLinksSort as M, BaseApi as N, type ServerApiOptions as O, type PayloadFindResponse as P, ServerCommerceClient as Q, type RemoveDiscountParams as R, type Sort as S, type TenantIntrospectionClient as T, type UpdateItemParams as U, type BanCustomerParams as V, type Where as W, type CommunityBan as X, type UnbanCustomerParams as Y, type ClientServerConfig as Z, type RootServerClientWithEvents as _, CommunityClient as a, type CalculateShippingResult as a$, type CollectionSchemaResponse as a0, type EventGuestCancelParams as a1, type EventGuestRegistration as a2, type EventGuestRegistrationResponse as a3, type EventRegistrationAnswerInput as a4, type EventRegistrationAttendeeInput as a5, type EventRegistrationPublic as a6, type EventRegistrationRegisterParams as a7, type EventRegistrationRegisterResponse as a8, type EventsCalendarItem as a9, type CustomerAuthResponse as aA, type CustomerLoginData as aB, type CustomerRegisterResponse as aC, type CustomerRegisterData as aD, type CustomerRefreshResponse as aE, type UpdateProfileData as aF, type ProductListingPageBaseParams as aG, type ProductListingPageParams as aH, type ProductDetailParams as aI, type ProductDetailResult as aJ, type ProductListingPageCatalogParams as aK, type ProductListingPageResult as aL, type ProductListingGroupsCatalogItem as aM, type ProductListingPageFullParams as aN, type ProductListingGroupsItem as aO, type ProductDetail as aP, type ProductDetailCatalog as aQ, type StockSnapshotResponse as aR, type ProductSelectionMediaSource as aS, type ProductDisplayMediaSource as aT, type ResolveProductSelectionMediaInput as aU, type ResolveProductSelectionMediaResult as aV, type ProductSelectionMediaPointer as aW, type RootClientWithEvents as aX, type BulkImportFulfillmentsParams as aY, type BulkImportFulfillmentsResponse as aZ, type CalculateShippingParams as a_, type EventsClientOptions as aa, type EventsDateParam as ab, type EventsExternalSource as ac, type EventsLocation as ad, type EventsOccurrenceLocation as ae, type EventsRangeEvent as af, type EventsRangeOccurrence as ag, type EventsRangeParams as ah, type EventsRangeResponse as ai, type EventsTaxonomyItem as aj, ModerationApi as ak, type RootServerClient as al, type TenantFeatureProgressEvidenceValue as am, type TenantFeatureProgressFeature as an, type TenantFeatureProgressGroup as ao, type TenantFeatureProgressInput as ap, type TenantFeatureProgressItem as aq, type TenantFeatureProgressItemState as ar, type TenantFeatureProgressResponse as as, type TenantFeatureProgressSeverity as at, type TenantFeatureProgressStatus as au, TenantIntrospectionApi as av, type TenantIntrospectionApiOptions as aw, type PublicReadQueryOptions as ax, CustomerAuth as ay, type CustomerProfile as az, ContentClient as b, type ProductListingCard as b$, type CancelOrderParams as b0, type CancelOrderReconciliationStatus as b1, type CancelOrderResponse as b2, type CancelReasonCode as b3, CartApi as b4, type CartApiOptions as b5, type Comment as b6, type CommerceClientOptions as b7, type CommunityClientOptions as b8, type CommunityComment as b9, type OrderApiOptions as bA, PRODUCT_PLP_FIND_OPTIONS as bB, PRODUCT_UPSERT_READONLY_FIELD_REASON as bC, PRODUCT_UPSERT_UNKNOWN_FIELD_REASON as bD, type PrepareFulfillmentOrderParams as bE, type PrepareFulfillmentOrderResponse as bF, ProductApi as bG, type ProductApiOptions as bH, type ProductDetailBrand as bI, type ProductDetailCatalogListing as bJ, type ProductDetailCatalogResult as bK, type ProductDetailCatalogVariant as bL, type ProductDetailCategory as bM, type ProductDetailImage as bN, type ProductDetailImageMedia as bO, type ProductDetailListing as bP, type ProductDetailMedia as bQ, type ProductDetailOption as bR, type ProductDetailOptionValue as bS, type ProductDetailTag as bT, type ProductDetailUnavailableReason as bU, type ProductDetailVariant as bV, type ProductDetailVariantOptionValue as bW, type ProductDetailVideo as bX, type ProductHrefGroup as bY, type ProductHrefOptions as bZ, type ProductHrefProduct as b_, type CommunityCommentListSort as ba, type CommunityPost as bb, type CommunityPostCategory as bc, type CommunityPostListSort as bd, type CommunityPostTag as be, type CommunityPublicAuthorSnapshot as bf, type CommunityPublicMediaAsset as bg, type CommunityPublicReference as bh, type CompatibilityProductSelectionParamEvent as bi, type ConfirmPaymentParams as bj, type ConfirmPaymentResponse as bk, type CreateFulfillmentParams as bl, type CreateOrderItem as bm, type CreateOrderParams as bn, type CreateReturnParams as bo, type CustomerAuthOptions as bp, type CustomerSnapshot as bq, DiscountApi as br, type DiscountApiOptions as bs, type LegacyProductSelectionParamEvent as bt, type ListingGroupsParams as bu, type ListingPrimaryImageFallbackInput as bv, type MediaValue as bw, type NormalizedOptionSwatch as bx, type NormalizedProductSelection as by, OrderApi as bz, CustomerNamespace as c, type UpdateTransactionParams as c$, type ProductListingCardOptions as c0, type ProductListingCardPriceRange as c1, type ProductListingCardRepresentativeVariant as c2, type ProductListingGroup as c3, type ProductListingGroupCatalogSummary as c4, type ProductListingGroupCatalogVariant as c5, type ProductListingGroupSummary as c6, type ProductListingGroupVariant as c7, type ProductListingGroupsCatalogListing as c8, type ProductListingGroupsCatalogProduct as c9, type ProductSelectionUrlEmit as cA, type ProductSelectionVariant as cB, type ProductUpsertFieldValidationErrorBody as cC, type ProductUpsertFieldValidationErrorReason as cD, type ProductVariantShape as cE, type RequestOptions as cF, type ResolveCancelRefundFailedResponse as cG, type ResolveCancelRefundOutcome as cH, type ResolveCancelRefundParams as cI, type ResolveCancelRefundResponse as cJ, type ResolveCancelRefundSucceededResponse as cK, type ResolveProductDisplayMediaInput as cL, type ResolveProductDisplayMediaResult as cM, type ReturnItem as cN, type ReturnReason as cO, type ReturnWithRefundItem as cP, type ReturnWithRefundParams as cQ, ShippingApi as cR, type ShippingApiOptions as cS, type StockCheckParams as cT, type StockCheckResponse as cU, type StockCheckResult as cV, type StockSnapshotItem as cW, type StockSnapshotParams as cX, type UpdateFulfillmentParams as cY, type UpdateOrderParams as cZ, type UpdateReturnParams as c_, type ProductListingGroupsCatalogResponse as ca, type ProductListingGroupsProduct as cb, type ProductListingGroupsResponse as cc, type ProductListingPageFilters as cd, type ProductListingPageSort as ce, type ProductListingProductShape as cf, type ProductListingProjection as cg, type ProductListingSwatch as ch, type ProductMediaResolutionSource as ci, type ProductOptionMatrix as cj, type ProductOptionMatrixOption as ck, type ProductOptionMatrixValue as cl, type ProductOptionMatrixVariant as cm, type ProductOptionShape as cn, type ProductOptionValueShape as co, type ProductOptionValueSwatch as cp, type ProductOptionValueSwatchInput as cq, type ProductSelectionAvailableSwatch as cr, type ProductSelectionAvailableValue as cs, type ProductSelectionByOptionValue as ct, ProductSelectionCodecError as cu, type ProductSelectionCodecOptions as cv, type ProductSelectionInput as cw, type ProductSelectionOptionValue as cx, type ProductSelectionResolution as cy, type ProductSelectionResolutionContext as cz, type ClientState as d, type ValidateDiscountParams as d0, type ValidateDiscountResult as d1, type WithIdempotencyKey as d2, buildProductHref as d3, buildProductListingCard as d4, buildProductListingGroupsByOption as d5, buildProductListingProjection as d6, buildProductOptionMatrix as d7, buildProductOptionMatrixFromDetail as d8, createProductSelectionCodec as d9, getAvailableOptionValues as da, getProductSelectionImages as db, getSelectedValueByOptionId as dc, isProductUpsertFieldValidationErrorBody as dd, normalizeProductSelection as de, normalizeProductSelectionFromMatrix as df, normalizeSelectedValueIds as dg, parseProductSelection as dh, resolveListingPrimaryImagePointer as di, resolveProductDisplayMedia as dj, resolveProductSelection as dk, resolveProductSelectionFromMatrix as dl, resolveProductSelectionMedia as dm, resolveVariantForSelection as dn, selectNext as dp, selectedSwatchMediaItemId as dq, stringifyProductSelection as dr, toShopifyPriceRangeV2 as ds, type ClientConfig as e, type ApiQueryOptions as f, type ApplyDiscountParams as g, type CheckoutParams as h, type ClearCartParams as i, type ClientMetadata as j, type ContentClientOptions as k, type DeepPartial as l, type ExtractArrayType as m, type PayloadMutationResponse as n, type PublicCart as o, type PublicCartItem as p, type PublicCartReference as q, type PublicMediaAsset as r, type PublicMediaSize as s, type PublicOrder as t, type PublicOrderItem as u, type PublicOrderReference as v, type RemoveItemParams as w, type RetryConfig as x, type RootClient as y, type RootCollectionClient as z };
|
|
@@ -52,7 +52,11 @@ function collectionKeys(collection) {
|
|
|
52
52
|
details: () => [collection, "detail"],
|
|
53
53
|
detail: (id, options) => [collection, "detail", id, options],
|
|
54
54
|
infinites: () => [collection, "infinite"],
|
|
55
|
-
infinite: (options) => [
|
|
55
|
+
infinite: (options, pageSize) => [
|
|
56
|
+
collection,
|
|
57
|
+
"infinite",
|
|
58
|
+
pageSize === void 0 ? options : { ...options, limit: pageSize }
|
|
59
|
+
]
|
|
56
60
|
};
|
|
57
61
|
}
|
|
58
62
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/ui/Canvas/server.ts","../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/css-sanitizer.ts","../../../src/ui/Canvas/catalog-mappers.ts"],"sourcesContent":["// Server-safe exports (no 'use client' directive).\n// Use `@01.software/sdk/ui/canvas/server` for server components and route loaders.\n\nexport { prefetchCanvas } from './prefetchCanvas'\nexport type { PrefetchCanvasOptions } from './prefetchCanvas'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport type {\n CanvasData,\n CanvasNode,\n CanvasEdge,\n CanvasViewport,\n CanvasNodePosition,\n CanvasNodeData,\n DynamicNodeData,\n FrameNodeData,\n CanvasBounds,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { sanitizeCSS, validateTenantCSS } from './css-sanitizer'\nexport { toEdgeTypeDef, toNodeTypeDef } from './catalog-mappers'\n","import type { ServerCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\n\nexport function collectionKeys<T extends ServerCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>) =>\n [collection, 'infinite', options] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsCatalog: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'catalog', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'infinite', options] as const,\n listingGroupsCatalogInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n ) =>\n ['products', 'listing-groups', 'catalog', 'infinite', options] as const,\n detail: (params: { slug: string } | { id: string }) =>\n ['products', 'detail', params] as const,\n detailAll: () => ['products', 'detail'] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './client-types'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.collections.from('canvases').findById(id)\n const result = await client.collections.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.collections.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.collections.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './client-types'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\ninterface CanvasPrefetchQueryClient {\n prefetchQuery(options: unknown): Promise<unknown>\n}\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** React Query client to prefetch into. */\n queryClient: CanvasPrefetchQueryClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, queryClient, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, queryClient, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { width: number; height: number } {\n const style = node.style as { width?: number; height?: number } | undefined\n\n return {\n width:\n style?.width ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n style?.height ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: CanvasEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: CanvasBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n }\n}\n","export type CanvasStyle = object\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\n parentId?: string\n style?: CanvasStyle\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface CanvasEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: CanvasStyle\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'date'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n editorIntent?: 'text' | 'image'\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n isDefaultEdge?: boolean\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n /** Whether this node is currently selected */\n selected?: boolean\n /** Measured node width (undefined before first measurement) */\n width?: number\n /** Measured node height (undefined before first measurement) */\n height?: number\n /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */\n defaultRender?: unknown\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n width?: number\n height?: number\n children?: unknown\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: CanvasStyle\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: unknown\n}\n\n// S8: Viewport focus\nexport interface CanvasBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import postcss from 'postcss'\n\nconst ALLOWED_AT_RULES = new Set([\n 'keyframes',\n 'media',\n 'supports',\n 'container',\n 'layer',\n])\nconst BLOCKED_VALUE_PATTERNS = [\n /url\\s*\\(/i,\n /expression\\s*\\(/i,\n /paint\\s*\\(/i,\n /-moz-binding/i,\n]\nconst DANGEROUS_SELECTOR = /(?:^|[\\s,])(?::root|html|body)\\b/\nconst BLOCKED_PROPERTY_VALUES: Record<string, RegExp> = {\n // absolute is allowed — contained by nearest positioned ancestor (node wrapper)\n position: /fixed|sticky/i,\n}\nconst TENANT_CSS_BLOCKED_PATTERNS = [\n { pattern: /<\\/style/i, label: '</style' },\n { pattern: /<script/i, label: '<script' },\n { pattern: /@import/i, label: '@import' },\n { pattern: /url\\s*\\(/i, label: 'url(' },\n] as const\nconst Z_INDEX_MAX = 9998\n\ntype SanitizeCSSStats = {\n css: string\n removedRules: number\n removedDecls: number\n removedAtRules: number\n}\n\nfunction normalizeCSSEscapes(value: string): string {\n return value.replace(\n /\\\\(?:([0-9a-fA-F]{1,6})(?:\\r\\n|[ \\t\\r\\n\\f])?|([^\\r\\n\\f]))/g,\n (match, hex: string | undefined, escaped: string | undefined) => {\n if (hex) {\n const cp = parseInt(hex, 16)\n if (Number.isNaN(cp) || cp > 0x10ffff) return match\n try {\n return String.fromCodePoint(cp)\n } catch {\n return match\n }\n }\n return escaped ?? match\n },\n )\n}\n\n/**\n * Sanitize tenant-authored CSS using PostCSS AST parsing.\n *\n * - At-rules: allowlist only (@keyframes, @media, @supports, @container, @layer)\n * - Declarations: blocks url(), expression(), paint(), -moz-binding\n * - Selectors: removes :root/html/body targets; scopes remainder under scopeClass\n *\n * Returns empty string on parse failure (fail-closed).\n *\n * @param css - Raw CSS string from tenant\n * @param scopeClass - Container class to scope selectors (e.g. 'flow-node--my-type')\n */\nexport function sanitizeCSS(css: string, scopeClass?: string): string {\n return sanitizeCSSWithStats(css, scopeClass).css\n}\n\nfunction sanitizeCSSWithStats(\n css: string,\n scopeClass?: string,\n): SanitizeCSSStats {\n let root: postcss.Root\n try {\n root = postcss.parse(css)\n } catch {\n return { css: '', removedRules: 0, removedDecls: 0, removedAtRules: 0 }\n }\n const stats: SanitizeCSSStats = {\n css: '',\n removedRules: 0,\n removedDecls: 0,\n removedAtRules: 0,\n }\n\n // Compute safe scope class once (strip CSS metacharacters and whitespace)\n const safeScopeClass = scopeClass\n ? scopeClass.replace(/[{}()[\\];,'\"\\\\<>\\s]/g, '')\n : ''\n\n // @keyframes name scoping (skip when no scope)\n const keyframeNameMap = new Map<string, string>()\n if (safeScopeClass) {\n root.walkAtRules(/^keyframes$/i, (node) => {\n // Strip surrounding quotes; replace spaces with underscores for valid identifier output\n // e.g. @keyframes \"fade in\" → flow-node--slug__fade_in\n const rawName = node.params.trim().replace(/^['\"]|['\"]$/g, '')\n const originalName = rawName // keep spaces for map key lookup\n const scopedName = `${safeScopeClass}__${rawName.replace(/\\s+/g, '_')}`\n keyframeNameMap.set(originalName, scopedName)\n node.params = scopedName\n })\n }\n\n // Rewrite animation-name / animation shorthand to use scoped keyframe names\n if (safeScopeClass && keyframeNameMap.size > 0) {\n const ANIM_KEYWORDS = new Set([\n 'none',\n 'initial',\n 'inherit',\n 'unset',\n 'revert',\n ])\n // Strip quotes from token before map lookup (animation-name: 'fade' → look up 'fade')\n const replaceAnimName = (token: string) => {\n const t = token.trim().replace(/^['\"]|['\"]$/g, '')\n return ANIM_KEYWORDS.has(t) ? token : (keyframeNameMap.get(t) ?? token)\n }\n // Use regex filter for case-insensitive match (Animation:, ANIMATION-NAME:)\n root.walkDecls(/^animation-name$/i, (node) => {\n node.value = node.value.split(',').map(replaceAnimName).join(', ')\n })\n root.walkDecls(/^animation$/i, (node) => {\n node.value = node.value\n .split(',')\n .map((anim) =>\n anim\n .split(/(\\s+)/)\n .map((token) => (/\\s/.test(token) ? token : replaceAnimName(token)))\n .join(''),\n )\n .join(',')\n })\n }\n\n // At-rules: remove anything not in the allowlist\n root.walkAtRules((node) => {\n if (!ALLOWED_AT_RULES.has(node.name.toLowerCase())) {\n stats.removedAtRules++\n node.remove()\n }\n })\n\n // Declarations: remove dangerous values\n root.walkDecls((node) => {\n // Normalize value: strip CSS block comments so fi/**/xed → fixed (browser behaviour)\n const normalizedValue = normalizeCSSEscapes(\n node.value.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''),\n )\n if (BLOCKED_VALUE_PATTERNS.some((p) => p.test(normalizedValue))) {\n stats.removedDecls++\n node.remove()\n return\n }\n // Block dangerous property+value combinations (position: fixed/sticky, oversized z-index)\n const propLower = node.prop.toLowerCase()\n const blockedValuePattern = BLOCKED_PROPERTY_VALUES[propLower]\n if (blockedValuePattern) {\n if (blockedValuePattern.test(normalizedValue)) {\n stats.removedDecls++\n node.remove()\n return\n }\n }\n if (propLower === 'z-index') {\n const zv = node.value.trim()\n // Allow CSS-wide keywords and 'auto'\n if (\n zv === 'auto' ||\n zv === 'initial' ||\n zv === 'inherit' ||\n zv === 'unset' ||\n zv === 'revert'\n ) {\n // pass through\n } else {\n // Only allow plain integers ≤ Z_INDEX_MAX. calc(), var(), and non-integers are removed.\n const val = parseInt(zv, 10)\n if (isNaN(val) || String(val) !== zv || val > Z_INDEX_MAX) {\n stats.removedDecls++\n node.remove()\n return\n }\n }\n }\n })\n\n // Rules: strip dangerous selectors, then scope the rest\n root.walkRules((rule) => {\n const safeSelectors = rule.selectors.filter(\n (s) => s.trim() && !DANGEROUS_SELECTOR.test(s),\n )\n if (!safeSelectors.length) {\n stats.removedRules++\n rule.remove()\n return\n }\n if (safeSelectors.length !== rule.selectors.length) {\n stats.removedRules++\n }\n rule.selectors = safeSelectors\n if (scopeClass) {\n if (!safeScopeClass) {\n stats.removedRules++\n rule.remove()\n return\n }\n // Skip scoping inside @keyframes — from/to/0% are not element selectors\n const parent = rule.parent\n if (\n parent?.type === 'atrule' &&\n (parent as postcss.AtRule).name.toLowerCase() === 'keyframes'\n ) {\n return\n }\n rule.selectors = rule.selectors.map((sel) => `.${safeScopeClass} ${sel}`)\n }\n })\n\n // Post-process: escape </style to prevent HTML parser closing the style tag in SSR contexts.\n // postcss parses this as valid CSS string content and reproduces it verbatim.\n stats.css = root.toString().replace(/<\\/style/gi, '<\\\\/style')\n return stats\n}\n\nexport function validateTenantCSS(css: string): string | null {\n const trimmed = css.trim()\n if (!trimmed) return null\n\n const deescapedCSS = normalizeCSSEscapes(css)\n for (const { pattern, label } of TENANT_CSS_BLOCKED_PATTERNS) {\n if (pattern.test(deescapedCSS)) {\n return `CSS contains blocked pattern: ${label}`\n }\n }\n\n try {\n postcss.parse(css)\n } catch {\n return 'CSS parse error'\n }\n\n const sanitized = sanitizeCSSWithStats(\n css,\n 'flow-node--tenant-css-validation',\n )\n if (!sanitized.css.trim()) {\n return 'CSS must contain safe rules'\n }\n if (\n sanitized.removedRules > 0 ||\n sanitized.removedDecls > 0 ||\n sanitized.removedAtRules > 0\n ) {\n return 'CSS contains unsafe rules or selectors'\n }\n\n return null\n}\n","import type { EdgeTypeDef, NodeTypeDef } from './types'\n\nexport function toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n editorIntent:\n doc.editorIntent === 'text' || doc.editorIntent === 'image'\n ? doc.editorIntent\n : undefined,\n transparentBackground: Boolean(\n doc.hasTransparentBackground ?? doc.transparentBackground,\n ),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nexport function toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated:\n (doc.isAnimated as boolean | undefined) ??\n (doc.animated as boolean | undefined) ??\n false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n isDefaultEdge: Boolean(doc.isDefaultEdge),\n }\n}\n"],"mappings":"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","names":["postcss"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/Canvas/server.ts","../../../src/core/query/query-keys.ts","../../../src/ui/Canvas/query-options.ts","../../../src/ui/Canvas/prefetchCanvas.ts","../../../src/ui/Canvas/utils.ts","../../../src/ui/Canvas/types.ts","../../../src/ui/Canvas/css-sanitizer.ts","../../../src/ui/Canvas/catalog-mappers.ts"],"sourcesContent":["// Server-safe exports (no 'use client' directive).\n// Use `@01.software/sdk/ui/canvas/server` for server components and route loaders.\n\nexport { prefetchCanvas } from './prefetchCanvas'\nexport type { PrefetchCanvasOptions } from './prefetchCanvas'\nexport { getNodeBounds, getFrames, getFrameData } from './utils'\nexport type { FrameData } from './utils'\nexport type {\n CanvasData,\n CanvasNode,\n CanvasEdge,\n CanvasViewport,\n CanvasNodePosition,\n CanvasNodeData,\n DynamicNodeData,\n FrameNodeData,\n CanvasBounds,\n NodeTypeDef,\n NodeTypeFieldDef,\n EdgeTypeDef,\n} from './types'\nexport { isDynamicNode, isFrameNode } from './types'\nexport { sanitizeCSS, validateTenantCSS } from './css-sanitizer'\nexport { toEdgeTypeDef, toNodeTypeDef } from './catalog-mappers'\n","import type { ServerCollection, ApiQueryOptions } from '../client/types'\nimport type { ProductListingPageParams } from '../api'\nimport type { ProductListingGroupsQueryOptions } from './query-hooks'\n\ntype ProductListingPageKeyParams = {\n mode: 'catalog' | 'full'\n page?: number\n limit?: number\n search?: string\n sort?: ProductListingPageParams['sort']\n filters?: NonNullable<ProductListingPageParams['filters']>\n basePath?: string\n trailingSlash?: boolean\n emit?: ProductListingPageParams['emit']\n preferCompleteVariantFromHint?: ProductListingPageParams[\n 'preferCompleteVariantFromHint'\n ]\n}\n\nfunction nonEmpty(values: string[] | undefined): string[] | undefined {\n return values?.length ? values : undefined\n}\n\nfunction canonicalProductListingPageParams(\n params: ProductListingPageParams = {},\n limit?: number,\n): ProductListingPageKeyParams {\n const filters = params.filters\n const canonicalFilters: NonNullable<ProductListingPageParams['filters']> = {}\n const ids = nonEmpty(filters?.ids)\n if (ids) canonicalFilters.ids = ids\n const slugs = nonEmpty(filters?.slugs)\n if (slugs) canonicalFilters.slugs = slugs\n const handles = nonEmpty(filters?.handles)\n if (handles) canonicalFilters.handles = handles\n const categoryIds = nonEmpty(filters?.categoryIds)\n if (categoryIds) canonicalFilters.categoryIds = categoryIds\n const tagIds = nonEmpty(filters?.tagIds)\n if (tagIds) canonicalFilters.tagIds = tagIds\n if (filters?.price?.min != null || filters?.price?.max != null) {\n canonicalFilters.price = {\n ...(filters.price.min != null && { min: filters.price.min }),\n ...(filters.price.max != null && { max: filters.price.max }),\n }\n }\n if (filters?.availableForSale != null) {\n canonicalFilters.availableForSale = filters.availableForSale\n }\n\n const search = params.search?.trim()\n return {\n mode: params.mode ?? 'catalog',\n ...(params.page != null && { page: params.page }),\n ...(limit != null\n ? { limit }\n : params.limit != null\n ? { limit: params.limit }\n : {}),\n ...(search && { search }),\n ...(params.sort != null && { sort: params.sort }),\n ...(Object.keys(canonicalFilters).length > 0 && {\n filters: canonicalFilters,\n }),\n ...(params.basePath != null && { basePath: params.basePath }),\n ...(params.trailingSlash != null && { trailingSlash: params.trailingSlash }),\n ...(params.emit != null && { emit: params.emit }),\n ...(params.preferCompleteVariantFromHint != null && {\n preferCompleteVariantFromHint: params.preferCompleteVariantFromHint,\n }),\n }\n}\n\nexport function collectionKeys<T extends ServerCollection>(collection: T) {\n return {\n all: [collection] as const,\n lists: () => [collection, 'list'] as const,\n list: (options?: ApiQueryOptions) => [collection, 'list', options] as const,\n details: () => [collection, 'detail'] as const,\n detail: (id: string, options?: ApiQueryOptions) =>\n [collection, 'detail', id, options] as const,\n infinites: () => [collection, 'infinite'] as const,\n infinite: (options?: Omit<ApiQueryOptions, 'page'>, pageSize?: number) =>\n [\n collection,\n 'infinite',\n pageSize === undefined ? options : { ...options, limit: pageSize },\n ] as const,\n }\n}\n\nexport const customerKeys = {\n all: ['customer'] as const,\n me: () => ['customer', 'me'] as const,\n}\n\nexport const productKeys = {\n listingGroups: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'list', options] as const,\n listingGroupsCatalog: (options?: ProductListingGroupsQueryOptions) =>\n ['products', 'listing-groups', 'catalog', options] as const,\n listingGroupsInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n pageSize?: number,\n ) =>\n [\n 'products',\n 'listing-groups',\n 'infinite',\n pageSize === undefined ? options : { ...options, limit: pageSize },\n ] as const,\n listingGroupsCatalogInfinite: (\n options?: Omit<ProductListingGroupsQueryOptions, 'page' | 'limit'>,\n pageSize?: number,\n ) =>\n [\n 'products',\n 'listing-groups',\n 'catalog',\n 'infinite',\n pageSize === undefined ? options : { ...options, limit: pageSize },\n ] as const,\n listingPage: (params?: ProductListingPageParams) =>\n ['products', 'listing-page', canonicalProductListingPageParams(params)] as const,\n listingPageInfinite: (\n params?: Omit<ProductListingPageParams, 'page' | 'limit'>,\n pageSize?: number,\n ) =>\n [\n 'products',\n 'listing-page',\n 'infinite',\n canonicalProductListingPageParams(\n params as ProductListingPageParams | undefined,\n pageSize,\n ),\n ] as const,\n detail: (params: { slug: string } | { id: string }) =>\n ['products', 'detail', params] as const,\n detailAll: () => ['products', 'detail'] as const,\n}\n","import { collectionKeys } from '../../core/query/query-keys'\nimport type { SDKClient } from './client-types'\n\nexport function canvasQueryOptions(\n client: SDKClient,\n slug?: string,\n id?: string,\n) {\n const identifier = id ?? slug ?? ''\n return {\n queryKey: collectionKeys('canvases').detail(identifier),\n queryFn: async () => {\n if (id) return client.collections.from('canvases').findById(id)\n const result = await client.collections.from('canvases').find({\n where: { slug: { equals: slug } },\n limit: 1,\n })\n const doc = result.docs[0]\n if (!doc) throw new Error(`Canvas not found: ${slug}`)\n return doc\n },\n }\n}\n\nexport function nodeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-node-types').lists(),\n queryFn: async () => {\n // limit: 0 = fetch all documents (Payload CMS convention, disables pagination)\n const result = await client.collections.from('canvas-node-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n\nexport function edgeTypesQueryOptions(client: SDKClient) {\n return {\n queryKey: collectionKeys('canvas-edge-types').lists(),\n queryFn: async () => {\n const result = await client.collections.from('canvas-edge-types').find({ limit: 0 })\n return result.docs\n },\n }\n}\n","import type { SDKClient } from './client-types'\nimport {\n canvasQueryOptions,\n nodeTypesQueryOptions,\n edgeTypesQueryOptions,\n} from './query-options'\n\ninterface CanvasPrefetchQueryClient {\n prefetchQuery(options: unknown): Promise<unknown>\n}\n\nexport interface PrefetchCanvasOptions {\n /** SDK client instance (Client or ServerClient) */\n client: SDKClient\n /** React Query client to prefetch into. */\n queryClient: CanvasPrefetchQueryClient\n /** Canvas slug (URL-friendly identifier) */\n slug?: string\n /** Canvas document ID (UUID) */\n id?: string\n}\n\n/**\n * Prefetch canvas data into the query cache.\n * Call in route loaders or server components to eliminate loading states on mount.\n *\n * ```ts\n * // React Router loader / Server Component\n * await prefetchCanvas({ client, queryClient, slug: 'Home' })\n * ```\n */\nexport async function prefetchCanvas(\n options: PrefetchCanvasOptions,\n): Promise<void> {\n const { client, queryClient, slug, id } = options\n\n if (!slug && !id) {\n throw new Error('prefetchCanvas requires either slug or id')\n }\n\n await Promise.all([\n queryClient.prefetchQuery(canvasQueryOptions(client, slug, id)),\n queryClient.prefetchQuery(nodeTypesQueryOptions(client)),\n queryClient.prefetchQuery(edgeTypesQueryOptions(client)),\n ])\n}\n","import type { CanvasNode, CanvasEdge, CanvasBounds, CanvasData } from './types'\n\n// ── Shared helpers ──\n\nfunction getNodeSize(node: CanvasNode): { width: number; height: number } {\n const style = node.style as { width?: number; height?: number } | undefined\n\n return {\n width:\n style?.width ??\n node.measured?.width ??\n node.width ??\n 200,\n height:\n style?.height ??\n node.measured?.height ??\n node.height ??\n 200,\n }\n}\n\nfunction getAbsolutePosition(\n node: CanvasNode,\n nodeMap: Map<string, CanvasNode>,\n): { x: number; y: number } {\n let x = node.position.x\n let y = node.position.y\n let current = node\n const visited = new Set<string>([node.id])\n while (current.parentId) {\n const parentId = current.parentId\n if (visited.has(parentId)) break\n const parent = nodeMap.get(parentId)\n if (!parent) break\n visited.add(parent.id)\n x += parent.position.x\n y += parent.position.y\n current = parent\n }\n return { x, y }\n}\n\n/** Collect a node and all its descendants using a pre-built parent→children map (O(N)). */\nfunction collectDescendants(\n nodes: CanvasNode[],\n rootId: string,\n): Set<string> {\n // Build parent → children lookup in O(N)\n const childrenMap = new Map<string, string[]>()\n for (const n of nodes) {\n if (n.parentId) {\n let siblings = childrenMap.get(n.parentId)\n if (!siblings) {\n siblings = []\n childrenMap.set(n.parentId, siblings)\n }\n siblings.push(n.id)\n }\n }\n\n // BFS over children map in O(descendants)\n const result = new Set<string>([rootId])\n const queue = [rootId]\n let i = 0\n while (i < queue.length) {\n const children = childrenMap.get(queue[i++]!)\n if (children) {\n for (const childId of children) {\n if (!result.has(childId)) {\n result.add(childId)\n queue.push(childId)\n }\n }\n }\n }\n return result\n}\n\n// ── Public utilities ──\n\n/**\n * Calculate bounding box for given node IDs.\n * Pure function — usable in SSR, server components, or outside React.\n */\nexport function getNodeBounds(\n nodes: CanvasNode[],\n nodeIds: string[],\n): CanvasBounds | undefined {\n const idSet = new Set(nodeIds)\n const targetNodes = nodes.filter((n) => idSet.has(n.id))\n if (targetNodes.length === 0) return undefined\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n for (const node of targetNodes) {\n const abs = getAbsolutePosition(node, nodeMap)\n const { width: w, height: h } = getNodeSize(node)\n minX = Math.min(minX, abs.x)\n minY = Math.min(minY, abs.y)\n maxX = Math.max(maxX, abs.x + w)\n maxY = Math.max(maxY, abs.y + h)\n }\n\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/**\n * Get all frame nodes with their bounds.\n * Sorted by position (top-left to bottom-right).\n */\nexport function getFrames(\n nodes: CanvasNode[],\n): Array<{ id: string; label: string; bounds: CanvasBounds }> {\n const frames = nodes.filter((n) => n.type === 'frame')\n if (frames.length === 0) return []\n\n const nodeMap = new Map(nodes.map((n) => [n.id, n]))\n\n return frames\n .map((f) => {\n const data = f.data as { label?: string }\n const abs = getAbsolutePosition(f, nodeMap)\n const { width: w, height: h } = getNodeSize(f)\n return {\n id: f.id,\n label: data.label ?? '',\n bounds: { x: abs.x, y: abs.y, width: w, height: h },\n }\n })\n .sort((a, b) => a.bounds.y - b.bounds.y || a.bounds.x - b.bounds.x)\n}\n\n/** Result of getFrameData — contains filtered canvas + dual bounds. */\nexport interface FrameData {\n /** Canvas data containing only the frame's descendants (nodes have draggable: false). */\n data: CanvasData\n /** Bounding box of child content nodes — use for initial viewport fit (centering). */\n fitBounds: CanvasBounds\n /** Bounding box of the frame itself — use for panning/zoom restriction (clamp). */\n clampBounds: CanvasBounds\n}\n\n/**\n * Extract a frame's descendants and related edges from canvas data.\n * Recursively collects all nested children (supports nested frames).\n * Returns undefined if frameId is not found or is not a frame node.\n *\n * Child nodes are marked `draggable: false` to prevent interfering with canvas panning.\n * The frame node itself is included (use `frameRenderer={() => null}` to hide it).\n *\n * Returns dual bounds:\n * - `fitBounds`: child content bounding box (for centering the viewport)\n * - `clampBounds`: frame area bounding box (for panning restriction)\n */\nexport function getFrameData(\n data: CanvasData,\n frameId: string,\n): FrameData | undefined {\n const frame = data.nodes.find((n) => n.id === frameId)\n if (!frame || frame.type !== 'frame') return undefined\n\n // Recursively collect frame + all descendants\n const descendantIds = collectDescendants(data.nodes, frameId)\n const childNodes = data.nodes\n .filter((n) => descendantIds.has(n.id))\n .map((n) => ({ ...n, draggable: false }))\n\n // Keep only edges where both source and target are within the frame\n const childEdges = data.edges.filter(\n (e: CanvasEdge) => descendantIds.has(e.source) && descendantIds.has(e.target),\n )\n\n // clampBounds: frame's own bounding box (for panning restriction)\n const frameBounds = getNodeBounds(data.nodes, [frameId])\n const { width: w, height: h } = getNodeSize(frame)\n const clampBounds: CanvasBounds = frameBounds ?? {\n x: frame.position.x,\n y: frame.position.y,\n width: w,\n height: h,\n }\n\n // fitBounds: child content bounding box (for centering)\n const contentNodeIds = childNodes\n .filter((n) => n.id !== frameId)\n .map((n) => n.id)\n const contentBounds = contentNodeIds.length > 0\n ? getNodeBounds(data.nodes, contentNodeIds)\n : undefined\n const fitBounds = contentBounds ?? clampBounds\n\n return {\n data: {\n nodes: childNodes,\n edges: childEdges,\n viewport: data.viewport,\n },\n fitBounds,\n clampBounds,\n }\n}\n","export type CanvasStyle = object\n\n// ── Dynamic node data ──\n\nexport interface DynamicNodeData {\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n}\n\nexport type CanvasNodeData = (DynamicNodeData | FrameNodeData) &\n Record<string, unknown>\n\n// ── Canvas types (mirrors @xyflow/react but standalone) ──\n\nexport interface CanvasNodePosition {\n x: number\n y: number\n}\n\nexport interface CanvasNode {\n id: string\n type?: string\n position: CanvasNodePosition\n data: CanvasNodeData\n parentId?: string\n style?: CanvasStyle\n width?: number\n height?: number\n measured?: { width?: number; height?: number }\n draggable?: boolean\n selectable?: boolean\n [key: string]: unknown\n}\n\nexport interface CanvasEdge {\n id: string\n source: string\n target: string\n sourceHandle?: string | null\n targetHandle?: string | null\n type?: string\n style?: CanvasStyle\n animated?: boolean\n markerStart?: unknown\n markerEnd?: unknown\n edgeTypeSlug?: string\n fields?: Record<string, unknown>\n [key: string]: unknown\n}\n\nexport interface CanvasViewport {\n x: number\n y: number\n zoom: number\n}\n\nexport interface CanvasData {\n nodes: CanvasNode[]\n edges: CanvasEdge[]\n viewport: CanvasViewport\n}\n\n// ── Node type definitions (mirrors console's NodeTypeDef) ──\n\nexport interface NodeTypeFieldDef {\n name: string\n label: string\n fieldType:\n | 'text'\n | 'textarea'\n | 'number'\n | 'url'\n | 'color'\n | 'image'\n | 'date'\n | 'select'\n | 'toggle'\n options?: { label: string; value: string }[]\n defaultValue?: string\n required?: boolean\n}\n\nexport interface NodeTypeDef {\n slug: string\n name: string\n color: string\n defaultSize: { width: number; height: number }\n fields: NodeTypeFieldDef[]\n editorIntent?: 'text' | 'image'\n transparentBackground?: boolean\n template?: string | null\n customCSS?: string | null\n}\n\n// ── Edge type definitions (mirrors console's EdgeTypeDef) ──\n\nexport interface EdgeTypeDef {\n slug: string\n name: string\n color: string\n strokeWidth: number\n animated: boolean\n lineStyle: string\n markerStart: string\n markerEnd: string\n fields: NodeTypeFieldDef[]\n isDefaultEdge?: boolean\n}\n\n// ── Type guards ──\n\nexport function isDynamicNode(\n node: CanvasNode,\n): node is CanvasNode & { data: DynamicNodeData } {\n return node.type === 'dynamic'\n}\n\nexport function isFrameNode(\n node: CanvasNode,\n): node is CanvasNode & { data: FrameNodeData } {\n return node.type === 'frame'\n}\n\n// ── Component slot props ──\n\nexport interface DynamicNodeSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n fields: Record<string, unknown>\n nodeTypeDef?: NodeTypeDef\n /** Whether this node is currently selected */\n selected?: boolean\n /** Measured node width (undefined before first measurement) */\n width?: number\n /** Measured node height (undefined before first measurement) */\n height?: number\n /** The default rendering (template or field-based). Allows custom renderers to wrap/extend instead of replacing entirely. */\n defaultRender?: unknown\n}\n\n// ── Frame node data ──\n\nexport interface FrameNodeData {\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n}\n\n// S1: Frame renderer slot\nexport interface FrameNodeSlotProps {\n id: string\n label: string\n color?: string\n padding?: number\n borderStyle?: 'dashed' | 'solid' | 'none'\n opacity?: number\n width?: number\n height?: number\n children?: unknown\n}\n\n// S2: Edge renderer slot\nexport interface EdgeSlotProps {\n id: string\n edgeTypeSlug?: string\n source: string\n target: string\n label?: string\n fields?: Record<string, unknown>\n edgeTypeDef?: EdgeTypeDef\n style?: CanvasStyle\n}\n\n// S3: Node wrapper slot\nexport interface NodeWrapperSlotProps {\n id: string\n nodeTypeSlug: string\n label: string\n selected?: boolean\n nodeTypeDef?: NodeTypeDef\n children: unknown\n}\n\n// S8: Viewport focus\nexport interface CanvasBounds {\n x: number\n y: number\n width: number\n height: number\n}\n","import postcss from 'postcss'\n\nconst ALLOWED_AT_RULES = new Set([\n 'keyframes',\n 'media',\n 'supports',\n 'container',\n 'layer',\n])\nconst BLOCKED_VALUE_PATTERNS = [\n /url\\s*\\(/i,\n /expression\\s*\\(/i,\n /paint\\s*\\(/i,\n /-moz-binding/i,\n]\nconst DANGEROUS_SELECTOR = /(?:^|[\\s,])(?::root|html|body)\\b/\nconst BLOCKED_PROPERTY_VALUES: Record<string, RegExp> = {\n // absolute is allowed — contained by nearest positioned ancestor (node wrapper)\n position: /fixed|sticky/i,\n}\nconst TENANT_CSS_BLOCKED_PATTERNS = [\n { pattern: /<\\/style/i, label: '</style' },\n { pattern: /<script/i, label: '<script' },\n { pattern: /@import/i, label: '@import' },\n { pattern: /url\\s*\\(/i, label: 'url(' },\n] as const\nconst Z_INDEX_MAX = 9998\n\ntype SanitizeCSSStats = {\n css: string\n removedRules: number\n removedDecls: number\n removedAtRules: number\n}\n\nfunction normalizeCSSEscapes(value: string): string {\n return value.replace(\n /\\\\(?:([0-9a-fA-F]{1,6})(?:\\r\\n|[ \\t\\r\\n\\f])?|([^\\r\\n\\f]))/g,\n (match, hex: string | undefined, escaped: string | undefined) => {\n if (hex) {\n const cp = parseInt(hex, 16)\n if (Number.isNaN(cp) || cp > 0x10ffff) return match\n try {\n return String.fromCodePoint(cp)\n } catch {\n return match\n }\n }\n return escaped ?? match\n },\n )\n}\n\n/**\n * Sanitize tenant-authored CSS using PostCSS AST parsing.\n *\n * - At-rules: allowlist only (@keyframes, @media, @supports, @container, @layer)\n * - Declarations: blocks url(), expression(), paint(), -moz-binding\n * - Selectors: removes :root/html/body targets; scopes remainder under scopeClass\n *\n * Returns empty string on parse failure (fail-closed).\n *\n * @param css - Raw CSS string from tenant\n * @param scopeClass - Container class to scope selectors (e.g. 'flow-node--my-type')\n */\nexport function sanitizeCSS(css: string, scopeClass?: string): string {\n return sanitizeCSSWithStats(css, scopeClass).css\n}\n\nfunction sanitizeCSSWithStats(\n css: string,\n scopeClass?: string,\n): SanitizeCSSStats {\n let root: postcss.Root\n try {\n root = postcss.parse(css)\n } catch {\n return { css: '', removedRules: 0, removedDecls: 0, removedAtRules: 0 }\n }\n const stats: SanitizeCSSStats = {\n css: '',\n removedRules: 0,\n removedDecls: 0,\n removedAtRules: 0,\n }\n\n // Compute safe scope class once (strip CSS metacharacters and whitespace)\n const safeScopeClass = scopeClass\n ? scopeClass.replace(/[{}()[\\];,'\"\\\\<>\\s]/g, '')\n : ''\n\n // @keyframes name scoping (skip when no scope)\n const keyframeNameMap = new Map<string, string>()\n if (safeScopeClass) {\n root.walkAtRules(/^keyframes$/i, (node) => {\n // Strip surrounding quotes; replace spaces with underscores for valid identifier output\n // e.g. @keyframes \"fade in\" → flow-node--slug__fade_in\n const rawName = node.params.trim().replace(/^['\"]|['\"]$/g, '')\n const originalName = rawName // keep spaces for map key lookup\n const scopedName = `${safeScopeClass}__${rawName.replace(/\\s+/g, '_')}`\n keyframeNameMap.set(originalName, scopedName)\n node.params = scopedName\n })\n }\n\n // Rewrite animation-name / animation shorthand to use scoped keyframe names\n if (safeScopeClass && keyframeNameMap.size > 0) {\n const ANIM_KEYWORDS = new Set([\n 'none',\n 'initial',\n 'inherit',\n 'unset',\n 'revert',\n ])\n // Strip quotes from token before map lookup (animation-name: 'fade' → look up 'fade')\n const replaceAnimName = (token: string) => {\n const t = token.trim().replace(/^['\"]|['\"]$/g, '')\n return ANIM_KEYWORDS.has(t) ? token : (keyframeNameMap.get(t) ?? token)\n }\n // Use regex filter for case-insensitive match (Animation:, ANIMATION-NAME:)\n root.walkDecls(/^animation-name$/i, (node) => {\n node.value = node.value.split(',').map(replaceAnimName).join(', ')\n })\n root.walkDecls(/^animation$/i, (node) => {\n node.value = node.value\n .split(',')\n .map((anim) =>\n anim\n .split(/(\\s+)/)\n .map((token) => (/\\s/.test(token) ? token : replaceAnimName(token)))\n .join(''),\n )\n .join(',')\n })\n }\n\n // At-rules: remove anything not in the allowlist\n root.walkAtRules((node) => {\n if (!ALLOWED_AT_RULES.has(node.name.toLowerCase())) {\n stats.removedAtRules++\n node.remove()\n }\n })\n\n // Declarations: remove dangerous values\n root.walkDecls((node) => {\n // Normalize value: strip CSS block comments so fi/**/xed → fixed (browser behaviour)\n const normalizedValue = normalizeCSSEscapes(\n node.value.replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''),\n )\n if (BLOCKED_VALUE_PATTERNS.some((p) => p.test(normalizedValue))) {\n stats.removedDecls++\n node.remove()\n return\n }\n // Block dangerous property+value combinations (position: fixed/sticky, oversized z-index)\n const propLower = node.prop.toLowerCase()\n const blockedValuePattern = BLOCKED_PROPERTY_VALUES[propLower]\n if (blockedValuePattern) {\n if (blockedValuePattern.test(normalizedValue)) {\n stats.removedDecls++\n node.remove()\n return\n }\n }\n if (propLower === 'z-index') {\n const zv = node.value.trim()\n // Allow CSS-wide keywords and 'auto'\n if (\n zv === 'auto' ||\n zv === 'initial' ||\n zv === 'inherit' ||\n zv === 'unset' ||\n zv === 'revert'\n ) {\n // pass through\n } else {\n // Only allow plain integers ≤ Z_INDEX_MAX. calc(), var(), and non-integers are removed.\n const val = parseInt(zv, 10)\n if (isNaN(val) || String(val) !== zv || val > Z_INDEX_MAX) {\n stats.removedDecls++\n node.remove()\n return\n }\n }\n }\n })\n\n // Rules: strip dangerous selectors, then scope the rest\n root.walkRules((rule) => {\n const safeSelectors = rule.selectors.filter(\n (s) => s.trim() && !DANGEROUS_SELECTOR.test(s),\n )\n if (!safeSelectors.length) {\n stats.removedRules++\n rule.remove()\n return\n }\n if (safeSelectors.length !== rule.selectors.length) {\n stats.removedRules++\n }\n rule.selectors = safeSelectors\n if (scopeClass) {\n if (!safeScopeClass) {\n stats.removedRules++\n rule.remove()\n return\n }\n // Skip scoping inside @keyframes — from/to/0% are not element selectors\n const parent = rule.parent\n if (\n parent?.type === 'atrule' &&\n (parent as postcss.AtRule).name.toLowerCase() === 'keyframes'\n ) {\n return\n }\n rule.selectors = rule.selectors.map((sel) => `.${safeScopeClass} ${sel}`)\n }\n })\n\n // Post-process: escape </style to prevent HTML parser closing the style tag in SSR contexts.\n // postcss parses this as valid CSS string content and reproduces it verbatim.\n stats.css = root.toString().replace(/<\\/style/gi, '<\\\\/style')\n return stats\n}\n\nexport function validateTenantCSS(css: string): string | null {\n const trimmed = css.trim()\n if (!trimmed) return null\n\n const deescapedCSS = normalizeCSSEscapes(css)\n for (const { pattern, label } of TENANT_CSS_BLOCKED_PATTERNS) {\n if (pattern.test(deescapedCSS)) {\n return `CSS contains blocked pattern: ${label}`\n }\n }\n\n try {\n postcss.parse(css)\n } catch {\n return 'CSS parse error'\n }\n\n const sanitized = sanitizeCSSWithStats(\n css,\n 'flow-node--tenant-css-validation',\n )\n if (!sanitized.css.trim()) {\n return 'CSS must contain safe rules'\n }\n if (\n sanitized.removedRules > 0 ||\n sanitized.removedDecls > 0 ||\n sanitized.removedAtRules > 0\n ) {\n return 'CSS contains unsafe rules or selectors'\n }\n\n return null\n}\n","import type { EdgeTypeDef, NodeTypeDef } from './types'\n\nexport function toNodeTypeDef(doc: Record<string, unknown>): NodeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? '#e5e7eb'),\n defaultSize: (doc.defaultSize as NodeTypeDef['defaultSize']) ?? {\n width: 200,\n height: 200,\n },\n fields: Array.isArray(doc.fields)\n ? (doc.fields as NodeTypeDef['fields'])\n : [],\n editorIntent:\n doc.editorIntent === 'text' || doc.editorIntent === 'image'\n ? doc.editorIntent\n : undefined,\n transparentBackground: Boolean(\n doc.hasTransparentBackground ?? doc.transparentBackground,\n ),\n template: (doc.template as string) ?? null,\n customCSS: (doc.customCSS as string) ?? null,\n }\n}\n\nexport function toEdgeTypeDef(doc: Record<string, unknown>): EdgeTypeDef {\n return {\n slug: String(doc.slug ?? ''),\n name: String(doc.title ?? ''),\n color: String(doc.color ?? ''),\n strokeWidth: (doc.strokeWidth as number) ?? 2,\n animated:\n (doc.isAnimated as boolean | undefined) ??\n (doc.animated as boolean | undefined) ??\n false,\n lineStyle: String(doc.lineStyle ?? 'default'),\n markerStart: String(doc.markerStart ?? 'none'),\n markerEnd: String(doc.markerEnd ?? 'arrow'),\n fields: Array.isArray(doc.fields)\n ? (doc.fields as EdgeTypeDef['fields'])\n : [],\n isDefaultEdge: Boolean(doc.isDefaultEdge),\n }\n}\n"],"mappings":"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","names":["postcss"]}
|
package/dist/ui/canvas/server.js
CHANGED
|
@@ -7,7 +7,11 @@ function collectionKeys(collection) {
|
|
|
7
7
|
details: () => [collection, "detail"],
|
|
8
8
|
detail: (id, options) => [collection, "detail", id, options],
|
|
9
9
|
infinites: () => [collection, "infinite"],
|
|
10
|
-
infinite: (options) => [
|
|
10
|
+
infinite: (options, pageSize) => [
|
|
11
|
+
collection,
|
|
12
|
+
"infinite",
|
|
13
|
+
pageSize === void 0 ? options : { ...options, limit: pageSize }
|
|
14
|
+
]
|
|
11
15
|
};
|
|
12
16
|
}
|
|
13
17
|
|