@sixtyninecommerce/admin 0.11.0 → 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/README.md +1501 -23
- package/dist/auth/index.d.ts +7 -1
- package/dist/auth/index.js +8 -1
- package/dist/catalog/documents.d.ts +142 -0
- package/dist/catalog/documents.js +114 -0
- package/dist/catalog/index.d.ts +48 -7
- package/dist/catalog/index.js +6 -1
- package/dist/catalog/metadata.d.ts +244 -0
- package/dist/catalog/metadata.js +220 -0
- package/dist/catalog/properties.d.ts +38 -0
- package/dist/catalog/properties.js +52 -1
- package/dist/catalog/recommendations.d.ts +33 -6
- package/dist/catalog/recommendations.js +94 -2
- package/dist/catalog/reviews.d.ts +17 -4
- package/dist/catalog/reviews.js +7 -0
- package/dist/catalog/variants.d.ts +60 -0
- package/dist/catalog/variants.js +39 -0
- package/dist/catalog/visibility.d.ts +18 -2
- package/dist/client.d.ts +29 -3
- package/dist/client.js +19 -8
- package/dist/content/assets.d.ts +3 -4
- package/dist/content/forms.d.ts +332 -1
- package/dist/content/forms.js +140 -4
- package/dist/content/items.d.ts +31 -8
- package/dist/content/items.js +1 -1
- package/dist/content/menus.d.ts +254 -0
- package/dist/content/menus.js +70 -0
- package/dist/content/strings.d.ts +137 -0
- package/dist/content/strings.js +82 -0
- package/dist/customers/delivery-terms.d.ts +44 -0
- package/dist/customers/delivery-terms.js +32 -0
- package/dist/customers/index.d.ts +15 -0
- package/dist/customers/index.js +4 -0
- package/dist/documents/emails.d.ts +150 -0
- package/dist/documents/emails.js +220 -0
- package/dist/documents/index.d.ts +13 -0
- package/dist/documents/index.js +2 -0
- package/dist/fulfillments/index.d.ts +119 -1
- package/dist/fulfillments/index.js +124 -4
- package/dist/index.d.ts +43 -23
- package/dist/index.js +11 -5
- package/dist/integrations/exact-online-types.d.ts +542 -0
- package/dist/integrations/exact-online.d.ts +541 -5
- package/dist/integrations/exact-online.js +714 -1
- package/dist/integrations/index.d.ts +23 -8
- package/dist/integrations/index.js +9 -4
- package/dist/integrations/pipeline-discoveries.d.ts +65 -0
- package/dist/integrations/pipeline-discoveries.js +65 -0
- package/dist/integrations/pipeline-runs.d.ts +119 -0
- package/dist/integrations/pipeline-runs.js +87 -0
- package/dist/integrations/pipelines.d.ts +73 -2
- package/dist/integrations/pipelines.js +36 -1
- package/dist/integrations/price-import.d.ts +223 -0
- package/dist/integrations/price-import.js +124 -0
- package/dist/integrations/types.d.ts +221 -3
- package/dist/integrations/types.js +4 -3
- package/dist/meta/index.d.ts +10 -0
- package/dist/metafields/index.d.ts +8 -1
- package/dist/metafields/index.js +10 -0
- package/dist/orders/cancel-with-money.d.ts +10 -0
- package/dist/orders/cancel-with-money.js +2 -0
- package/dist/orders/commit-edit.d.ts +16 -0
- package/dist/orders/commit-edit.js +14 -1
- package/dist/orders/deposit-policy.d.ts +3 -1
- package/dist/orders/index.d.ts +22 -11
- package/dist/orders/index.js +5 -2
- package/dist/orders/list.d.ts +26 -5
- package/dist/orders/list.js +123 -13
- package/dist/orders/manual-discounts.d.ts +13 -5
- package/dist/orders/money-view.d.ts +149 -0
- package/dist/orders/money-view.js +99 -0
- package/dist/orders/plan-edit.d.ts +34 -2
- package/dist/orders/plan-edit.js +110 -12
- package/dist/orders/surcharges.d.ts +12 -0
- package/dist/orders/surcharges.js +34 -9
- package/dist/payments/account-credit.d.ts +17 -1
- package/dist/payments/account-credit.js +25 -2
- package/dist/payments/credit-noted-fields.d.ts +8 -1
- package/dist/payments/credit-noted-fields.js +34 -2
- package/dist/payments/customer-consent.d.ts +30 -0
- package/dist/payments/customer-consent.js +49 -0
- package/dist/payments/index.d.ts +89 -14
- package/dist/payments/index.js +22 -2
- package/dist/payments/requests.d.ts +6 -3
- package/dist/payments/requests.js +1 -0
- package/dist/pickups/index.d.ts +5 -3
- package/dist/pickups/index.js +5 -2
- package/dist/platform/email-gateways.d.ts +165 -0
- package/dist/platform/email-gateways.js +78 -0
- package/dist/platform/tax.d.ts +11 -3
- package/dist/platform/tax.js +30 -0
- package/dist/pos/exchanges.d.ts +6 -1
- package/dist/pos/index.d.ts +229 -10
- package/dist/pos/index.js +113 -4
- package/dist/pos/offline-sales.d.ts +44 -3
- package/dist/pos/offline-sales.js +57 -3
- package/dist/pos/returns.d.ts +28 -1
- package/dist/pos/returns.js +36 -6
- package/dist/pricing/price-lists.d.ts +3 -1
- package/dist/purchasing/alerts.d.ts +19 -4
- package/dist/purchasing/alerts.js +29 -3
- package/dist/purchasing/backorders.d.ts +61 -0
- package/dist/purchasing/backorders.js +92 -0
- package/dist/purchasing/index.d.ts +21 -3
- package/dist/purchasing/index.js +8 -0
- package/dist/purchasing/links.d.ts +263 -0
- package/dist/purchasing/links.js +192 -0
- package/dist/purchasing/purchase-orders.d.ts +4 -1
- package/dist/purchasing/receipts.d.ts +396 -0
- package/dist/purchasing/receipts.js +287 -0
- package/dist/purchasing/returns.d.ts +273 -0
- package/dist/purchasing/returns.js +229 -0
- package/dist/quotes/index.d.ts +20 -3
- package/dist/returns/index.d.ts +62 -1
- package/dist/returns/index.js +61 -0
- package/dist/seo/config.d.ts +128 -0
- package/dist/seo/config.js +95 -0
- package/dist/seo/redirects.d.ts +125 -0
- package/dist/seo/redirects.js +60 -1
- package/dist/seo/settings.d.ts +147 -0
- package/dist/seo/settings.js +209 -0
- package/dist/shipping/index.d.ts +6 -0
- package/dist/shipping/index.js +2 -0
- package/dist/shipping/methods.d.ts +8 -1
- package/dist/shipping/myparcel.d.ts +415 -1
- package/dist/shipping/myparcel.js +291 -3
- package/dist/shipping/rate-tables.d.ts +149 -4
- package/dist/shipping/rate-tables.js +229 -23
- package/dist/shipping/ship-to-countries.d.ts +75 -0
- package/dist/shipping/ship-to-countries.js +47 -0
- package/dist/stock/by-location.d.ts +86 -0
- package/dist/stock/by-location.js +94 -0
- package/dist/stock/index.d.ts +8 -1
- package/dist/stock/index.js +4 -0
- package/dist/stock/settings.d.ts +106 -0
- package/dist/stock/settings.js +103 -0
- package/dist/stock/transfers.d.ts +171 -10
- package/dist/stock/transfers.js +82 -4
- package/dist/stored-value/index.d.ts +98 -7
- package/dist/stored-value/index.js +71 -4
- package/dist/tax/display-policy.d.ts +105 -0
- package/dist/tax/display-policy.js +84 -0
- package/dist/tax/index.d.ts +3 -0
- package/dist/tax/index.js +2 -0
- package/dist/tenant/email-templates.d.ts +222 -1
- package/dist/tenant/email-templates.js +227 -10
- package/package.json +2 -2
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Integrations (headless spec §9.2): the store's connections to other systems. The data
|
|
3
|
-
* pipelines
|
|
4
|
-
* connection (`esp`), the AFAS Profit connection with what is sent to it (`afas`) and
|
|
5
|
-
* Online connection with its settings
|
|
6
|
-
*
|
|
3
|
+
* pipelines with their source connections, connectors and import and export set-ups, the e-mail
|
|
4
|
+
* marketing connection (`esp`), the AFAS Profit connection with what is sent to it (`afas`) and
|
|
5
|
+
* the Exact Online connection with its settings, its inbound sync, its shipping-method mapping
|
|
6
|
+
* and its connection logs (`exactOnline`), and the bulk price import with
|
|
7
|
+
* its AI conversion (`priceImport`).
|
|
7
8
|
*/
|
|
8
9
|
import type { Transport } from '@sixtyninecommerce/core';
|
|
9
10
|
import { type AfasModule } from './afas.js';
|
|
10
11
|
import { type EspModule } from './esp.js';
|
|
11
12
|
import { type ExactOnlineModule } from './exact-online.js';
|
|
12
13
|
import { type IntegrationPipelinesModule } from './pipelines.js';
|
|
14
|
+
import { type PriceImportModule } from './price-import.js';
|
|
13
15
|
export type { AfasConfigModule, AfasModule, AfasPaymentTermsModule, AfasWarehouseMappingsModule, } from './afas.js';
|
|
14
16
|
export { AFAS_SYNC_LOG_PAGE_LIMIT } from './afas.js';
|
|
15
17
|
export type { AfasCustomersModule, AfasOrdersModule, AfasStockTransfersModule, } from './afas-actions.js';
|
|
@@ -19,22 +21,35 @@ export type { PipelineConnectionsModule } from './connections.js';
|
|
|
19
21
|
export { PIPELINE_CONNECTION_PRESERVE_KEYS } from './connections.js';
|
|
20
22
|
export type { ConnectEspWithTokenInput, EspBackfillResource, EspConnection, EspConnectionTestResult, EspConnectMetadata, EspCredentialsPushState, EspInboundWebhookState, EspModule, EspSyncLog, EspSyncLogFilter, UpdateEspConnectionInput, } from './esp.js';
|
|
21
23
|
export { ESP_BACKFILL_RESOURCES, ESP_SYNC_LOG_PAGE_LIMIT } from './esp.js';
|
|
22
|
-
export type { ExactOnlineConfigModule, ExactOnlineCredentialsModule, ExactOnlineModule, ExactOnlineSamplesModule, ExactOnlineStructureModule, ExactOnlineWebhooksModule, } from './exact-online.js';
|
|
24
|
+
export type { ExactOnlineConfigModule, ExactOnlineConnectionLogsModule, ExactOnlineCredentialsModule, ExactOnlineCustomersModule, ExactOnlineModule, ExactOnlineOrdersModule, ExactOnlineProductsModule, ExactOnlineSamplesModule, ExactOnlineShippingModule, ExactOnlineStructureModule, ExactOnlineSyncModule, ExactOnlineTermsModule, ExactOnlineWebhooksModule, } from './exact-online.js';
|
|
25
|
+
export { EXACT_ONLINE_LOG_EXPORT_TIMEOUT_MS, EXACT_ONLINE_SYNC_LOG_LIMIT } from './exact-online.js';
|
|
23
26
|
export type * from './exact-online-types.js';
|
|
27
|
+
export type { PipelineDiscoveriesModule } from './pipeline-discoveries.js';
|
|
28
|
+
export type { PipelineRunsModule } from './pipeline-runs.js';
|
|
24
29
|
export type { IntegrationPipelinesModule, PipelineDraftsModule } from './pipelines.js';
|
|
25
30
|
export { PIPELINE_DRAFT_PRESERVE_KEYS, PIPELINE_DRAFT_SLOW_TIMEOUT_MS } from './pipelines.js';
|
|
31
|
+
export type { PriceImportConversion, PriceImportConversionProgress, PriceImportConversionStep, PriceImportConvertInput, PriceImportDocument, PriceImportFollowOptions, PriceImportFormat, PriceImportModule, PriceImportReport, PriceImportRow, PriceImportRowStatus, PriceImportRunInput, PriceImportSummary, PriceImportTaxMode, PriceImportUpload, } from './price-import.js';
|
|
32
|
+
export { PRICE_IMPORT_PREVIEW_TIMEOUT_MS, PRICE_IMPORT_RUN_TIMEOUT_MS } from './price-import.js';
|
|
26
33
|
export type * from './types.js';
|
|
27
34
|
export interface IntegrationsModule {
|
|
28
35
|
/**
|
|
29
|
-
* Data pipelines: the source connections (`connections`), the
|
|
30
|
-
* export set-ups kept on the server (`drafts`).
|
|
36
|
+
* Data pipelines: the pipelines themselves, the source connections (`connections`), the
|
|
37
|
+
* connectors, and the import and export set-ups kept on the server (`drafts`).
|
|
31
38
|
*/
|
|
32
39
|
pipelines: IntegrationPipelinesModule;
|
|
33
40
|
/** The store's e-mail marketing connection (sixtynine.email). See {@link EspModule}. */
|
|
34
41
|
esp: EspModule;
|
|
35
42
|
/** The store's AFAS Profit connection and its settings. See {@link AfasModule}. */
|
|
36
43
|
afas: AfasModule;
|
|
37
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* The store's Exact Online connection, its settings, its inbound sync, its shipping-method
|
|
46
|
+
* mapping and its connection logs. See {@link ExactOnlineModule}.
|
|
47
|
+
*/
|
|
38
48
|
exactOnline: ExactOnlineModule;
|
|
49
|
+
/**
|
|
50
|
+
* The bulk price import (a dry run, then the rows to write) and the AI conversion of a
|
|
51
|
+
* supplier file into a document it accepts. See {@link PriceImportModule}.
|
|
52
|
+
*/
|
|
53
|
+
priceImport: PriceImportModule;
|
|
39
54
|
}
|
|
40
55
|
export declare function createIntegrationsModule(transport: Transport): IntegrationsModule;
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Integrations (headless spec §9.2): the store's connections to other systems. The data
|
|
3
|
-
* pipelines
|
|
4
|
-
* connection (`esp`), the AFAS Profit connection with what is sent to it (`afas`) and
|
|
5
|
-
* Online connection with its settings
|
|
6
|
-
*
|
|
3
|
+
* pipelines with their source connections, connectors and import and export set-ups, the e-mail
|
|
4
|
+
* marketing connection (`esp`), the AFAS Profit connection with what is sent to it (`afas`) and
|
|
5
|
+
* the Exact Online connection with its settings, its inbound sync, its shipping-method mapping
|
|
6
|
+
* and its connection logs (`exactOnline`), and the bulk price import with
|
|
7
|
+
* its AI conversion (`priceImport`).
|
|
7
8
|
*/
|
|
8
9
|
import { createAfasModule } from './afas.js';
|
|
9
10
|
import { createEspModule } from './esp.js';
|
|
10
11
|
import { createExactOnlineModule } from './exact-online.js';
|
|
11
12
|
import { createIntegrationPipelinesModule } from './pipelines.js';
|
|
13
|
+
import { createPriceImportModule } from './price-import.js';
|
|
12
14
|
export { AFAS_SYNC_LOG_PAGE_LIMIT } from './afas.js';
|
|
13
15
|
export { AFAS_CUSTOMER_SEARCH_LIMIT } from './afas-actions.js';
|
|
14
16
|
export { PIPELINE_CONNECTION_PRESERVE_KEYS } from './connections.js';
|
|
15
17
|
export { ESP_BACKFILL_RESOURCES, ESP_SYNC_LOG_PAGE_LIMIT } from './esp.js';
|
|
18
|
+
export { EXACT_ONLINE_LOG_EXPORT_TIMEOUT_MS, EXACT_ONLINE_SYNC_LOG_LIMIT } from './exact-online.js';
|
|
16
19
|
export { PIPELINE_DRAFT_PRESERVE_KEYS, PIPELINE_DRAFT_SLOW_TIMEOUT_MS } from './pipelines.js';
|
|
20
|
+
export { PRICE_IMPORT_PREVIEW_TIMEOUT_MS, PRICE_IMPORT_RUN_TIMEOUT_MS } from './price-import.js';
|
|
17
21
|
export function createIntegrationsModule(transport) {
|
|
18
22
|
return {
|
|
19
23
|
pipelines: createIntegrationPipelinesModule(transport),
|
|
20
24
|
esp: createEspModule(transport),
|
|
21
25
|
afas: createAfasModule(transport),
|
|
22
26
|
exactOnline: createExactOnlineModule(transport),
|
|
27
|
+
priceImport: createPriceImportModule(transport),
|
|
23
28
|
};
|
|
24
29
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { type PipelineDiscoveryProgressEvent, type ProgressStream, type Transport } from '@sixtyninecommerce/core';
|
|
2
|
+
import type { Call } from '../types.js';
|
|
3
|
+
import type { PipelineDiscovery, PipelineSchemaMap, PipelineWatchOptions } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* What a source holds and how it maps onto the store: a discovery samples a connection's source
|
|
6
|
+
* (a fixed-schema connector answers at once; any other asks the AI) and proposes a schema map per
|
|
7
|
+
* kind of record. The import set-ups (`drafts.discover`) start theirs themselves; these doors are
|
|
8
|
+
* for following one, and for a caller that runs a discovery outside a set-up.
|
|
9
|
+
*
|
|
10
|
+
* - **A discovery belongs to its connection's store**: another store's is not found (`get`
|
|
11
|
+
* answers `null`; `schemaMaps` and `watch` are refused `NotFoundError`; an older plugins
|
|
12
|
+
* service refuses `watch` inside the opened stream, `PROGRESS_STREAM_REFUSED`).
|
|
13
|
+
* - Refusals: `PIPELINES_NOT_CONFIGURED` (503, `start`): the platform cannot read connection
|
|
14
|
+
* credentials; `ORGANIZATION_WORKSPACE_NOT_A_STORE` (422, `start`); an app below
|
|
15
|
+
* `customerData: full` is refused every door (`CUSTOMER_DATA_NOT_GRANTED`): the schema maps
|
|
16
|
+
* quote sample records of the source.
|
|
17
|
+
* - Reads and `watch` need `ReadCatalog`; `start` needs `UpdateCatalog`.
|
|
18
|
+
*/
|
|
19
|
+
export interface PipelineDiscoveriesModule {
|
|
20
|
+
/**
|
|
21
|
+
* Start a discovery of the connection's source. Answers it `pending`; follow it with `watch` or
|
|
22
|
+
* `get`. Not idempotent: every call samples the source again (and may ask the AI again; an
|
|
23
|
+
* unchanged source is answered from a 24-hour cache).
|
|
24
|
+
*
|
|
25
|
+
* @effect write
|
|
26
|
+
* @permission UpdateCatalog
|
|
27
|
+
*/
|
|
28
|
+
start(connectionId: string, options?: Call): Promise<PipelineDiscovery>;
|
|
29
|
+
/**
|
|
30
|
+
* One discovery, or `null` when the store has none with that id.
|
|
31
|
+
*
|
|
32
|
+
* @effect read
|
|
33
|
+
* @permission ReadCatalog
|
|
34
|
+
*/
|
|
35
|
+
get(discoveryId: string, options?: Call): Promise<PipelineDiscovery | null>;
|
|
36
|
+
/**
|
|
37
|
+
* The discovery's schema maps, the most records first: one per kind of record the source holds,
|
|
38
|
+
* with its field mappings and sample values as stored. Empty until the discovery completes.
|
|
39
|
+
*
|
|
40
|
+
* @effect read
|
|
41
|
+
* @permission ReadCatalog
|
|
42
|
+
*/
|
|
43
|
+
schemaMaps(discoveryId: string, options?: Call): Promise<PipelineSchemaMap[]>;
|
|
44
|
+
/**
|
|
45
|
+
* The discovery as it happens: an async iterable of its `progress` events (phase, sentence,
|
|
46
|
+
* percentage), ending after its terminal event, `complete` (with its warnings and the source's
|
|
47
|
+
* detected plugins; read the maps with `schemaMaps`) or `error` (the reason, yielded, not
|
|
48
|
+
* thrown). A discovery that had already ended answers its ended state at once.
|
|
49
|
+
*
|
|
50
|
+
* It opens on the first `next()`, and reopens a connection that drops before the end (see
|
|
51
|
+
* {@link PipelineWatchOptions.maxReconnects}); it never retries a refusal: a 401 or 403, or
|
|
52
|
+
* a discovery the store does not have (another store's included), which the plugins service
|
|
53
|
+
* refuses with a 404 `PIPELINE_DISCOVERY_NOT_FOUND` (`NotFoundError`) before the stream opens;
|
|
54
|
+
* a plugins service from before that refuses inside the opened stream,
|
|
55
|
+
* `PROGRESS_STREAM_REFUSED` (`UpstreamError`). It throws `PROGRESS_STREAM_CLOSED` /
|
|
56
|
+
* `PROGRESS_STREAM_STALLED` once the reopens are spent, and
|
|
57
|
+
* `REQUEST_ABORTED` when `signal` fires. An id that is not a discovery id is refused
|
|
58
|
+
* `PROGRESS_STREAM_ID_INVALID` before anything is sent.
|
|
59
|
+
*
|
|
60
|
+
* @effect read
|
|
61
|
+
* @permission ReadCatalog
|
|
62
|
+
*/
|
|
63
|
+
watch(discoveryId: string, options?: PipelineWatchOptions): ProgressStream<PipelineDiscoveryProgressEvent>;
|
|
64
|
+
}
|
|
65
|
+
export declare function createPipelineDiscoveriesModule(transport: Transport): PipelineDiscoveriesModule;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { NotFoundError, openProgressStream, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { PIPELINE_DRAFT_PRESERVE_KEYS } from './pipeline-keys.js';
|
|
3
|
+
const segment = (value) => encodeURIComponent(value);
|
|
4
|
+
const texts = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
|
|
5
|
+
/** The documented fields: the wire also answers the connection row and the result bag. */
|
|
6
|
+
function toDiscovery(raw) {
|
|
7
|
+
return {
|
|
8
|
+
id: raw.id,
|
|
9
|
+
connectionId: raw.connectionId,
|
|
10
|
+
status: raw.status,
|
|
11
|
+
source: raw.source ?? 'ai',
|
|
12
|
+
errorMessage: raw.errorMessage ?? null,
|
|
13
|
+
warnings: texts(raw.result?.warnings),
|
|
14
|
+
detectedPlugins: texts(raw.result?.detectedPlugins),
|
|
15
|
+
startedAt: raw.startedAt ?? null,
|
|
16
|
+
completedAt: raw.completedAt ?? null,
|
|
17
|
+
createdAt: raw.createdAt,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function toSchemaMap(raw) {
|
|
21
|
+
return {
|
|
22
|
+
id: raw.id,
|
|
23
|
+
discoveryId: raw.discoveryId,
|
|
24
|
+
entityType: raw.entityType,
|
|
25
|
+
enabled: raw.enabled,
|
|
26
|
+
confidence: raw.confidence,
|
|
27
|
+
entityCount: raw.entityCount,
|
|
28
|
+
subCounts: raw.subCounts ?? null,
|
|
29
|
+
sourceSchema: raw.sourceSchema ?? {},
|
|
30
|
+
targetSchema: raw.targetSchema ?? {},
|
|
31
|
+
fieldMappings: (raw.fieldMappings ?? []).map((mapping) => ({
|
|
32
|
+
sourceField: mapping.sourceField,
|
|
33
|
+
sourcePath: mapping.sourcePath,
|
|
34
|
+
targetField: mapping.targetField,
|
|
35
|
+
targetPath: mapping.targetPath,
|
|
36
|
+
transform: mapping.transform ?? null,
|
|
37
|
+
confidence: mapping.confidence,
|
|
38
|
+
enabled: mapping.enabled,
|
|
39
|
+
})),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function createPipelineDiscoveriesModule(transport) {
|
|
43
|
+
return {
|
|
44
|
+
async start(connectionId, options) {
|
|
45
|
+
return toDiscovery(await transport.rest('plugins', { method: 'POST', path: `/pipelines/connections/${segment(connectionId)}/discover` }, { ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS }));
|
|
46
|
+
},
|
|
47
|
+
async get(discoveryId, options) {
|
|
48
|
+
try {
|
|
49
|
+
return toDiscovery(await transport.rest('plugins', { method: 'GET', path: `/pipelines/discoveries/${segment(discoveryId)}` }, { ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS }));
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (error instanceof NotFoundError)
|
|
53
|
+
return null;
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
async schemaMaps(discoveryId, options) {
|
|
58
|
+
const maps = await transport.rest('plugins', { method: 'GET', path: `/pipelines/discoveries/${segment(discoveryId)}/schema-maps` },
|
|
59
|
+
// `source_schema` / `target_schema` carry the source's own names: never re-cased.
|
|
60
|
+
{ ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS });
|
|
61
|
+
return (Array.isArray(maps) ? maps : []).map(toSchemaMap);
|
|
62
|
+
},
|
|
63
|
+
watch: (discoveryId, options = {}) => openProgressStream(transport, { kind: 'pipeline-discovery', id: discoveryId }, options),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type Page, type PipelineRunProgressEvent, type ProgressStream, type Transport } from '@sixtyninecommerce/core';
|
|
2
|
+
import type { Call, ListOptions } from '../types.js';
|
|
3
|
+
import type { ListPipelineRunLogsOptions, PipelineRun, PipelineRunLog, PipelineWatchOptions, StartPipelineRunInput } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* A pipeline's runs: start one, follow it, pause, resume or cancel it, and read what it did with
|
|
6
|
+
* each record (its logs).
|
|
7
|
+
*
|
|
8
|
+
* - **A run is also a job** with the same id (`admin.jobs`, kind `pipeline.import` or
|
|
9
|
+
* `pipeline.export`), once the jobs resource has indexed it: `admin.jobs.list()` indexes the
|
|
10
|
+
* runs it has not seen yet, and `admin.jobs.wait(run.id)` then waits for the run to end.
|
|
11
|
+
* `get` here reads the run itself, with its per-entity counts.
|
|
12
|
+
* - **Pause and cancel take effect at the next batch boundary**: the batch in flight finishes and
|
|
13
|
+
* is recorded, then the run stops. Only a `running` run can be paused or cancelled (a `paused`
|
|
14
|
+
* one can be cancelled too); a queued (`pending`) one is refused `PIPELINE_RUN_NOT_STARTED`.
|
|
15
|
+
* - **Deleting the pipeline cancels its runs** (`pipelines.delete`): a queued or paused run ends
|
|
16
|
+
* `cancelled` at once, a running one stops after the batch it is working on, and nothing more
|
|
17
|
+
* is imported or sent. Each says so in `errorMessage`. Such a run can still be read here by its
|
|
18
|
+
* id; the pipeline's run list is gone with the pipeline.
|
|
19
|
+
* - Refusals, all `PlatformError`s branching on `code`:
|
|
20
|
+
* - `PIPELINE_RUN_NOT_FOUND` (404): no such run in this store (another store's included);
|
|
21
|
+
* - `PIPELINE_RUN_ALREADY_ENDED`, `PIPELINE_RUN_NOT_STARTED`, `PIPELINE_RUN_NOT_RUNNING`,
|
|
22
|
+
* `PIPELINE_RUN_NOT_PAUSED` (409): the run is not in a state the action accepts;
|
|
23
|
+
* - `PIPELINE_CHANNEL_TOKEN_MISMATCH` (403, `start` and `resume`): the client's channel token
|
|
24
|
+
* is not this store's any more (the store was renamed); build a client with the new one;
|
|
25
|
+
* - `PIPELINE_COLLECTION_*`: a collection rebuild the pipeline cannot do (an export, no
|
|
26
|
+
* products, a resume, `replace` without SuperAdmin);
|
|
27
|
+
* - `PIPELINES_NOT_CONFIGURED` (503): the platform cannot read connection credentials;
|
|
28
|
+
* - `ORGANIZATION_WORKSPACE_NOT_A_STORE` (422): `start` and `resume` in an organization
|
|
29
|
+
* workspace.
|
|
30
|
+
* - Reads need `ReadCatalog`; `start`, `pause`, `resume` and `cancel` need `UpdateCatalog`. An app
|
|
31
|
+
* below `customerData: full` is refused every door (`CUSTOMER_DATA_NOT_GRANTED`): a run's logs
|
|
32
|
+
* quote the records it moved.
|
|
33
|
+
*/
|
|
34
|
+
export interface PipelineRunsModule {
|
|
35
|
+
/**
|
|
36
|
+
* Queue a run of the pipeline now, whatever its schedule (a paused pipeline too). Answers the
|
|
37
|
+
* run, `pending`. Not idempotent: every call queues another run, so a caller that lost the
|
|
38
|
+
* answer lists the runs before starting again. An export run sends the store's orders to the
|
|
39
|
+
* other system, which cannot be taken back.
|
|
40
|
+
*
|
|
41
|
+
* @effect irreversible
|
|
42
|
+
* @permission UpdateCatalog
|
|
43
|
+
*/
|
|
44
|
+
start(pipelineId: string, input?: StartPipelineRunInput, options?: Call): Promise<PipelineRun>;
|
|
45
|
+
/**
|
|
46
|
+
* The pipeline's runs, newest first. A pipeline the store does not have (deleted included) is a
|
|
47
|
+
* `NotFoundError`.
|
|
48
|
+
*
|
|
49
|
+
* @effect read
|
|
50
|
+
* @permission ReadCatalog
|
|
51
|
+
*/
|
|
52
|
+
list(pipelineId: string, options?: ListOptions): Promise<Page<PipelineRun>>;
|
|
53
|
+
/**
|
|
54
|
+
* One run, or `null` when the store has none with that id.
|
|
55
|
+
*
|
|
56
|
+
* @effect read
|
|
57
|
+
* @permission ReadCatalog
|
|
58
|
+
*/
|
|
59
|
+
get(runId: string, options?: Call): Promise<PipelineRun | null>;
|
|
60
|
+
/**
|
|
61
|
+
* Pause a `running` run at its next batch boundary; resume it later. A run already paused
|
|
62
|
+
* answers as it is.
|
|
63
|
+
*
|
|
64
|
+
* @effect write
|
|
65
|
+
* @permission UpdateCatalog
|
|
66
|
+
*/
|
|
67
|
+
pause(runId: string, options?: Call): Promise<PipelineRun>;
|
|
68
|
+
/**
|
|
69
|
+
* Queue a `paused` run again (`pending`); it continues where it stopped. A run started with a
|
|
70
|
+
* collection rebuild cannot be resumed (`PIPELINE_COLLECTION_REBUILD_NOT_RESUMABLE`).
|
|
71
|
+
*
|
|
72
|
+
* @effect irreversible
|
|
73
|
+
* @permission UpdateCatalog
|
|
74
|
+
*/
|
|
75
|
+
resume(runId: string, options?: Call): Promise<PipelineRun>;
|
|
76
|
+
/**
|
|
77
|
+
* Cancel a `running` or `paused` run: it ends `cancelled` now, and a running one stops at its
|
|
78
|
+
* next batch boundary. What it already did stays done. A run already cancelled answers as it is.
|
|
79
|
+
*
|
|
80
|
+
* @effect write
|
|
81
|
+
* @permission UpdateCatalog
|
|
82
|
+
*/
|
|
83
|
+
cancel(runId: string, options?: Call): Promise<PipelineRun>;
|
|
84
|
+
/**
|
|
85
|
+
* What the run did with each record, newest first, `total` counting every match. Filter by
|
|
86
|
+
* `entityType` and by `result` (its errors: `errored`; what it skipped: `skipped`). There is no
|
|
87
|
+
* level to filter by: a record's outcome is its `result`.
|
|
88
|
+
*
|
|
89
|
+
* @effect read
|
|
90
|
+
* @permission ReadCatalog
|
|
91
|
+
*/
|
|
92
|
+
logs(runId: string, options?: ListPipelineRunLogsOptions): Promise<Page<PipelineRunLog>>;
|
|
93
|
+
/**
|
|
94
|
+
* The run as it happens: an async iterable of its events, each with the run's `phase`, a
|
|
95
|
+
* `message` and the per-entity counts so far (`progress`). `progress` events arrive while it
|
|
96
|
+
* works (at most about one a second, naming the `entityType` it is on), and the iteration ENDS
|
|
97
|
+
* after the one terminal event: `complete`, `error` (the run failed; the reason is the event's
|
|
98
|
+
* `message`, yielded, not thrown), `cancelled` or `paused`. A run that had already ended answers
|
|
99
|
+
* its ended state at once; a queued one says nothing until it starts. A resumed run is followed
|
|
100
|
+
* by watching it again.
|
|
101
|
+
*
|
|
102
|
+
* The counts are the stream's: a run cancelled by its pipeline's deletion ends the stream at
|
|
103
|
+
* once, and the batch it was working on may still finish after that; `get` reads the final
|
|
104
|
+
* counts. It opens on the first `next()` and reopens a connection that drops before the end (see
|
|
105
|
+
* {@link PipelineWatchOptions.maxReconnects}); it never retries a refusal: a 401 or 403, or a
|
|
106
|
+
* run the store does not have (another store's included), which the plugins service refuses
|
|
107
|
+
* with a 404 `PIPELINE_RUN_NOT_FOUND` (`NotFoundError`) before the stream opens; a plugins
|
|
108
|
+
* service from before that refuses inside the opened stream, `PROGRESS_STREAM_REFUSED`
|
|
109
|
+
* (`UpstreamError`). It throws
|
|
110
|
+
* `PROGRESS_STREAM_CLOSED` / `PROGRESS_STREAM_STALLED` once the reopens are spent, and
|
|
111
|
+
* `REQUEST_ABORTED` when `signal` fires. An id that is not a run id is refused
|
|
112
|
+
* `PROGRESS_STREAM_ID_INVALID` before anything is sent.
|
|
113
|
+
*
|
|
114
|
+
* @effect read
|
|
115
|
+
* @permission ReadCatalog
|
|
116
|
+
*/
|
|
117
|
+
watch(runId: string, options?: PipelineWatchOptions): ProgressStream<PipelineRunProgressEvent>;
|
|
118
|
+
}
|
|
119
|
+
export declare function createPipelineRunsModule(transport: Transport): PipelineRunsModule;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createPage, NotFoundError, openProgressStream, readRestPage, } from '@sixtyninecommerce/core';
|
|
2
|
+
import { PIPELINE_DRAFT_PRESERVE_KEYS } from './pipeline-keys.js';
|
|
3
|
+
const PIPELINES = '/pipelines';
|
|
4
|
+
const RUNS = '/pipelines/runs';
|
|
5
|
+
const segment = (value) => encodeURIComponent(value);
|
|
6
|
+
/**
|
|
7
|
+
* The documented fields only. The wire also carries the run's internal id maps (every source id
|
|
8
|
+
* the run mapped, which can run to tens of thousands of entries) and, on some answers, its
|
|
9
|
+
* pipeline's row.
|
|
10
|
+
*/
|
|
11
|
+
function toRun(raw) {
|
|
12
|
+
return {
|
|
13
|
+
id: raw.id,
|
|
14
|
+
pipelineId: raw.pipelineId,
|
|
15
|
+
trigger: raw.trigger,
|
|
16
|
+
status: raw.status,
|
|
17
|
+
progress: raw.progress ?? {},
|
|
18
|
+
errorMessage: raw.errorMessage ?? null,
|
|
19
|
+
syncPolicy: raw.syncPolicy,
|
|
20
|
+
collectionAssignmentMode: raw.collectionAssignmentMode ?? 'merge',
|
|
21
|
+
startedAt: raw.startedAt ?? null,
|
|
22
|
+
completedAt: raw.completedAt ?? null,
|
|
23
|
+
createdAt: raw.createdAt,
|
|
24
|
+
updatedAt: raw.updatedAt,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function toLog(raw) {
|
|
28
|
+
return {
|
|
29
|
+
id: raw.id,
|
|
30
|
+
runId: raw.runId,
|
|
31
|
+
entityType: raw.entityType,
|
|
32
|
+
sourceId: raw.sourceId ?? null,
|
|
33
|
+
targetId: raw.targetId ?? null,
|
|
34
|
+
result: raw.result,
|
|
35
|
+
message: raw.message ?? null,
|
|
36
|
+
createdAt: raw.createdAt,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function createPipelineRunsModule(transport) {
|
|
40
|
+
// `progress` (keyed by entity type) and `idMaps` are stored data: preserved, never re-cased.
|
|
41
|
+
const call = async (method, path, options, body) => toRun(await transport.rest('plugins', { method, path, ...(body === undefined ? {} : { body }) }, { ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS }));
|
|
42
|
+
async function list(pipelineId, options) {
|
|
43
|
+
const body = await transport.rest('plugins', {
|
|
44
|
+
method: 'GET',
|
|
45
|
+
path: `${PIPELINES}/${segment(pipelineId)}/runs`,
|
|
46
|
+
// `cursor=1` asks for a keyset page; without it the door answers every run as an array.
|
|
47
|
+
query: { cursor: 1, after: options?.after, limit: options?.limit },
|
|
48
|
+
}, { ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS });
|
|
49
|
+
const { items, meta } = readRestPage(body);
|
|
50
|
+
return createPage(items.map(toRun), meta, (cursor) => list(pipelineId, { ...options, after: cursor }));
|
|
51
|
+
}
|
|
52
|
+
async function logs(runId, options) {
|
|
53
|
+
const body = await transport.rest('plugins', {
|
|
54
|
+
method: 'GET',
|
|
55
|
+
path: `${RUNS}/${segment(runId)}/logs`,
|
|
56
|
+
query: {
|
|
57
|
+
cursor: 1,
|
|
58
|
+
entity_type: options?.entityType,
|
|
59
|
+
result: options?.result,
|
|
60
|
+
after: options?.after,
|
|
61
|
+
limit: options?.limit,
|
|
62
|
+
},
|
|
63
|
+
}, options);
|
|
64
|
+
const { items, meta } = readRestPage(body);
|
|
65
|
+
return createPage(items.map(toLog), meta, (cursor) => logs(runId, { ...options, after: cursor }));
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
// No body unless something is overridden: the door's body is optional.
|
|
69
|
+
start: (pipelineId, input, options) => call('POST', `${PIPELINES}/${segment(pipelineId)}/runs`, options, input && Object.keys(input).length > 0 ? input : undefined),
|
|
70
|
+
list,
|
|
71
|
+
async get(runId, options) {
|
|
72
|
+
try {
|
|
73
|
+
return await call('GET', `${RUNS}/${segment(runId)}`, options);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (error instanceof NotFoundError)
|
|
77
|
+
return null;
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
pause: (runId, options) => call('POST', `${RUNS}/${segment(runId)}/pause`, options),
|
|
82
|
+
resume: (runId, options) => call('POST', `${RUNS}/${segment(runId)}/resume`, options),
|
|
83
|
+
cancel: (runId, options) => call('POST', `${RUNS}/${segment(runId)}/cancel`, options),
|
|
84
|
+
logs,
|
|
85
|
+
watch: (runId, options = {}) => openProgressStream(transport, { kind: 'pipeline-run', id: runId }, options),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type Page, type Transport } from '@sixtyninecommerce/core';
|
|
2
2
|
import type { Call, ListOptions } from '../types.js';
|
|
3
3
|
import { type PipelineConnectionsModule } from './connections.js';
|
|
4
|
-
import
|
|
4
|
+
import { type PipelineDiscoveriesModule } from './pipeline-discoveries.js';
|
|
5
|
+
import { type PipelineRunsModule } from './pipeline-runs.js';
|
|
6
|
+
import type { CommittedPipelineDraft, ImportDependency, ListPipelinesOptions, Pipeline, PipelineConnector, PipelineDirection, PipelineDraft, PipelineDraftSummary, UpdatePipelineDraftInput, UpdatePipelineDraftSchemaMapInput, UpdatePipelineInput } from './types.js';
|
|
5
7
|
export { PIPELINE_DRAFT_PRESERVE_KEYS, PIPELINE_DRAFT_SLOW_TIMEOUT_MS } from './pipeline-keys.js';
|
|
6
8
|
/**
|
|
7
9
|
* Half-finished import and export set-ups, kept on the server for the store (headless spec §7).
|
|
@@ -90,9 +92,78 @@ export interface PipelineDraftsModule {
|
|
|
90
92
|
*/
|
|
91
93
|
discard(id: string, options?: Call): Promise<void>;
|
|
92
94
|
}
|
|
93
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Data pipelines (imports and exports between the store and another system): the pipelines
|
|
97
|
+
* themselves (`list`, `get`, `update`, `delete`), their runs and the runs' logs (`runs`), the
|
|
98
|
+
* set-ups that create them (`drafts`), the discoveries of a source (`discoveries`), their source
|
|
99
|
+
* connections and the connectors.
|
|
100
|
+
*
|
|
101
|
+
* A pipeline is created by committing a set-up (`drafts.commit`). A run is followed live with
|
|
102
|
+
* `runs.watch` (or read with `runs.get`), and is also a `jobs` entry.
|
|
103
|
+
*
|
|
104
|
+
* - **Schedules are wall-clock times in the pipeline's own `timezone`** (an IANA zone): `daily`
|
|
105
|
+
* runs at 03:00 there and `weekly` on Mondays at 03:00, through its daylight saving changes.
|
|
106
|
+
* A set-up starts with the store's zone; a pipeline made before zones were asked for holds `UTC`.
|
|
107
|
+
* - **Pausing is `update(id, { isActive: false })`**: the schedule is unregistered and a commerce
|
|
108
|
+
* plugin's export through it (Hendriks) is refused until `isActive: true`. Starting a run by hand
|
|
109
|
+
* still works.
|
|
110
|
+
* - Reads need `ReadCatalog`, `update` and `delete` need `UpdateCatalog`. Another store's pipeline
|
|
111
|
+
* is not found (`get` answers `null`, a write a `NotFoundError`). An organization workspace is
|
|
112
|
+
* not a store: an `update` there is refused `ORGANIZATION_WORKSPACE_NOT_A_STORE` (422) unless it
|
|
113
|
+
* only pauses. An app below `customerData: full` is refused every door (`CUSTOMER_DATA_NOT_GRANTED`).
|
|
114
|
+
*/
|
|
94
115
|
export interface IntegrationPipelinesModule {
|
|
116
|
+
/**
|
|
117
|
+
* The store's pipelines, newest first, each with the connection it runs over (never a
|
|
118
|
+
* credential). `direction` lists only imports or only exports.
|
|
119
|
+
*
|
|
120
|
+
* @effect read
|
|
121
|
+
* @permission ReadCatalog
|
|
122
|
+
*/
|
|
123
|
+
list(options?: ListPipelinesOptions): Promise<Page<Pipeline>>;
|
|
124
|
+
/**
|
|
125
|
+
* One pipeline, or `null` when the store has none with that id (deleted, or another store's).
|
|
126
|
+
*
|
|
127
|
+
* @effect read
|
|
128
|
+
* @permission ReadCatalog
|
|
129
|
+
*/
|
|
130
|
+
get(id: string, options?: Call): Promise<Pipeline | null>;
|
|
131
|
+
/**
|
|
132
|
+
* Change a pipeline: its name, its schedule (`scheduleType`, `cronExpression`, `timezone`), its
|
|
133
|
+
* sync policy, whether it is paused (`isActive`), or an export's filter (`config.triggerFilter`).
|
|
134
|
+
* A field left out stays as stored. A change to the schedule or to `isActive` re-registers the
|
|
135
|
+
* schedule at once. Refused, saving nothing, with a `ValidationError` (400) coded:
|
|
136
|
+
*
|
|
137
|
+
* - `PIPELINE_CRON_REQUIRED`: a `custom` schedule with no cron;
|
|
138
|
+
* - `PIPELINE_CRON_NEVER_FIRES`: a cron the scheduler can never run (`0 0 31 4 *`), checked in
|
|
139
|
+
* `timezone`;
|
|
140
|
+
* - `PIPELINE_EXPORT_FILTER_UNSUPPORTED`, `PIPELINE_EXPORT_FILTER_BLANK`,
|
|
141
|
+
* `PIPELINE_EXPORT_FILTER_VALUE_UNKNOWN`: a filter key the export does not honour, a key with
|
|
142
|
+
* no value, or a value no order can have (`details[].field` is `triggerFilter`). An
|
|
143
|
+
* unhonoured filter would export everything, an impossible one nothing at all;
|
|
144
|
+
* - `VALIDATION_FAILED`: a field of the wrong shape (an unknown zone, a cron that is not 5
|
|
145
|
+
* parts).
|
|
146
|
+
*
|
|
147
|
+
* @effect write
|
|
148
|
+
* @permission UpdateCatalog
|
|
149
|
+
*/
|
|
150
|
+
update(id: string, input: UpdatePipelineInput, options?: Call): Promise<Pipeline>;
|
|
151
|
+
/**
|
|
152
|
+
* Delete a pipeline: its schedule is unregistered at once and it leaves the list. Its runs that
|
|
153
|
+
* have not ended are cancelled in the same step: a queued or paused one at once, a running one
|
|
154
|
+
* after the batch it is working on, and nothing more is imported or sent (each says so in
|
|
155
|
+
* `errorMessage`; read them with `runs.get`). Its past runs and their logs are kept. Its
|
|
156
|
+
* connection is not deleted, and can be once nothing else uses it.
|
|
157
|
+
*
|
|
158
|
+
* @effect destructive
|
|
159
|
+
* @permission UpdateCatalog
|
|
160
|
+
*/
|
|
161
|
+
delete(id: string, options?: Call): Promise<void>;
|
|
162
|
+
/** The pipelines' runs and their logs. See {@link PipelineRunsModule}. */
|
|
163
|
+
runs: PipelineRunsModule;
|
|
95
164
|
drafts: PipelineDraftsModule;
|
|
165
|
+
/** The discoveries of a connection's source. See {@link PipelineDiscoveriesModule}. */
|
|
166
|
+
discoveries: PipelineDiscoveriesModule;
|
|
96
167
|
/** The store's source connections. See {@link PipelineConnectionsModule}. */
|
|
97
168
|
connections: PipelineConnectionsModule;
|
|
98
169
|
/**
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { createPage, readRestPage } from '@sixtyninecommerce/core';
|
|
1
|
+
import { createPage, NotFoundError, readRestPage, } from '@sixtyninecommerce/core';
|
|
2
2
|
import { createPipelineConnectionsModule, listPipelineConnectors, } from './connections.js';
|
|
3
|
+
import { createPipelineDiscoveriesModule, } from './pipeline-discoveries.js';
|
|
3
4
|
import { PIPELINE_DRAFT_PRESERVE_KEYS, PIPELINE_DRAFT_SLOW_TIMEOUT_MS } from './pipeline-keys.js';
|
|
5
|
+
import { createPipelineRunsModule } from './pipeline-runs.js';
|
|
4
6
|
export { PIPELINE_DRAFT_PRESERVE_KEYS, PIPELINE_DRAFT_SLOW_TIMEOUT_MS } from './pipeline-keys.js';
|
|
7
|
+
const PIPELINES = '/pipelines';
|
|
5
8
|
const DRAFTS = '/pipelines/drafts';
|
|
6
9
|
const segment = (value) => encodeURIComponent(value);
|
|
7
10
|
export function createIntegrationPipelinesModule(transport) {
|
|
@@ -34,8 +37,40 @@ export function createIntegrationPipelinesModule(transport) {
|
|
|
34
37
|
await transport.rest('plugins', { method: 'DELETE', path: `${DRAFTS}/${segment(id)}`, expect: 'void' }, options);
|
|
35
38
|
},
|
|
36
39
|
};
|
|
40
|
+
async function listPipelines(options) {
|
|
41
|
+
const body = await transport.rest('plugins', {
|
|
42
|
+
method: 'GET',
|
|
43
|
+
path: PIPELINES,
|
|
44
|
+
// `cursor=1` asks for a keyset page; without it the door answers the whole list as an array.
|
|
45
|
+
query: {
|
|
46
|
+
cursor: 1,
|
|
47
|
+
direction: options?.direction,
|
|
48
|
+
after: options?.after,
|
|
49
|
+
limit: options?.limit,
|
|
50
|
+
},
|
|
51
|
+
}, { ...options, preserveKeys: PIPELINE_DRAFT_PRESERVE_KEYS });
|
|
52
|
+
const { items, meta } = readRestPage(body);
|
|
53
|
+
return createPage(items, meta, (cursor) => listPipelines({ ...options, after: cursor }));
|
|
54
|
+
}
|
|
37
55
|
return {
|
|
56
|
+
list: listPipelines,
|
|
57
|
+
async get(id, options) {
|
|
58
|
+
try {
|
|
59
|
+
return await read(`${PIPELINES}/${segment(id)}`, options);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof NotFoundError)
|
|
63
|
+
return null;
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
update: (id, input, options) => write('PATCH', `${PIPELINES}/${segment(id)}`, input, options),
|
|
68
|
+
async delete(id, options) {
|
|
69
|
+
await transport.rest('plugins', { method: 'DELETE', path: `${PIPELINES}/${segment(id)}`, expect: 'void' }, options);
|
|
70
|
+
},
|
|
71
|
+
runs: createPipelineRunsModule(transport),
|
|
38
72
|
drafts,
|
|
73
|
+
discoveries: createPipelineDiscoveriesModule(transport),
|
|
39
74
|
connections: createPipelineConnectionsModule(transport),
|
|
40
75
|
connectors: (options) => listPipelineConnectors(transport, options),
|
|
41
76
|
async importDependencies(options) {
|