Skip to content

Commit 61fab91

Browse files
committed
Use newly separated programming model package
1 parent 07e0fc4 commit 61fab91

16 files changed

+684
-430
lines changed

azure-pipelines/build.yml

-26
Original file line numberDiff line numberDiff line change
@@ -68,38 +68,12 @@ jobs:
6868
publishVstsFeed: 'e6a70c92-4128-439f-8012-382fe78d6396/f37f760c-aebd-443e-9714-ce725cd427df'
6969
allowPackageConflicts: true
7070
displayName: 'Push NuGet package to the AzureFunctionsPreRelease feed'
71-
# In order for the SBOM to be accurate, we want to explicitly specify the components folder, but the types package doesn't have any components
72-
# We'll create an empty folder that _would_ store the components if it had any
73-
- bash: |
74-
mkdir types/node_modules
75-
displayName: 'mkdir types/node_modules'
76-
- task: CopyFiles@2
77-
displayName: 'Copy types files to staging'
78-
inputs:
79-
sourceFolder: '$(Build.SourcesDirectory)/types'
80-
contents: |
81-
index.d.ts
82-
LICENSE
83-
package.json
84-
README.md
85-
targetFolder: '$(Build.ArtifactStagingDirectory)/types'
86-
cleanTargetFolder: true
87-
- task: ManifestGeneratorTask@0
88-
displayName: 'Generate SBOM for types'
89-
inputs:
90-
BuildDropPath: '$(Build.ArtifactStagingDirectory)/types'
91-
BuildComponentPath: '$(Build.SourcesDirectory)/types/node_modules'
92-
PackageName: 'Azure Functions Type Definitions'
93-
- script: npm pack
94-
displayName: 'npm pack types'
95-
workingDirectory: '$(Build.ArtifactStagingDirectory)/types'
9671
- task: CopyFiles@2
9772
displayName: 'Copy packages to staging drop folder'
9873
inputs:
9974
sourceFolder: '$(Build.ArtifactStagingDirectory)'
10075
contents: |
10176
worker/*.nupkg
102-
types/*.tgz
10377
targetFolder: '$(Build.ArtifactStagingDirectory)/drop'
10478
cleanTargetFolder: true
10579
- task: PublishPipelineArtifact@1

package-lock.json

+22-31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+4-7
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
"description": "Microsoft Azure Functions NodeJS Worker",
66
"license": "(MIT OR Apache-2.0)",
77
"dependencies": {
8+
"@azure/functions": "file:../js-framework/azure-functions-3.4.0.tgz",
89
"@grpc/grpc-js": "^1.2.7",
910
"@grpc/proto-loader": "^0.6.4",
1011
"blocked-at": "^1.2.0",
1112
"fs-extra": "^10.0.1",
12-
"long": "^4.0.0",
13-
"minimist": "^1.2.5",
14-
"uuid": "^8.3.0"
13+
"minimist": "^1.2.5"
1514
},
1615
"devDependencies": {
1716
"@types/blocked-at": "^1.0.1",
@@ -49,8 +48,6 @@
4948
"sinon": "^7.0.0",
5049
"ts-node": "^3.3.0",
5150
"typescript": "^4.5.5",
52-
"typescript3": "npm:typescript@~3.7.0",
53-
"typescript4": "npm:typescript@~4.0.0",
5451
"webpack": "^5.72.1",
5552
"webpack-cli": "^4.8.0"
5653
},
@@ -64,13 +61,13 @@
6461
},
6562
"scripts": {
6663
"clean": "rimraf dist && rimraf azure-functions-language-worker-protobuf/src/rpc*",
67-
"build": "rimraf dist && npm run gen && shx mkdir -p dist/azure-functions-language-worker-protobuf/src && shx cp azure-functions-language-worker-protobuf/src/rpc.* dist/azure-functions-language-worker-protobuf/src/. && node ./node_modules/typescript/bin/tsc",
64+
"build": "rimraf dist && npm run gen && shx mkdir -p dist/azure-functions-language-worker-protobuf/src && shx cp azure-functions-language-worker-protobuf/src/rpc.* dist/azure-functions-language-worker-protobuf/src/. && tsc",
6865
"gen": "node scripts/generateProtos.js",
6966
"test": "mocha -r ts-node/register \"./test/**/*.ts\" --reporter mocha-multi-reporters --reporter-options configFile=test/mochaReporterOptions.json",
7067
"lint": "eslint .",
7168
"lint-fix": "eslint . --fix",
7269
"updateVersion": "ts-node ./scripts/updateVersion.ts",
73-
"watch": "node ./node_modules/typescript/bin/tsc --watch",
70+
"watch": "tsc --watch",
7471
"webpack": "webpack --mode production"
7572
},
7673
"files": [

scripts/updateVersion.ts

+2-29
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import * as semver from 'semver';
99

1010
const repoRoot = path.join(__dirname, '..');
1111
const packageJsonPath = path.join(repoRoot, 'package.json');
12-
const typesRoot = path.join(repoRoot, 'types');
13-
const typesPackageJsonPath = path.join(typesRoot, 'package.json');
1412
const nuspecPath = path.join(repoRoot, 'Worker.nuspec');
1513
const nuspecVersionRegex = /<version>(.*)\$prereleaseSuffix\$<\/version>/i;
1614
const constantsPath = path.join(repoRoot, 'src', 'constants.ts');
@@ -24,9 +22,6 @@ if (args.validate) {
2422
} else {
2523
console.log(`This script can be used to either update the version of the worker or validate that the repo is in a valid state with regards to versioning.
2624
27-
NOTE: For the types package, only the major & minor version need to match the worker. We follow the same pattern as DefinitelyTyped as described here:
28-
https://github.com/DefinitelyTyped/DefinitelyTyped#how-do-definitely-typed-package-versions-relate-to-versions-of-the-corresponding-library
29-
3025
Example usage:
3126
3227
npm run updateVersion -- --version 3.3.0
@@ -39,35 +34,21 @@ function validateVersion() {
3934
const packageJson = readJSONSync(packageJsonPath);
4035
const packageJsonVersion = packageJson.version;
4136

42-
const typesPackageJson = readJSONSync(typesPackageJsonPath);
43-
const typesPackageJsonVersion = typesPackageJson.version;
44-
4537
const nuspecVersion = getVersion(nuspecPath, nuspecVersionRegex);
4638

4739
const constantsVersion = getVersion(constantsPath, constantsVersionRegex);
4840

4941
console.log('Found the following versions:');
5042
console.log(`- package.json: ${packageJsonVersion}`);
51-
console.log(`- types/package.json: ${typesPackageJsonVersion}`);
5243
console.log(`- Worker.nuspec: ${nuspecVersion}`);
5344
console.log(`- src/constants.ts: ${constantsVersion}`);
5445

5546
const parsedVersion = semver.parse(packageJsonVersion);
56-
const parsedTypesVersion = semver.parse(typesPackageJsonVersion);
57-
58-
if (
59-
!packageJsonVersion ||
60-
!nuspecVersion ||
61-
!constantsVersion ||
62-
!typesPackageJsonVersion ||
63-
!parsedVersion ||
64-
!parsedTypesVersion
65-
) {
47+
48+
if (!packageJsonVersion || !nuspecVersion || !constantsVersion || !parsedVersion) {
6649
throw new Error('Failed to detect valid versions in all expected files');
6750
} else if (nuspecVersion !== packageJsonVersion || constantsVersion !== packageJsonVersion) {
6851
throw new Error(`Worker versions do not match.`);
69-
} else if (parsedVersion.major !== parsedTypesVersion.major || parsedVersion.minor !== parsedTypesVersion.minor) {
70-
throw new Error(`Types package does not match the major/minor version of the worker.`);
7152
} else {
7253
console.log('Versions match! 🎉');
7354
}
@@ -84,15 +65,7 @@ function getVersion(filePath: string, regex: RegExp): string {
8465

8566
function updateVersion(newVersion: string) {
8667
updatePackageJsonVersion(repoRoot, newVersion);
87-
88-
if (newVersion.endsWith('.0')) {
89-
updatePackageJsonVersion(typesRoot, newVersion);
90-
} else {
91-
console.log(`Skipping types/package.json because this is a patch version.`);
92-
}
93-
9468
updateVersionByRegex(nuspecPath, nuspecVersionRegex, newVersion);
95-
9669
updateVersionByRegex(constantsPath, constantsVersionRegex, newVersion);
9770
}
9871

src/FunctionLoader.ts

+26-29
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,60 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License.
33

4+
import { FunctionCallback } from '@azure/functions-core';
45
import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc';
5-
import { FunctionInfo } from './FunctionInfo';
66
import { loadScriptFile } from './loadScriptFile';
77
import { PackageJson } from './parsers/parsePackageJson';
88
import { InternalException } from './utils/InternalException';
99
import { nonNullProp } from './utils/nonNull';
1010

1111
export interface IFunctionLoader {
1212
load(functionId: string, metadata: rpc.IRpcFunctionMetadata, packageJson: PackageJson): Promise<void>;
13-
getInfo(functionId: string): FunctionInfo;
14-
getFunc(functionId: string): Function;
13+
getRpcMetadata(functionId: string): rpc.IRpcFunctionMetadata;
14+
getCallback(functionId: string): FunctionCallback;
1515
}
1616

17-
export class FunctionLoader implements IFunctionLoader {
18-
#loadedFunctions: {
19-
[k: string]: {
20-
info: FunctionInfo;
21-
func: Function;
22-
thisArg: unknown;
23-
};
24-
} = {};
17+
interface LoadedFunction {
18+
metadata: rpc.IRpcFunctionMetadata;
19+
callback: FunctionCallback;
20+
thisArg: unknown;
21+
}
22+
23+
export class FunctionLoader<TContext = unknown> {
24+
#loadedFunctions: { [k: string]: LoadedFunction | undefined } = {};
2525

2626
async load(functionId: string, metadata: rpc.IRpcFunctionMetadata, packageJson: PackageJson): Promise<void> {
2727
if (metadata.isProxy === true) {
2828
return;
2929
}
3030
const script: any = await loadScriptFile(nonNullProp(metadata, 'scriptFile'), packageJson);
3131
const entryPoint = <string>(metadata && metadata.entryPoint);
32-
const [userFunction, thisArg] = getEntryPoint(script, entryPoint);
33-
this.#loadedFunctions[functionId] = {
34-
info: new FunctionInfo(metadata),
35-
func: userFunction,
36-
thisArg,
37-
};
32+
const [callback, thisArg] = getEntryPoint(script, entryPoint);
33+
this.#loadedFunctions[functionId] = { metadata, callback, thisArg };
3834
}
3935

40-
getInfo(functionId: string): FunctionInfo {
41-
const loadedFunction = this.#loadedFunctions[functionId];
42-
if (loadedFunction && loadedFunction.info) {
43-
return loadedFunction.info;
44-
} else {
45-
throw new InternalException(`Function info for '${functionId}' is not loaded and cannot be invoked.`);
46-
}
36+
getRpcMetadata(functionId: string): rpc.IRpcFunctionMetadata {
37+
const loadedFunction = this.#getLoadedFunction(functionId);
38+
return loadedFunction.metadata;
39+
}
40+
41+
getCallback(functionId: string): FunctionCallback<TContext> {
42+
const loadedFunction = this.#getLoadedFunction(functionId);
43+
// `bind` is necessary to set the `this` arg, but it's also nice because it makes a clone of the function, preventing this invocation from affecting future invocations
44+
return loadedFunction.callback.bind(loadedFunction.thisArg);
4745
}
4846

49-
getFunc(functionId: string): Function {
47+
#getLoadedFunction(functionId: string): LoadedFunction {
5048
const loadedFunction = this.#loadedFunctions[functionId];
51-
if (loadedFunction && loadedFunction.func) {
52-
// `bind` is necessary to set the `this` arg, but it's also nice because it makes a clone of the function, preventing this invocation from affecting future invocations
53-
return loadedFunction.func.bind(loadedFunction.thisArg);
49+
if (loadedFunction) {
50+
return loadedFunction;
5451
} else {
5552
throw new InternalException(`Function code for '${functionId}' is not loaded and cannot be invoked.`);
5653
}
5754
}
5855
}
5956

60-
function getEntryPoint(f: any, entryPoint?: string): [Function, unknown] {
57+
function getEntryPoint(f: any, entryPoint?: string): [FunctionCallback, unknown] {
6158
let thisArg: unknown;
6259
if (f !== null && typeof f === 'object') {
6360
thisArg = f;

src/WorkerChannel.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
import { HookCallback, HookContext, HookData } from '@azure/functions-core';
4+
import { HookCallback, HookContext, HookData, ProgrammingModel } from '@azure/functions-core';
55
import { AzureFunctionsRpcMessages as rpc } from '../azure-functions-language-worker-protobuf/src/rpc';
66
import { Disposable } from './Disposable';
77
import { IFunctionLoader } from './FunctionLoader';
@@ -27,6 +27,7 @@ export class WorkerChannel {
2727
* this hook data is limited to the app-level scope and persisted only for app-level hooks
2828
*/
2929
appLevelOnlyHookData: HookData = {};
30+
programmingModel?: ProgrammingModel<unknown>;
3031
#preInvocationHooks: HookCallback[] = [];
3132
#postInvocationHooks: HookCallback[] = [];
3233
#appStartHooks: HookCallback[] = [];

src/constants.ts

-12
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,3 @@
22
// Licensed under the MIT License.
33

44
export const version = '3.4.0';
5-
6-
export enum HeaderName {
7-
contentType = 'content-type',
8-
contentDisposition = 'content-disposition',
9-
}
10-
11-
export enum MediaType {
12-
multipartForm = 'multipart/form-data',
13-
urlEncodedForm = 'application/x-www-form-urlencoded',
14-
octetStream = 'application/octet-stream',
15-
json = 'application/json',
16-
}

0 commit comments

Comments
 (0)