@servicenow/sdk-build-core 4.6.1 → 4.7.1
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/compiler.d.ts +2 -0
- package/dist/compiler.js +13 -7
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/now-config.d.ts +37 -0
- package/dist/now-config.js +9 -0
- package/dist/now-config.js.map +1 -1
- package/dist/package-inventory.d.ts +15 -0
- package/dist/package-inventory.js +59 -0
- package/dist/package-inventory.js.map +1 -0
- package/dist/plugins/context.d.ts +2 -2
- package/dist/plugins/index.d.ts +0 -1
- package/dist/plugins/index.js +0 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/plugin.d.ts +41 -53
- package/dist/plugins/plugin.js +502 -160
- package/dist/plugins/plugin.js.map +1 -1
- package/dist/plugins/shape.d.ts +13 -2
- package/dist/plugins/shape.js +96 -15
- package/dist/plugins/shape.js.map +1 -1
- package/dist/taxonomy.js +7 -2
- package/dist/taxonomy.js.map +1 -1
- package/dist/telemetry/clients/detect-agent.d.ts +4 -0
- package/dist/telemetry/clients/detect-agent.js +84 -0
- package/dist/telemetry/clients/detect-agent.js.map +1 -0
- package/dist/telemetry/clients/node-client.d.ts +2 -0
- package/dist/telemetry/clients/node-client.js +10 -9
- package/dist/telemetry/clients/node-client.js.map +1 -1
- package/dist/telemetry/index.d.ts +1 -1
- package/now.config.schema.json +19 -0
- package/package.json +9 -5
- package/src/compiler.ts +14 -7
- package/src/index.ts +1 -0
- package/src/now-config.ts +11 -0
- package/src/package-inventory.ts +75 -0
- package/src/plugins/context.ts +2 -2
- package/src/plugins/index.ts +0 -1
- package/src/plugins/plugin.ts +682 -228
- package/src/plugins/shape.ts +115 -24
- package/src/taxonomy.ts +8 -2
- package/src/telemetry/clients/detect-agent.ts +88 -0
- package/src/telemetry/clients/node-client.ts +12 -8
- package/src/telemetry/index.ts +1 -1
- package/dist/plugins/cache.d.ts +0 -15
- package/dist/plugins/cache.js +0 -22
- package/dist/plugins/cache.js.map +0 -1
- package/dist/plugins/usage.d.ts +0 -11
- package/dist/plugins/usage.js +0 -26
- package/dist/plugins/usage.js.map +0 -1
- package/src/plugins/cache.ts +0 -23
- package/src/plugins/usage.ts +0 -26
package/src/compiler.ts
CHANGED
|
@@ -40,6 +40,7 @@ export class Compiler extends ts.Project {
|
|
|
40
40
|
private readonly rootDir: string
|
|
41
41
|
private readonly sourceFileToRelativeModuleSpecifier: Record<string, string> = {}
|
|
42
42
|
private readonly generatedTableFilePath: string
|
|
43
|
+
private readonly generatedBootstrappedTablesFilePath: string
|
|
43
44
|
private moduleProject: ts.Project | undefined
|
|
44
45
|
|
|
45
46
|
constructor(
|
|
@@ -63,6 +64,7 @@ export class Compiler extends ts.Project {
|
|
|
63
64
|
|
|
64
65
|
this.rootDir = rootDir
|
|
65
66
|
this.generatedTableFilePath = path.join(this.rootDir, '$$GENERATED$$_common_table.ts')
|
|
67
|
+
this.generatedBootstrappedTablesFilePath = path.join(this.rootDir, '$$GENERATED$$_bootstrapped_tables.ts')
|
|
66
68
|
this.addGlobalTableDefinitionFile()
|
|
67
69
|
if (typesDir) {
|
|
68
70
|
this.addTypesTableDeclaration(typesDir)
|
|
@@ -89,7 +91,7 @@ export class Compiler extends ts.Project {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
addGlobalTableDefinitionFile() {
|
|
92
|
-
const
|
|
94
|
+
const tableDefinitionContent = `
|
|
93
95
|
import '@servicenow/sdk/global'
|
|
94
96
|
import { Table } from '@servicenow/sdk/core'
|
|
95
97
|
|
|
@@ -105,10 +107,18 @@ declare global {
|
|
|
105
107
|
}
|
|
106
108
|
}
|
|
107
109
|
`
|
|
108
|
-
this.createSourceFile(this.generatedTableFilePath,
|
|
110
|
+
this.createSourceFile(this.generatedTableFilePath, tableDefinitionContent, {
|
|
109
111
|
overwrite: true,
|
|
110
112
|
scriptKind: ts.ScriptKind.TS,
|
|
111
113
|
})
|
|
114
|
+
this.createSourceFile(this.generatedBootstrappedTablesFilePath, tableDefinitionContent, {
|
|
115
|
+
overwrite: true,
|
|
116
|
+
scriptKind: ts.ScriptKind.TS,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getGeneratedBootstrappedTablesFile(): ts.SourceFile | undefined {
|
|
121
|
+
return this.getSourceFile(this.generatedBootstrappedTablesFilePath)
|
|
112
122
|
}
|
|
113
123
|
|
|
114
124
|
/**
|
|
@@ -332,16 +342,15 @@ declare module '*.html' {
|
|
|
332
342
|
return this.generatedTableFilePath === sourcePath
|
|
333
343
|
}
|
|
334
344
|
|
|
335
|
-
// Cache for table column types that need coercion (boolean/number only)
|
|
345
|
+
// Cache for table column types that need coercion (boolean/number only).
|
|
346
|
+
// Populated on first call to getTableColumnTypes(); subsequent calls return immediately.
|
|
336
347
|
private tableColumnTypesCache = new Map<string, Map<string, 'boolean' | 'number' | 'array' | 'array-optional'>>()
|
|
337
348
|
|
|
338
349
|
getTableColumnTypes(tableName: string): Map<string, 'boolean' | 'number' | 'array' | 'array-optional'> | undefined {
|
|
339
|
-
// Return cached value if available
|
|
340
350
|
if (this.tableColumnTypesCache.has(tableName)) {
|
|
341
351
|
return this.tableColumnTypesCache.get(tableName)
|
|
342
352
|
}
|
|
343
353
|
|
|
344
|
-
// Lazily resolve and cache on first access
|
|
345
354
|
const tempFilePath = path.join(this.rootDir, 'src', '$$TEMP_DATA_RESOLVER$$.ts')
|
|
346
355
|
const typeDeclaration = `type T = import('@servicenow/sdk/core').Data<'${tableName}'>`
|
|
347
356
|
|
|
@@ -367,10 +376,8 @@ declare module '*.html' {
|
|
|
367
376
|
if (typeText === 'boolean' || typeText === 'number') {
|
|
368
377
|
columnTypes.set(property.getName(), typeText)
|
|
369
378
|
} else if (typeText.match(/^\(.*\)\[\]$/)) {
|
|
370
|
-
// Matches `(...)[]` -> this field should always be an array
|
|
371
379
|
columnTypes.set(property.getName(), 'array')
|
|
372
380
|
} else if (typeText.match(/^.*\[\]$/)) {
|
|
373
|
-
// Matches `[]` -> this field may be an array or a single value
|
|
374
381
|
columnTypes.set(property.getName(), 'array-optional')
|
|
375
382
|
}
|
|
376
383
|
})
|
package/src/index.ts
CHANGED
package/src/now-config.ts
CHANGED
|
@@ -136,6 +136,15 @@ const NetworkPolicySchema = z
|
|
|
136
136
|
|
|
137
137
|
export type NetworkPolicy = z.infer<typeof NetworkPolicySchema>
|
|
138
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Schema for Linter configuration options
|
|
141
|
+
*/
|
|
142
|
+
const LinterSchema = z
|
|
143
|
+
.object({
|
|
144
|
+
module: z.object({ enabled: z.boolean().default(true) }),
|
|
145
|
+
})
|
|
146
|
+
.default({ module: { enabled: true } })
|
|
147
|
+
|
|
139
148
|
/**
|
|
140
149
|
* Network Pillar Schema for Wildcard Policy
|
|
141
150
|
*/
|
|
@@ -248,6 +257,7 @@ const NowConfigSchema = z
|
|
|
248
257
|
trustedModules: z.array(z.string()).default([]),
|
|
249
258
|
tsconfigPath: z.string().optional(),
|
|
250
259
|
scripts: z.record(z.string(), z.string()).default({}),
|
|
260
|
+
linter: LinterSchema,
|
|
251
261
|
tableOutputFormat: z.enum(['bootstrap', 'component']).default('bootstrap').optional(),
|
|
252
262
|
defaultLanguage: z
|
|
253
263
|
.string()
|
|
@@ -334,6 +344,7 @@ const NowConfigSchema = z
|
|
|
334
344
|
| 'description'
|
|
335
345
|
| 'installedAsDependency'
|
|
336
346
|
| 'scripts'
|
|
347
|
+
| 'linter'
|
|
337
348
|
| 'tableOutputFormat'
|
|
338
349
|
| 'defaultLanguage'
|
|
339
350
|
| 'tableDefaultLanguage'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { crypto } from './crypto'
|
|
2
|
+
import { FileSystem } from './fs'
|
|
3
|
+
import { path } from './path'
|
|
4
|
+
|
|
5
|
+
export interface PackageInventoryConfig {
|
|
6
|
+
build: string
|
|
7
|
+
type: 'scoped' | 'global'
|
|
8
|
+
appVersion: string
|
|
9
|
+
version?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Generate SHA-256 hash for file content (matches ServiceNow's package_inventory.csv format)
|
|
14
|
+
*/
|
|
15
|
+
export async function sha256(content: string | Uint8Array): Promise<string> {
|
|
16
|
+
const data = typeof content === 'string' ? new TextEncoder().encode(content) : content
|
|
17
|
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data)
|
|
18
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer))
|
|
19
|
+
return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Recursively find all files in a directory
|
|
24
|
+
*/
|
|
25
|
+
function findAllFiles(fs: FileSystem, dir: string, baseDir: string): string[] {
|
|
26
|
+
const files: string[] = []
|
|
27
|
+
|
|
28
|
+
if (!FileSystem.existsSync(fs, dir)) {
|
|
29
|
+
return files
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
33
|
+
const fullPath = path.join(dir, entry.name)
|
|
34
|
+
if (entry.isDirectory()) {
|
|
35
|
+
files.push(...findAllFiles(fs, fullPath, baseDir))
|
|
36
|
+
} else {
|
|
37
|
+
files.push(path.relative(baseDir, fullPath))
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return files
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Generate package_inventory.csv from files in a directory on disk (for pack command)
|
|
46
|
+
*/
|
|
47
|
+
export async function generatePackageInventoryFromDirectory(
|
|
48
|
+
fs: FileSystem,
|
|
49
|
+
appOutputDir: string,
|
|
50
|
+
config: PackageInventoryConfig
|
|
51
|
+
): Promise<string> {
|
|
52
|
+
const headerLines: string[] = [
|
|
53
|
+
`#build=${config.build}`,
|
|
54
|
+
`#appVersion=${config.appVersion}`,
|
|
55
|
+
`#type=${config.type}`,
|
|
56
|
+
`#version=${config.version ?? '1.0.0'}`,
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
// Find all files in directory
|
|
60
|
+
const filePaths = findAllFiles(fs, appOutputDir, appOutputDir)
|
|
61
|
+
.filter((f) => !f.endsWith('package_inventory.csv'))
|
|
62
|
+
.sort()
|
|
63
|
+
|
|
64
|
+
// Hash all files in parallel for better performance
|
|
65
|
+
const hashResults = await Promise.all(
|
|
66
|
+
filePaths.map(async (relativePath) => {
|
|
67
|
+
const fullPath = path.join(appOutputDir, relativePath)
|
|
68
|
+
const content = fs.readFileSync(fullPath)
|
|
69
|
+
const hash = await sha256(content)
|
|
70
|
+
return `${relativePath};${hash}`
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return `${[...headerLines, ...hashResults].join('\n')}\n`
|
|
75
|
+
}
|
package/src/plugins/context.ts
CHANGED
|
@@ -43,12 +43,12 @@ export interface Diagnostics {
|
|
|
43
43
|
|
|
44
44
|
export interface Transform {
|
|
45
45
|
toShape(node: ts.Node, ...plugins: Plugin[]): Promise<Result<Shape>>
|
|
46
|
-
|
|
47
|
-
toSubclass<const S extends Shape>(shape: S, ...plugins: Plugin[]): Promise<Result<S>>
|
|
46
|
+
toSubclass<const S extends Shape>(shape: S, ...plugins: Plugin[]): Promise<S>
|
|
48
47
|
toRecord(node: ts.Node, ...plugins: Plugin[]): Promise<Result<Record>>
|
|
49
48
|
toRecord(shape: Shape, ...plugins: Plugin[]): Promise<Result<Record>>
|
|
50
49
|
toRecord(file: File, ...plugins: Plugin[]): Promise<Result<Record>>
|
|
51
50
|
toRecord(source: ts.Node | Shape | File, ...plugins: Plugin[]): Promise<Result<Record>>
|
|
51
|
+
recordToShape(record: Record, database: Database, ...plugins: Plugin[]): Promise<Result<Shape>>
|
|
52
52
|
getUpdateName(record: Record, ...plugins: Plugin[]): Promise<string>
|
|
53
53
|
}
|
|
54
54
|
|