bulkyard 1.0.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/LICENSE +28 -0
- package/README.md +136 -0
- package/lib/commands/bulkyard/extract.d.ts +18 -0
- package/lib/commands/bulkyard/extract.js +84 -0
- package/lib/commands/bulkyard/extract.js.map +1 -0
- package/lib/commands/bulkyard/load.d.ts +19 -0
- package/lib/commands/bulkyard/load.js +98 -0
- package/lib/commands/bulkyard/load.js.map +1 -0
- package/lib/core/config.d.ts +23 -0
- package/lib/core/config.js +52 -0
- package/lib/core/config.js.map +1 -0
- package/lib/core/database.d.ts +15 -0
- package/lib/core/database.js +67 -0
- package/lib/core/database.js.map +1 -0
- package/lib/core/extractor.d.ts +11 -0
- package/lib/core/extractor.js +33 -0
- package/lib/core/extractor.js.map +1 -0
- package/lib/core/loader.d.ts +13 -0
- package/lib/core/loader.js +59 -0
- package/lib/core/loader.js.map +1 -0
- package/lib/core/type-map.d.ts +1 -0
- package/lib/core/type-map.js +32 -0
- package/lib/core/type-map.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/messages/bulkyard.extract.md +55 -0
- package/messages/bulkyard.load.md +59 -0
- package/oclif.lock +7821 -0
- package/oclif.manifest.json +252 -0
- package/package.json +191 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export async function loadObject(conn, db, objConfig) {
|
|
2
|
+
const tableName = objConfig.table ?? objConfig.object;
|
|
3
|
+
try {
|
|
4
|
+
if (!db.tableExists(tableName)) {
|
|
5
|
+
return {
|
|
6
|
+
object: objConfig.object,
|
|
7
|
+
table: tableName,
|
|
8
|
+
totalRecords: 0,
|
|
9
|
+
successCount: 0,
|
|
10
|
+
failureCount: 0,
|
|
11
|
+
success: false,
|
|
12
|
+
errors: [`Table "${tableName}" does not exist in the database.`],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const rows = db.readAllRows(tableName);
|
|
16
|
+
if (rows.length === 0) {
|
|
17
|
+
return {
|
|
18
|
+
object: objConfig.object,
|
|
19
|
+
table: tableName,
|
|
20
|
+
totalRecords: 0,
|
|
21
|
+
successCount: 0,
|
|
22
|
+
failureCount: 0,
|
|
23
|
+
success: true,
|
|
24
|
+
errors: [],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const bulkResult = await conn.bulk2.loadAndWaitForResults({
|
|
28
|
+
object: objConfig.object,
|
|
29
|
+
operation: objConfig.operation,
|
|
30
|
+
input: rows,
|
|
31
|
+
...(objConfig.externalIdField ? { externalIdFieldName: objConfig.externalIdField } : {}),
|
|
32
|
+
});
|
|
33
|
+
const successCount = bulkResult.successfulResults.length;
|
|
34
|
+
const failureCount = bulkResult.failedResults.length;
|
|
35
|
+
const errors = bulkResult.failedResults.map((f) => `${f.sf__Id ?? 'unknown'}: ${f.sf__Error ?? 'unknown error'}`);
|
|
36
|
+
return {
|
|
37
|
+
object: objConfig.object,
|
|
38
|
+
table: tableName,
|
|
39
|
+
totalRecords: rows.length,
|
|
40
|
+
successCount,
|
|
41
|
+
failureCount,
|
|
42
|
+
success: failureCount === 0,
|
|
43
|
+
errors,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
48
|
+
return {
|
|
49
|
+
object: objConfig.object,
|
|
50
|
+
table: tableName,
|
|
51
|
+
totalRecords: 0,
|
|
52
|
+
successCount: 0,
|
|
53
|
+
failureCount: 0,
|
|
54
|
+
success: false,
|
|
55
|
+
errors: [message],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/core/loader.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAgB,EAChB,EAAoB,EACpB,SAA+B;IAE/B,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,IAAI,SAAS,CAAC,MAAM,CAAC;IACtD,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,OAAO;gBACL,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,KAAK,EAAE,SAAS;gBAChB,YAAY,EAAE,CAAC;gBACf,YAAY,EAAE,CAAC;gBACf,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,CAAC,UAAU,SAAS,mCAAmC,CAAC;aACjE,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO;gBACL,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,KAAK,EAAE,SAAS;gBAChB,YAAY,EAAE,CAAC;gBACf,YAAY,EAAE,CAAC;gBACf,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,IAAI;gBACb,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC;YACxD,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,SAAS,EAAE,SAAS,CAAC,SAAsD;YAC3E,KAAK,EAAE,IAAqC;YAC5C,GAAG,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,SAAS,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACzF,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,UAAU,CAAC,iBAAiB,CAAC,MAAM,CAAC;QACzD,MAAM,YAAY,GAAG,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC;QACrD,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,SAAS,KAAK,CAAC,CAAC,SAAS,IAAI,eAAe,EAAE,CAAC,CAAC;QAElH,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,IAAI,CAAC,MAAM;YACzB,YAAY;YACZ,YAAY;YACZ,OAAO,EAAE,YAAY,KAAK,CAAC;YAC3B,MAAM;SACP,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,YAAY,EAAE,CAAC;YACf,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,CAAC,OAAO,CAAC;SAClB,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function sfTypeToSqlite(sfType: string): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const SF_TYPE_TO_SQLITE = {
|
|
2
|
+
int: 'INTEGER',
|
|
3
|
+
integer: 'INTEGER',
|
|
4
|
+
boolean: 'INTEGER',
|
|
5
|
+
double: 'REAL',
|
|
6
|
+
currency: 'REAL',
|
|
7
|
+
percent: 'REAL',
|
|
8
|
+
long: 'INTEGER',
|
|
9
|
+
string: 'TEXT',
|
|
10
|
+
id: 'TEXT',
|
|
11
|
+
reference: 'TEXT',
|
|
12
|
+
textarea: 'TEXT',
|
|
13
|
+
url: 'TEXT',
|
|
14
|
+
email: 'TEXT',
|
|
15
|
+
phone: 'TEXT',
|
|
16
|
+
picklist: 'TEXT',
|
|
17
|
+
multipicklist: 'TEXT',
|
|
18
|
+
combobox: 'TEXT',
|
|
19
|
+
date: 'TEXT',
|
|
20
|
+
datetime: 'TEXT',
|
|
21
|
+
time: 'TEXT',
|
|
22
|
+
encryptedstring: 'TEXT',
|
|
23
|
+
address: 'TEXT',
|
|
24
|
+
location: 'TEXT',
|
|
25
|
+
anytype: 'TEXT',
|
|
26
|
+
complexvalue: 'TEXT',
|
|
27
|
+
base64: 'BLOB',
|
|
28
|
+
};
|
|
29
|
+
export function sfTypeToSqlite(sfType) {
|
|
30
|
+
return SF_TYPE_TO_SQLITE[sfType.toLowerCase()] ?? 'TEXT';
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=type-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-map.js","sourceRoot":"","sources":["../../src/core/type-map.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAA2B;IAChD,GAAG,EAAE,SAAS;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,MAAM;IACf,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,MAAM;IACd,EAAE,EAAE,MAAM;IACV,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,GAAG,EAAE,MAAM;IACX,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,MAAM;IAChB,aAAa,EAAE,MAAM;IACrB,QAAQ,EAAE,MAAM;IAChB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,MAAM;IAChB,IAAI,EAAE,MAAM;IACZ,eAAe,EAAE,MAAM;IACvB,OAAO,EAAE,MAAM;IACf,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,MAAM;IACf,YAAY,EAAE,MAAM;IACpB,MAAM,EAAE,MAAM;CACf,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,iBAAiB,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,IAAI,MAAM,CAAC;AAC3D,CAAC"}
|
package/lib/index.d.ts
ADDED
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# summary
|
|
2
|
+
|
|
3
|
+
Extract data from a Salesforce org into a local SQLite database using Bulk API 2.0.
|
|
4
|
+
|
|
5
|
+
# description
|
|
6
|
+
|
|
7
|
+
Reads a YAML config file to determine which objects to query, then uses Bulk API 2.0 to extract records and write them to a local SQLite database. Each object is stored in its own table.
|
|
8
|
+
|
|
9
|
+
Alternatively, use --sobject and --query to extract a single object without a config file.
|
|
10
|
+
|
|
11
|
+
# examples
|
|
12
|
+
|
|
13
|
+
- Extract data using a config file:
|
|
14
|
+
|
|
15
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg --config-file bulkyard.config.yml
|
|
16
|
+
|
|
17
|
+
- Extract a single object inline:
|
|
18
|
+
|
|
19
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg --sobject Account --query "SELECT Id, Name FROM Account"
|
|
20
|
+
|
|
21
|
+
- Extract inline with a custom database and table name:
|
|
22
|
+
|
|
23
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg -s Account -q "SELECT Id, Name FROM Account" -d my.db -t Account_Backup
|
|
24
|
+
|
|
25
|
+
# flags.config-file.summary
|
|
26
|
+
|
|
27
|
+
Path to the YAML config file.
|
|
28
|
+
|
|
29
|
+
# flags.sobject.summary
|
|
30
|
+
|
|
31
|
+
Salesforce object API name (e.g. Account, Contact).
|
|
32
|
+
|
|
33
|
+
# flags.query.summary
|
|
34
|
+
|
|
35
|
+
SOQL query to execute for extraction.
|
|
36
|
+
|
|
37
|
+
# flags.database.summary
|
|
38
|
+
|
|
39
|
+
Path to the SQLite database file.
|
|
40
|
+
|
|
41
|
+
# flags.table.summary
|
|
42
|
+
|
|
43
|
+
SQLite table name override (defaults to the object name).
|
|
44
|
+
|
|
45
|
+
# info.extracting
|
|
46
|
+
|
|
47
|
+
Extracting %s...
|
|
48
|
+
|
|
49
|
+
# info.complete
|
|
50
|
+
|
|
51
|
+
Extraction complete.
|
|
52
|
+
|
|
53
|
+
# error.objectFailed
|
|
54
|
+
|
|
55
|
+
Failed to extract %s: %s
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# summary
|
|
2
|
+
|
|
3
|
+
Load data from a local SQLite database into a Salesforce org using Bulk API 2.0.
|
|
4
|
+
|
|
5
|
+
# description
|
|
6
|
+
|
|
7
|
+
Reads a YAML config file to determine which tables to load, then uses Bulk API 2.0 to insert, update, or upsert records from a local SQLite database into the target Salesforce org.
|
|
8
|
+
|
|
9
|
+
Alternatively, use --sobject and --operation to load a single object without a config file.
|
|
10
|
+
|
|
11
|
+
# examples
|
|
12
|
+
|
|
13
|
+
- Load data using a config file:
|
|
14
|
+
|
|
15
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg --config-file bulkyard.config.yml
|
|
16
|
+
|
|
17
|
+
- Load a single object inline:
|
|
18
|
+
|
|
19
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg --sobject Account --operation upsert --external-id-field Id
|
|
20
|
+
|
|
21
|
+
- Load inline with a custom database and table name:
|
|
22
|
+
|
|
23
|
+
<%= config.bin %> <%= command.id %> --target-org myOrg -s Account -p insert -d my.db -t Account_Staging
|
|
24
|
+
|
|
25
|
+
# flags.config-file.summary
|
|
26
|
+
|
|
27
|
+
Path to the YAML config file.
|
|
28
|
+
|
|
29
|
+
# flags.sobject.summary
|
|
30
|
+
|
|
31
|
+
Salesforce object API name (e.g. Account, Contact).
|
|
32
|
+
|
|
33
|
+
# flags.operation.summary
|
|
34
|
+
|
|
35
|
+
Bulk API operation: insert, update, upsert, or delete.
|
|
36
|
+
|
|
37
|
+
# flags.external-id-field.summary
|
|
38
|
+
|
|
39
|
+
External ID field for upsert operations.
|
|
40
|
+
|
|
41
|
+
# flags.database.summary
|
|
42
|
+
|
|
43
|
+
Path to the SQLite database file.
|
|
44
|
+
|
|
45
|
+
# flags.table.summary
|
|
46
|
+
|
|
47
|
+
SQLite table name override (defaults to the object name).
|
|
48
|
+
|
|
49
|
+
# info.loading
|
|
50
|
+
|
|
51
|
+
Loading %s...
|
|
52
|
+
|
|
53
|
+
# info.complete
|
|
54
|
+
|
|
55
|
+
Load complete.
|
|
56
|
+
|
|
57
|
+
# error.objectFailed
|
|
58
|
+
|
|
59
|
+
Failed to load %s: %s
|