qstd 0.3.53 → 0.3.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/aws/ddb/copy-table.d.ts +51 -0
- package/dist/server/aws/ddb/copy-table.d.ts.map +1 -0
- package/dist/server/aws/ddb/index.d.ts +1 -0
- package/dist/server/aws/ddb/index.d.ts.map +1 -1
- package/dist/server/aws/s3/domain.d.ts +13 -14
- package/dist/server/aws/s3/domain.d.ts.map +1 -1
- package/dist/server/index.cjs +252 -24
- package/dist/server/index.js +252 -25
- package/package.json +4 -2
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
|
|
2
|
+
type CopyTableProps = {
|
|
3
|
+
/** Source table configuration */
|
|
4
|
+
source: {
|
|
5
|
+
tableName: string;
|
|
6
|
+
/** Optional AWS config for cross-region copying */
|
|
7
|
+
config?: DynamoDBClientConfig;
|
|
8
|
+
};
|
|
9
|
+
/** Destination table configuration */
|
|
10
|
+
destination: {
|
|
11
|
+
tableName: string;
|
|
12
|
+
/** Optional AWS config for cross-region copying */
|
|
13
|
+
config?: DynamoDBClientConfig;
|
|
14
|
+
};
|
|
15
|
+
/** Whether to create destination table if it doesn't exist */
|
|
16
|
+
create?: boolean;
|
|
17
|
+
/** If true, only copy schema without data */
|
|
18
|
+
schemaOnly?: boolean;
|
|
19
|
+
/** Whether to enable continuous backups on destination table */
|
|
20
|
+
continuousBackups?: boolean;
|
|
21
|
+
/** Optional function to transform each item during copy */
|
|
22
|
+
transform?: (item: Record<string, unknown>, index: number) => Record<string, unknown>;
|
|
23
|
+
/** Whether to show progress logs */
|
|
24
|
+
log?: boolean;
|
|
25
|
+
};
|
|
26
|
+
type CopyTableResult = {
|
|
27
|
+
/** Number of items copied */
|
|
28
|
+
count: number;
|
|
29
|
+
/** Operation status */
|
|
30
|
+
status: "SUCCESS" | "FAIL";
|
|
31
|
+
/** Whether only schema was copied */
|
|
32
|
+
schemaOnly?: boolean;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Copy a DynamoDB table to another table, with support for cross-region copying,
|
|
36
|
+
* schema-only copying, and data transformation.
|
|
37
|
+
*
|
|
38
|
+
* This function can:
|
|
39
|
+
* - Copy data between tables in the same or different regions
|
|
40
|
+
* - Create the destination table if it doesn't exist
|
|
41
|
+
* - Copy only the schema without data
|
|
42
|
+
* - Transform items during the copy process
|
|
43
|
+
* - Enable continuous backups on the destination table
|
|
44
|
+
* - Handle large tables with proper pagination and retry logic
|
|
45
|
+
*
|
|
46
|
+
* @param props Configuration options for the copy operation
|
|
47
|
+
* @returns Promise resolving to copy results
|
|
48
|
+
*/
|
|
49
|
+
export declare const copyTable: (props: CopyTableProps) => Promise<CopyTableResult>;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=copy-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copy-table.d.ts","sourceRoot":"","sources":["../../../../src/server/aws/ddb/copy-table.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,oBAAoB,EAG1B,MAAM,0BAA0B,CAAC;AAqKlC,KAAK,cAAc,GAAG;IACpB,iCAAiC;IACjC,MAAM,EAAE;QACN,SAAS,EAAE,MAAM,CAAC;QAClB,mDAAmD;QACnD,MAAM,CAAC,EAAE,oBAAoB,CAAC;KAC/B,CAAC;IACF,sCAAsC;IACtC,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,mDAAmD;QACnD,MAAM,CAAC,EAAE,oBAAoB,CAAC;KAC/B,CAAC;IACF,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,2DAA2D;IAC3D,SAAS,CAAC,EAAE,CACV,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,oCAAoC;IACpC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,qCAAqC;IACrC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GACpB,OAAO,cAAc,KACpB,OAAO,CAAC,eAAe,CAsMzB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/aws/ddb/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,YAAY,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/server/aws/ddb/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type DeleteObjectCommandOutput, type GetObjectCommandOutput, type HeadObjectCommandOutput } from "@aws-sdk/client-s3";
|
|
2
2
|
import { type PresignedPost } from "@aws-sdk/s3-presigned-post";
|
|
3
3
|
import * as _t from "./types";
|
|
4
4
|
export declare const create: (props?: _t.CreateProps) => _t.Client;
|
|
@@ -25,19 +25,18 @@ export type FileProps = {
|
|
|
25
25
|
export declare const getFile: (s3: _t.Client, props: FileProps) => Promise<GetObjectCommandOutput>;
|
|
26
26
|
export declare const deleteFile: (s3: _t.Client, props: FileProps) => Promise<DeleteObjectCommandOutput>;
|
|
27
27
|
export declare const getFileMetadata: (s3: _t.Client, props: FileProps) => Promise<HeadObjectCommandOutput>;
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}): Promise<boolean>;
|
|
28
|
+
/**
|
|
29
|
+
* Create a new S3 bucket
|
|
30
|
+
*/
|
|
31
|
+
export declare const createBucket: (s3: _t.Client, bucketName: string) => Promise<import("@aws-sdk/client-s3").CreateBucketCommandOutput>;
|
|
32
|
+
/**
|
|
33
|
+
* Delete an S3 bucket
|
|
34
|
+
*/
|
|
35
|
+
export declare const deleteBucket: (s3: _t.Client, bucketName: string) => Promise<import("@aws-sdk/client-s3").DeleteBucketCommandOutput>;
|
|
36
|
+
/**
|
|
37
|
+
* Check if an S3 bucket exists
|
|
38
|
+
*/
|
|
39
|
+
export declare const bucketExists: (s3: _t.Client, bucketName: string) => Promise<boolean>;
|
|
41
40
|
/**
|
|
42
41
|
* Copy and delete original files from src bucket to target bucket.
|
|
43
42
|
* @param s3
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../../src/server/aws/s3/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,yBAAyB,EAC9B,KAAK,
|
|
1
|
+
{"version":3,"file":"domain.d.ts","sourceRoot":"","sources":["../../../../src/server/aws/s3/domain.ts"],"names":[],"mappings":"AAAA,OAAO,EAYL,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAE7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,eAAO,MAAM,MAAM,GAAI,QAAO,EAAE,CAAC,WAAgB,KAAG,EAAE,CAAC,MAKtD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,EAAE,CAAC,MAAM,EACb,KAAK,EAAE,EAAE,CAAC,iBAAiB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAAC;AACnB,wBAAgB,eAAe,CAC7B,EAAE,EAAE,EAAE,CAAC,MAAM,EACb,KAAK,EAAE,EAAE,CAAC,kBAAkB,GAC3B,OAAO,CAAC,aAAa,CAAC,CAAC;AA4C1B;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,IAAI,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,WAAW,iEAU9D,CAAC;AAMF,MAAM,MAAM,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,eAAO,MAAM,OAAO,GAClB,IAAI,EAAE,CAAC,MAAM,EACb,OAAO,SAAS,KACf,OAAO,CAAC,sBAAsB,CAWhC,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,IAAI,EAAE,CAAC,MAAM,EACb,OAAO,SAAS,KACf,OAAO,CAAC,yBAAyB,CAWnC,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,IAAI,EAAE,CAAC,MAAM,EACb,OAAO,SAAS,KACf,OAAO,CAAC,uBAAuB,CAWjC,CAAC;AAMF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,IAAI,EAAE,CAAC,MAAM,EAAE,YAAY,MAAM,oEAG7D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,IAAI,EAAE,CAAC,MAAM,EAAE,YAAY,MAAM,oEAG7D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,GAAU,IAAI,EAAE,CAAC,MAAM,EAAE,YAAY,MAAM,qBAgBnE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,IAAI,EAAE,CAAC,MAAM,EACb,SAAS,EAAE,CAAC,kBAAkB,qDAkB/B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,EAAE,CAAC,SAAS,EAAE,GAAG,IAgB9D,CAAC"}
|
package/dist/server/index.cjs
CHANGED
|
@@ -6,6 +6,7 @@ var fs = require('fs');
|
|
|
6
6
|
var arktype = require('arktype');
|
|
7
7
|
var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
8
8
|
var clientDynamodb = require('@aws-sdk/client-dynamodb');
|
|
9
|
+
var signale = require('signale');
|
|
9
10
|
var clientSns = require('@aws-sdk/client-sns');
|
|
10
11
|
var clientSqs = require('@aws-sdk/client-sqs');
|
|
11
12
|
var clientSes = require('@aws-sdk/client-ses');
|
|
@@ -17,6 +18,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
|
|
|
17
18
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
19
|
|
|
19
20
|
var awaitSpawn__default = /*#__PURE__*/_interopDefault(awaitSpawn);
|
|
21
|
+
var signale__default = /*#__PURE__*/_interopDefault(signale);
|
|
20
22
|
|
|
21
23
|
var __defProp = Object.defineProperty;
|
|
22
24
|
var __export = (target, all) => {
|
|
@@ -1060,6 +1062,7 @@ __export(ddb_exports, {
|
|
|
1060
1062
|
batchDelete: () => batchDelete,
|
|
1061
1063
|
batchGet: () => batchGet,
|
|
1062
1064
|
batchWrite: () => batchWrite,
|
|
1065
|
+
copyTable: () => copyTable,
|
|
1063
1066
|
create: () => create2,
|
|
1064
1067
|
deleteTable: () => deleteTable,
|
|
1065
1068
|
find: () => find,
|
|
@@ -1659,6 +1662,232 @@ var lsiPhash = {
|
|
|
1659
1662
|
name: "phash-lsi",
|
|
1660
1663
|
sk: "phash"
|
|
1661
1664
|
};
|
|
1665
|
+
var validateTableName = (tableName) => {
|
|
1666
|
+
const regex = /^[a-zA-Z0-9_.-]{3,255}$/;
|
|
1667
|
+
if (!regex.test(tableName)) {
|
|
1668
|
+
throw new Error(
|
|
1669
|
+
`tableName must follow AWS naming rules (3-255 length, and only the following characters: a-z, A-Z, 0-9, _-.) but received: ${tableName}`
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
};
|
|
1673
|
+
var clearTableSchema = (table) => {
|
|
1674
|
+
const cleanTable = {
|
|
1675
|
+
TableName: table.TableName,
|
|
1676
|
+
AttributeDefinitions: table.AttributeDefinitions,
|
|
1677
|
+
KeySchema: table.KeySchema
|
|
1678
|
+
};
|
|
1679
|
+
if (table.BillingModeSummary?.BillingMode) {
|
|
1680
|
+
cleanTable.BillingMode = table.BillingModeSummary.BillingMode;
|
|
1681
|
+
}
|
|
1682
|
+
if (table.ProvisionedThroughput && table.BillingModeSummary?.BillingMode !== "PAY_PER_REQUEST") {
|
|
1683
|
+
cleanTable.ProvisionedThroughput = {
|
|
1684
|
+
ReadCapacityUnits: table.ProvisionedThroughput.ReadCapacityUnits,
|
|
1685
|
+
WriteCapacityUnits: table.ProvisionedThroughput.WriteCapacityUnits
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
if (table.LocalSecondaryIndexes && table.LocalSecondaryIndexes.length > 0) {
|
|
1689
|
+
cleanTable.LocalSecondaryIndexes = table.LocalSecondaryIndexes.map(
|
|
1690
|
+
(lsi3) => ({
|
|
1691
|
+
IndexName: lsi3.IndexName,
|
|
1692
|
+
KeySchema: lsi3.KeySchema,
|
|
1693
|
+
Projection: lsi3.Projection
|
|
1694
|
+
})
|
|
1695
|
+
);
|
|
1696
|
+
}
|
|
1697
|
+
if (table.GlobalSecondaryIndexes && table.GlobalSecondaryIndexes.length > 0) {
|
|
1698
|
+
cleanTable.GlobalSecondaryIndexes = table.GlobalSecondaryIndexes.map(
|
|
1699
|
+
(gsi) => {
|
|
1700
|
+
const cleanGsi = {
|
|
1701
|
+
IndexName: gsi.IndexName,
|
|
1702
|
+
KeySchema: gsi.KeySchema,
|
|
1703
|
+
Projection: gsi.Projection
|
|
1704
|
+
};
|
|
1705
|
+
if (gsi.ProvisionedThroughput && table.BillingModeSummary?.BillingMode !== "PAY_PER_REQUEST") {
|
|
1706
|
+
cleanGsi.ProvisionedThroughput = {
|
|
1707
|
+
ReadCapacityUnits: gsi.ProvisionedThroughput.ReadCapacityUnits,
|
|
1708
|
+
WriteCapacityUnits: gsi.ProvisionedThroughput.WriteCapacityUnits
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
return cleanGsi;
|
|
1712
|
+
}
|
|
1713
|
+
);
|
|
1714
|
+
}
|
|
1715
|
+
if (table.SSEDescription) {
|
|
1716
|
+
cleanTable.SSESpecification = {
|
|
1717
|
+
Enabled: table.SSEDescription.Status === "ENABLED" || table.SSEDescription.Status === "ENABLING"
|
|
1718
|
+
};
|
|
1719
|
+
if (table.SSEDescription.SSEType === "KMS" && table.SSEDescription.KMSMasterKeyArn) {
|
|
1720
|
+
cleanTable.SSESpecification.SSEType = "KMS";
|
|
1721
|
+
cleanTable.SSESpecification.KMSMasterKeyId = table.SSEDescription.KMSMasterKeyArn;
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
if (table.StreamSpecification) {
|
|
1725
|
+
cleanTable.StreamSpecification = {
|
|
1726
|
+
StreamEnabled: table.StreamSpecification.StreamEnabled,
|
|
1727
|
+
StreamViewType: table.StreamSpecification.StreamViewType
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
return cleanTable;
|
|
1731
|
+
};
|
|
1732
|
+
var waitForActive = async (tableName, client, log2) => {
|
|
1733
|
+
if (log2) {
|
|
1734
|
+
signale__default.default.log(`Waiting for table "${tableName}" to become active...`);
|
|
1735
|
+
}
|
|
1736
|
+
await clientDynamodb.waitUntilTableExists(
|
|
1737
|
+
{
|
|
1738
|
+
client,
|
|
1739
|
+
// Check every 5 seconds
|
|
1740
|
+
minDelay: 5,
|
|
1741
|
+
maxDelay: 5,
|
|
1742
|
+
// Wait up to 10 minutes
|
|
1743
|
+
maxWaitTime: 600
|
|
1744
|
+
},
|
|
1745
|
+
{ TableName: tableName }
|
|
1746
|
+
);
|
|
1747
|
+
if (log2) signale__default.default.success(`Table "${tableName}" is now active!`);
|
|
1748
|
+
};
|
|
1749
|
+
var sleep4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1750
|
+
var copyTable = async (props) => {
|
|
1751
|
+
try {
|
|
1752
|
+
validateTableName(props.source.tableName);
|
|
1753
|
+
validateTableName(props.destination.tableName);
|
|
1754
|
+
const sourceDynamoClient = new clientDynamodb.DynamoDBClient({
|
|
1755
|
+
...props.source.config,
|
|
1756
|
+
region: props.source.config?.region || "us-east-1"
|
|
1757
|
+
});
|
|
1758
|
+
const sourceDocClient = libDynamodb.DynamoDBDocumentClient.from(sourceDynamoClient);
|
|
1759
|
+
const destDynamoClient = new clientDynamodb.DynamoDBClient({
|
|
1760
|
+
...props.destination.config,
|
|
1761
|
+
region: props.destination.config?.region || "us-east-1"
|
|
1762
|
+
});
|
|
1763
|
+
const destDocClient = libDynamodb.DynamoDBDocumentClient.from(destDynamoClient);
|
|
1764
|
+
let counter = 0;
|
|
1765
|
+
if (props.create) {
|
|
1766
|
+
try {
|
|
1767
|
+
const sourceCommand = new clientDynamodb.DescribeTableCommand({
|
|
1768
|
+
TableName: props.source.tableName
|
|
1769
|
+
});
|
|
1770
|
+
const sourceResponse = await sourceDynamoClient.send(sourceCommand);
|
|
1771
|
+
if (sourceResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1772
|
+
throw new Error("Source table is not active");
|
|
1773
|
+
}
|
|
1774
|
+
const cleanedTable = clearTableSchema(sourceResponse.Table);
|
|
1775
|
+
cleanedTable.TableName = props.destination.tableName;
|
|
1776
|
+
try {
|
|
1777
|
+
const createCommand = new clientDynamodb.CreateTableCommand(cleanedTable);
|
|
1778
|
+
await destDynamoClient.send(createCommand);
|
|
1779
|
+
} catch (error2) {
|
|
1780
|
+
if (error2 instanceof Error && error2.name !== "ResourceInUseException") {
|
|
1781
|
+
throw error2;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
await waitForActive(
|
|
1785
|
+
props.destination.tableName,
|
|
1786
|
+
destDynamoClient,
|
|
1787
|
+
props.log
|
|
1788
|
+
);
|
|
1789
|
+
if (props.schemaOnly) {
|
|
1790
|
+
return { count: 0, status: "SUCCESS", schemaOnly: true };
|
|
1791
|
+
}
|
|
1792
|
+
if (props.continuousBackups) {
|
|
1793
|
+
try {
|
|
1794
|
+
const sourceBackupsCommand = new clientDynamodb.DescribeContinuousBackupsCommand({
|
|
1795
|
+
TableName: props.source.tableName
|
|
1796
|
+
});
|
|
1797
|
+
const sourceBackupsResponse = await sourceDynamoClient.send(
|
|
1798
|
+
sourceBackupsCommand
|
|
1799
|
+
);
|
|
1800
|
+
if (sourceBackupsResponse.ContinuousBackupsDescription?.ContinuousBackupsStatus === "ENABLED") {
|
|
1801
|
+
const updateBackupsCommand = new clientDynamodb.UpdateContinuousBackupsCommand({
|
|
1802
|
+
TableName: props.destination.tableName,
|
|
1803
|
+
PointInTimeRecoverySpecification: {
|
|
1804
|
+
PointInTimeRecoveryEnabled: true
|
|
1805
|
+
}
|
|
1806
|
+
});
|
|
1807
|
+
await destDynamoClient.send(updateBackupsCommand);
|
|
1808
|
+
}
|
|
1809
|
+
} catch (error2) {
|
|
1810
|
+
console.warn("Failed to enable continuous backups:", error2);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
} catch (error2) {
|
|
1814
|
+
signale__default.default.error({ error: error2 });
|
|
1815
|
+
return { count: 0, status: "FAIL" };
|
|
1816
|
+
}
|
|
1817
|
+
} else {
|
|
1818
|
+
try {
|
|
1819
|
+
const sourceCommand = new clientDynamodb.DescribeTableCommand({
|
|
1820
|
+
TableName: props.source.tableName
|
|
1821
|
+
});
|
|
1822
|
+
const sourceResponse = await sourceDynamoClient.send(sourceCommand);
|
|
1823
|
+
if (sourceResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1824
|
+
throw new Error("Source table is not active");
|
|
1825
|
+
}
|
|
1826
|
+
const destCommand = new clientDynamodb.DescribeTableCommand({
|
|
1827
|
+
TableName: props.destination.tableName
|
|
1828
|
+
});
|
|
1829
|
+
const destResponse = await destDynamoClient.send(destCommand);
|
|
1830
|
+
if (destResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1831
|
+
throw new Error("Destination table is not active");
|
|
1832
|
+
}
|
|
1833
|
+
} catch (error2) {
|
|
1834
|
+
signale__default.default.error({ error: error2 });
|
|
1835
|
+
return { count: 0, status: "FAIL" };
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
let lastEvaluatedKey = void 0;
|
|
1839
|
+
while (true) {
|
|
1840
|
+
const scanInput = {
|
|
1841
|
+
TableName: props.source.tableName,
|
|
1842
|
+
Limit: 25,
|
|
1843
|
+
// Process 25 items at a time
|
|
1844
|
+
ExclusiveStartKey: lastEvaluatedKey
|
|
1845
|
+
};
|
|
1846
|
+
const scanCommand = new libDynamodb.ScanCommand(scanInput);
|
|
1847
|
+
const scanResponse = await sourceDocClient.send(
|
|
1848
|
+
scanCommand
|
|
1849
|
+
);
|
|
1850
|
+
const items = scanResponse.Items || [];
|
|
1851
|
+
if (items.length === 0) {
|
|
1852
|
+
break;
|
|
1853
|
+
}
|
|
1854
|
+
const writeRequests = items.map(
|
|
1855
|
+
(item2, index) => ({
|
|
1856
|
+
PutRequest: {
|
|
1857
|
+
Item: props.transform ? props.transform(item2, index) : item2
|
|
1858
|
+
}
|
|
1859
|
+
})
|
|
1860
|
+
);
|
|
1861
|
+
let retries = 0;
|
|
1862
|
+
let unprocessedItems = writeRequests;
|
|
1863
|
+
while (unprocessedItems.length > 0) {
|
|
1864
|
+
const batchWriteCommand = new libDynamodb.BatchWriteCommand({
|
|
1865
|
+
RequestItems: {
|
|
1866
|
+
[props.destination.tableName]: unprocessedItems
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1869
|
+
const batchResponse = await destDocClient.send(batchWriteCommand);
|
|
1870
|
+
const stillUnprocessed = batchResponse.UnprocessedItems?.[props.destination.tableName] || [];
|
|
1871
|
+
counter += unprocessedItems.length - stillUnprocessed.length;
|
|
1872
|
+
if (stillUnprocessed.length > 0) {
|
|
1873
|
+
retries++;
|
|
1874
|
+
unprocessedItems = stillUnprocessed;
|
|
1875
|
+
await sleep4(2 * retries * 100);
|
|
1876
|
+
} else {
|
|
1877
|
+
unprocessedItems = [];
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
process.stdout.write(`\rCopied ${counter} items`);
|
|
1881
|
+
lastEvaluatedKey = scanResponse.LastEvaluatedKey;
|
|
1882
|
+
if (!lastEvaluatedKey) break;
|
|
1883
|
+
}
|
|
1884
|
+
process.stdout.write("\n");
|
|
1885
|
+
return { count: counter, status: "SUCCESS" };
|
|
1886
|
+
} catch (error2) {
|
|
1887
|
+
console.error("Copy operation failed:", error2);
|
|
1888
|
+
return { count: 0, status: "FAIL" };
|
|
1889
|
+
}
|
|
1890
|
+
};
|
|
1662
1891
|
|
|
1663
1892
|
// src/server/aws/sns/index.ts
|
|
1664
1893
|
var sns_exports = {};
|
|
@@ -1765,9 +1994,11 @@ var send2 = (ses, email) => {
|
|
|
1765
1994
|
// src/server/aws/s3/index.ts
|
|
1766
1995
|
var s3_exports = {};
|
|
1767
1996
|
__export(s3_exports, {
|
|
1768
|
-
|
|
1997
|
+
bucketExists: () => bucketExists,
|
|
1769
1998
|
create: () => create6,
|
|
1999
|
+
createBucket: () => createBucket,
|
|
1770
2000
|
createSignedUrl: () => createSignedUrl,
|
|
2001
|
+
deleteBucket: () => deleteBucket,
|
|
1771
2002
|
deleteFile: () => deleteFile,
|
|
1772
2003
|
getFile: () => getFile,
|
|
1773
2004
|
getFileMetadata: () => getFileMetadata,
|
|
@@ -1878,31 +2109,28 @@ var getFileMetadata = async (s3, props) => {
|
|
|
1878
2109
|
throw err;
|
|
1879
2110
|
}
|
|
1880
2111
|
};
|
|
1881
|
-
|
|
1882
|
-
const
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
}
|
|
1899
|
-
console.log(err);
|
|
1900
|
-
throw err;
|
|
2112
|
+
var createBucket = (s3, bucketName) => {
|
|
2113
|
+
const command = new clientS3.CreateBucketCommand({ Bucket: bucketName });
|
|
2114
|
+
return s3.client.send(command);
|
|
2115
|
+
};
|
|
2116
|
+
var deleteBucket = (s3, bucketName) => {
|
|
2117
|
+
const command = new clientS3.DeleteBucketCommand({ Bucket: bucketName });
|
|
2118
|
+
return s3.client.send(command);
|
|
2119
|
+
};
|
|
2120
|
+
var bucketExists = async (s3, bucketName) => {
|
|
2121
|
+
try {
|
|
2122
|
+
const command = new clientS3.HeadBucketCommand({ Bucket: bucketName });
|
|
2123
|
+
await s3.client.send(command);
|
|
2124
|
+
return true;
|
|
2125
|
+
} catch (err) {
|
|
2126
|
+
const awsError = err;
|
|
2127
|
+
if (awsError.$metadata?.httpStatusCode === 404 || awsError.$metadata?.httpStatusCode === 400) {
|
|
2128
|
+
return false;
|
|
1901
2129
|
}
|
|
1902
|
-
|
|
1903
|
-
throw
|
|
2130
|
+
console.log(err);
|
|
2131
|
+
throw err;
|
|
1904
2132
|
}
|
|
1905
|
-
}
|
|
2133
|
+
};
|
|
1906
2134
|
var migrateBucketContents = async (s3, buckets) => {
|
|
1907
2135
|
const command = new clientS3.ListObjectsV2Command({ Bucket: buckets.from });
|
|
1908
2136
|
const srcFiles = await s3.client.send(command);
|
package/dist/server/index.js
CHANGED
|
@@ -3,7 +3,8 @@ import awaitSpawn from 'await-spawn';
|
|
|
3
3
|
import { promises } from 'fs';
|
|
4
4
|
import { ArkErrors } from 'arktype';
|
|
5
5
|
import { DynamoDBDocumentClient, ScanCommand, QueryCommand, DeleteCommand, PutCommand, BatchGetCommand, TransactWriteCommand, BatchWriteCommand } from '@aws-sdk/lib-dynamodb';
|
|
6
|
-
import { DynamoDBClient, DeleteTableCommand, DescribeTableCommand, DynamoDBServiceException } from '@aws-sdk/client-dynamodb';
|
|
6
|
+
import { DynamoDBClient, DeleteTableCommand, DescribeTableCommand, DynamoDBServiceException, CreateTableCommand, DescribeContinuousBackupsCommand, UpdateContinuousBackupsCommand, waitUntilTableExists } from '@aws-sdk/client-dynamodb';
|
|
7
|
+
import signale from 'signale';
|
|
7
8
|
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
|
|
8
9
|
import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
|
|
9
10
|
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
|
|
@@ -1053,6 +1054,7 @@ __export(ddb_exports, {
|
|
|
1053
1054
|
batchDelete: () => batchDelete,
|
|
1054
1055
|
batchGet: () => batchGet,
|
|
1055
1056
|
batchWrite: () => batchWrite,
|
|
1057
|
+
copyTable: () => copyTable,
|
|
1056
1058
|
create: () => create2,
|
|
1057
1059
|
deleteTable: () => deleteTable,
|
|
1058
1060
|
find: () => find,
|
|
@@ -1652,6 +1654,232 @@ var lsiPhash = {
|
|
|
1652
1654
|
name: "phash-lsi",
|
|
1653
1655
|
sk: "phash"
|
|
1654
1656
|
};
|
|
1657
|
+
var validateTableName = (tableName) => {
|
|
1658
|
+
const regex = /^[a-zA-Z0-9_.-]{3,255}$/;
|
|
1659
|
+
if (!regex.test(tableName)) {
|
|
1660
|
+
throw new Error(
|
|
1661
|
+
`tableName must follow AWS naming rules (3-255 length, and only the following characters: a-z, A-Z, 0-9, _-.) but received: ${tableName}`
|
|
1662
|
+
);
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
var clearTableSchema = (table) => {
|
|
1666
|
+
const cleanTable = {
|
|
1667
|
+
TableName: table.TableName,
|
|
1668
|
+
AttributeDefinitions: table.AttributeDefinitions,
|
|
1669
|
+
KeySchema: table.KeySchema
|
|
1670
|
+
};
|
|
1671
|
+
if (table.BillingModeSummary?.BillingMode) {
|
|
1672
|
+
cleanTable.BillingMode = table.BillingModeSummary.BillingMode;
|
|
1673
|
+
}
|
|
1674
|
+
if (table.ProvisionedThroughput && table.BillingModeSummary?.BillingMode !== "PAY_PER_REQUEST") {
|
|
1675
|
+
cleanTable.ProvisionedThroughput = {
|
|
1676
|
+
ReadCapacityUnits: table.ProvisionedThroughput.ReadCapacityUnits,
|
|
1677
|
+
WriteCapacityUnits: table.ProvisionedThroughput.WriteCapacityUnits
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
if (table.LocalSecondaryIndexes && table.LocalSecondaryIndexes.length > 0) {
|
|
1681
|
+
cleanTable.LocalSecondaryIndexes = table.LocalSecondaryIndexes.map(
|
|
1682
|
+
(lsi3) => ({
|
|
1683
|
+
IndexName: lsi3.IndexName,
|
|
1684
|
+
KeySchema: lsi3.KeySchema,
|
|
1685
|
+
Projection: lsi3.Projection
|
|
1686
|
+
})
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
if (table.GlobalSecondaryIndexes && table.GlobalSecondaryIndexes.length > 0) {
|
|
1690
|
+
cleanTable.GlobalSecondaryIndexes = table.GlobalSecondaryIndexes.map(
|
|
1691
|
+
(gsi) => {
|
|
1692
|
+
const cleanGsi = {
|
|
1693
|
+
IndexName: gsi.IndexName,
|
|
1694
|
+
KeySchema: gsi.KeySchema,
|
|
1695
|
+
Projection: gsi.Projection
|
|
1696
|
+
};
|
|
1697
|
+
if (gsi.ProvisionedThroughput && table.BillingModeSummary?.BillingMode !== "PAY_PER_REQUEST") {
|
|
1698
|
+
cleanGsi.ProvisionedThroughput = {
|
|
1699
|
+
ReadCapacityUnits: gsi.ProvisionedThroughput.ReadCapacityUnits,
|
|
1700
|
+
WriteCapacityUnits: gsi.ProvisionedThroughput.WriteCapacityUnits
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
return cleanGsi;
|
|
1704
|
+
}
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
if (table.SSEDescription) {
|
|
1708
|
+
cleanTable.SSESpecification = {
|
|
1709
|
+
Enabled: table.SSEDescription.Status === "ENABLED" || table.SSEDescription.Status === "ENABLING"
|
|
1710
|
+
};
|
|
1711
|
+
if (table.SSEDescription.SSEType === "KMS" && table.SSEDescription.KMSMasterKeyArn) {
|
|
1712
|
+
cleanTable.SSESpecification.SSEType = "KMS";
|
|
1713
|
+
cleanTable.SSESpecification.KMSMasterKeyId = table.SSEDescription.KMSMasterKeyArn;
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
if (table.StreamSpecification) {
|
|
1717
|
+
cleanTable.StreamSpecification = {
|
|
1718
|
+
StreamEnabled: table.StreamSpecification.StreamEnabled,
|
|
1719
|
+
StreamViewType: table.StreamSpecification.StreamViewType
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
return cleanTable;
|
|
1723
|
+
};
|
|
1724
|
+
var waitForActive = async (tableName, client, log2) => {
|
|
1725
|
+
if (log2) {
|
|
1726
|
+
signale.log(`Waiting for table "${tableName}" to become active...`);
|
|
1727
|
+
}
|
|
1728
|
+
await waitUntilTableExists(
|
|
1729
|
+
{
|
|
1730
|
+
client,
|
|
1731
|
+
// Check every 5 seconds
|
|
1732
|
+
minDelay: 5,
|
|
1733
|
+
maxDelay: 5,
|
|
1734
|
+
// Wait up to 10 minutes
|
|
1735
|
+
maxWaitTime: 600
|
|
1736
|
+
},
|
|
1737
|
+
{ TableName: tableName }
|
|
1738
|
+
);
|
|
1739
|
+
if (log2) signale.success(`Table "${tableName}" is now active!`);
|
|
1740
|
+
};
|
|
1741
|
+
var sleep4 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1742
|
+
var copyTable = async (props) => {
|
|
1743
|
+
try {
|
|
1744
|
+
validateTableName(props.source.tableName);
|
|
1745
|
+
validateTableName(props.destination.tableName);
|
|
1746
|
+
const sourceDynamoClient = new DynamoDBClient({
|
|
1747
|
+
...props.source.config,
|
|
1748
|
+
region: props.source.config?.region || "us-east-1"
|
|
1749
|
+
});
|
|
1750
|
+
const sourceDocClient = DynamoDBDocumentClient.from(sourceDynamoClient);
|
|
1751
|
+
const destDynamoClient = new DynamoDBClient({
|
|
1752
|
+
...props.destination.config,
|
|
1753
|
+
region: props.destination.config?.region || "us-east-1"
|
|
1754
|
+
});
|
|
1755
|
+
const destDocClient = DynamoDBDocumentClient.from(destDynamoClient);
|
|
1756
|
+
let counter = 0;
|
|
1757
|
+
if (props.create) {
|
|
1758
|
+
try {
|
|
1759
|
+
const sourceCommand = new DescribeTableCommand({
|
|
1760
|
+
TableName: props.source.tableName
|
|
1761
|
+
});
|
|
1762
|
+
const sourceResponse = await sourceDynamoClient.send(sourceCommand);
|
|
1763
|
+
if (sourceResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1764
|
+
throw new Error("Source table is not active");
|
|
1765
|
+
}
|
|
1766
|
+
const cleanedTable = clearTableSchema(sourceResponse.Table);
|
|
1767
|
+
cleanedTable.TableName = props.destination.tableName;
|
|
1768
|
+
try {
|
|
1769
|
+
const createCommand = new CreateTableCommand(cleanedTable);
|
|
1770
|
+
await destDynamoClient.send(createCommand);
|
|
1771
|
+
} catch (error2) {
|
|
1772
|
+
if (error2 instanceof Error && error2.name !== "ResourceInUseException") {
|
|
1773
|
+
throw error2;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
await waitForActive(
|
|
1777
|
+
props.destination.tableName,
|
|
1778
|
+
destDynamoClient,
|
|
1779
|
+
props.log
|
|
1780
|
+
);
|
|
1781
|
+
if (props.schemaOnly) {
|
|
1782
|
+
return { count: 0, status: "SUCCESS", schemaOnly: true };
|
|
1783
|
+
}
|
|
1784
|
+
if (props.continuousBackups) {
|
|
1785
|
+
try {
|
|
1786
|
+
const sourceBackupsCommand = new DescribeContinuousBackupsCommand({
|
|
1787
|
+
TableName: props.source.tableName
|
|
1788
|
+
});
|
|
1789
|
+
const sourceBackupsResponse = await sourceDynamoClient.send(
|
|
1790
|
+
sourceBackupsCommand
|
|
1791
|
+
);
|
|
1792
|
+
if (sourceBackupsResponse.ContinuousBackupsDescription?.ContinuousBackupsStatus === "ENABLED") {
|
|
1793
|
+
const updateBackupsCommand = new UpdateContinuousBackupsCommand({
|
|
1794
|
+
TableName: props.destination.tableName,
|
|
1795
|
+
PointInTimeRecoverySpecification: {
|
|
1796
|
+
PointInTimeRecoveryEnabled: true
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
await destDynamoClient.send(updateBackupsCommand);
|
|
1800
|
+
}
|
|
1801
|
+
} catch (error2) {
|
|
1802
|
+
console.warn("Failed to enable continuous backups:", error2);
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
} catch (error2) {
|
|
1806
|
+
signale.error({ error: error2 });
|
|
1807
|
+
return { count: 0, status: "FAIL" };
|
|
1808
|
+
}
|
|
1809
|
+
} else {
|
|
1810
|
+
try {
|
|
1811
|
+
const sourceCommand = new DescribeTableCommand({
|
|
1812
|
+
TableName: props.source.tableName
|
|
1813
|
+
});
|
|
1814
|
+
const sourceResponse = await sourceDynamoClient.send(sourceCommand);
|
|
1815
|
+
if (sourceResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1816
|
+
throw new Error("Source table is not active");
|
|
1817
|
+
}
|
|
1818
|
+
const destCommand = new DescribeTableCommand({
|
|
1819
|
+
TableName: props.destination.tableName
|
|
1820
|
+
});
|
|
1821
|
+
const destResponse = await destDynamoClient.send(destCommand);
|
|
1822
|
+
if (destResponse.Table?.TableStatus !== "ACTIVE") {
|
|
1823
|
+
throw new Error("Destination table is not active");
|
|
1824
|
+
}
|
|
1825
|
+
} catch (error2) {
|
|
1826
|
+
signale.error({ error: error2 });
|
|
1827
|
+
return { count: 0, status: "FAIL" };
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
let lastEvaluatedKey = void 0;
|
|
1831
|
+
while (true) {
|
|
1832
|
+
const scanInput = {
|
|
1833
|
+
TableName: props.source.tableName,
|
|
1834
|
+
Limit: 25,
|
|
1835
|
+
// Process 25 items at a time
|
|
1836
|
+
ExclusiveStartKey: lastEvaluatedKey
|
|
1837
|
+
};
|
|
1838
|
+
const scanCommand = new ScanCommand(scanInput);
|
|
1839
|
+
const scanResponse = await sourceDocClient.send(
|
|
1840
|
+
scanCommand
|
|
1841
|
+
);
|
|
1842
|
+
const items = scanResponse.Items || [];
|
|
1843
|
+
if (items.length === 0) {
|
|
1844
|
+
break;
|
|
1845
|
+
}
|
|
1846
|
+
const writeRequests = items.map(
|
|
1847
|
+
(item2, index) => ({
|
|
1848
|
+
PutRequest: {
|
|
1849
|
+
Item: props.transform ? props.transform(item2, index) : item2
|
|
1850
|
+
}
|
|
1851
|
+
})
|
|
1852
|
+
);
|
|
1853
|
+
let retries = 0;
|
|
1854
|
+
let unprocessedItems = writeRequests;
|
|
1855
|
+
while (unprocessedItems.length > 0) {
|
|
1856
|
+
const batchWriteCommand = new BatchWriteCommand({
|
|
1857
|
+
RequestItems: {
|
|
1858
|
+
[props.destination.tableName]: unprocessedItems
|
|
1859
|
+
}
|
|
1860
|
+
});
|
|
1861
|
+
const batchResponse = await destDocClient.send(batchWriteCommand);
|
|
1862
|
+
const stillUnprocessed = batchResponse.UnprocessedItems?.[props.destination.tableName] || [];
|
|
1863
|
+
counter += unprocessedItems.length - stillUnprocessed.length;
|
|
1864
|
+
if (stillUnprocessed.length > 0) {
|
|
1865
|
+
retries++;
|
|
1866
|
+
unprocessedItems = stillUnprocessed;
|
|
1867
|
+
await sleep4(2 * retries * 100);
|
|
1868
|
+
} else {
|
|
1869
|
+
unprocessedItems = [];
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
process.stdout.write(`\rCopied ${counter} items`);
|
|
1873
|
+
lastEvaluatedKey = scanResponse.LastEvaluatedKey;
|
|
1874
|
+
if (!lastEvaluatedKey) break;
|
|
1875
|
+
}
|
|
1876
|
+
process.stdout.write("\n");
|
|
1877
|
+
return { count: counter, status: "SUCCESS" };
|
|
1878
|
+
} catch (error2) {
|
|
1879
|
+
console.error("Copy operation failed:", error2);
|
|
1880
|
+
return { count: 0, status: "FAIL" };
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1655
1883
|
|
|
1656
1884
|
// src/server/aws/sns/index.ts
|
|
1657
1885
|
var sns_exports = {};
|
|
@@ -1758,9 +1986,11 @@ var send2 = (ses, email) => {
|
|
|
1758
1986
|
// src/server/aws/s3/index.ts
|
|
1759
1987
|
var s3_exports = {};
|
|
1760
1988
|
__export(s3_exports, {
|
|
1761
|
-
|
|
1989
|
+
bucketExists: () => bucketExists,
|
|
1762
1990
|
create: () => create6,
|
|
1991
|
+
createBucket: () => createBucket,
|
|
1763
1992
|
createSignedUrl: () => createSignedUrl,
|
|
1993
|
+
deleteBucket: () => deleteBucket,
|
|
1764
1994
|
deleteFile: () => deleteFile,
|
|
1765
1995
|
getFile: () => getFile,
|
|
1766
1996
|
getFileMetadata: () => getFileMetadata,
|
|
@@ -1871,31 +2101,28 @@ var getFileMetadata = async (s3, props) => {
|
|
|
1871
2101
|
throw err;
|
|
1872
2102
|
}
|
|
1873
2103
|
};
|
|
1874
|
-
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
}
|
|
1892
|
-
console.log(err);
|
|
1893
|
-
throw err;
|
|
2104
|
+
var createBucket = (s3, bucketName) => {
|
|
2105
|
+
const command = new CreateBucketCommand({ Bucket: bucketName });
|
|
2106
|
+
return s3.client.send(command);
|
|
2107
|
+
};
|
|
2108
|
+
var deleteBucket = (s3, bucketName) => {
|
|
2109
|
+
const command = new DeleteBucketCommand({ Bucket: bucketName });
|
|
2110
|
+
return s3.client.send(command);
|
|
2111
|
+
};
|
|
2112
|
+
var bucketExists = async (s3, bucketName) => {
|
|
2113
|
+
try {
|
|
2114
|
+
const command = new HeadBucketCommand({ Bucket: bucketName });
|
|
2115
|
+
await s3.client.send(command);
|
|
2116
|
+
return true;
|
|
2117
|
+
} catch (err) {
|
|
2118
|
+
const awsError = err;
|
|
2119
|
+
if (awsError.$metadata?.httpStatusCode === 404 || awsError.$metadata?.httpStatusCode === 400) {
|
|
2120
|
+
return false;
|
|
1894
2121
|
}
|
|
1895
|
-
|
|
1896
|
-
throw
|
|
2122
|
+
console.log(err);
|
|
2123
|
+
throw err;
|
|
1897
2124
|
}
|
|
1898
|
-
}
|
|
2125
|
+
};
|
|
1899
2126
|
var migrateBucketContents = async (s3, buckets) => {
|
|
1900
2127
|
const command = new ListObjectsV2Command({ Bucket: buckets.from });
|
|
1901
2128
|
const srcFiles = await s3.client.send(command);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qstd",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.55",
|
|
4
4
|
"description": "Standard Block component and utilities library with Panda CSS",
|
|
5
5
|
"author": "malin1",
|
|
6
6
|
"license": "MIT",
|
|
@@ -90,7 +90,8 @@
|
|
|
90
90
|
"react-loader-spinner": "^6.1.6",
|
|
91
91
|
"react-spinners": "^0.17.0",
|
|
92
92
|
"use-immer": "^0.11.0",
|
|
93
|
-
"await-spawn": "^4.0.2"
|
|
93
|
+
"await-spawn": "^4.0.2",
|
|
94
|
+
"signale": "^1.4.0"
|
|
94
95
|
},
|
|
95
96
|
"devDependencies": {
|
|
96
97
|
"@eslint/js": "^9.39.1",
|
|
@@ -101,6 +102,7 @@
|
|
|
101
102
|
"@types/node": "^22.10.5",
|
|
102
103
|
"@types/react": "^19.1.12",
|
|
103
104
|
"@types/react-dom": "^19.1.8",
|
|
105
|
+
"@types/signale": "^1.4.7",
|
|
104
106
|
"eslint": "^9.39.1",
|
|
105
107
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
106
108
|
"globals": "^16.2.0",
|